106 Commits

Author SHA1 Message Date
Eduardo Bart
8f0ad27735 Minor SDL improvements 2013-03-11 14:43:42 -03:00
Eduardo Bart
d60413f7d6 Progress in SDL platform 2013-03-08 15:36:32 -03:00
Eduardo Bart
e6ee88af43 Changes to compile on android 2013-03-08 15:35:40 -03:00
Henrique Santiago
b3b849000d Add texture abstract class 2013-03-08 15:35:40 -03:00
Henrique
ab9351196c EGL and WGL working 2013-03-08 15:32:21 -03:00
Henrique Santiago
96bbe20588 EGL and GLX working 2013-03-08 15:32:21 -03:00
Henrique Santiago
77995a2e88 Compiling on linux again 2013-03-08 15:32:20 -03:00
Eduardo Bart
adf51f1852 Use SDL 2.0 2013-03-08 15:32:20 -03:00
Henrique
45eda6c573 Now drawing on windows again 2013-03-08 15:32:20 -03:00
Henrique Santiago
c3c951ebbb More changes to context 2013-03-08 15:32:20 -03:00
Henrique
a989ceb10c Add graphics context 2013-03-08 15:32:20 -03:00
Eduardo Bart
fb8552d142 Very basic rendering with SDL1.2 + OGL 2013-03-08 15:32:20 -03:00
Eduardo Bart
65b32d283b Add first SDL files 2013-03-08 15:32:20 -03:00
Eduardo Bart
64fc4570c9 Try to fix compilation for gcc 4.6 [3] 2013-03-06 15:47:38 -03:00
Eduardo Bart
392acc0b43 Try to fix compilation for gcc 4.6 [2] 2013-03-06 15:40:47 -03:00
Eduardo Bart
69f72b9c86 Try to fix compilation for gcc 4.6 2013-03-06 13:05:46 -03:00
Eduardo Bart
489688e9fb Merge branch 'sql' 2013-03-06 13:00:21 -03:00
Eduardo Bart
d911b38d68 defaults SQL to off 2013-03-06 12:59:59 -03:00
Eduardo Bart
61be2103ed Fix linkage 2013-03-06 12:54:27 -03:00
BeniS
a7b27ef8dd Forgot to add MySQLResult lua binding 2013-03-05 20:33:27 +13:00
Eduardo Bart
10a16169a4 Fix hotkeys reload and implement filters for console 2013-03-05 04:02:54 -03:00
Eduardo Bart
44bf4dcb6e Fix ubuntu compile errors 2013-03-05 02:54:08 -03:00
BeniS
9305053e34 Few issues with compilation and layout 2013-03-05 17:47:43 +13:00
Eduardo Bart
1dd558d57e Revert "Use boost::thread instead of std::thread"
This reverts commit 71b5c5f2e4.
2013-03-05 01:47:23 -03:00
BeniS
15ee7962f1 Some minor clean ups 2013-03-05 17:31:19 +13:00
Eduardo Bart
8c016b143a Fix #294 2013-03-04 23:59:37 -03:00
Henrique Santiago
a85ca0fb17 Merge pull request #296 from conde2/master
Fix spell cooldown
2013-03-04 18:58:47 -08:00
Joao Pasqualini Costa
115bf08364 Fix spell cooldown timer 2013-03-04 23:45:19 -03:00
Eduardo Bart
71b5c5f2e4 Use boost::thread instead of std::thread 2013-03-04 23:06:00 -03:00
Henrique Santiago
5396ea6231 Fix to last commit 2013-03-04 22:46:14 -03:00
Henrique Santiago
9955de573b Avoid infinite loop 2013-03-04 22:44:29 -03:00
Eduardo Bart
0be7bd5360 Implement async dispatcher #221 2013-03-04 18:56:22 -03:00
Eduardo Bart
c452e74e0c Implement stdext::shared_ptr
It's an alternative to stdext::shared_object_ptr
with weak pointers support and some other functionallity, however
it's heavier, uses more memory, more allocation and slower,
this class should be used when really needed, prefer
stdext::shared_object_ptr
2013-03-04 13:14:35 -03:00
Eduardo Bart
bdbe065c23 Add thread safety for std::shared_object_ptr 2013-03-04 10:47:07 -03:00
BeniS
f4263384bc Fix boost issue on Ubuntu and fix MySQL lib issue
* Add framework options for configuration
* libboost_chrono-mt.a dependency issue (with clock_gettime)
* MySQL lib must be added before zlib
2013-03-04 18:03:04 +13:00
BeniS
f50c63e9e5 Removed singleton instance & added more lua bindings
* Some tidying up
2013-03-04 04:11:29 +13:00
BeniS
48ac91d173 A few clean ups and also tested, its working fine 2013-03-04 01:27:07 +13:00
BeniS
8db85e4e3a Use stdext::millis not g_clock.millis 2013-03-03 19:43:25 +13:00
BeniS
02d32565e9 Work on sql framework classes 2013-03-03 19:19:22 +13:00
BeniS
3980f859b7 Forgot to remove header includes 2013-03-03 19:17:48 +13:00
Eduardo Bart
c392bcca90 Fix win32 alt bug 2013-03-03 00:00:13 -03:00
Eduardo Bart
62921dee9b Fixes in options, hotkeys and viplist 2013-03-02 17:01:52 -03:00
BeniS
3ca85cbe87 Removed Position dependencies inside the framework 2013-03-02 18:33:14 +13:00
Eduardo Bart
32df317163 Fix luajit on Mac OS X 2013-03-01 17:14:18 -03:00
Eduardo Bart
a145ad282b Add live_sprites_reload command 2013-03-01 17:14:18 -03:00
Samuel
884102833e OTB loading fix 2013-03-01 15:30:50 +01:00
Eduardo Bart
50b6cc69e1 Implement live_module_reload command 2013-03-01 06:38:05 -03:00
Eduardo Bart
8314b84f69 Add live_textures_reload command 2013-03-01 05:46:55 -03:00
Henrique Santiago
e85afd4b63 Platform modtime, little changes to entergame 2013-03-01 05:08:40 -03:00
Eduardo Bart
120c2b4231 Fixes in rule violations and private chat 2013-02-28 22:01:41 -03:00
Eduardo Bart
dad3026ba0 Optimize terminal buffering 2013-02-28 21:35:35 -03:00
Eduardo Bart
9312d20a0f More terminal improvements 2013-02-28 20:10:36 -03:00
Eduardo Bart
425bfd998b Add about_modules command 2013-02-28 19:05:53 -03:00
Eduardo Bart
b804dd6959 Fixes and new tuned terminal 2013-02-28 18:46:42 -03:00
Eduardo Bart
69e762385e Warn when shared_object_ptr misused 2013-02-28 12:19:42 -03:00
Eduardo Bart
e528fcc8f8 Minor fixes and improvements 2013-02-28 02:43:26 -03:00
Henrique Santiago
46aa0c005f Support to miniwindow margin, fix protocollogin connectCallback, pt translation 2013-02-27 23:45:03 -03:00
BeniS
eb46b96ffa Fix typo from last commit 2013-02-28 10:31:15 +13:00
BeniS
ccbe491e3c Should resolve #289 (please test and give feedback) 2013-02-28 10:23:22 +13:00
Henrique Santiago
864ac3fdd9 Pt translations, #286 2013-02-27 15:57:13 -03:00
BeniS
5f26303389 Added latest protocol/client support for cipservers 2013-02-28 04:38:48 +13:00
BeniS
0bf909d52f Fix #283 and more:
* Might have fixed death window issue but not confirmed
* Stop hotkey window from display while offline
* Moved some required features to >= 840 if statement
  (protocol 840/842 arent supported in otclient yet)
2013-02-28 01:01:51 +13:00
Eduardo Bart
ef20f59a98 Fix new line in utf8 conversion 2013-02-26 18:31:09 -03:00
Eduardo Bart
406c7bdae6 Fix #276 2013-02-26 18:13:50 -03:00
Eduardo Bart
41b81da76f Towards 0.6.2 2013-02-26 17:56:50 -03:00
Eduardo Bart
dc3559a5c0 Fix hotkey bug and compile error on Mac 2013-02-26 17:50:08 -03:00
Eduardo Bart
d0576da69d Implement dash walking and zoom out again 2013-02-26 16:37:02 -03:00
Eduardo Bart
2a225b99b7 Only show ping when available 2013-02-25 23:16:15 -03:00
Eduardo Bart
04f52d77d2 Walk ping is not supported anymore 2013-02-24 22:39:25 -03:00
Eduardo Bart
06e2b6eca2 Platform fixes and rework ping 2013-02-24 22:16:45 -03:00
Henrique Santiago
a8c175452b Pt translations 2013-02-23 20:15:12 -03:00
BeniS
92228e9553 Prompt user before removing server list entry 2013-02-24 01:26:49 +13:00
BeniS
67ed9e21ad Forget account/password when "Remember password" is unchecked 2013-02-24 01:14:30 +13:00
BeniS
01126eee62 Some fixes for the server list module
* Fixed an indexing issue in the settings
Note: Forgot to mention that it will store the last account/password used for that server
2013-02-24 01:02:24 +13:00
BeniS
8e9f65779c Implemented client_serverlist module! Close #200
* Will store servers that are not already in the list when logging in
* Can add servers manually if required too
* Fixed a bug in table.size
2013-02-24 00:41:21 +13:00
BeniS
2296e35174 Fix issue with closing containers
* Wasn't clearing references properly.
2013-02-23 19:38:52 +13:00
BeniS
28e70516a4 Use full path in SpelllistSettings
* Fix reload errors from previous commit
2013-02-23 19:23:18 +13:00
BeniS
039c3072dc Preload properly with g_textures.preload
* Thanks Baxnie for advising me of this method :)
2013-02-23 19:16:42 +13:00
BeniS
f4f9e319d8 Buffer condition/cooldown icons on module init
* This should hopefully avoid some lag with slow hdd computers
2013-02-23 18:53:27 +13:00
Eduardo Bart
035ce26728 Fix link error in Mac OS X 2013-02-22 19:42:28 -03:00
Eduardo Bart
04c4943fa8 Remove boost::filesystem dependency 2013-02-22 19:29:58 -03:00
Eduardo Bart
09c937998f Dont use boost locale anymore 2013-02-22 18:49:36 -03:00
Eduardo Bart
e4e3d7d053 New platform APIs and new OpenAL cmake 2013-02-22 16:53:49 -03:00
Eduardo Bart
5b573afdfc Change network errors message 2013-02-22 16:53:49 -03:00
Henrique Santiago
90d2032e9e More changes to painter 2013-02-22 03:31:13 -03:00
Henrique Santiago
3eeb5ae890 Painter became PainterOGL, new Painter generic class 2013-02-22 02:55:35 -03:00
Eduardo Bart
9a54bfcc90 Minimap, hotkeys and lot of other changes
* Begin working on a new layout system for UIMinimap and later UIMap,
this new layout system allows to add widgets to the minimap
* Add option to disable motd
* Rework hotkey binding
* Lots of fixes in hotkeys manager
* Add fullmap view using Ctrl+Shift+M
* Prevent some crashs in ThingType draw
* Add function to load minimap from PNG files
* Fixes in minimap saving
* Fixes in Tile::isClickable
* Add UIMapAnchorLayout, new layout for maps
* Fix freezes in win32 when pressing alt key
2013-02-21 17:03:05 -03:00
Henrique Santiago
f8b078ea91 Little fixes 2013-02-20 21:50:45 -03:00
Henrique
33ce0aa704 A few more changes to dx9 2013-02-20 19:12:52 -03:00
Henrique
bb304f9f4e Fixes to npc trade, begin native directx support 2013-02-20 15:41:28 -03:00
Ben Dol
a84d0bbf11 Update tools/tfs_extendedopcode.patch
Fixed issue with sending Player ptr in dispatcher (apparently causes issues in TFS)
2013-02-21 04:51:10 +13:00
BeniS
cb3f06358c Missed existing onInventoryChange hook 2013-02-21 04:34:06 +13:00
BeniS
3b91c4d509 Minor quantity fix from previous commit 2013-02-21 00:28:45 +13:00
BeniS
f4c7d98bd5 Fixes to trade npc module:
* Will now update player goods on inventory change
* Sell all no longer shows inventory items when ignore is checked
* Sell all tooltip now updates properly
* Will tell you the sell all total
2013-02-21 00:19:30 +13:00
BeniS
88c59afb8c Added 'sell all' tooltip to show items you can sell
* Now 'sell all' button with enable/disable
* Fixed display issue with 'sell all' button
* Also changed spinbox button click
2013-02-20 23:08:03 +13:00
BeniS
b61094c053 Minor fix to scroll bar 2013-02-20 15:03:45 +13:00
BeniS
3b9acab7a1 Fixed Market laoding and 'search all' issue. 2013-02-20 14:44:06 +13:00
Henrique Santiago
6d456994f4 Fix scrollbar 2013-02-19 21:34:50 -03:00
BeniS
e87e669c87 Few market UI fixes 2013-02-19 23:19:43 +13:00
Henrique Santiago
59a5b8115a Fix locale send, spelllist reload, few changes 2013-02-18 22:18:10 -03:00
Eduardo Bart
67fc77d507 Add sell all button to NPC trade 2013-02-15 16:38:57 -02:00
Eduardo Bart
28cdd6aa53 Fix minor walk delay 2013-02-15 16:38:29 -02:00
Henrique Santiago
4f423432fa Missing change for hotkeys 2013-02-14 18:29:35 -02:00
Eduardo Bart
62f38d678d Fix for chat commands #s #w #y
* Some progressbar changes
2013-02-14 16:34:55 -02:00
Henrique Santiago
07dd78002b Save console messages #263, change settings names 2013-02-14 15:30:45 -02:00
Henrique Santiago
5fc1ac8051 Save gamemap height #207. UISplitter needs a rework. 2013-02-14 13:54:51 -02:00
232 changed files with 6737 additions and 2739 deletions

2
.gitignore vendored
View File

@@ -37,3 +37,5 @@ otclient.layout
LOCALTODO LOCALTODO
tags tags
Thumbs.db Thumbs.db
.directory
src/framework/graphics/dx/

View File

@@ -1,12 +1,14 @@
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
project(otclient) project(otclient)
set(VERSION "0.6.1") set(VERSION "0.6.2")
option(FRAMEWORK_SOUND "Use SOUND " ON)
option(FRAMEWORK_GRAPHICS "Use GRAPHICS " ON)
option(FRAMEWORK_XML "Use XML " ON)
option(FRAMEWORK_NET "Use NET " ON)
option(FRAMEWORK_SQL "Use SQL" OFF)
set(FRAMEWORK_SOUND ON)
set(FRAMEWORK_GRAPHICS ON)
set(FRAMEWORK_XML ON)
set(FRAMEWORK_NET ON)
include(src/framework/CMakeLists.txt) include(src/framework/CMakeLists.txt)
include(src/client/CMakeLists.txt) include(src/client/CMakeLists.txt)

View File

@@ -0,0 +1,8 @@
Font
name: terminus-10px
texture: terminus-10px
height: 12
y-offset: 0
glyph-size: 16 16
fixed-glyph-width: 6
space-width: 6

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

BIN
data/images/ui/icon_add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 661 B

After

Width:  |  Height:  |  Size: 646 B

View File

@@ -5,6 +5,7 @@ locale = {
-- As tradu<64><75>es devem vir sempre em ordem alfab<61>tica. -- As tradu<64><75>es devem vir sempre em ordem alfab<61>tica.
translation = { translation = {
["%d of experience per hour"] = "%d de experi<72>ncia por hora",
["%s of experience left"] = "%s de experi<72>ncia faltando", ["%s of experience left"] = "%s de experi<72>ncia faltando",
["%s: (use object on target)"] = "%s: (usar objeto no alvo)", ["%s: (use object on target)"] = "%s: (usar objeto no alvo)",
["%s: (use object on yourself)"] = "%s: (usar objeto em si)", ["%s: (use object on yourself)"] = "%s: (usar objeto em si)",
@@ -33,6 +34,7 @@ locale = {
["Account name"] = "Nome da conta", ["Account name"] = "Nome da conta",
["Account Status"] = "Estado da Conta", ["Account Status"] = "Estado da Conta",
["Action"] = "A<EFBFBD><EFBFBD>o", ["Action"] = "A<EFBFBD><EFBFBD>o",
["Add new server"] = "Adicionar novo servidor",
["Add new VIP"] = "Adicionar nova VIP", ["Add new VIP"] = "Adicionar nova VIP",
["Add to VIP list"] = "Adicionar a lista VIP", ["Add to VIP list"] = "Adicionar a lista VIP",
["Add"] = "Adicionar", ["Add"] = "Adicionar",
@@ -89,6 +91,7 @@ locale = {
["Comment"] = "Coment<EFBFBD>rio", ["Comment"] = "Coment<EFBFBD>rio",
["Connecting to game server..."] = "Conectando no servidor do jogo...", ["Connecting to game server..."] = "Conectando no servidor do jogo...",
["Connecting to login server..."] = "Conectando no servidor de autentica<63><61>o...", ["Connecting to login server..."] = "Conectando no servidor de autentica<63><61>o...",
["Connection Error"] = "Erro de Conex<65>o",
["Console"] = "Console", ["Console"] = "Console",
["Cooldown"] = "Cooldown", ["Cooldown"] = "Cooldown",
["Cooldowns"] = "Cooldowns", ["Cooldowns"] = "Cooldowns",
@@ -122,6 +125,7 @@ locale = {
["Edit List"] = "Editar lista", ["Edit List"] = "Editar lista",
["Edit Text"] = "Editar Texto", ["Edit Text"] = "Editar Texto",
["Enable audio"] = "Ativar <20>udio", ["Enable audio"] = "Ativar <20>udio",
["Enable dash walking"] = "Ativar andar r<>pido",
["Enable lights"] = "Ativar luzes", ["Enable lights"] = "Ativar luzes",
["Enable music sound"] = "Ativar m<>sica", ["Enable music sound"] = "Ativar m<>sica",
["Enable music"] = "Ativar musica", ["Enable music"] = "Ativar musica",
@@ -169,6 +173,7 @@ locale = {
["Hide spells for other vocations"] = "Esconder feiti<74>os de outras voca<63><61>es", ["Hide spells for other vocations"] = "Esconder feiti<74>os de outras voca<63><61>es",
["Hit Points"] = "Pontos de Vida", ["Hit Points"] = "Pontos de Vida",
["Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks"] = "Segure o bot<6F>o esquerdo para navegar\nGire o bot<6F>o do centro do mouse para ampliar\nClique com o bot<6F>o direito do mouse para criar marcas", ["Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks"] = "Segure o bot<6F>o esquerdo para navegar\nGire o bot<6F>o do centro do mouse para ampliar\nClique com o bot<6F>o direito do mouse para criar marcas",
["Host"] = "Host",
["Hotkeys"] = "Atalhos", ["Hotkeys"] = "Atalhos",
["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."] = "Se voc<6F> desligar o programa o seu personagem pode continuar no jogo.\nClique em 'Sair' para assegurar que seu personagem saia do jogo adequadamente.\nClique em 'For<6F>ar Saida' para fechar o programa sem desconectar seu personagem.", ["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."] = "Se voc<6F> desligar o programa o seu personagem pode continuar no jogo.\nClique em 'Sair' para assegurar que seu personagem saia do jogo adequadamente.\nClique em 'For<6F>ar Saida' para fechar o programa sem desconectar seu personagem.",
["Ignore capacity"] = "Ignorar capacidade", ["Ignore capacity"] = "Ignorar capacidade",
@@ -221,6 +226,8 @@ locale = {
["Name Report + Banishment"] = "Reportar Nome + Banimento", ["Name Report + Banishment"] = "Reportar Nome + Banimento",
["Name Report"] = "Reportar Nome", ["Name Report"] = "Reportar Nome",
["Name"] = "Nome", ["Name"] = "Nome",
["New Server"] = "Novo Servidor",
["Next level in %d hours and %d minutes"] = "Pr<EFBFBD>ximo n<>vel em %d horas e %d minutos",
["No graphics card detected, everything will be drawn using the CPU,\nthus the performance will be really bad.\nPlease update your graphics driver to have a better performance."] = false, ["No graphics card detected, everything will be drawn using the CPU,\nthus the performance will be really bad.\nPlease update your graphics driver to have a better performance."] = false,
["No item selected."] = "Nenhum item selecionado", ["No item selected."] = "Nenhum item selecionado",
["No Mount"] = "Sem montaria", ["No Mount"] = "Sem montaria",
@@ -287,12 +294,16 @@ locale = {
["Select object"] = "Selecionar objeto", ["Select object"] = "Selecionar objeto",
["Select Outfit"] = "Selecionar Roupa", ["Select Outfit"] = "Selecionar Roupa",
["Select your language"] = "Selecione sua l<>ngua", ["Select your language"] = "Selecione sua l<>ngua",
["Select"] = "Selecionar",
["Sell All"] = "Vender Todos",
["Sell Now"] = "Vender agora", ["Sell Now"] = "Vender agora",
["Sell Offers"] = "Ofertas de venda", ["Sell Offers"] = "Ofertas de venda",
["Sell"] = "Vender", ["Sell"] = "Vender",
["Send automatically"] = "Enviar automaticamente", ["Send automatically"] = "Enviar automaticamente",
["Send Message"] = "Enviar Mensagem", ["Send Message"] = "Enviar Mensagem",
["Send"] = "Enviar", ["Send"] = "Enviar",
["Server List"] = "Lista de Servidores",
["Server list"] = "Lista de servidores",
["Server Log"] = "Registro do servidor", ["Server Log"] = "Registro do servidor",
["Server"] = "Servidor", ["Server"] = "Servidor",
["Set Outfit"] = "Escolher Roupa", ["Set Outfit"] = "Escolher Roupa",
@@ -337,8 +348,9 @@ locale = {
["Trade"] = "Trocar", ["Trade"] = "Trocar",
["Trying to reconnect in %s seconds."] = "Tentando reconectar em %s segundos.", ["Trying to reconnect in %s seconds."] = "Tentando reconectar em %s segundos.",
["Type"] = "Tipo", ["Type"] = "Tipo",
["Unable to load dat file, please place a valid dat in '%s'"] = "N<EFBFBD>o foi poss<73>vel carregar o arquivo dat, por favor coloque um arquivo v<>lido em %s", ["Unable to establish a connection. (err: %d)"] = "N<EFBFBD>o foi poss<73>vel estabilizar a conex<65>. (err: %d)",
["Unable to load spr file, please place a valid spr in '%s'"] = "N<EFBFBD>o foi poss<73>vel carregar o arquivo spr, por favor coloque um arquivo v<>lido em %s", ["Unable to load dat file, please place a valid dat in '%s'"] = "N<EFBFBD>o foi poss<73>vel carregar o arquivo DAT, por favor coloque um arquivo v<>lido em %s",
["Unable to load spr file, please place a valid spr in '%s'"] = "N<EFBFBD>o foi poss<73>vel carregar o arquivo SPR, por favor coloque um arquivo v<>lido em %s",
["Unable to logout."] = "N<EFBFBD>o <20> possivel sair", ["Unable to logout."] = "N<EFBFBD>o <20> possivel sair",
["Unignore"] = "Designorar", ["Unignore"] = "Designorar",
["Unload"] = "Descarregar", ["Unload"] = "Descarregar",
@@ -354,6 +366,7 @@ locale = {
["Waiting List"] = "Lista de espera", ["Waiting List"] = "Lista de espera",
["Website"] = "Website", ["Website"] = "Website",
["Weight"] = "Peso", ["Weight"] = "Peso",
["Will boost your walk on high speed characters"] = "Ir<EFBFBD> melhorar o andar de persnagens r<>pidos",
["Will detect when to use diagonal step based on the\nkeys you are pressing"] = "Detectar quando usar o passo diagonal\nbaseado nas teclas pressionadas", ["Will detect when to use diagonal step based on the\nkeys you are pressing"] = "Detectar quando usar o passo diagonal\nbaseado nas teclas pressionadas",
["With crosshair"] = "Com mira", ["With crosshair"] = "Com mira",
["Yes"] = "Sim", ["Yes"] = "Sim",
@@ -388,6 +401,7 @@ locale = {
["Your Capacity"] = "Sua capacidade", ["Your Capacity"] = "Sua capacidade",
["Your character health is %d out of %d."] = "A vida do seu personagem <20> %d de %d.", ["Your character health is %d out of %d."] = "A vida do seu personagem <20> %d de %d.",
["Your character mana is %d out of %d."] = "A mana do seu personagem <20> %d de %d.", ["Your character mana is %d out of %d."] = "A mana do seu personagem <20> %d de %d.",
["Your connection has been lost. (err: %d)"] = "A sua conex<65>o foi perdida. (err: %d)",
["Your Money"] = "Seu dinheiro", ["Your Money"] = "Seu dinheiro",
} }
} }

View File

@@ -66,4 +66,18 @@ PreviousButton < UIButton
image-clip: 0 21 12 21 image-clip: 0 21 12 21
$disabled: $disabled:
image-color: #ffffff55 image-color: #ffffff55
AddButton < UIButton
size: 20 20
image-source: /images/ui/icon_add
image-color: #ffffffff
$hover !disabled:
image-color: #ffffff99
$pressed:
image-color: #ffffff44
$disabled:
image-color: #ffffff55

View File

@@ -38,7 +38,7 @@ CreatureButton < UICreatureButton
margin-left: 2 margin-left: 2
phantom: true phantom: true
ProgressBar LifeProgressBar
id: lifeBar id: lifeBar
height: 5 height: 5
anchors.left: spacer.right anchors.left: spacer.right

View File

@@ -4,3 +4,7 @@ Item < UIItem
image-source: /images/ui/item image-source: /images/ui/item
font: verdana-11px-rounded font: verdana-11px-rounded
border-color: white border-color: white
color: white
$disabled:
color: #646464

View File

@@ -21,45 +21,3 @@ MenuLabel < Label
GameLabel < UILabel GameLabel < UILabel
font: verdana-11px-antialised font: verdana-11px-antialised
color: #bbbbbb color: #bbbbbb
FrameCounterLabel < Label
font: verdana-11px-rounded
@onSetup: |
self.updateEvent = cycleEvent(function()
local text = 'FPS: ' .. g_app.getBackgroundPaneFps()
self:setText(text)
end, 1000)
@onDestroy: self.updateEvent:cancel()
PingLabel < Label
font: verdana-11px-rounded
@onSetup: |
self.updateEvent = cycleEvent(function()
if g_game.isOnline() and modules.client_options.getOption('showPing') then
local ping = -1
if g_game.getFeature(GameClientPing) or g_game.getFeature(GameExtendedClientPing) then
ping = g_game.getPing()
else
ping = g_game.getLocalPlayer():getWalkPing()
end
local text = 'Ping: '
if ping < 0 then
text = text .. "??"
self:setColor('yellow')
else
text = text .. ping .. ' ms'
if ping >= 500 then
self:setColor('red')
elseif ping >= 250 then
self:setColor('yellow')
else
self:setColor('green')
end
end
self:setText(text)
self:show()
else
self:hide()
end
end, 1000)
@onDestroy: self.updateEvent:cancel()

View File

@@ -1,12 +1,10 @@
ProgressBar < UIProgressBar ProgressBar < UIProgressBar
height: 16 height: 16
background-color: red background-color: red
border: 1 black
image-source: /images/ui/progressbar image-source: /images/ui/progressbar
image-border: 1 image-border: 1
font: verdana-11px-rounded font: verdana-11px-rounded
text-offset: 0 2 text-offset: 0 2
on: true
$!on: $!on:
visible: false visible: false
@@ -14,6 +12,14 @@ ProgressBar < UIProgressBar
margin-bottom: 0 margin-bottom: 0
height: 0 height: 0
LifeProgressBar < UIProgressBar
height: 16
background-color: green
border: 1 black
font: verdana-11px-rounded
text-offset: 0 2
margin: 2
ProgressRect < UIProgressRect ProgressRect < UIProgressRect
anchors.fill: parent anchors.fill: parent
phantom: true phantom: true

View File

@@ -5,7 +5,7 @@ ScrollBarSlider < UIButton
image-source: /images/ui/scrollbar image-source: /images/ui/scrollbar
image-clip: 0 26 13 13 image-clip: 0 26 13 13
image-border: 2 image-border: 2
image-color: #ffffffbb image-color: #ffffffff
$hover: $hover:
image-clip: 13 26 13 13 image-clip: 13 26 13 13
$pressed: $pressed:
@@ -14,6 +14,12 @@ ScrollBarSlider < UIButton
$disabled: $disabled:
image-color: #ffffff66 image-color: #ffffff66
ScrollBarValueLabel < Label
id: valueLabel
anchors.fill: parent
color: white
text-align: center
VerticalScrollBar < UIScrollBar VerticalScrollBar < UIScrollBar
orientation: vertical orientation: vertical
width: 13 width: 13
@@ -55,6 +61,8 @@ VerticalScrollBar < UIScrollBar
ScrollBarSlider ScrollBarSlider
ScrollBarValueLabel
HorizontalScrollBar < UIScrollBar HorizontalScrollBar < UIScrollBar
orientation: horizontal orientation: horizontal
height: 13 height: 13
@@ -97,3 +105,5 @@ HorizontalScrollBar < UIScrollBar
image-color: #ffffff66 image-color: #ffffff66
ScrollBarSlider ScrollBarSlider
ScrollBarValueLabel

View File

@@ -1,7 +1,9 @@
SpinBox < TextEdit SpinBox < TextEdit
__class: UISpinBox __class: UISpinBox
text-align: left
size: 86 20 size: 86 20
padding: 0 padding: 0
padding-left: 2
Button Button
id: up id: up
@@ -11,7 +13,6 @@ SpinBox < TextEdit
image-clip: 0 0 10 10 image-clip: 0 0 10 10
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
@onClick: self:getParent():up()
$hover: $hover:
image-clip: 0 10 10 10 image-clip: 0 10 10 10
@@ -26,7 +27,6 @@ SpinBox < TextEdit
image-clip: 0 0 10 10 image-clip: 0 0 10 10
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.right: parent.right anchors.right: parent.right
@onClick: self:getParent():down()
$hover: $hover:
image-clip: 0 10 10 10 image-clip: 0 10 10 10

View File

@@ -46,7 +46,11 @@ TopMenuPanel < Panel
image-repeated: true image-repeated: true
focusable: false focusable: false
TopMenuFrameCounterLabel < FrameCounterLabel TopMenuFrameCounterLabel < Label
font: verdana-11px-rounded
color: white color: white
margin-top: 4 margin-top: 4
margin-left: 5 margin-left: 5
TopMenuPingLabel < Label
font: verdana-11px-rounded

View File

@@ -1,8 +1,9 @@
MessageBoxLabel < Label MessageBoxLabel < Label
id: messageBoxLabel id: messageBoxLabel
text-auto-resize: true
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top anchors.top: parent.top
text-wrap: true
text-auto-resize: true
MessageBoxButtonHolder < UIWidget MessageBoxButtonHolder < UIWidget
id: buttonHolder id: buttonHolder

View File

@@ -1,10 +1,12 @@
MinimapFlag < UIWidget MinimapFlag < UIWidget
size: 11 11 size: 11 11
anchors.left: parent.left focusable: false
anchors.top: parent.top
MinimapFlags < UIWidget MinimapCross < UIWidget
anchors.fill: parent focusable: false
phantom: true
image: /images/game/minimap/cross
size: 16 16
MinimapFloorUpButton < Button MinimapFloorUpButton < Button
size: 20 20 size: 20 20
@@ -61,12 +63,7 @@ Minimap < UIMinimap
draggable: true draggable: true
focusable: false focusable: false
cross: true cross: true
@onGeometryChange: self:updateFlags() color: black
MinimapFlags
id: flags
phantom: true
focusable: false
MinimapFloorUpButton MinimapFloorUpButton
id: floorUp id: floorUp
@@ -245,22 +242,3 @@ MinimapFlagWindow < MainWindow
width: 64 width: 64
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
// Minimap Full Panel
MinimapFullPanel < FlatPanel
phantom: false
anchors.fill: parent
anchors.top: topMenu.bottom
ImageView
id: image
anchors.fill: parent
Button
!text: tr('Close')
margin-right: 4
margin-top: 4
anchors.right: parent.right
anchors.top: parent.top
@onClick: self:getParent():destroy()

View File

@@ -48,7 +48,7 @@ g_modules.ensureModuleLoaded("game_interface")
-- mods 1000-9999 -- mods 1000-9999
g_modules.autoLoadModules(9999) g_modules.autoLoadModules(9999)
local script = '/' .. g_app.getCompactName() .. 'rc' local script = '/' .. g_app.getCompactName() .. 'rc.lua'
if g_resources.fileExists(script) then if g_resources.fileExists(script) then
dofile(script) dofile(script)

View File

@@ -1,5 +1,5 @@
local musicFilename = "/sounds/startup" local musicFilename = "/sounds/startup"
local musicChannel = g_sounds.getChannel(1) local musicChannel = nil
function setMusic(filename) function setMusic(filename)
musicFilename = filename musicFilename = filename
@@ -11,7 +11,7 @@ function setMusic(filename)
end end
function reloadScripts() function reloadScripts()
g_textures.clearTexturesCache() g_textures.clearCache()
g_modules.reloadModules() g_modules.reloadModules()
local script = '/' .. g_app.getCompactName() .. 'rc' local script = '/' .. g_app.getCompactName() .. 'rc'
@@ -55,13 +55,16 @@ end
function init() function init()
connect(g_app, { onRun = startup, connect(g_app, { onRun = startup,
onExit = exit }) onExit = exit })
g_window.setMinimumSize({ width = 600, height = 480 }) g_window.setMinimumSize({ width = 600, height = 480 })
musicChannel = g_sounds.getChannel(1)
g_sounds.preload(musicFilename) g_sounds.preload(musicFilename)
-- initialize in fullscreen mode on mobile devices -- initialize in fullscreen mode on mobile devices
if g_window.getPlatformType() == "X11-EGL" then if g_app.getOs() == "android" then
g_window.setFullscreen(true) g_window.maximize()
--g_window.setFullscreen(true)
else else
-- window size -- window size
local size = { width = 800, height = 600 } local size = { width = 800, height = 600 }

View File

@@ -12,11 +12,11 @@ Module
load-later: load-later:
- client_styles - client_styles
- client_locales - client_locales
//- client_particles
- client_topmenu - client_topmenu
- client_background - client_background
- client_entergame
- client_options - client_options
- client_entergame
- client_terminal - client_terminal
- client_modulemanager - client_modulemanager
- client_serverlist
//- client_stats //- client_stats

View File

@@ -1,18 +1,19 @@
-- private variables -- private variables
local background local background
local clientVersionLabel
-- public functions -- public functions
function init() function init()
background = g_ui.displayUI('background') background = g_ui.displayUI('background')
background:lower() background:lower()
local clientVersionLabel = background:getChildById('clientVersionLabel') clientVersionLabel = background:getChildById('clientVersionLabel')
clientVersionLabel:setText(g_app.getName() .. ' ' .. g_app.getVersion() .. '\n' .. clientVersionLabel:setText(g_app.getName() .. ' ' .. g_app.getVersion() .. '\n' ..
'Rev ' .. g_app.getBuildRevision() .. ' ('.. g_app.getBuildCommit() .. ')\n' .. 'Rev ' .. g_app.getBuildRevision() .. ' ('.. g_app.getBuildCommit() .. ')\n' ..
'Built on ' .. g_app.getBuildDate()) 'Built on ' .. g_app.getBuildDate())
if not g_game.isOnline() then if not g_game.isOnline() then
g_effects.fadeIn(clientVersionLabel, 1500) addEvent(function() g_effects.fadeIn(clientVersionLabel, 1500) end)
end end
connect(g_game, { onGameStart = hide }) connect(g_game, { onGameStart = hide })
@@ -40,3 +41,7 @@ end
function hideVersionLabel() function hideVersionLabel()
background:getChildById('clientVersionLabel'):hide() background:getChildById('clientVersionLabel'):hide()
end end
function setVersionText(text)
clientVersionLabel:setText(text)
end

View File

@@ -111,7 +111,8 @@ end
function onGameConnectionError(message, code) function onGameConnectionError(message, code)
CharacterList.destroyLoadBox() CharacterList.destroyLoadBox()
errorBox = displayErrorBox(tr("Login Error"), message) local text = translateNetworkError(code, g_game.getProtocolGame() and g_game.getProtocolGame():isConnecting(), message)
errorBox = displayErrorBox(tr("Connection Error"), text)
errorBox.onOk = function() errorBox.onOk = function()
errorBox = nil errorBox = nil
CharacterList.showAgain() CharacterList.showAgain()

View File

@@ -8,6 +8,7 @@ local motdButton
local enterGameButton local enterGameButton
local protocolBox local protocolBox
local protocolLogin local protocolLogin
local motdEnabled = true
-- private functions -- private functions
local function onError(protocol, message, errorCode) local function onError(protocol, message, errorCode)
@@ -27,15 +28,31 @@ end
local function onMotd(protocol, motd) local function onMotd(protocol, motd)
G.motdNumber = tonumber(motd:sub(0, motd:find("\n"))) G.motdNumber = tonumber(motd:sub(0, motd:find("\n")))
G.motdMessage = motd:sub(motd:find("\n") + 1, #motd) G.motdMessage = motd:sub(motd:find("\n") + 1, #motd)
motdButton:show() if motdEnabled then
motdButton:show()
end
end end
local function onCharacterList(protocol, characters, account, otui) local function onCharacterList(protocol, characters, account, otui)
-- Try add server to the server list
ServerList.add(G.host, G.port, g_game.getProtocolVersion())
if enterGame:getChildById('rememberPasswordBox'):isChecked() then if enterGame:getChildById('rememberPasswordBox'):isChecked() then
g_settings.set('account', g_crypt.encrypt(G.account)) local account = g_crypt.encrypt(G.account)
g_settings.set('password', g_crypt.encrypt(G.password)) local password = g_crypt.encrypt(G.password)
g_settings.set('account', account)
g_settings.set('password', password)
ServerList.setServerAccount(G.host, account)
ServerList.setServerPassword(G.host, password)
g_settings.set('autologin', enterGame:getChildById('autoLoginBox'):isChecked()) g_settings.set('autologin', enterGame:getChildById('autoLoginBox'):isChecked())
else else
-- reset server list account/password
ServerList.setServerAccount(G.host, '')
ServerList.setServerPassword(G.host, '')
EnterGame.clearAccountFields() EnterGame.clearAccountFields()
end end
@@ -45,12 +62,14 @@ local function onCharacterList(protocol, characters, account, otui)
CharacterList.create(characters, account, otui) CharacterList.create(characters, account, otui)
CharacterList.show() CharacterList.show()
local lastMotdNumber = g_settings.getNumber("motd") if motdEnabled then
if G.motdNumber and G.motdNumber ~= lastMotdNumber then local lastMotdNumber = g_settings.getNumber("motd")
g_settings.set("motd", motdNumber) if G.motdNumber and G.motdNumber ~= lastMotdNumber then
motdWindow = displayInfoBox(tr('Message of the day'), G.motdMessage) g_settings.set("motd", motdNumber)
connect(motdWindow, { onOk = function() CharacterList.show() motdWindow = nil end }) motdWindow = displayInfoBox(tr('Message of the day'), G.motdMessage)
CharacterList.hide() connect(motdWindow, { onOk = function() CharacterList.show() motdWindow = nil end })
CharacterList.hide()
end
end end
end end
@@ -81,12 +100,12 @@ function EnterGame.init()
motdButton:hide() motdButton:hide()
g_keyboard.bindKeyDown('Ctrl+G', EnterGame.openWindow) g_keyboard.bindKeyDown('Ctrl+G', EnterGame.openWindow)
if G.motdNumber then if motdEnabled and G.motdNumber then
motdButton:show() motdButton:show()
end end
local account = g_crypt.decrypt(g_settings.get('account')) local account = g_settings.get('account')
local password = g_crypt.decrypt(g_settings.get('password')) local password = g_settings.get('password')
local host = g_settings.get('host') local host = g_settings.get('host')
local port = g_settings.get('port') local port = g_settings.get('port')
local autologin = g_settings.getBoolean('autologin') local autologin = g_settings.getBoolean('autologin')
@@ -94,20 +113,15 @@ function EnterGame.init()
if port == nil or port == 0 then port = 7171 end if port == nil or port == 0 then port = 7171 end
enterGame:getChildById('accountNameTextEdit'):setText(account) EnterGame.setAccountName(account)
enterGame:getChildById('accountNameTextEdit'):setCursorPos(-1) EnterGame.setPassword(password)
enterGame:getChildById('accountPasswordTextEdit'):setText(password)
enterGame:getChildById('serverHostTextEdit'):setText(host) enterGame:getChildById('serverHostTextEdit'):setText(host)
enterGame:getChildById('serverPortTextEdit'):setText(port) enterGame:getChildById('serverPortTextEdit'):setText(port)
enterGame:getChildById('autoLoginBox'):setChecked(autologin) enterGame:getChildById('autoLoginBox'):setChecked(autologin)
enterGame:getChildById('rememberPasswordBox'):setChecked(#account > 0)
protocolBox = enterGame:getChildById('protocolComboBox') protocolBox = enterGame:getChildById('protocolComboBox')
protocolBox.onOptionChange = onChangeProtocol protocolBox.onOptionChange = onChangeProtocol
for _i, proto in pairs(g_game.getSupportedProtocols()) do
protocolBox:addOption(proto)
end
if protocolVersion then if protocolVersion then
protocolBox:setCurrentOption(protocolVersion) protocolBox:setCurrentOption(protocolVersion)
end end
@@ -127,13 +141,15 @@ function EnterGame.firstShow()
local host = g_settings.get('host') local host = g_settings.get('host')
local autologin = g_settings.getBoolean('autologin') local autologin = g_settings.getBoolean('autologin')
if #host > 0 and #password > 0 and #account > 0 and autologin then if #host > 0 and #password > 0 and #account > 0 and autologin then
autoLoginEvent = addEvent(EnterGame.doLogin) addEvent(function()
if not g_settings.getBoolean('autologin') then return end
EnterGame.doLogin()
end)
end end
end end
function EnterGame.terminate() function EnterGame.terminate()
g_keyboard.unbindKeyDown('Ctrl+G') g_keyboard.unbindKeyDown('Ctrl+G')
removeEvent(autoLoginEvent)
enterGame:destroy() enterGame:destroy()
enterGame = nil enterGame = nil
enterGameButton:destroy() enterGameButton:destroy()
@@ -177,6 +193,18 @@ function EnterGame.openWindow()
end end
end end
function EnterGame.setAccountName(account)
local account = g_crypt.decrypt(account)
enterGame:getChildById('accountNameTextEdit'):setText(account)
enterGame:getChildById('accountNameTextEdit'):setCursorPos(-1)
enterGame:getChildById('rememberPasswordBox'):setChecked(#account > 0)
end
function EnterGame.setPassword(password)
local password = g_crypt.decrypt(password)
enterGame:getChildById('accountPasswordTextEdit'):setText(password)
end
function EnterGame.clearAccountFields() function EnterGame.clearAccountFields()
enterGame:getChildById('accountNameTextEdit'):clearText() enterGame:getChildById('accountNameTextEdit'):clearText()
enterGame:getChildById('accountPasswordTextEdit'):clearText() enterGame:getChildById('accountPasswordTextEdit'):clearText()
@@ -186,7 +214,6 @@ function EnterGame.clearAccountFields()
end end
function EnterGame.doLogin() function EnterGame.doLogin()
autoLoginEvent = nil
G.account = enterGame:getChildById('accountNameTextEdit'):getText() G.account = enterGame:getChildById('accountNameTextEdit'):getText()
G.password = enterGame:getChildById('accountPasswordTextEdit'):getText() G.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
G.host = enterGame:getChildById('serverHostTextEdit'):getText() G.host = enterGame:getChildById('serverHostTextEdit'):getText()
@@ -205,7 +232,7 @@ function EnterGame.doLogin()
g_settings.set('port', G.port) g_settings.set('port', G.port)
protocolLogin = ProtocolLogin.create() protocolLogin = ProtocolLogin.create()
protocolLogin.onError = onError protocolLogin.onLoginError = onError
protocolLogin.onMotd = onMotd protocolLogin.onMotd = onMotd
protocolLogin.onCharacterList = onCharacterList protocolLogin.onCharacterList = onCharacterList
protocolLogin.onUpdateNeeded = onUpdateNeeded protocolLogin.onUpdateNeeded = onUpdateNeeded
@@ -252,10 +279,6 @@ function EnterGame.setDefaultServer(host, port, protocol)
protocolBox:setCurrentOption(protocol) protocolBox:setCurrentOption(protocol)
accountTextEdit:setText('') accountTextEdit:setText('')
passwordTextEdit:setText('') passwordTextEdit:setText('')
if autoLoginEvent then
autoLoginEvent:cancel()
end
end end
end end
@@ -283,6 +306,11 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
protocolLabel:setVisible(false) protocolLabel:setVisible(false)
protocolLabel:setHeight(0) protocolLabel:setHeight(0)
local serverListButton = enterGame:getChildById('serverListButton')
serverListButton:setVisible(false)
serverListButton:setHeight(0)
serverListButton:setWidth(0)
local rememberPasswordBox = enterGame:getChildById('rememberPasswordBox') local rememberPasswordBox = enterGame:getChildById('rememberPasswordBox')
rememberPasswordBox:setMarginTop(-5) rememberPasswordBox:setMarginTop(-5)
@@ -297,3 +325,7 @@ function EnterGame.setServerInfo(message)
label:setText(message) label:setText(message)
end end
function EnterGame.disableMotd()
motdEnabled = false
motdButton:hide()
end

View File

@@ -1,9 +1,26 @@
EnterGameWindow < MainWindow EnterGameWindow < MainWindow
!text: tr('Enter Game')
size: 236 274
EnterGameButton < Button
width: 64
ServerListButton < UIButton
size: 17 17
image-source: /images/topbuttons/minimap
image-color: #ffffffff
$hover !disabled:
image-color: #ffffff99
$pressed:
image-color: #ffffff44
$disabled:
image-color: #ffffff55
EnterGameWindow EnterGameWindow
id: enterGame id: enterGame
!text: tr('Enter Game')
size: 236 274
@onEnter: EnterGame.doLogin() @onEnter: EnterGame.doLogin()
MenuLabel MenuLabel
@@ -41,13 +58,22 @@ EnterGameWindow
margin-top: 8 margin-top: 8
text-auto-resize: true text-auto-resize: true
ServerListButton
id: serverListButton
!tooltip: tr('Server list')
anchors.right: parent.right
anchors.top: serverLabel.bottom
margin-top: 3
@onClick: ServerList.show()
TextEdit TextEdit
id: serverHostTextEdit id: serverHostTextEdit
!tooltip: tr('Make sure that your client uses\nthe correct game protocol version') !tooltip: tr('Make sure that your client uses\nthe correct game protocol version')
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: serverListButton.left
anchors.top: serverLabel.bottom anchors.top: serverLabel.bottom
margin-top: 2 margin-top: 2
margin-right: 4
MenuLabel MenuLabel
id: protocolLabel id: protocolLabel
@@ -66,6 +92,10 @@ EnterGameWindow
margin-top: 2 margin-top: 2
margin-right: 3 margin-right: 3
width: 90 width: 90
@onSetup: |
for _, proto in pairs(g_game.getSupportedProtocols()) do
self:addOption(proto)
end
MenuLabel MenuLabel
id: portLabel id: portLabel
@@ -103,9 +133,8 @@ EnterGameWindow
anchors.top: prev.bottom anchors.top: prev.bottom
margin-top: 2 margin-top: 2
Button EnterGameButton
!text: tr('Ok') !text: tr('Ok')
width: 64
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@onClick: EnterGame.doLogin() @onClick: EnterGame.doLogin()

View File

@@ -1,7 +1,7 @@
MainWindow MainWindow
id: waitingWindow id: waitingWindow
!text: tr('Waiting List') !text: tr('Waiting List')
size: 260 160 size: 260 180
@onEscape: CharacterList.cancelWait() @onEscape: CharacterList.cancelWait()
Label Label

View File

@@ -121,7 +121,7 @@ function installLocale(locale)
end end
if updatesNeeded > 0 then if updatesNeeded > 0 then
pwarning('Locale \'' .. locale.name .. '\' is missing ' .. updatesNeeded .. ' translations.') pdebug('Locale \'' .. locale.name .. '\' is missing ' .. updatesNeeded .. ' translations.')
end end
end end
@@ -146,6 +146,9 @@ function setLocale(name)
pwarning("Locale " .. name .. ' does not exist.') pwarning("Locale " .. name .. ' does not exist.')
return false return false
end end
if currentLocale then
sendLocale(locale.name)
end
currentLocale = locale currentLocale = locale
g_settings.set('locale', name) g_settings.set('locale', name)
if onLocaleChanged then onLocaleChanged(name) end if onLocaleChanged then onLocaleChanged(name) end
@@ -179,7 +182,7 @@ function _G.tr(text, ...)
if not translation then if not translation then
if translation == nil then if translation == nil then
if currentLocale.name ~= defaultLocaleName then if currentLocale.name ~= defaultLocaleName then
pwarning('Unable to translate: \"' .. text .. '\"') pdebug('Unable to translate: \"' .. text .. '\"')
end end
end end
translation = text translation = text

View File

@@ -5,6 +5,5 @@ Module
website: www.otclient.info website: www.otclient.info
sandboxed: true sandboxed: true
scripts: [ locales ] scripts: [ locales ]
dependencies: [ client_topmenu ]
@onLoad: init() @onLoad: init()
@onUnload: terminate() @onUnload: terminate()

View File

@@ -1,11 +1,3 @@
VolumeScrollbar < HorizontalScrollBar
step: 1
@onValueChange: modules.client_options.setOption(self:getId(), self:getValue())
@onSetup: |
UIScrollBar.onSetup(self)
local value = modules.client_options.getOption(self:getId())
self:setValue(value)
Panel Panel
OptionCheckBox OptionCheckBox
id: enableAudio id: enableAudio
@@ -26,7 +18,7 @@ Panel
local value = modules.client_options.getOption('musicSoundVolume') local value = modules.client_options.getOption('musicSoundVolume')
self:setText(tr('Music volume: %d', value)) self:setText(tr('Music volume: %d', value))
VolumeScrollbar OptionScrollbar
id: musicSoundVolume id: musicSoundVolume
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right

View File

@@ -12,6 +12,11 @@ Panel
!text: tr('Enable smart walking') !text: tr('Enable smart walking')
!tooltip: tr('Will detect when to use diagonal step based on the\nkeys you are pressing') !tooltip: tr('Will detect when to use diagonal step based on the\nkeys you are pressing')
OptionCheckBox
id: dashWalk
!text: tr('Enable dash walking')
!tooltip: tr('Will boost your walk on high speed characters')
OptionCheckBox OptionCheckBox
id: showPing id: showPing
!text: tr('Show connection ping') !text: tr('Show connection ping')

View File

@@ -1,12 +1,3 @@
FrameRateScrollbar < HorizontalScrollBar
step: 1
@onValueChange: modules.client_options.setOption(self:getId(), self:getValue())
@onSetup: |
UIScrollBar.onSetup(self)
local value = modules.client_options.getOption(self:getId())
if value == 0 then value = self:getMaximum() end
self:setValue(value)
Panel Panel
ButtonBox ButtonBox
id: opengl1 id: opengl1
@@ -65,7 +56,7 @@ Panel
self:setText(tr('Game framerate limit: %s', text)) self:setText(tr('Game framerate limit: %s', text))
FrameRateScrollbar OptionScrollbar
id: backgroundFrameRate id: backgroundFrameRate
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@@ -89,7 +80,7 @@ Panel
self:setText(tr('Interface framerate limit: %s', text)) self:setText(tr('Interface framerate limit: %s', text))
FrameRateScrollbar OptionScrollbar
id: foregroundFrameRate id: foregroundFrameRate
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@@ -108,7 +99,7 @@ Panel
local value = modules.client_options.getOption('ambientLight') local value = modules.client_options.getOption('ambientLight')
self:setText(tr('Ambient light: %s%%', value)) self:setText(tr('Ambient light: %s%%', value))
FrameRateScrollbar OptionScrollbar
id: ambientLight id: ambientLight
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right

View File

@@ -5,6 +5,7 @@ local defaultOptions = {
fullscreen = false, fullscreen = false,
classicControl = false, classicControl = false,
smartWalk = false, smartWalk = false,
dashWalk = false,
autoChaseOverride = true, autoChaseOverride = true,
showStatusMessagesInConsole = true, showStatusMessagesInConsole = true,
showEventMessagesInConsole = true, showEventMessagesInConsole = true,
@@ -81,45 +82,20 @@ local function setupGraphicsEngines()
end end
function init() function init()
for k,v in pairs(defaultOptions) do
g_settings.setDefault(k, v)
options[k] = v
end
optionsWindow = g_ui.displayUI('options') optionsWindow = g_ui.displayUI('options')
optionsWindow:hide() optionsWindow:hide()
optionsButton = modules.client_topmenu.addLeftButton('optionsButton', tr('Options'), '/images/topbuttons/options', toggle)
optionsTabBar = optionsWindow:getChildById('optionsTabBar') optionsTabBar = optionsWindow:getChildById('optionsTabBar')
optionsTabBar:setContentWidget(optionsWindow:getChildById('optionsTabContent')) optionsTabBar:setContentWidget(optionsWindow:getChildById('optionsTabContent'))
addEvent(function() setup() end)
g_keyboard.bindKeyDown('Ctrl+Shift+F', function() toggleOption('fullscreen') end) g_keyboard.bindKeyDown('Ctrl+Shift+F', function() toggleOption('fullscreen') end)
g_keyboard.bindKeyDown('Ctrl+N', toggleDisplays) g_keyboard.bindKeyDown('Ctrl+N', toggleDisplays)
audioButton = modules.client_topmenu.addLeftButton('audioButton', tr('Audio'), '/images/topbuttons/audio', function() toggleOption('enableAudio') end)
end
function terminate()
g_keyboard.unbindKeyDown('Ctrl+Shift+F')
g_keyboard.unbindKeyDown('Ctrl+N')
optionsWindow:destroy()
optionsButton:destroy()
audioButton:destroy()
optionsTabBar = nil
generalPanel = nil
consolePanel = nil
graphicsPanel = nil
audioPanel = nil
end
function setup()
-- load options
for k,v in pairs(defaultOptions) do
g_settings.setDefault(k, v)
if type(v) == 'boolean' then
setOption(k, g_settings.getBoolean(k))
elseif type(v) == 'number' then
setOption(k, g_settings.getNumber(k))
end
end
generalPanel = g_ui.loadUI('game') generalPanel = g_ui.loadUI('game')
optionsTabBar:addTab(tr('Game'), generalPanel, '/images/optionstab/game') optionsTabBar:addTab(tr('Game'), generalPanel, '/images/optionstab/game')
@@ -132,7 +108,31 @@ function setup()
audioPanel = g_ui.loadUI('audio') audioPanel = g_ui.loadUI('audio')
optionsTabBar:addTab(tr('Audio'), audioPanel, '/images/optionstab/audio') optionsTabBar:addTab(tr('Audio'), audioPanel, '/images/optionstab/audio')
optionsButton = modules.client_topmenu.addLeftButton('optionsButton', tr('Options'), '/images/topbuttons/options', toggle)
audioButton = modules.client_topmenu.addLeftButton('audioButton', tr('Audio'), '/images/topbuttons/audio', function() toggleOption('enableAudio') end)
addEvent(function() setup() end)
end
function terminate()
g_keyboard.unbindKeyDown('Ctrl+Shift+F')
g_keyboard.unbindKeyDown('Ctrl+N')
optionsWindow:destroy()
optionsButton:destroy()
audioButton:destroy()
end
function setup()
setupGraphicsEngines() setupGraphicsEngines()
-- load options
for k,v in pairs(defaultOptions) do
if type(v) == 'boolean' then
setOption(k, g_settings.getBoolean(k), true)
elseif type(v) == 'number' then
setOption(k, g_settings.getNumber(k), true)
end
end
end end
function toggle() function toggle()
@@ -171,106 +171,70 @@ function toggleOption(key)
setOption(key, not getOption(key)) setOption(key, not getOption(key))
end end
function setOption(key, value) function setOption(key, value, force)
if options[key] == value then return end if not force and options[key] == value then return end
local gameMapPanel = modules.game_interface.getMapPanel() local gameMapPanel = modules.game_interface.getMapPanel()
local panel = nil
if key == 'vsync' then if key == 'vsync' then
g_window.setVerticalSync(value) g_window.setVerticalSync(value)
elseif key == 'showFps' then elseif key == 'showFps' then
addEvent(function() modules.client_topmenu.setFpsVisible(value)
local frameCounter = rootWidget:recursiveGetChildById('frameCounter')
if frameCounter then frameCounter:setVisible(value) end
end)
elseif key == 'showPing' then elseif key == 'showPing' then
addEvent(function() modules.client_topmenu.setPingVisible(value)
local ping = rootWidget:recursiveGetChildById('pingLabel')
if ping then ping:setVisible(value) end
end)
elseif key == 'fullscreen' then elseif key == 'fullscreen' then
g_window.setFullscreen(value) g_window.setFullscreen(value)
panel = graphicsPanel
elseif key == 'enableAudio' then elseif key == 'enableAudio' then
g_sounds.setAudioEnabled(value) g_sounds.setAudioEnabled(value)
addEvent(function() if value then
if value then audioButton:setIcon('/images/topbuttons/audio')
audioButton:setIcon('/images/topbuttons/audio') else
else audioButton:setIcon('/images/topbuttons/audio_mute')
audioButton:setIcon('/images/topbuttons/audio_mute') end
end
end)
panel = audioPanel
elseif key == 'enableMusicSound' then elseif key == 'enableMusicSound' then
g_sounds.getChannel(SoundChannels.Music):setEnabled(value) g_sounds.getChannel(SoundChannels.Music):setEnabled(value)
elseif key == 'musicSoundVolume' then elseif key == 'musicSoundVolume' then
g_sounds.getChannel(SoundChannels.Music):setGain(value/100) g_sounds.getChannel(SoundChannels.Music):setGain(value/100)
if audioPanel then audioPanel:getChildById('musicSoundVolumeLabel'):setText(tr('Music volume: %d', value))
audioPanel:getChildById('musicSoundVolumeLabel'):setText(tr('Music volume: %d', value))
end
elseif key == 'showLeftPanel' then elseif key == 'showLeftPanel' then
addEvent(function() modules.game_interface.getLeftPanel():setOn(value)
modules.game_interface.getLeftPanel():setOn(value)
end)
elseif key == 'backgroundFrameRate' then elseif key == 'backgroundFrameRate' then
local text = value local text, v = value, value
if value <= 0 or value >= 201 then if value <= 0 or value >= 201 then text = 'max' v = 0 end
text = 'max' graphicsPanel:getChildById('backgroundFrameRateLabel'):setText(tr('Game framerate limit: %s', text))
value = 0 g_app.setBackgroundPaneMaxFps(v)
end
if graphicsPanel then
graphicsPanel:getChildById('backgroundFrameRateLabel'):setText(tr('Game framerate limit: %s', text))
end
g_app.setBackgroundPaneMaxFps(value)
elseif key == 'foregroundFrameRate' then elseif key == 'foregroundFrameRate' then
local text = value local text, v = value, value
if value <= 0 or value >= 61 then if value <= 0 or value >= 61 then text = 'max' v = 0 end
text = 'max' graphicsPanel:getChildById('foregroundFrameRateLabel'):setText(tr('Interface framerate limit: %s', text))
value = 0 g_app.setForegroundPaneMaxFps(v)
end
if graphicsPanel then
graphicsPanel:getChildById('foregroundFrameRateLabel'):setText(tr('Interface framerate limit: %s', text))
end
g_app.setForegroundPaneMaxFps(value)
elseif key == 'enableLights' then elseif key == 'enableLights' then
addEvent(function() gameMapPanel:setDrawLights(value and options['ambientLight'] < 100)
local map = modules.game_interface.getMapPanel() graphicsPanel:getChildById('ambientLight'):setEnabled(value)
map:setDrawLights(value and options['ambientLight'] < 100) graphicsPanel:getChildById('ambientLightLabel'):setEnabled(value)
if graphicsPanel then
graphicsPanel:getChildById('ambientLight'):setEnabled(value)
graphicsPanel:getChildById('ambientLightLabel'):setEnabled(value)
end
end)
elseif key == 'ambientLight' then elseif key == 'ambientLight' then
addEvent(function() graphicsPanel:getChildById('ambientLightLabel'):setText(tr('Ambient light: %s%%', value))
local map = modules.game_interface.getMapPanel() gameMapPanel:setMinimumAmbientLight(value/100)
if graphicsPanel then gameMapPanel:setDrawLights(options['enableLights'] and value < 100)
graphicsPanel:getChildById('ambientLightLabel'):setText(tr('Ambient light: %s%%', value))
end
map:setMinimumAmbientLight(value/100)
map:setDrawLights(options['enableLights'] and value < 100)
end)
elseif key == 'painterEngine' then elseif key == 'painterEngine' then
g_graphics.selectPainterEngine(value) g_graphics.selectPainterEngine(value)
elseif key == 'displayNames' then elseif key == 'displayNames' then
gameMapPanel:setDrawNames(value) gameMapPanel:setDrawNames(value)
panel = generalPanel
elseif key == 'displayHealth' then elseif key == 'displayHealth' then
gameMapPanel:setDrawHealthBars(value) gameMapPanel:setDrawHealthBars(value)
panel = generalPanel
elseif key == 'displayText' then elseif key == 'displayText' then
gameMapPanel:setDrawTexts(value) gameMapPanel:setDrawTexts(value)
panel = generalPanel
end end
-- change value for keybind updates -- change value for keybind updates
if panel then for _,panel in pairs(optionsTabBar:getTabsPanel()) do
local widget = panel:recursiveGetChildById(key) local widget = panel:recursiveGetChildById(key)
if widget and widget:getStyle().__class == 'UICheckBox' then if widget then
widget:setChecked(value) if widget:getStyle().__class == 'UICheckBox' then
widget:setChecked(value)
elseif widget:getStyle().__class == 'UIScrollBar' then
widget:setValue(value)
end
break
end end
end end

View File

@@ -4,7 +4,6 @@ Module
author: edubart, BeniS author: edubart, BeniS
website: www.otclient.info website: www.otclient.info
sandboxed: true sandboxed: true
dependencies: [ client_topmenu ]
scripts: [ options ] scripts: [ options ]
@onLoad: init() @onLoad: init()
@onUnload: terminate() @onUnload: terminate()

View File

@@ -1,6 +1,5 @@
OptionCheckBox < CheckBox OptionCheckBox < CheckBox
@onCheckChange: modules.client_options.setOption(self:getId(), self:isChecked()) @onCheckChange: modules.client_options.setOption(self:getId(), self:isChecked())
@onSetup: self:setChecked(modules.client_options.getOption(self:getId()))
height: 16 height: 16
$first: $first:
@@ -14,6 +13,10 @@ OptionCheckBox < CheckBox
anchors.top: prev.bottom anchors.top: prev.bottom
margin-top: 2 margin-top: 2
OptionScrollbar < HorizontalScrollBar
step: 1
@onValueChange: modules.client_options.setOption(self:getId(), self:getValue())
MainWindow MainWindow
id: optionsWindow id: optionsWindow
!text: tr('Options') !text: tr('Options')

View File

@@ -0,0 +1,38 @@
AddServer = {}
-- private variables
local addServerWindow = nil
-- public functions
function AddServer.init()
addServerWindow = g_ui.displayUI('addserver')
end
function AddServer.terminate()
addServerWindow:destroy()
end
function AddServer.add()
local host = addServerWindow:getChildById('host'):getText()
local port = addServerWindow:getChildById('port'):getText()
local protocol = addServerWindow:getChildById('protocol'):getCurrentOption().text
local added, error = ServerList.add(host, port, protocol)
if not added then
displayErrorBox(tr('Add Error'), tr(error))
else
AddServer.hide()
end
end
function AddServer.show()
addServerWindow:show()
addServerWindow:raise()
addServerWindow:focus()
addServerWindow:lock()
end
function AddServer.hide()
addServerWindow:hide()
addServerWindow:unlock()
end

View File

@@ -0,0 +1,72 @@
MainWindow
id: addServerWindow
!text: tr('New Server')
size: 180 180
visible: false
@onEscape: AddServer.hide()
@onEnter: AddServer.add()
Label
id: hostLabel
!text: tr('Host') .. ':'
anchors.top: parent.top
anchors.left: parent.left
margin-bottom: 2
TextEdit
id: host
anchors.top: hostLabel.bottom
anchors.left: hostLabel.left
anchors.right: parent.right
auto-focus: first
Label
id: portLabel
!text: tr('Port') .. ':'
anchors.top: host.bottom
anchors.left: host.left
margin-top: 3
margin-bottom: 2
TextEdit
id: port
text: 7171
anchors.top: portLabel.bottom
anchors.left: portLabel.left
anchors.right: host.right
Label
id: protocolLabel
!text: tr('Protocol') .. ':'
anchors.top: port.bottom
anchors.left: port.left
margin-top: 3
margin-bottom: 2
ComboBox
id: protocol
anchors.top: protocolLabel.bottom
anchors.left: protocolLabel.left
anchors.right: port.right
@onSetup: |
for _, proto in pairs(g_game.getSupportedProtocols()) do
self:addOption(proto)
end
Button
id: buttonAdd
!text: tr('Add')
width: 64
anchors.right: parent.horizontalCenter
anchors.bottom: parent.bottom
margin-right: 2
@onClick: AddServer.add()
Button
id: buttonCancel
!text: tr('Cancel')
width: 64
anchors.left: parent.horizontalCenter
anchors.bottom: parent.bottom
margin-left: 2
@onClick: AddServer.hide()

View File

@@ -0,0 +1,128 @@
ServerList = {}
-- private variables
local serverListWindow = nil
local serverTextList = nil
local removeWindow = nil
local servers = {}
-- public functions
function ServerList.init()
serverListWindow = g_ui.displayUI('serverlist')
serverTextList = serverListWindow:getChildById('serverList')
servers = g_settings.getNode('ServerList') or {}
ServerList.load()
end
function ServerList.terminate()
ServerList.destroy()
g_settings.setNode('ServerList', servers)
ServerList = nil
end
function ServerList.load()
for k,server in pairs(servers) do
ServerList.add(k, server.port, server.protocol, true)
end
end
function ServerList.select()
local selected = serverTextList:getFocusedChild()
if selected then
local server = servers[selected:getId()]
if server then
EnterGame.setDefaultServer(selected:getId(), server.port, server.protocol)
EnterGame.setAccountName(server.account)
EnterGame.setPassword(server.password)
ServerList.hide()
end
end
end
function ServerList.add(host, port, protocol, load)
if not load and servers[host] then
return false, 'Server already exists'
elseif host == '' or port == '' then
return false, 'Required fields are missing'
end
local widget = g_ui.createWidget('ServerWidget', serverTextList)
widget:setId(host)
if not load then
servers[host] = {
port = port,
protocol = protocol,
account = '',
password = ''
}
end
local details = widget:getChildById('details')
details:setText(host..':'..port)
local proto = widget:getChildById('protocol')
proto:setText(protocol)
connect(widget, { onDoubleClick = function () ServerList.select() return true end } )
return true
end
function ServerList.remove(widget)
local host = widget:getId()
if removeWindow then
return
end
local yesCallback = function()
widget:destroy()
servers[host] = nil
removeWindow:destroy()
removeWindow=nil
end
local noCallback = function()
removeWindow:destroy()
removeWindow=nil
end
removeWindow = displayGeneralBox(tr('Remove'), tr('Remove '..host..'?'), {
{ text=tr('Yes'), callback=yesCallback },
{ text=tr('No'), callback=noCallback },
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
end
function ServerList.destroy()
if serverListWindow then
serverTextList = nil
serverListWindow:destroy()
serverListWindow = nil
end
end
function ServerList.show()
if g_game.isOnline() then
return
end
serverListWindow:show()
serverListWindow:raise()
serverListWindow:focus()
end
function ServerList.hide()
serverListWindow:hide()
end
function ServerList.setServerAccount(host, account)
if servers[host] then
servers[host].account = account
end
end
function ServerList.setServerPassword(host, password)
if servers[host] then
servers[host].password = password
end
end

View File

@@ -0,0 +1,18 @@
Module
name: client_serverlist
description: Manages a server list of previously entered servers
author: BeniS
website: www.otclient.info
dependencies:
- client_entergame
@onLoad: |
dofile 'serverlist'
dofile 'addserver'
ServerList.init()
AddServer.init()
@onUnload: |
ServerList.terminate()
AddServer.terminate()

View File

@@ -0,0 +1,110 @@
ServerWidget < UIWidget
height: 14
background-color: alpha
&updateOnStates: |
function(self)
local children = self:getChildren()
for i=1,#children do
children[i]:setOn(self:isFocused())
end
end
@onFocusChange: self:updateOnStates()
@onSetup: self:updateOnStates()
$focus:
background-color: #ffffff22
Label
id: details
color: #aaaaaa
anchors.top: parent.top
anchors.left: parent.left
font: verdana-11px-monochrome
text-auto-resize: true
background-color: alpha
text-offset: 2 0
$on:
color: #ffffff
Label
id: protocol
color: #ffffff
color: #aaaaaa
anchors.top: parent.top
anchors.right: next.left
margin-right: 5
font: verdana-11px-monochrome
text-auto-resize: true
background-color: alpha
&baseText: '(%s)'
$on:
color: #ffffff
Button
id: remove
text: x
width: 12
height: 12
anchors.top: parent.top
anchors.right: parent.right
margin-right: 4
margin-top: 1
@onClick: ServerList.remove(self:getParent())
MainWindow
id: serverListWindow
!text: tr('Server List')
size: 340 290
visible: false
@onEnter: ServerList.select()
@onEscape: ServerList.hide()
@onSetup: |
g_keyboard.bindKeyPress('Up', function() self:getChildById('serverList'):focusPreviousChild(KeyboardFocusReason) end, self)
g_keyboard.bindKeyPress('Down', function() self:getChildById('serverList'):focusNextChild(KeyboardFocusReason) end, self)
TextList
id: serverList
anchors.top: parent.top
anchors.left: parent.left
anchors.right: serverListScrollBar.left
anchors.bottom: buttonOk.top
margin-bottom: 5
padding: 1
focusable: false
vertical-scrollbar: serverListScrollBar
auto-focus: first
VerticalScrollBar
id: serverListScrollBar
anchors.top: parent.top
anchors.bottom: buttonOk.top
anchors.right: parent.right
margin-bottom: 5
step: 14
pixels-scroll: true
AddButton
id: buttonAdd
!tooltip: tr('Add new server')
anchors.left: parent.left
anchors.bottom: parent.bottom
@onClick: AddServer.show()
Button
id: buttonOk
!text: tr('Select')
width: 64
anchors.right: next.left
anchors.bottom: parent.bottom
margin-right: 10
@onClick: ServerList.select()
Button
id: buttonCancel
!text: tr('Cancel')
width: 64
anchors.right: parent.right
anchors.bottom: parent.bottom
@onClick: ServerList.hide()

View File

@@ -25,6 +25,8 @@ end
function terminate() function terminate()
disconnect(g_game, { onGameStart = onGameStart, disconnect(g_game, { onGameStart = onGameStart,
onGameEnd = onGameEnd }) onGameEnd = onGameEnd })
removeEvent(firstReportEvent)
removeEvent(sendReportEvent)
end end
function configure(host, port, delay) function configure(host, port, delay)
@@ -45,13 +47,15 @@ end
function onGameStart() function onGameStart()
if not HOST then return end if not HOST then return end
removeEvent(firstReportEvent)
removeEvent(sendReportEvent)
firstReportEvent = addEvent(sendReport, FIRST_REPORT_DELAY*1000) firstReportEvent = addEvent(sendReport, FIRST_REPORT_DELAY*1000)
sendReportEvent = cycleEvent(sendReport, REPORT_DELAY*1000) sendReportEvent = cycleEvent(sendReport, REPORT_DELAY*1000)
end end
function onGameEnd() function onGameEnd()
removeEvent(sendReportEvent)
removeEvent(firstReportEvent) removeEvent(firstReportEvent)
removeEvent(sendReportEvent)
end end
function onConnect(protocol) function onConnect(protocol)
@@ -84,6 +88,7 @@ function onConnect(protocol)
post = post .. '&cpu=' .. g_platform.getCPUName() post = post .. '&cpu=' .. g_platform.getCPUName()
post = post .. '&mem=' .. g_platform.getTotalSystemMemory() post = post .. '&mem=' .. g_platform.getTotalSystemMemory()
post = post .. '&os_name=' .. g_platform.getOSName() post = post .. '&os_name=' .. g_platform.getOSName()
post = post .. getAdditionalData()
local message = '' local message = ''
message = message .. "POST /report HTTP/1.1\r\n" message = message .. "POST /report HTTP/1.1\r\n"
@@ -98,6 +103,10 @@ function onConnect(protocol)
protocol:recv() protocol:recv()
end end
function getAdditionalData()
return ''
end
function onRecv(protocol, message) function onRecv(protocol, message)
if string.find(message, 'HTTP/1.1 200 OK') then if string.find(message, 'HTTP/1.1 200 OK') then
--pinfo('Stats sent to server successfully!') --pinfo('Stats sent to server successfully!')

View File

@@ -1,94 +1,177 @@
function dumpWidgets(widget, level) local function pcolored(text, color)
widget = widget or rootWidget color = color or 'white'
level = level or 0 modules.client_terminal.addLine(tostring(text), color)
for i=1,widget:getChildCount() do end
local child = widget:getChildByIndex(i)
if child:isVisible() then function draw_debug_boxes()
local name = child:getId() g_ui.setDebugBoxesDrawing(not g_ui.isDrawingDebugBoxes())
if name:match('widget%d+') == nil then end
print(string.rep(' ', level) .. name)
end function hide_map()
if child:getId() ~= 'terminalBuffer' then modules.game_interface.getMapPanel():hide()
dumpWidgets(child, level+1) end
end
function show_map()
modules.game_interface.getMapPanel():show()
end
function live_textures_reload()
g_textures.liveReload()
end
function live_module_reload(name)
if not name then
pcolored('ERROR: missing module name', 'red')
return
end
local module = g_modules.getModule(name)
if not module then
pcolored('ERROR: unable to find module ' .. name, 'red')
return
end
if not module:isReloadble() then
pcolored('ERROR: that module is not reloadable', 'red')
return
end
if not module:canReload() then
pcolored('ERROR: some other modules requires this module, cannot reload now', 'red')
return
end
local files = {}
local hasFile = false
for _,file in pairs(g_resources.listDirectoryFiles('/' .. name)) do
local filepath = '/' .. name .. '/' .. file
local time = g_resources.getFileTime(filepath)
if time > 0 then
files[filepath] = time
hasFile = true
end end
end end
end
function drawDebugBoxes(enable) if not hasFile then
if enable == nil then enable = true end pcolored('ERROR: unable to find any file for module', 'red')
g_ui.setDebugBoxesDrawing(enable) return
end end
function hideMap() cycleEvent(function()
local map = rootWidget:recursiveGetChildById('gameMapPanel') for filepath,time in pairs(files) do
if map then map:hide() end local newtime = g_resources.getFileTime(filepath)
end if newtime > time then
pcolored('Reloading ' .. name, 'green')
modules.client_terminal.flushLines()
module:reload()
files[filepath] = newtime
function showMap() if name == 'client_terminal' then
local map = rootWidget:recursiveGetChildById('gameMapPanel') modules.client_terminal.show()
if map then map:show() end end
end break
function debugContainersItems()
function UIItem:onHoverChange(hovered)
if hovered then
local item = self:getItem()
if item then
local text = "id: " ..item:getId() ..
"\n stackable: " ..tostring(item:isStackable()) ..
"\n marketable: " ..tostring(item:isMarketable()) ..
"\n vocation: "..(item:getMarketData() and item:getMarketData().restrictVocation or 'none') ..
"\n cloth slot: " ..item:getClothSlot()
g_tooltip.display(text)
end end
else end
g_tooltip.hide() end, 1000)
end
function live_sprites_reload()
local files = {}
for _,file in pairs(g_resources.listDirectoryFiles('/things')) do
local filepath = '/things/' .. file
local time = g_resources.getFileTime(filepath)
if time > 0 then
files[filepath] = time
hasFile = true
end end
end end
if not hasFile then
pcolored('ERROR: unable to find things file for module', 'red')
return
end
cycleEvent(function()
for filepath,time in pairs(files) do
local newtime = g_resources.getFileTime(filepath)
if newtime > time then
pcolored('Reloading sprites...', 'green')
modules.client_terminal.flushLines()
modules.game_things.load()
files[filepath] = newtime
if name == 'client_terminal' then
modules.client_terminal.show()
end
break
end
end
end, 1000)
end end
function debugPosition(enable) local pinging = false
if enable == nil then enable = true end local function pingBack(ping)
local label = rootWidget:getChildById('debugPositionLabel') if ping < 300 then color = 'green'
if not label then elseif ping < 600 then color = 'yellow'
label = g_ui.createWidget('GameLabel', rootWidget) else color = 'red' end
label:setColor('pink') pcolored(g_game.getWorldName() .. ' => ' .. ping .. ' ms', color)
label:setFont('terminus-14px-bold') end
label:setId('debugPositionLabel') function ping()
label:setPosition({x= 10, y = 40 }) if pinging then
label:setPhantom(true) pcolored('Ping stopped.')
label:setTextAutoResize(true) g_game.setPingDelay(1000)
end disconnect(g_game, 'onPingBack', pingBack)
if enable then
label.event = cycleEvent(function()
local player = g_game.getLocalPlayer()
if player then
local pos = g_game.getLocalPlayer():getPosition()
label:show()
label:setText('x: ' .. pos.x .. '\ny: ' .. pos.y .. '\nz: ' .. pos.z)
else
label:hide()
end
end, 100)
else else
removeEvent(label.event) if not (g_game.getFeature(GameClientPing) or g_game.getFeature(GameExtendedClientPing)) then
label.event = nil pcolored('this server does not support ping', 'red')
label:hide() return
elseif not g_game.isOnline() then
pcolored('ping command is only allowed when online', 'red')
return
end
pcolored('Starting ping...')
g_game.setPingDelay(0)
connect(g_game, 'onPingBack', pingBack)
end
pinging = not pinging
end
function clear()
modules.client_terminal.clear()
end
function ls(path)
path = path or '/'
local files = g_resources.listDirectoryFiles(path)
for k,v in pairs(files) do
if g_resources.directoryExists(path .. v) then
pcolored(path .. v, 'blue')
else
pcolored(path .. v)
end
end end
end end
function autoReloadModule(name) function about_version()
local function reloadEvent() pcolored(g_app.getName() .. ' ' .. g_app.getVersion() .. '\n' ..
reloadModule(name) 'Rev ' .. g_app.getBuildRevision() .. ' ('.. g_app.getBuildCommit() .. ')\n' ..
scheduleEvent(reloadEvent, 1000) 'Built on ' .. g_app.getBuildDate())
end
reloadEvent()
end end
function createDebugUIItem(id) function about_graphics()
local uiitem = g_ui.createWidget('Item', rootWidget) pcolored('Vendor ' .. g_graphics.getVendor() )
uiitem:setPosition({x= 200, y = 200 }) pcolored('Renderer' .. g_graphics.getRenderer())
uiitem:setItemId(id) pcolored('Version' .. g_graphics.getVersion())
uiitem:show() end
function about_modules()
for k,m in pairs(g_modules.getModules()) do
local loadedtext
if m:isLoaded() then
pcolored(m:getName() .. ' => loaded', 'green')
else
pcolored(m:getName() .. ' => not loaded', 'red')
end
end
end end

View File

@@ -1,21 +1,32 @@
-- configs -- configs
local LogColors = { [LogInfo] = 'white', local LogColors = { [LogDebug] = 'pink',
[LogInfo] = 'white',
[LogWarning] = 'yellow', [LogWarning] = 'yellow',
[LogError] = 'red' } [LogError] = 'red' }
local MaxLogLines = 80 local MaxLogLines = 128
local LabelHeight = 16
local MaxHistory = 1000 local MaxHistory = 1000
local oldenv = getfenv(0)
setfenv(0, _G)
_G.commandEnv = runinsandbox('commands')
setfenv(0, oldenv)
-- private variables -- private variables
local terminalWindow local terminalWindow
local terminalButton local terminalButton
local logLocked = false local logLocked = false
local commandEnv = {}
setmetatable(commandEnv, { __index = getfenv() } )
local commandTextEdit local commandTextEdit
local terminalBuffer local terminalBuffer
local commandHistory = { } local commandHistory = { }
local currentHistoryIndex = 0 local currentHistoryIndex = 0
local poped = false
local oldPos
local oldSize
local firstShown = false
local flushEvent
local cachedLines = {}
local disabled = false
local allLines = {}
-- private functions -- private functions
local function navigateCommand(step) local function navigateCommand(step)
@@ -96,9 +107,7 @@ local function doCommand()
end end
local function onLog(level, message, time) local function onLog(level, message, time)
-- debug messages are ignored if disabled then return end
if level == LogDebug then return end
-- avoid logging while reporting logs (would cause a infinite loop) -- avoid logging while reporting logs (would cause a infinite loop)
if logLocked then return end if logLocked then return end
@@ -112,22 +121,7 @@ function init()
terminalWindow = g_ui.displayUI('terminal') terminalWindow = g_ui.displayUI('terminal')
terminalWindow:setVisible(false) terminalWindow:setVisible(false)
local poped = false terminalWindow.onDoubleClick = popWindow
terminalWindow.onDoubleClick = function(self)
if poped then
self:fill('parent')
self:getChildById('bottomResizeBorder'):disable()
self:getChildById('rightResizeBorder'):disable()
poped = false
else
self:breakAnchors()
self:resize(g_window.getWidth()/2, g_window.getHeight()/2)
self:move(g_window.getWidth()/2, g_window.getHeight()/2)
self:getChildById('bottomResizeBorder'):enable()
self:getChildById('rightResizeBorder'):enable()
poped = true
end
end
terminalButton = modules.client_topmenu.addLeftButton('terminalButton', tr('Terminal') .. ' (Ctrl + T)', '/images/topbuttons/terminal', toggle) terminalButton = modules.client_topmenu.addLeftButton('terminalButton', tr('Terminal') .. ' (Ctrl + T)', '/images/topbuttons/terminal', toggle)
g_keyboard.bindKeyDown('Ctrl+T', toggle) g_keyboard.bindKeyDown('Ctrl+T', toggle)
@@ -137,32 +131,105 @@ function init()
commandTextEdit = terminalWindow:getChildById('commandTextEdit') commandTextEdit = terminalWindow:getChildById('commandTextEdit')
g_keyboard.bindKeyPress('Up', function() navigateCommand(1) end, commandTextEdit) g_keyboard.bindKeyPress('Up', function() navigateCommand(1) end, commandTextEdit)
g_keyboard.bindKeyPress('Down', function() navigateCommand(-1) end, commandTextEdit) g_keyboard.bindKeyPress('Down', function() navigateCommand(-1) end, commandTextEdit)
g_keyboard.bindKeyPress('Ctrl+C',
function()
if commandTextEdit:hasSelection() or not terminalSelectText:hasSelection() then return false end
g_window.setClipboardText(terminalSelectText:getSelection())
return true
end, commandTextEdit)
g_keyboard.bindKeyDown('Tab', completeCommand, commandTextEdit) g_keyboard.bindKeyDown('Tab', completeCommand, commandTextEdit)
g_keyboard.bindKeyDown('Enter', doCommand, commandTextEdit) g_keyboard.bindKeyDown('Enter', doCommand, commandTextEdit)
g_keyboard.bindKeyDown('Escape', hide, terminalWindow) g_keyboard.bindKeyDown('Escape', hide, terminalWindow)
terminalBuffer = terminalWindow:getChildById('terminalBuffer') terminalBuffer = terminalWindow:getChildById('terminalBuffer')
terminalSelectText = terminalWindow:getChildById('terminalSelectText')
terminalSelectText.onDoubleClick = popWindow
terminalSelectText.onMouseWheel = function(a,b,c) terminalBuffer:onMouseWheel(b,c) end
terminalBuffer.onScrollChange = function(self, value) terminalSelectText:setTextVirtualOffset(value) end
g_logger.setOnLog(onLog) g_logger.setOnLog(onLog)
g_logger.fireOldMessages()
if not g_app.isRunning() then
g_logger.fireOldMessages()
elseif _G.terminalLines then
for _,line in pairs(_G.terminalLines) do
addLine(line.text, line.color)
end
end
end end
function terminate() function terminate()
g_settings.setList('terminal-history', commandHistory) g_settings.setList('terminal-history', commandHistory)
removeEvent(flushEvent)
if poped then
oldPos = terminalWindow:getPosition()
oldSize = terminalWindow:getSize()
end
local settings = {
size = oldSize,
pos = oldPos,
poped = poped
}
g_settings.setNode('terminal-window', settings)
g_keyboard.unbindKeyDown('Ctrl+T') g_keyboard.unbindKeyDown('Ctrl+T')
g_logger.setOnLog(nil) g_logger.setOnLog(nil)
terminalWindow:destroy() terminalWindow:destroy()
terminalButton:destroy() terminalButton:destroy()
commandEnv = nil commandEnv = nil
_G.terminalLines = allLines
end end
function hideButton() function hideButton()
terminalButton:hide() terminalButton:hide()
end end
function popWindow()
if poped then
oldPos = terminalWindow:getPosition()
oldSize = terminalWindow:getSize()
terminalWindow:fill('parent')
terminalWindow:setOn(false)
terminalWindow:getChildById('bottomResizeBorder'):disable()
terminalWindow:getChildById('rightResizeBorder'):disable()
terminalWindow:getChildById('titleBar'):hide()
terminalWindow:getChildById('terminalScroll'):setMarginTop(0)
terminalWindow:getChildById('terminalScroll'):setMarginBottom(0)
terminalWindow:getChildById('terminalScroll'):setMarginRight(0)
poped = false
else
terminalWindow:breakAnchors()
terminalWindow:setOn(true)
local size = oldSize or { width = g_window.getWidth()/2, height = g_window.getHeight()/2 }
terminalWindow:setSize(size)
local pos = oldPos or { x = (g_window.getWidth() - terminalWindow:getWidth())/2, y = (g_window.getHeight() - terminalWindow:getHeight())/2 }
terminalWindow:setPosition(pos)
terminalWindow:getChildById('bottomResizeBorder'):enable()
terminalWindow:getChildById('rightResizeBorder'):enable()
terminalWindow:getChildById('titleBar'):show()
terminalWindow:getChildById('terminalScroll'):setMarginTop(18)
terminalWindow:getChildById('terminalScroll'):setMarginBottom(1)
terminalWindow:getChildById('terminalScroll'):setMarginRight(1)
terminalWindow:bindRectToParent()
poped = true
end
end
function toggle() function toggle()
if terminalWindow:isVisible() then if terminalWindow:isVisible() then
hide() hide()
else else
if not firstShow then
local settings = g_settings.getNode('terminal-window')
if settings then
if settings.size then oldSize = size end
if settings.pos then oldPos = settings.pos end
if settings.poped then popWindow() end
end
firstShown = true
end
show() show()
end end
end end
@@ -180,36 +247,52 @@ end
function disable() function disable()
terminalButton:hide() terminalButton:hide()
g_keyboard.unbindKeyDown('Ctrl+T') g_keyboard.unbindKeyDown('Ctrl+T')
disabled = true
end
function flushLines()
local numLines = terminalBuffer:getChildCount() + #cachedLines
local fulltext = terminalSelectText:getText()
for _,line in pairs(cachedLines) do
-- delete old lines if needed
if numLines > MaxLogLines then
local len = #terminalBuffer:getChildByIndex(1):getText()
terminalBuffer:getChildByIndex(1):destroy()
table.remove(allLines, 1)
fulltext = string.sub(fulltext, len)
end
local label = g_ui.createWidget('TerminalLabel', terminalBuffer)
label:setId('terminalLabel' .. numLines)
label:setText(line.text)
label:setColor(line.color)
table.insert(allLines, {text=line.text,color=line.color})
fulltext = fulltext .. '\n' .. line.text
end
terminalSelectText:setText(fulltext)
cachedLines = {}
removeEvent(flushEvent)
flushEvent = nil
end end
function addLine(text, color) function addLine(text, color)
-- delete old lines if needed if not flushEvent then
local numLines = terminalBuffer:getChildCount() + 1 flushEvent = scheduleEvent(flushLines, 10)
if numLines > MaxLogLines then
terminalBuffer:getChildByIndex(1):destroy()
end end
-- create new line label table.insert(cachedLines, {text=text, color=color})
local label = g_ui.createWidget('TerminalLabel', terminalBuffer)
label:setId('terminalLabel' .. numLines)
label:setText(text)
label:setColor(color)
end end
function executeCommand(command) function executeCommand(command)
if command == nil or #command == 0 then return end if command == nil or #command == 0 then return end
logLocked = true -- add command line
g_logger.log(LogInfo, '> ' .. command) addLine("> " .. command, "#ffffff")
logLocked = false
-- detect and convert commands with simple syntax
local realCommand
if string.sub(command, 1, 1) == '=' then
realCommand = 'print(' .. string.sub(command,2) .. ')'
else
realCommand = command
end
-- reset current history index -- reset current history index
currentHistoryIndex = 0 currentHistoryIndex = 0
@@ -222,15 +305,33 @@ function executeCommand(command)
end end
end end
-- add command line -- detect and convert commands with simple syntax
--addLine(">> " .. command, "#ffffff") local realCommand
if string.sub(command, 1, 1) == '=' then
realCommand = 'print(' .. string.sub(command,2) .. ')'
else
realCommand = command
end
-- load command buffer
local func, err = loadstring(realCommand, "@") local func, err = loadstring(realCommand, "@")
-- detect terminal commands
if not func then
local command_name = command:match('^([%w_]+)[%s]*.*')
if command_name then
local args = string.split(command:match('^[%w_]+[%s]*(.*)'), ' ')
if commandEnv[command_name] and type(commandEnv[command_name]) == 'function' then
func = function() modules.client_terminal.commandEnv[command_name](unpack(args)) end
elseif command_name == command then
addLine('ERROR: command not found', 'red')
return
end
end
end
-- check for syntax errors -- check for syntax errors
if not func then if not func then
g_logger.log(LogError, 'incorrect lua syntax: ' .. err:sub(5)) addLine('ERROR: incorrect lua syntax: ' .. err:sub(5), 'red')
return return
end end
@@ -241,8 +342,15 @@ function executeCommand(command)
local ok, ret = pcall(func) local ok, ret = pcall(func)
if ok then if ok then
-- if the command returned a value, print it -- if the command returned a value, print it
if ret then print(ret) end if ret then addLine(ret, 'white') end
else else
g_logger.log(LogError, 'command failed: ' .. ret) addLine('ERROR: command failed: ' .. ret, 'red')
end end
end end
function clear()
terminalBuffer:destroyChildren()
terminalSelectText:setText('')
cachedLines = {}
allLines = {}
end

View File

@@ -3,7 +3,7 @@ Module
description: Terminal for executing lua functions description: Terminal for executing lua functions
author: edubart author: edubart
website: www.otclient.info website: www.otclient.info
scripts: [ terminal, commands ] scripts: [ terminal ]
sandboxed: true sandboxed: true
@onLoad: init() @onLoad: init()
@onUnload: terminate() @onUnload: terminate()

View File

@@ -1,7 +1,21 @@
TerminalLabel < UILabel TerminalLabel < UILabel
font: terminus-14px-bold font: terminus-10px
text-wrap: true text-wrap: true
text-auto-resize: true text-auto-resize: true
phantom: true
TerminalSelectText < UITextEdit
font: terminus-10px
text-wrap: true
text-align: bottomLeft
editable: false
change-cursor-image: false
cursor-visible: false
selection-color: black
selection-background-color: white
color: alpha
focusable: false
auto-scroll: false
UIWindow UIWindow
id: terminalWindow id: terminalWindow
@@ -9,36 +23,69 @@ UIWindow
opacity: 0.85 opacity: 0.85
clipping: true clipping: true
anchors.fill: parent anchors.fill: parent
border: 0 white
$on:
border: 1 black
Panel Label
id: terminalBuffer id: titleBar
layout: !text: tr('Terminal')
type: verticalBox border: 1 black
fit-children: true color: white
focusable: false anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
background-color: #ffffff11
text-align: left
text-offset: 4 0
height: 18
visible: false
ScrollablePanel
id: terminalBuffer
focusable: false
anchors.left: parent.left
anchors.right: terminalScroll.left
anchors.top: terminalScroll.top
anchors.bottom: commandSymbolLabel.top anchors.bottom: commandSymbolLabel.top
layout:
type: verticalBox
align-bottom: true
vertical-scrollbar: terminalScroll
inverted-scroll: true
margin-left: 2 margin-left: 2
TerminalSelectText
id: terminalSelectText
anchors.fill: terminalBuffer
focusable: false
VerticalScrollBar
id: terminalScroll
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
step: 48
pixels-scroll: true
UILabel UILabel
id: commandSymbolLabel id: commandSymbolLabel
size: 12 16 size: 12 12
fixed-size: true fixed-size: true
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
margin-left: 2 margin-left: 2
font: terminus-14px-bold font: terminus-10px
text: > text: >
UITextEdit UITextEdit
id: commandTextEdit id: commandTextEdit
height: 16 height: 12
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: commandSymbolLabel.right anchors.left: commandSymbolLabel.right
anchors.right: parent.right anchors.right: parent.right
margin-left: 5 margin-left: 1
font: terminus-14px-bold font: terminus-10px
selection-color: black selection-color: black
selection-background-color: white selection-background-color: white

View File

@@ -37,8 +37,10 @@ end
-- public functions -- public functions
function init() function init()
connect(g_game, { onGameStart = showGameButtons, connect(g_game, { onGameStart = online,
onGameEnd = hideGameButtons }) onGameEnd = offline,
onPingBack = updatePing })
connect(g_app, { onFps = updateFps })
topMenu = g_ui.displayUI('topmenu') topMenu = g_ui.displayUI('topmenu')
@@ -46,20 +48,73 @@ function init()
rightButtonsPanel = topMenu:getChildById('rightButtonsPanel') rightButtonsPanel = topMenu:getChildById('rightButtonsPanel')
leftGameButtonsPanel = topMenu:getChildById('leftGameButtonsPanel') leftGameButtonsPanel = topMenu:getChildById('leftGameButtonsPanel')
rightGameButtonsPanel = topMenu:getChildById('rightGameButtonsPanel') rightGameButtonsPanel = topMenu:getChildById('rightGameButtonsPanel')
pingLabel = topMenu:getChildById('pingLabel')
fpsLabel = topMenu:getChildById('fpsLabel')
if g_game.isOnline() then if g_game.isOnline() then
leftGameButtonsPanel:show() online()
rightGameButtonsPanel:show()
end end
end end
function terminate() function terminate()
disconnect(g_game, { onGameStart = showGameButtons, disconnect(g_game, { onGameStart = online,
onGameEnd = hideGameButtons }) onGameEnd = offline,
onPingBack = updatePing })
disconnect(g_app, { onFps = updateFps })
topMenu:destroy() topMenu:destroy()
end end
function online()
showGameButtons()
addEvent(function()
if modules.client_options.getOption('showPing') and (g_game.getFeature(GameClientPing) or g_game.getFeature(GameExtendedClientPing)) then
pingLabel:show()
else
pingLabel:hide()
end
end)
end
function offline()
hideGameButtons()
pingLabel:hide()
end
function updateFps(fps)
text = 'FPS: ' .. fps
fpsLabel:setText(text)
end
function updatePing(ping)
local text = 'Ping: '
local color
if ping < 0 then
text = text .. "??"
color = 'yellow'
else
text = text .. ping .. ' ms'
if ping >= 500 then
color = 'red'
elseif ping >= 250 then
color = 'yellow'
else
color = 'green'
end
end
pingLabel:setColor(color)
pingLabel:setText(text)
end
function setPingVisible(enable)
pingLabel:setVisible(enable)
end
function setFpsVisible(enable)
fpsLabel:setVisible(enable)
end
function addLeftButton(id, description, icon, callback, front) function addLeftButton(id, description, icon, callback, front)
return addButton(id, description, icon, callback, leftButtonsPanel, false, front) return addButton(id, description, icon, callback, leftButtonsPanel, false, front)
end end
@@ -92,16 +147,16 @@ function addRightGameToggleButton(id, description, icon, callback, front)
return addButton(id, description, icon, callback, rightGameButtonsPanel, true, front) return addButton(id, description, icon, callback, rightGameButtonsPanel, true, front)
end end
function hideGameButtons()
leftGameButtonsPanel:hide()
rightGameButtonsPanel:hide()
end
function showGameButtons() function showGameButtons()
leftGameButtonsPanel:show() leftGameButtonsPanel:show()
rightGameButtonsPanel:show() rightGameButtonsPanel:show()
end end
function hideGameButtons()
leftGameButtonsPanel:hide()
rightGameButtonsPanel:hide()
end
function getButton(id) function getButton(id)
return topMenu:recursiveGetChildById(id) return topMenu:recursiveGetChildById(id)
end end

View File

@@ -18,17 +18,17 @@ TopMenuPanel
visible: false visible: false
TopMenuFrameCounterLabel TopMenuFrameCounterLabel
id: frameCounter id: fpsLabel
text-auto-resize: true text-auto-resize: true
anchors.top: parent.top anchors.top: parent.top
anchors.left: leftGameButtonsPanel.right anchors.left: leftGameButtonsPanel.right
PingLabel TopMenuPingLabel
color: white color: white
id: pingLabel id: pingLabel
text-auto-resize: true text-auto-resize: true
anchors.top: frameCounter.bottom anchors.top: fpsLabel.bottom
anchors.left: frameCounter.left anchors.left: fpsLabel.left
TopMenuButtonsPanel TopMenuButtonsPanel
id: rightButtonsPanel id: rightButtonsPanel

View File

@@ -317,4 +317,5 @@ NetworkMessageTypes = {
SoundChannels = { SoundChannels = {
Music = 1, Music = 1,
Ambient = 2, Ambient = 2,
Effect = 3,
} }

View File

@@ -17,6 +17,7 @@ Module
dofile 'settings' dofile 'settings'
dofile 'keyboard' dofile 'keyboard'
dofile 'mouse' dofile 'mouse'
dofile 'net'
dofiles 'ui' dofiles 'ui'

View File

@@ -4,7 +4,6 @@ g_keyboard = {}
-- private functions -- private functions
function translateKeyCombo(keyCombo) function translateKeyCombo(keyCombo)
if not keyCombo or #keyCombo == 0 then return nil end if not keyCombo or #keyCombo == 0 then return nil end
table.sort(keyCombo)
local keyComboDesc = '' local keyComboDesc = ''
for k,v in pairs(keyCombo) do for k,v in pairs(keyCombo) do
local keyDesc = KeyCodeDescs[v] local keyDesc = KeyCodeDescs[v]
@@ -65,47 +64,29 @@ function determineKeyComboDesc(keyCode, keyboardModifiers)
end end
table.insert(keyCombo, keyCode) table.insert(keyCombo, keyCode)
end end
table.sort(keyCombo)
return translateKeyCombo(keyCombo) return translateKeyCombo(keyCombo)
end end
local function onWidgetKeyDown(widget, keyCode, keyboardModifiers) local function onWidgetKeyDown(widget, keyCode, keyboardModifiers)
if keyCode == KeyUnknown then return false end if keyCode == KeyUnknown then return false end
local callback = widget.boundAloneKeyDownCombos[determineKeyComboDesc(keyCode, KeyboardNoModifier)] local callback = widget.boundAloneKeyDownCombos[determineKeyComboDesc(keyCode, KeyboardNoModifier)]
if callback then signalcall(callback, widget, keyCode)
callback(widget, keyCode)
end
callback = widget.boundKeyDownCombos[determineKeyComboDesc(keyCode, keyboardModifiers)] callback = widget.boundKeyDownCombos[determineKeyComboDesc(keyCode, keyboardModifiers)]
if callback then return signalcall(callback, widget, keyCode)
callback(widget, keyCode)
return true
end
return false
end end
local function onWidgetKeyUp(widget, keyCode, keyboardModifiers) local function onWidgetKeyUp(widget, keyCode, keyboardModifiers)
if keyCode == KeyUnknown then return false end if keyCode == KeyUnknown then return false end
local callback = widget.boundAloneKeyUpCombos[determineKeyComboDesc(keyCode, KeyboardNoModifier)] local callback = widget.boundAloneKeyUpCombos[determineKeyComboDesc(keyCode, KeyboardNoModifier)]
if callback then signalcall(callback, widget, keyCode)
callback(widget, keyCode)
end
callback = widget.boundKeyUpCombos[determineKeyComboDesc(keyCode, keyboardModifiers)] callback = widget.boundKeyUpCombos[determineKeyComboDesc(keyCode, keyboardModifiers)]
if callback then return signalcall(callback, widget, keyCode)
callback(widget, keyCode)
return true
end
return false
end end
local function onWidgetKeyPress(widget, keyCode, keyboardModifiers, autoRepeatTicks) local function onWidgetKeyPress(widget, keyCode, keyboardModifiers, autoRepeatTicks)
if keyCode == KeyUnknown then return false end if keyCode == KeyUnknown then return false end
local keyComboDesc = determineKeyComboDesc(keyCode, keyboardModifiers) local callback = widget.boundKeyPressCombos[determineKeyComboDesc(keyCode, keyboardModifiers)]
local comboConf = widget.boundKeyPressCombos[keyComboDesc] return signalcall(callback, widget, keyCode, autoRepeatTicks)
if comboConf and (autoRepeatTicks >= comboConf.autoRepeatDelay or autoRepeatTicks == 0) and comboConf.callback then
comboConf.callback(widget, keyCode)
return true
end
return false
end end
local function connectKeyDownEvent(widget) local function connectKeyDownEvent(widget)
@@ -133,13 +114,10 @@ function g_keyboard.bindKeyDown(keyComboDesc, callback, widget, alone)
widget = widget or rootWidget widget = widget or rootWidget
connectKeyDownEvent(widget) connectKeyDownEvent(widget)
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc) local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
if widget.boundKeyDownCombos[keyComboDesc] then
pwarning('KeyDown event \'' .. keyComboDesc .. '\' redefined on widget ' .. widget:getId())
end
if alone then if alone then
widget.boundAloneKeyDownCombos[keyComboDesc] = callback connect(widget.boundAloneKeyDownCombos, keyComboDesc, callback)
else else
widget.boundKeyDownCombos[keyComboDesc] = callback connect(widget.boundKeyDownCombos, keyComboDesc, callback)
end end
end end
@@ -147,53 +125,50 @@ function g_keyboard.bindKeyUp(keyComboDesc, callback, widget, alone)
widget = widget or rootWidget widget = widget or rootWidget
connectKeyUpEvent(widget) connectKeyUpEvent(widget)
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc) local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
if widget.boundKeyUpCombos[keyComboDesc] then
pwarning('KeyUp event \'' .. keyComboDesc .. '\' redefined on widget ' .. widget:getId())
end
if alone then if alone then
widget.boundAloneKeyUpCombos[keyComboDesc] = callback connect(widget.boundAloneKeyUpCombos, keyComboDesc, callback)
else else
widget.boundKeyUpCombos[keyComboDesc] = callback connect(widget.boundKeyUpCombos, keyComboDesc, callback)
end end
end end
function g_keyboard.bindKeyPress(keyComboDesc, callback, widget, autoRepeatDelay) function g_keyboard.bindKeyPress(keyComboDesc, callback, widget)
autoRepeatDelay = autoRepeatDelay or 500
widget = widget or rootWidget widget = widget or rootWidget
connectKeyPressEvent(widget) connectKeyPressEvent(widget)
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc) local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
if widget.boundKeyPressCombos[keyComboDesc] then connect(widget.boundKeyPressCombos, keyComboDesc, callback)
pwarning('KeyPress event \'' .. keyComboDesc .. '\' redefined on widget ' .. widget:getId())
end
widget.boundKeyPressCombos[keyComboDesc] = { callback = callback, autoRepeatDelay = autoRepeatDelay }
widget:setAutoRepeatDelay(math.min(autoRepeatDelay, widget:getAutoRepeatDelay()))
end end
function g_keyboard.unbindKeyDown(keyComboDesc, widget) local function getUnbindArgs(arg1, arg2)
local callback
local widget
if type(arg1) == 'function' then callback = arg1
elseif type(arg2) == 'function' then callback = arg2 end
if type(arg1) == 'userdata' then widget = arg1
elseif type(arg2) == 'userdata' then widget = arg2 end
widget = widget or rootWidget widget = widget or rootWidget
return callback, widget
end
function g_keyboard.unbindKeyDown(keyComboDesc, arg1, arg2)
local callback, widget = getUnbindArgs(arg1, arg2)
if widget.boundKeyDownCombos == nil then return end if widget.boundKeyDownCombos == nil then return end
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc) local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
if keyComboDesc then disconnect(widget.boundKeyDownCombos, keyComboDesc, callback)
widget.boundKeyDownCombos[keyComboDesc] = nil
end
end end
function g_keyboard.unbindKeyUp(keyComboDesc, widget) function g_keyboard.unbindKeyUp(keyComboDesc, widget)
widget = widget or rootWidget local callback, widget = getUnbindArgs(arg1, arg2)
if widget.boundKeyUpCombos == nil then return end if widget.boundKeyUpCombos == nil then return end
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc) local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
if keyComboDesc then disconnect(widget.boundKeyUpCombos, keyComboDesc, callback)
widget.boundKeyUpCombos[keyComboDesc] = nil
end
end end
function g_keyboard.unbindKeyPress(keyComboDesc, widget) function g_keyboard.unbindKeyPress(keyComboDesc, widget, callback)
widget = widget or rootWidget local callback, widget = getUnbindArgs(arg1, arg2)
if widget.boundKeyPressCombos == nil then return end if widget.boundKeyPressCombos == nil then return end
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc) local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
if keyComboDesc then disconnect(widget.boundKeyPressCombos, keyComboDesc, callback)
widget.boundKeyPressCombos[keyComboDesc] = nil
end
end end
function g_keyboard.getModifiers() function g_keyboard.getModifiers()

16
modules/corelib/net.lua Normal file
View File

@@ -0,0 +1,16 @@
function translateNetworkError(errcode, connecting, errdesc)
local text
if errcode == 111 then
text = tr('Connection refused, the server might be offline or restarting.\nPlease try again later.')
elseif errcode == 110 then
text = tr('Connection timed out. Either your network is failing or the server is offline.')
elseif errcode == 1 then
text = tr('Connection failed, the server address does not exist.')
elseif connecting then
text = tr('Connection failed.')
else
text = tr('Your connection has been lost.\nEither your network or the server went down.')
end
text = text .. ' ' .. tr('(ERROR %d)', errcode)
return text
end

View File

@@ -13,6 +13,12 @@ function table.dump(t, depth)
end end
end end
function table.clear(t)
for k,v in pairs(t) do
t[k] = nil
end
end
function table.copy(t) function table.copy(t)
local res = {} local res = {}
for k,v in pairs(t) do for k,v in pairs(t) do
@@ -138,6 +144,15 @@ function table.findbyfield(t, fieldname, fieldvalue)
return nil return nil
end end
function table.size(t)
local size = 0
for i, n in pairs(t) do
size = size + 1
end
return size
end
function table.tostring(t) function table.tostring(t)
local maxn = #t local maxn = #t
local str = "" local str = ""
@@ -152,3 +167,17 @@ function table.tostring(t)
end end
return str return str
end end
function table.collect(t, func)
local res = {}
for k,v in pairs(t) do
local a,b = func(k,v)
if a and b then
res[a] = b
elseif a ~= nil then
table.insert(res,a)
end
end
return res
end

View File

@@ -166,9 +166,10 @@ end
function UIMiniWindow:onDragLeave(droppedWidget, mousePos) function UIMiniWindow:onDragLeave(droppedWidget, mousePos)
if self.movedWidget then if self.movedWidget then
self.setMovedChildMargin(0) self.setMovedChildMargin(self.movedOldMargin or 0)
self.movedWidget = nil self.movedWidget = nil
self.setMovedChildMargin = nil self.setMovedChildMargin = nil
self.movedOldMargin = nil
self.movedIndex = nil self.movedIndex = nil
end end
@@ -190,14 +191,16 @@ function UIMiniWindow:onDragMove(mousePos, mouseMoved)
end end
if self.movedWidget then if self.movedWidget then
self.setMovedChildMargin(0) self.setMovedChildMargin(self.movedOldMargin or 0)
self.setMovedChildMargin = nil self.setMovedChildMargin = nil
end end
if mousePos.y < childCenterY then if mousePos.y < childCenterY then
self.movedOldMargin = child:getMarginTop()
self.setMovedChildMargin = function(v) child:setMarginTop(v) end self.setMovedChildMargin = function(v) child:setMarginTop(v) end
self.movedIndex = 0 self.movedIndex = 0
else else
self.movedOldMargin = child:getMarginBottom()
self.setMovedChildMargin = function(v) child:setMarginBottom(v) end self.setMovedChildMargin = function(v) child:setMarginBottom(v) end
self.movedIndex = 1 self.movedIndex = 1
end end
@@ -209,7 +212,7 @@ function UIMiniWindow:onDragMove(mousePos, mouseMoved)
end end
if not overAnyWidget and self.movedWidget then if not overAnyWidget and self.movedWidget then
self.setMovedChildMargin(0) self.setMovedChildMargin(self.movedOldMargin or 0)
self.movedWidget = nil self.movedWidget = nil
end end

View File

@@ -127,7 +127,7 @@ end
function UIMiniWindowContainer:scheduleInsert(widget, index) function UIMiniWindowContainer:scheduleInsert(widget, index)
if index - 1 > self:getChildCount() then if index - 1 > self:getChildCount() then
if self.scheduledWidgets[index] then if self.scheduledWidgets[index] then
pwarning('replacing scheduled widget id ' .. widget:getId()) pdebug('replacing scheduled widget id ' .. widget:getId())
end end
self.scheduledWidgets[index] = widget self.scheduledWidgets[index] = widget
else else

View File

@@ -83,10 +83,17 @@ local function onTabDragMove(tab, mousePos, mouseMoved)
end end
end end
local function tabBlink(tab) local function tabBlink(tab, step)
if not tab.blinking then return end step = step or 0
tab:setOn(not tab:isOn()) tab:setOn(not tab:isOn())
tab.blinkEvent = scheduleEvent(function() tabBlink(tab) end, 500)
removeEvent(tab.blinkEvent)
if step < 4 then
tab.blinkEvent = scheduleEvent(function() tabBlink(tab, step+1) end, 500)
else
tab:setOn(true)
tab.blinkEvent = nil
end
end end
-- public functions -- public functions
@@ -240,7 +247,7 @@ function UIMoveableTabBar:selectPrevTab()
end end
function UIMoveableTabBar:blinkTab(tab) function UIMoveableTabBar:blinkTab(tab)
if tab:isChecked() or tab.blinking then return end if tab:isChecked() then return end
tab.blinking = true tab.blinking = true
tabBlink(tab) tabBlink(tab)
end end

View File

@@ -4,6 +4,7 @@ UIProgressBar = extends(UIWidget)
function UIProgressBar.create() function UIProgressBar.create()
local progressbar = UIProgressBar.internalCreate() local progressbar = UIProgressBar.internalCreate()
progressbar:setFocusable(false) progressbar:setFocusable(false)
progressbar:setOn(true)
progressbar.min = 0 progressbar.min = 0
progressbar.max = 100 progressbar.max = 100
progressbar.value = 0 progressbar.value = 0

View File

@@ -73,23 +73,23 @@ end
function UIScrollArea:setVerticalScrollBar(scrollbar) function UIScrollArea:setVerticalScrollBar(scrollbar)
self.verticalScrollBar = scrollbar self.verticalScrollBar = scrollbar
self.verticalScrollBar.onValueChange = function(scrollbar, value) connect(self.verticalScrollBar, 'onValueChange', function(scrollbar, value)
local virtualOffset = self:getVirtualOffset() local virtualOffset = self:getVirtualOffset()
virtualOffset.y = value virtualOffset.y = value
self:setVirtualOffset(virtualOffset) self:setVirtualOffset(virtualOffset)
if self.onScrollbarChange then self:onScrollbarChange(value) end signalcall(self.onScrollChange, self, virtualOffset)
end end)
self:updateScrollBars() self:updateScrollBars()
end end
function UIScrollArea:setHorizontalScrollBar(scrollbar) function UIScrollArea:setHorizontalScrollBar(scrollbar)
self.horizontalScrollBar = scrollbar self.horizontalScrollBar = scrollbar
self.horizontalScrollBar.onValueChange = function(scrollbar, value) connect(self.horizontalScrollBar, 'onValueChange', function(scrollbar, value)
local virtualOffset = self:getVirtualOffset() local virtualOffset = self:getVirtualOffset()
virtualOffset.x = value virtualOffset.x = value
self:setVirtualOffset(virtualOffset) self:setVirtualOffset(virtualOffset)
if self.onScrollbarChange then self:onScrollbarChange(value) end signalcall(self.onScrollChange, self, virtualOffset)
end end)
self:updateScrollBars() self:updateScrollBars()
end end
@@ -135,7 +135,7 @@ function UIScrollArea:ensureChildVisible(child)
if deltaY > 0 then if deltaY > 0 then
self.verticalScrollBar:increment(deltaY) self.verticalScrollBar:increment(deltaY)
end end
else elseif self.horizontalScrollBar then
local deltaX = paddingRect.x - child:getX() local deltaX = paddingRect.x - child:getX()
if deltaX > 0 then if deltaX > 0 then
self.horizontalScrollBar:decrement(deltaX) self.horizontalScrollBar:decrement(deltaX)

View File

@@ -55,8 +55,7 @@ local function updateValueDisplay(widget)
if widget == nil then return end if widget == nil then return end
if widget:getShowValue() then if widget:getShowValue() then
local symbol = widget:getSymbol() widget:setText(widget:getValue() .. (widget:getSymbol() or ''))
widget:setText(widget:getValue()..(symbol and symbol or ''))
end end
end end
@@ -171,7 +170,10 @@ end
function UIScrollBar:setMaximum(maximum) function UIScrollBar:setMaximum(maximum)
if maximum == self.maximum then return end if maximum == self.maximum then return end
self.maximum = maximum self.maximum = maximum
if self.minimum > maximum then
self:setMinimum(maximum)
end
if self.value > maximum then if self.value > maximum then
self:setValue(maximum) self:setValue(maximum)
else else
@@ -182,6 +184,9 @@ end
function UIScrollBar:setMinimum(minimum) function UIScrollBar:setMinimum(minimum)
if minimum == self.minimum then return end if minimum == self.minimum then return end
self.minimum = minimum self.minimum = minimum
if self.maximum < minimum then
self:setMaximum(minimum)
end
if self.value < minimum then if self.value < minimum then
self:setValue(minimum) self:setValue(minimum)
else else
@@ -217,6 +222,13 @@ function UIScrollBar:setOrientation(orientation)
self.orientation = orientation self.orientation = orientation
end end
function UIScrollBar:setText(text)
local valueLabel = self:getChildById('valueLabel')
if valueLabel then
valueLabel:setText(text)
end
end
function UIScrollBar:onGeometryChange() function UIScrollBar:onGeometryChange()
updateSlider(self) updateSlider(self)
end end
@@ -225,7 +237,7 @@ function UIScrollBar:onMouseWheel(mousePos, mouseWheel)
if not self.mouseScroll then if not self.mouseScroll then
return false return false
end end
if mouseWheel == MouseWheelDown then if mouseWheel == MouseWheelUp then
if self.orientation == 'vertical' then if self.orientation == 'vertical' then
self:decrement() self:decrement()
else else

View File

@@ -15,6 +15,11 @@ function UISpinBox.create()
return spinbox return spinbox
end end
function UISpinBox:onSetup()
g_mouse.bindAutoPress(self:getChildById('up'), function() self:up() end, 300)
g_mouse.bindAutoPress(self:getChildById('down'), function() self:down() end, 300)
end
function UISpinBox:onMouseWheel(mousePos, direction) function UISpinBox:onMouseWheel(mousePos, direction)
if direction == MouseWheelUp then if direction == MouseWheelUp then
self:up() self:up()

View File

@@ -144,3 +144,11 @@ end
function UITabBar:getCurrentTab() function UITabBar:getCurrentTab()
return self.currentTab return self.currentTab
end end
function UITabBar:getTabs()
return self.tabs
end
function UITabBar:getTabsPanel()
return table.collect(self.tabs, function(_,tab) return tab.tabPanel end)
end

View File

@@ -19,14 +19,15 @@ function UITextEdit:onMouseWheel(mousePos, mouseWheel)
else else
self.verticalScrollBar:increment() self.verticalScrollBar:increment()
end end
return true
elseif self.horizontalScrollBar then elseif self.horizontalScrollBar then
if mouseWheel == MouseWheelUp then if mouseWheel == MouseWheelUp then
self.horizontalScrollBar:increment() self.horizontalScrollBar:increment()
else else
self.horizontalScrollBar:decrement() self.horizontalScrollBar:decrement()
end end
return true
end end
return true
end end
function UITextEdit:onTextAreaUpdate(virtualOffset, virtualSize, totalSize) function UITextEdit:onTextAreaUpdate(virtualOffset, virtualSize, totalSize)

View File

@@ -67,6 +67,11 @@ function connect(object, arg1, arg2, arg3)
elseif type(object[signal]) == 'function' then elseif type(object[signal]) == 'function' then
object[signal] = { object[signal] } object[signal] = { object[signal] }
end end
if type(slot) ~= 'function' then
perror(debug.traceback('unable to connect a non function value'))
end
if type(object[signal]) == 'table' then if type(object[signal]) == 'table' then
if pushFront then if pushFront then
table.insert(object[signal], 1, slot) table.insert(object[signal], 1, slot)
@@ -80,9 +85,15 @@ end
function disconnect(object, arg1, arg2) function disconnect(object, arg1, arg2)
local signalsAndSlots local signalsAndSlots
if type(arg1) == 'string' then if type(arg1) == 'string' then
if arg2 == nil then
object[arg1] = nil
return
end
signalsAndSlots = { [arg1] = arg2 } signalsAndSlots = { [arg1] = arg2 }
else elseif type(arg1) == 'table' then
signalsAndSlots = arg1 signalsAndSlots = arg1
else
perror(debug.traceback('unable to disconnect'))
end end
for signal,slot in pairs(signalsAndSlots) do for signal,slot in pairs(signalsAndSlots) do

View File

@@ -51,7 +51,7 @@ SayModes = {
[3] = { speakTypeDesc = 'yell', icon = '/images/game/console/yell' } [3] = { speakTypeDesc = 'yell', icon = '/images/game/console/yell' }
} }
MAX_HISTORY = 1000 MAX_HISTORY = 500
MAX_LINES = 100 MAX_LINES = 100
HELP_CHANNEL = 9 HELP_CHANNEL = 9
@@ -72,6 +72,7 @@ violationsChannelId = nil
violationWindow = nil violationWindow = nil
violationReportTab = nil violationReportTab = nil
ignoredChannels = {} ignoredChannels = {}
filters = {}
local ignoreSettings = { local ignoreSettings = {
privateMessages = false, privateMessages = false,
@@ -80,18 +81,20 @@ local ignoreSettings = {
} }
function init() function init()
connect(g_game, { onTalk = onTalk, connect(g_game, {
onChannelList = onChannelList, onTalk = onTalk,
onOpenChannel = onOpenChannel, onChannelList = onChannelList,
onOpenPrivateChannel = onOpenPrivateChannel, onOpenChannel = onOpenChannel,
onOpenOwnPrivateChannel = onOpenOwnPrivateChannel, onOpenPrivateChannel = onOpenPrivateChannel,
onCloseChannel = onCloseChannel, onOpenOwnPrivateChannel = onOpenOwnPrivateChannel,
onRuleViolationChannel = onRuleViolationChannel, onCloseChannel = onCloseChannel,
onRuleViolationRemove = onRuleViolationRemove, onRuleViolationChannel = onRuleViolationChannel,
onRuleViolationCancel = onRuleViolationCancel, onRuleViolationRemove = onRuleViolationRemove,
onRuleViolationLock = onRuleViolationLock, onRuleViolationCancel = onRuleViolationCancel,
onGameStart = online, onRuleViolationLock = onRuleViolationLock,
onGameEnd = offline }) onGameStart = online,
onGameEnd = offline
})
consolePanel = g_ui.loadUI('console', modules.game_interface.getBottomPanel()) consolePanel = g_ui.loadUI('console', modules.game_interface.getBottomPanel())
consoleTextEdit = consolePanel:getChildById('consoleTextEdit') consoleTextEdit = consolePanel:getChildById('consoleTextEdit')
@@ -137,23 +140,25 @@ function init()
g_keyboard.bindKeyDown('Ctrl+E', removeCurrentTab) g_keyboard.bindKeyDown('Ctrl+E', removeCurrentTab)
g_keyboard.bindKeyDown('Ctrl+H', openHelp) g_keyboard.bindKeyDown('Ctrl+H', openHelp)
-- Ignore List load()
loadIgnoreSettings()
end end
function terminate() function terminate()
disconnect(g_game, { onTalk = onTalk, save()
onChannelList = onChannelList, disconnect(g_game, {
onOpenChannel = onOpenChannel, onTalk = onTalk,
onOpenPrivateChannel = onOpenPrivateChannel, onChannelList = onChannelList,
onOpenOwnPrivateChannel = onOpenPrivateChannel, onOpenChannel = onOpenChannel,
onCloseChannel = onCloseChannel, onOpenPrivateChannel = onOpenPrivateChannel,
onRuleViolationChannel = onRuleViolationChannel, onOpenOwnPrivateChannel = onOpenPrivateChannel,
onRuleViolationRemove = onRuleViolationRemove, onCloseChannel = onCloseChannel,
onRuleViolationCancel = onRuleViolationCancel, onRuleViolationChannel = onRuleViolationChannel,
onRuleViolationLock = onRuleViolationLock, onRuleViolationRemove = onRuleViolationRemove,
onGameStart = online, onRuleViolationCancel = onRuleViolationCancel,
onGameEnd = offline }) onRuleViolationLock = onRuleViolationLock,
onGameStart = online,
onGameEnd = offline
})
if g_game.isOnline() then clear() end if g_game.isOnline() then clear() end
@@ -181,6 +186,20 @@ function terminate()
Console = nil Console = nil
end end
function save()
local settings = {}
settings.messageHistory = messageHistory
g_settings.setNode('game_console', settings)
end
function load()
local settings = g_settings.getNode('game_console')
if settings then
messageHistory = settings.messageHistory or {}
end
loadIgnoreSettings()
end
function onTabChange(tabBar, tab) function onTabChange(tabBar, tab)
if tab == defaultTab or tab == serverTab then if tab == defaultTab or tab == serverTab then
consolePanel:getChildById('closeChannelButton'):disable() consolePanel:getChildById('closeChannelButton'):disable()
@@ -243,7 +262,6 @@ end
function clearChannel(consoleTabBar) function clearChannel(consoleTabBar)
consoleTabBar:getCurrentTab().tabPanel:getChildById('consoleBuffer'):destroyChildren() consoleTabBar:getCurrentTab().tabPanel:getChildById('consoleBuffer'):destroyChildren()
consoleTabBar:getCurrentTab().tabPanel:getChildById('consoleBufferHighlight'):destroyChildren()
end end
function setTextEditText(text) function setTextEditText(text)
@@ -271,6 +289,7 @@ function openPlayerReportRuleViolationWindow()
g_game.talkChannel(MessageModes.RVRChannel, 0, text) g_game.talkChannel(MessageModes.RVRChannel, 0, text)
violationReportTab = addTab(tr('Report Rule') .. '...', true) violationReportTab = addTab(tr('Report Rule') .. '...', true)
addTabText(tr('Please wait patiently for a gamemaster to reply') .. '.', SpeakTypesSettings.privateRed, violationReportTab) addTabText(tr('Please wait patiently for a gamemaster to reply') .. '.', SpeakTypesSettings.privateRed, violationReportTab)
addTabText(applyMessagePrefixies(g_game.getCharacterName(), 0, text), SpeakTypesSettings.say, violationReportTab, g_game.getCharacterName())
violationReportTab.locked = true violationReportTab.locked = true
violationWindow:destroy() violationWindow:destroy()
violationWindow = nil violationWindow = nil
@@ -295,15 +314,17 @@ function removeTab(tab)
tab = consoleTabBar:getTab(tab) tab = consoleTabBar:getTab(tab)
end end
if tab == defaultTab or tab == serverTab then return end if tab == defaultTab or tab == serverTab then
return
end
if tab == violationReportTab then if tab == violationReportTab then
g_game.cancelRuleViolation() g_game.cancelRuleViolation()
violationReportTab = nil violationReportTab = nil
elseif tab.violationChatName then elseif tab.violationChatName then
g_game.closeRuleViolation(tab.violationChatName) g_game.closeRuleViolation(tab.violationChatName)
-- notificate the server that we are leaving the channel
elseif tab.channelId then elseif tab.channelId then
-- notificate the server that we are leaving the channel
for k, v in pairs(channels) do for k, v in pairs(channels) do
if (k == tab.channelId) then channels[k] = nil end if (k == tab.channelId) then channels[k] = nil end
end end
@@ -316,8 +337,7 @@ function removeTab(tab)
end end
function removeCurrentTab() function removeCurrentTab()
local tab = consoleTabBar:getCurrentTab() removeTab(consoleTabBar:getCurrentTab())
removeTab(tab)
end end
function getTab(name) function getTab(name)
@@ -433,17 +453,16 @@ function addTabText(text, speaktype, tab, creatureName)
consoleTabBar:blinkTab(tab) consoleTabBar:blinkTab(tab)
-- Overlay for consoleBuffer which shows highlighted words only -- Overlay for consoleBuffer which shows highlighted words only
local consoleBufferHighlight = panel:getChildById('consoleBufferHighlight')
local labelHighlight = g_ui.createWidget('ConsolePhantomLabel', consoleBufferHighlight)
labelHighlight:setId('consoleLabel' .. consoleBufferHighlight:getChildCount()) if speaktype.npcChat and (g_game.getCharacterName() ~= creatureName or g_game.getCharacterName() == 'Account Manager') then
labelHighlight:setColor("#1f9ffe")
if speaktype.npcChat and (g_game.getCharacterName() ~= creatureName or g_game.getCharacterName() == 'Account Manager') then -- Check if it is the npc who is talking
local highlightData = getHighlightedText(text) local highlightData = getHighlightedText(text)
if #highlightData == 0 then if #highlightData > 0 then
labelHighlight:setText("") local labelHighlight = g_ui.createWidget('ConsolePhantomLabel', label)
else labelHighlight:fill('parent')
labelHighlight:setId('consoleLabelHighlight' .. consoleBuffer:getChildCount())
labelHighlight:setColor("#1f9ffe")
-- Remove the curly braces -- Remove the curly braces
for i = 1, #highlightData / 3 do for i = 1, #highlightData / 3 do
local dataBlock = { _start = highlightData[(i-1)*3+1], _end = highlightData[(i-1)*3+2], words = highlightData[(i-1)*3+3] } local dataBlock = { _start = highlightData[(i-1)*3+1], _end = highlightData[(i-1)*3+2], words = highlightData[(i-1)*3+3] }
@@ -482,8 +501,6 @@ function addTabText(text, speaktype, tab, creatureName)
labelHighlight:setText(tmpText) labelHighlight:setText(tmpText)
end end
else
labelHighlight:setText("")
end end
label.name = creatureName label.name = creatureName
@@ -494,10 +511,6 @@ function addTabText(text, speaktype, tab, creatureName)
if consoleBuffer:getChildCount() > MAX_LINES then if consoleBuffer:getChildCount() > MAX_LINES then
consoleBuffer:getFirstChild():destroy() consoleBuffer:getFirstChild():destroy()
end end
if consoleBufferHighlight:getChildCount() > MAX_LINES then
consoleBufferHighlight:getFirstChild():destroy()
end
end end
function removeTabLabelByName(tab, name) function removeTabLabelByName(tab, name)
@@ -579,10 +592,24 @@ function sendCurrentMessage()
sendMessage(message) sendMessage(message)
end end
function addFilter(filter)
table.insert(filters, filter)
end
function removeFilter(filter)
table.removevalue(filters, filter)
end
function sendMessage(message, tab) function sendMessage(message, tab)
local tab = tab or getCurrentTab() local tab = tab or getCurrentTab()
if not tab then return end if not tab then return end
for k,func in pairs(filters) do
if func(message) then
return true
end
end
-- when talking on server log, the message goes to default channel -- when talking on server log, the message goes to default channel
local name = tab:getText() local name = tab:getText()
if tab == serverTab or tab == getRuleViolationsTab() then if tab == serverTab or tab == getRuleViolationsTab() then
@@ -591,18 +618,36 @@ function sendMessage(message, tab)
end end
-- handling chat commands -- handling chat commands
local channel = tab.channelId
local originalMessage = message local originalMessage = message
local chatCommandSayMode local chatCommandSayMode
local chatCommandPrivate local chatCommandPrivate
local chatCommandPrivateReady local chatCommandPrivateReady
local chatCommandMessage
local chatCommandMessage = message:match("^%#y (.*)") -- player used yell command
if chatCommandMessage ~= nil then chatCommandSayMode = 'yell' end -- player used yell command chatCommandMessage = message:match("^%#y (.*)")
message = chatCommandMessage or message if chatCommandMessage ~= nil then
chatCommandSayMode = 'yell'
channel = 0
message = chatCommandMessage
end
-- player used whisper
local chatCommandMessage = message:match("^%#w (.*)") local chatCommandMessage = message:match("^%#w (.*)")
if chatCommandMessage ~= nil then chatCommandSayMode = 'whisper' end -- player used whisper if chatCommandMessage ~= nil then
message = chatCommandMessage or message chatCommandSayMode = 'whisper'
message = chatCommandMessage
channel = 0
end
-- player say
local chatCommandMessage = message:match("^%#s (.*)")
if chatCommandMessage ~= nil then
chatCommandSayMode = 'say'
message = chatCommandMessage
channel = 0
end
local findIni, findEnd, chatCommandInitial, chatCommandPrivate, chatCommandEnd, chatCommandMessage = message:find("([%*%@])(.+)([%*%@])(.*)") local findIni, findEnd, chatCommandInitial, chatCommandPrivate, chatCommandEnd, chatCommandMessage = message:find("([%*%@])(.+)([%*%@])(.*)")
if findIni ~= nil and findIni == 1 then -- player used private chat command if findIni ~= nil and findIni == 1 then -- player used private chat command
@@ -629,15 +674,15 @@ function sendMessage(message, tab)
end end
local speaktypedesc local speaktypedesc
if (tab.channelId or tab == defaultTab) and not chatCommandPrivateReady then if (channel or tab == defaultTab) and not chatCommandPrivateReady then
if tab == defaultTab then if tab == defaultTab then
speaktypedesc = chatCommandSayMode or SayModes[consolePanel:getChildById('sayModeButton').sayMode].speakTypeDesc speaktypedesc = chatCommandSayMode or SayModes[consolePanel:getChildById('sayModeButton').sayMode].speakTypeDesc
if speaktypedesc ~= 'say' then sayModeChange(2) end -- head back to say mode if speaktypedesc ~= 'say' then sayModeChange(2) end -- head back to say mode
else else
speaktypedesc = 'channelYellow' speaktypedesc = chatCommandSayMode or 'channelYellow'
end end
g_game.talkChannel(SpeakTypesSettings[speaktypedesc].speakType, tab.channelId, message) g_game.talkChannel(SpeakTypesSettings[speaktypedesc].speakType, channel, message)
return return
else else
local isPrivateCommand = false local isPrivateCommand = false
@@ -650,6 +695,10 @@ function sendMessage(message, tab)
elseif tab.npcChat then elseif tab.npcChat then
speaktypedesc = 'privatePlayerToNpc' speaktypedesc = 'privatePlayerToNpc'
elseif tab == violationReportTab then elseif tab == violationReportTab then
if violationReportTab.locked then
modules.game_textmessage.displayFailureMessage('Wait for a gamemaster reply.')
return
end
speaktypedesc = 'rvrContinue' speaktypedesc = 'rvrContinue'
tabname = tr('Report Rule') .. '...' tabname = tr('Report Rule') .. '...'
elseif tab.violationChatName then elseif tab.violationChatName then
@@ -857,6 +906,7 @@ end
function onRuleViolationLock() function onRuleViolationLock()
if not violationReportTab then return end if not violationReportTab then return end
violationReportTab.locked = false
addTabText(tr('Your request has been closed') .. '.', SpeakTypesSettings.privateRed, violationReportTab) addTabText(tr('Your request has been closed') .. '.', SpeakTypesSettings.privateRed, violationReportTab)
violationReportTab.locked = true violationReportTab.locked = true
end end
@@ -960,15 +1010,15 @@ function onClickIgnoreButton()
removeButton:disable() removeButton:disable()
ignoreListPanel.onChildFocusChange = function() removeButton:enable() end ignoreListPanel.onChildFocusChange = function() removeButton:enable() end
removeButton.onClick = function() removeButton.onClick = function()
local selection = ignoreListPanel:getFocusedChild() local selection = ignoreListPanel:getFocusedChild()
if selection then if selection then
ignoreListPanel:removeChild(selection) ignoreListPanel:removeChild(selection)
selection:destroy() selection:destroy()
end end
if ignoreListPanel:getChildCount() == 0 then if ignoreListPanel:getChildCount() == 0 then
removeButton:disable() removeButton:disable()
end end
end end
local newlyIgnoredPlayers = {} local newlyIgnoredPlayers = {}
local addName = ignoreWindow:getChildById('ignoreNameEdit') local addName = ignoreWindow:getChildById('ignoreNameEdit')

View File

@@ -15,13 +15,14 @@ ConsolePhantomLabel < UILabel
font: verdana-11px-antialised font: verdana-11px-antialised
height: 14 height: 14
color: yellow color: yellow
margin-left: 2
text-wrap: true text-wrap: true
text-auto-resize: true text-auto-resize: true
selection-color: #111416 selection-color: #111416
selection-background-color: #999999 selection-background-color: #999999
ConsoleTabBar < MoveableTabBar ConsoleTabBar < MoveableTabBar
height: 28
ConsoleTabBarPanel < MoveableTabBarPanel ConsoleTabBarPanel < MoveableTabBarPanel
id: consoleTab id: consoleTab
@@ -39,29 +40,6 @@ ConsoleTabBarPanel < MoveableTabBarPanel
inverted-scroll: true inverted-scroll: true
padding: 1 padding: 1
ScrollablePanel
id: consoleBufferHighlight
anchors.fill: parent
margin-right: 12
vertical-scrollbar: consoleScrollBarHighlight
layout:
type: verticalBox
align-bottom: true
inverted-scroll: true
padding: 1
@onScrollbarChange: |
local consoleScrollBar = self:getParent():getChildById('consoleScrollBar')
local consoleScrollBarHighlight = self:getParent():getChildById('consoleScrollBarHighlight')
consoleScrollBar:setValue(consoleScrollBarHighlight:getValue())
VerticalScrollBar
id: consoleScrollBarHighlight
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
step: 14
pixels-scroll: true
VerticalScrollBar VerticalScrollBar
id: consoleScrollBar id: consoleScrollBar
anchors.top: parent.top anchors.top: parent.top
@@ -88,7 +66,6 @@ Panel
ConsoleTabBar ConsoleTabBar
id: consoleTabBar id: consoleTabBar
height: 28
anchors.left: prev.right anchors.left: prev.right
anchors.top: parent.top anchors.top: parent.top
anchors.right: next.left anchors.right: next.left

View File

@@ -13,12 +13,14 @@ MainWindow
TextEdit TextEdit
id: text id: text
text-wrap: true
multiline: true multiline: true
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.bottom: next.top anchors.bottom: next.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
margin: 8 0 margin: 8 0
max-length: 255
Button Button
id: buttonOk id: buttonOk

View File

@@ -29,11 +29,15 @@ end
function clean() function clean()
for containerid,container in pairs(g_game.getContainers()) do for containerid,container in pairs(g_game.getContainers()) do
if container.window then destroy(container)
container.window:destroy() end
container.window = nil end
container.itemsPanel = nil
end function destroy(container)
if container.window then
container.window:destroy()
container.window = nil
container.itemsPanel = nil
end end
end end
@@ -103,7 +107,7 @@ function onContainerOpen(container, previousContainer)
end end
function onContainerClose(container) function onContainerClose(container)
if container.window then container.window:destroy() end destroy(container)
end end
function onContainerAddItem(container, slot, item) function onContainerAddItem(container, slot, item)

View File

@@ -6,7 +6,7 @@ local ProgressCallback = {
cooldownWindow = nil cooldownWindow = nil
cooldownButton = nil cooldownButton = nil
contentsPanel = nil contentsPanel = nil
spellCooldownPanel = nil cooldownPanel = nil
lastPlayer = nil lastPlayer = nil
function init() function init()
@@ -23,7 +23,12 @@ function init()
cooldownWindow:setup() cooldownWindow:setup()
contentsPanel = cooldownWindow:getChildById('contentsPanel') contentsPanel = cooldownWindow:getChildById('contentsPanel')
spellCooldownPanel = contentsPanel:getChildById('spellCooldownPanel') cooldownPanel = contentsPanel:getChildById('cooldownPanel')
-- preload cooldown images
for k,v in pairs(SpelllistSettings) do
g_textures.preload(v.iconFile)
end
if g_game.isOnline() then if g_game.isOnline() then
online() online()
@@ -39,6 +44,24 @@ function terminate()
cooldownButton:destroy() cooldownButton:destroy()
end end
function loadIcon(iconId)
local spell, profile, spellName = Spells.getSpellByIcon(iconId)
if not spellName then return end
clientIconId = Spells.getClientId(spellName)
if not clientIconId then return end
local icon = cooldownPanel:getChildById(iconId)
if not icon then
icon = g_ui.createWidget('SpellIcon')
icon:setId(iconId)
end
icon:setImageSource(SpelllistSettings[profile].iconFile)
icon:setImageClip(Spells.getImageClip(clientIconId, profile))
return icon
end
function onMiniWindowClose() function onMiniWindowClose()
cooldownButton:setOn(false) cooldownButton:setOn(false)
end end
@@ -68,7 +91,7 @@ function online()
end end
function refresh() function refresh()
spellCooldownPanel:destroyChildren() cooldownPanel:destroyChildren()
end end
function removeCooldown(progressRect) function removeCooldown(progressRect)
@@ -105,36 +128,28 @@ function initCooldown(progressRect, updateCallback, finishCallback)
updateCallback() updateCallback()
end end
function updateCooldown(progressRect, interval) function updateCooldown(progressRect, duration)
progressRect:setPercent(progressRect:getPercent() + 5) progressRect:setPercent(progressRect:getPercent() + 10000/duration)
if progressRect:getPercent() < 100 then if progressRect:getPercent() < 100 then
removeEvent(progressRect.event) removeEvent(progressRect.event)
progressRect.event = scheduleEvent(function() progressRect.callback[ProgressCallback.update]() end, interval) progressRect.event = scheduleEvent(function() progressRect.callback[ProgressCallback.update]() end, 100)
else else
progressRect.callback[ProgressCallback.finish]() progressRect.callback[ProgressCallback.finish]()
end end
end end
function onSpellCooldown(iconId, duration) function onSpellCooldown(iconId, duration)
local spell, profile, spellName = Spells.getSpellByIcon(iconId) local icon = loadIcon(iconId)
if not spellName then return end
clientIconId = Spells.getClientId(spellName)
if not clientIconId then return end
local icon = spellCooldownPanel:getChildById(spellName)
if not icon then if not icon then
icon = g_ui.createWidget('SpellIcon', spellCooldownPanel) return
icon:setId(spellName)
end end
icon:setImageSource('/images/game/spells/' .. SpelllistSettings[profile].iconFile) icon:setParent(cooldownPanel)
icon:setImageClip(Spells.getImageClip(clientIconId, profile))
local progressRect = icon:getChildById(spellName) local progressRect = icon:getChildById(iconId)
if not progressRect then if not progressRect then
progressRect = g_ui.createWidget('SpellProgressRect', icon) progressRect = g_ui.createWidget('SpellProgressRect', icon)
progressRect:setId(spellName) progressRect:setId(iconId)
progressRect.icon = icon progressRect.icon = icon
progressRect:fill('parent') progressRect:fill('parent')
else else
@@ -143,7 +158,7 @@ function onSpellCooldown(iconId, duration)
progressRect:setTooltip(spellName) progressRect:setTooltip(spellName)
local updateFunc = function() local updateFunc = function()
updateCooldown(progressRect, duration/19) updateCooldown(progressRect, duration)
end end
local finishFunc = function() local finishFunc = function()
removeCooldown(progressRect) removeCooldown(progressRect)
@@ -165,7 +180,7 @@ function onSpellGroupCooldown(groupId, duration)
if progressRect then if progressRect then
removeEvent(progressRect.event) removeEvent(progressRect.event)
local updateFunc = function() local updateFunc = function()
updateCooldown(progressRect, duration/19) updateCooldown(progressRect, duration)
end end
local finishFunc = function() local finishFunc = function()
turnOffCooldown(progressRect) turnOffCooldown(progressRect)

View File

@@ -87,7 +87,7 @@ MiniWindow
!tooltip: tr('Special') !tooltip: tr('Special')
Panel Panel
id: spellCooldownPanel id: cooldownPanel
layout: layout:
type: horizontalBox type: horizontalBox
height: 30 height: 30
@@ -98,4 +98,3 @@ MiniWindow
anchors.right: parent.right anchors.right: parent.right
background-color: #ffffff11 background-color: #ffffff11

View File

@@ -48,6 +48,11 @@ function init()
soulLabel = healthInfoWindow:recursiveGetChildById('soulLabel') soulLabel = healthInfoWindow:recursiveGetChildById('soulLabel')
capLabel = healthInfoWindow:recursiveGetChildById('capLabel') capLabel = healthInfoWindow:recursiveGetChildById('capLabel')
-- load condition icons
for k,v in pairs(Icons) do
g_textures.preload(v.path)
end
if g_game.isOnline() then if g_game.isOnline() then
local localPlayer = g_game.getLocalPlayer() local localPlayer = g_game.getLocalPlayer()
onHealthChange(localPlayer, localPlayer:getHealth(), localPlayer:getMaxHealth()) onHealthChange(localPlayer, localPlayer:getHealth(), localPlayer:getMaxHealth())
@@ -92,13 +97,19 @@ function toggleIcon(bitChanged)
if icon then if icon then
icon:destroy() icon:destroy()
else else
icon = g_ui.createWidget('ConditionWidget', content) icon = loadIcon(bitChanged)
icon:setId(Icons[bitChanged].id) icon:setParent(content)
icon:setImageSource(Icons[bitChanged].path)
icon:setTooltip(Icons[bitChanged].tooltip)
end end
end end
function loadIcon(bitChanged)
local icon = g_ui.createWidget('ConditionWidget', content)
icon:setId(Icons[bitChanged].id)
icon:setImageSource(Icons[bitChanged].path)
icon:setTooltip(Icons[bitChanged].tooltip)
return icon
end
function offline() function offline()
healthInfoWindow:recursiveGetChildById('conditionPanel'):destroyChildren() healthInfoWindow:recursiveGetChildById('conditionPanel'):destroyChildren()
end end
@@ -164,12 +175,27 @@ end
function setHealthTooltip(tooltip) function setHealthTooltip(tooltip)
healthTooltip = tooltip healthTooltip = tooltip
local localPlayer = g_game.getLocalPlayer()
if localPlayer then
healthBar:setTooltip(tr(healthTooltip, localPlayer:getHealth(), localPlayer:getMaxHealth()))
end
end end
function setManaTooltip(tooltip) function setManaTooltip(tooltip)
manaTooltip = tooltip manaTooltip = tooltip
local localPlayer = g_game.getLocalPlayer()
if localPlayer then
manaBar:setTooltip(tr(manaTooltip, localPlayer:getMana(), localPlayer:getMaxMana()))
end
end end
function setExperienceTooltip(tooltip) function setExperienceTooltip(tooltip)
experienceTooltip = tooltip experienceTooltip = tooltip
local localPlayer = g_game.getLocalPlayer()
if localPlayer then
experienceBar:setTooltip(tr(experienceTooltip, localPlayer:getLevelPercent(), localPlayer:getLevel()+1))
end
end end

View File

@@ -4,6 +4,7 @@ HealthBar < ProgressBar
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
margin: 1
ManaBar < ProgressBar ManaBar < ProgressBar
id: manaBar id: manaBar
@@ -11,6 +12,7 @@ ManaBar < ProgressBar
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
margin: 1
margin-top: 3 margin-top: 3
ExperienceBar < ProgressBar ExperienceBar < ProgressBar
@@ -19,9 +21,8 @@ ExperienceBar < ProgressBar
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
margin: 1
margin-top: 3 margin-top: 3
//margin-top: 6
//height: 12
SoulLabel < GameLabel SoulLabel < GameLabel
id: soulLabel id: soulLabel
@@ -66,7 +67,7 @@ MiniWindow
icon: /images/topbuttons/healthinfo icon: /images/topbuttons/healthinfo
id: healthInfoWindow id: healthInfoWindow
!text: tr('Health Info') !text: tr('Health Info')
height: 121 height: 123
@onClose: modules.game_healthinfo.onMiniWindowClose() @onClose: modules.game_healthinfo.onMiniWindowClose()
&save: true &save: true

View File

@@ -34,6 +34,7 @@ perCharacter = true
mouseGrabberWidget = nil mouseGrabberWidget = nil
useRadioGroup = nil useRadioGroup = nil
currentHotkeys = nil currentHotkeys = nil
boundCombosCallback = {}
hotkeysList = {} hotkeysList = {}
-- public functions -- public functions
@@ -75,6 +76,8 @@ function init()
onGameStart = online, onGameStart = online,
onGameEnd = offline onGameEnd = offline
}) })
load()
end end
function terminate() function terminate()
@@ -95,6 +98,7 @@ end
function configure(savePerServer, savePerCharacter) function configure(savePerServer, savePerCharacter)
perServer = savePerServer perServer = savePerServer
perCharacter = savePerCharacter perCharacter = savePerCharacter
reload()
end end
function online() function online()
@@ -108,6 +112,9 @@ function offline()
end end
function show() function show()
if not g_game.isOnline() then
return
end
hotkeysWindow:show() hotkeysWindow:show()
hotkeysWindow:raise() hotkeysWindow:raise()
hotkeysWindow:focus() hotkeysWindow:focus()
@@ -138,7 +145,7 @@ end
function load(forceDefaults) function load(forceDefaults)
hotkeysManagerLoaded = false hotkeysManagerLoaded = false
local hotkeySettings = g_settings.getNode('hotkeys') local hotkeySettings = g_settings.getNode('game_hotkeys')
local hotkeys = {} local hotkeys = {}
if not table.empty(hotkeySettings) then hotkeys = hotkeySettings end if not table.empty(hotkeySettings) then hotkeys = hotkeySettings end
@@ -149,6 +156,7 @@ function load(forceDefaults)
if not forceDefaults then if not forceDefaults then
if not table.empty(hotkeys) then if not table.empty(hotkeys) then
for keyCombo, setting in pairs(hotkeys) do for keyCombo, setting in pairs(hotkeys) do
keyCombo = tostring(keyCombo)
addKeyCombo(keyCombo, setting) addKeyCombo(keyCombo, setting)
hotkeyList[keyCombo] = setting hotkeyList[keyCombo] = setting
end end
@@ -163,12 +171,13 @@ function load(forceDefaults)
end end
function unload() function unload()
for _,child in pairs(currentHotkeys:getChildren()) do for keyCombo,callback in pairs(boundCombosCallback) do
g_keyboard.unbindKeyPress(child.keyCombo) g_keyboard.unbindKeyPress(keyCombo, callback)
end end
boundCombosCallback = {}
currentHotkeys:destroyChildren() currentHotkeys:destroyChildren()
currentHotkeyLabel = nil currentHotkeyLabel = nil
updateHotkeyForm() updateHotkeyForm(true)
hotkeyList = {} hotkeyList = {}
end end
@@ -183,19 +192,26 @@ function reload()
end end
function save() function save()
local hotkeySettings = g_settings.getNode('hotkeys') or {} local hotkeySettings = g_settings.getNode('game_hotkeys') or {}
local hotkeys = hotkeySettings local hotkeys = hotkeySettings
if perServer then if perServer then
hotkeys[G.host] = {} if not hotkeys[G.host] then
hotkeys[G.host] = {}
end
hotkeys = hotkeys[G.host] hotkeys = hotkeys[G.host]
end end
if perCharacter then if perCharacter then
hotkeys[g_game.getCharacterName()] = {} local char = g_game.getCharacterName()
hotkeys = hotkeys[g_game.getCharacterName()] if not hotkeys[char] then
hotkeys[char] = {}
end
hotkeys = hotkeys[char]
end end
table.clear(hotkeys)
for _,child in pairs(currentHotkeys:getChildren()) do for _,child in pairs(currentHotkeys:getChildren()) do
hotkeys[child.keyCombo] = { hotkeys[child.keyCombo] = {
autoSend = child.autoSend, autoSend = child.autoSend,
@@ -206,8 +222,8 @@ function save()
end end
hotkeyList = hotkeys hotkeyList = hotkeys
g_settings.setNode('hotkeys', hotkeySettings) g_settings.setNode('game_hotkeys', hotkeySettings)
--g_settings.save() g_settings.save()
end end
function loadDefautComboKeys() function loadDefautComboKeys()
@@ -258,7 +274,7 @@ function onChooseItemMouseRelease(self, mousePosition, mouseButton)
currentHotkeyLabel.value = nil currentHotkeyLabel.value = nil
currentHotkeyLabel.autoSend = false currentHotkeyLabel.autoSend = false
updateHotkeyLabel(currentHotkeyLabel) updateHotkeyLabel(currentHotkeyLabel)
updateHotkeyForm() updateHotkeyForm(true)
end end
show() show()
@@ -281,7 +297,7 @@ function clearObject()
currentHotkeyLabel.autoSend = nil currentHotkeyLabel.autoSend = nil
currentHotkeyLabel.value = nil currentHotkeyLabel.value = nil
updateHotkeyLabel(currentHotkeyLabel) updateHotkeyLabel(currentHotkeyLabel)
updateHotkeyForm() updateHotkeyForm(true)
end end
function addHotkey() function addHotkey()
@@ -294,6 +310,7 @@ function addHotkey()
end end
function addKeyCombo(keyCombo, keySettings, focus) function addKeyCombo(keyCombo, keySettings, focus)
if keyCombo == nil or #keyCombo == 0 then return end
if not keyCombo then return end if not keyCombo then return end
local hotkeyLabel = currentHotkeys:getChildById(keyCombo) local hotkeyLabel = currentHotkeys:getChildById(keyCombo)
if not hotkeyLabel then if not hotkeyLabel then
@@ -321,27 +338,28 @@ function addKeyCombo(keyCombo, keySettings, focus)
if keySettings then if keySettings then
currentHotkeyLabel = hotkeyLabel currentHotkeyLabel = hotkeyLabel
hotkeyLabel.keyCombo = keyCombo hotkeyLabel.keyCombo = keyCombo
hotkeyLabel.autoSend = keySettings.autoSend hotkeyLabel.autoSend = toboolean(keySettings.autoSend)
hotkeyLabel.itemId = keySettings.itemId hotkeyLabel.itemId = tonumber(keySettings.itemId)
hotkeyLabel.useType = tonumber(keySettings.useType) hotkeyLabel.useType = tonumber(keySettings.useType)
hotkeyLabel.value = keySettings.value if keySettings.value then hotkeyLabel.value = tostring(keySettings.value) end
else else
hotkeyLabel.keyCombo = keyCombo hotkeyLabel.keyCombo = keyCombo
hotkeyLabel.autoSend = nil hotkeyLabel.autoSend = false
hotkeyLabel.itemId = nil hotkeyLabel.itemId = nil
hotkeyLabel.useType = nil hotkeyLabel.useType = nil
hotkeyLabel.value = nil hotkeyLabel.value = ''
end end
updateHotkeyLabel(hotkeyLabel) updateHotkeyLabel(hotkeyLabel)
g_keyboard.bindKeyPress(keyCombo, function() doKeyCombo(keyCombo) end, nil, 350) boundCombosCallback[keyCombo] = function() doKeyCombo(keyCombo) end
g_keyboard.bindKeyPress(keyCombo, boundCombosCallback[keyCombo])
end end
if focus then if focus then
currentHotkeys:focusChild(hotkeyLabel) currentHotkeys:focusChild(hotkeyLabel)
currentHotkeys:ensureChildVisible(hotkeyLabel) currentHotkeys:ensureChildVisible(hotkeyLabel)
updateHotkeyForm() updateHotkeyForm(true)
end end
end end
@@ -357,7 +375,7 @@ function doKeyCombo(keyCombo)
modules.game_console.setTextEditText(hotKey.value) modules.game_console.setTextEditText(hotKey.value)
end end
elseif hotKey.useType == HOTKEY_MANAGER_USE then elseif hotKey.useType == HOTKEY_MANAGER_USE then
g_game.useInventoryItemWith(hotKey.itemId) g_game.useInventoryItem(hotKey.itemId)
elseif hotKey.useType == HOTKEY_MANAGER_USEONSELF then elseif hotKey.useType == HOTKEY_MANAGER_USEONSELF then
g_game.useInventoryItemWith(hotKey.itemId, g_game.getLocalPlayer()) g_game.useInventoryItemWith(hotKey.itemId, g_game.getLocalPlayer())
elseif hotKey.useType == HOTKEY_MANAGER_USEONTARGET then elseif hotKey.useType == HOTKEY_MANAGER_USEONTARGET then
@@ -398,7 +416,7 @@ function updateHotkeyLabel(hotkeyLabel)
end end
end end
function updateHotkeyForm() function updateHotkeyForm(reset)
if currentHotkeyLabel then if currentHotkeyLabel then
removeHotkeyButton:enable() removeHotkeyButton:enable()
if currentHotkeyLabel.itemId ~= nil then if currentHotkeyLabel.itemId ~= nil then
@@ -435,8 +453,10 @@ function updateHotkeyForm()
hotkeyText:enable() hotkeyText:enable()
hotkeyText:focus() hotkeyText:focus()
hotKeyTextLabel:enable() hotKeyTextLabel:enable()
if reset then
hotkeyText:setCursorPos(-1)
end
hotkeyText:setText(currentHotkeyLabel.value) hotkeyText:setText(currentHotkeyLabel.value)
hotkeyText:setCursorPos(-1)
sendAutomatically:setChecked(currentHotkeyLabel.autoSend) sendAutomatically:setChecked(currentHotkeyLabel.autoSend)
sendAutomatically:setEnabled(currentHotkeyLabel.value and #currentHotkeyLabel.value > 0) sendAutomatically:setEnabled(currentHotkeyLabel.value and #currentHotkeyLabel.value > 0)
selectObjectButton:enable() selectObjectButton:enable()
@@ -461,7 +481,8 @@ end
function removeHotkey() function removeHotkey()
if currentHotkeyLabel == nil then return end if currentHotkeyLabel == nil then return end
g_keyboard.unbindKeyPress(currentHotkeyLabel.keyCombo) g_keyboard.unbindKeyPress(currentHotkeyLabel.keyCombo, boundCombosCallback[currentHotkeyLabel.keyCombo])
boundCombosCallback[currentHotkeyLabel.keyCombo] = nil
currentHotkeyLabel:destroy() currentHotkeyLabel:destroy()
currentHotkeyLabel = nil currentHotkeyLabel = nil
end end
@@ -504,7 +525,7 @@ end
function onSelectHotkeyLabel(hotkeyLabel) function onSelectHotkeyLabel(hotkeyLabel)
currentHotkeyLabel = hotkeyLabel currentHotkeyLabel = hotkeyLabel
updateHotkeyForm() updateHotkeyForm(true)
end end
function hotkeyCapture(assignWindow, keyCode, keyboardModifiers) function hotkeyCapture(assignWindow, keyCode, keyboardModifiers)

View File

@@ -1,4 +1,3 @@
WALK_REPEAT_DELAY = 90
WALK_STEPS_RETRY = 10 WALK_STEPS_RETRY = 10
gameRootPanel = nil gameRootPanel = nil
@@ -16,16 +15,15 @@ limitZoom = false
currentViewMode = 0 currentViewMode = 0
smartWalkDirs = {} smartWalkDirs = {}
smartWalkDir = nil smartWalkDir = nil
walkFunction = g_game.walk walkFunction = nil
function init() function init()
g_ui.importStyle('styles/countwindow') g_ui.importStyle('styles/countwindow')
connect(g_game, { connect(g_game, {
onGameStart = onGameStart, onGameStart = onGameStart,
onGMActions = onGMActions,
onGameEnd = onGameEnd, onGameEnd = onGameEnd,
onLoginAdvice = onLoginAdvice onLoginAdvice = onLoginAdvice,
}, true) }, true)
gameRootPanel = g_ui.displayUI('gameinterface') gameRootPanel = g_ui.displayUI('gameinterface')
@@ -49,6 +47,7 @@ function init()
setupViewMode(0) setupViewMode(0)
bindKeys() bindKeys()
load()
if g_game.isOnline() then if g_game.isOnline() then
show() show()
@@ -56,6 +55,7 @@ function init()
end end
function bindKeys() function bindKeys()
gameRootPanel:setAutoRepeatDelay(250)
g_keyboard.bindKeyDown('Up', function() changeWalkDir(North) end, gameRootPanel, true) g_keyboard.bindKeyDown('Up', function() changeWalkDir(North) end, gameRootPanel, true)
g_keyboard.bindKeyDown('Right', function() changeWalkDir(East) end, gameRootPanel, true) g_keyboard.bindKeyDown('Right', function() changeWalkDir(East) end, gameRootPanel, true)
g_keyboard.bindKeyDown('Down', function() changeWalkDir(South) end, gameRootPanel, true) g_keyboard.bindKeyDown('Down', function() changeWalkDir(South) end, gameRootPanel, true)
@@ -80,30 +80,30 @@ function bindKeys()
g_keyboard.bindKeyUp('Numpad1', function() changeWalkDir(SouthWest, true) end, gameRootPanel, true) g_keyboard.bindKeyUp('Numpad1', function() changeWalkDir(SouthWest, true) end, gameRootPanel, true)
g_keyboard.bindKeyUp('Numpad4', function() changeWalkDir(West, true) end, gameRootPanel, true) g_keyboard.bindKeyUp('Numpad4', function() changeWalkDir(West, true) end, gameRootPanel, true)
g_keyboard.bindKeyUp('Numpad7', function() changeWalkDir(NorthWest, true) end, gameRootPanel, true) g_keyboard.bindKeyUp('Numpad7', function() changeWalkDir(NorthWest, true) end, gameRootPanel, true)
g_keyboard.bindKeyPress('Up', function() smartWalk(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Up', function() smartWalk(North) end, gameRootPanel)
g_keyboard.bindKeyPress('Right', function() smartWalk(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Right', function() smartWalk(East) end, gameRootPanel)
g_keyboard.bindKeyPress('Down', function() smartWalk(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Down', function() smartWalk(South) end, gameRootPanel)
g_keyboard.bindKeyPress('Left', function() smartWalk(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Left', function() smartWalk(West) end, gameRootPanel)
g_keyboard.bindKeyPress('Numpad8', function() smartWalk(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Numpad8', function() smartWalk(North) end, gameRootPanel)
g_keyboard.bindKeyPress('Numpad9', function() smartWalk(NorthEast) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Numpad9', function() smartWalk(NorthEast) end, gameRootPanel)
g_keyboard.bindKeyPress('Numpad6', function() smartWalk(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Numpad6', function() smartWalk(East) end, gameRootPanel)
g_keyboard.bindKeyPress('Numpad3', function() smartWalk(SouthEast) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Numpad3', function() smartWalk(SouthEast) end, gameRootPanel)
g_keyboard.bindKeyPress('Numpad2', function() smartWalk(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Numpad2', function() smartWalk(South) end, gameRootPanel)
g_keyboard.bindKeyPress('Numpad1', function() smartWalk(SouthWest) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Numpad1', function() smartWalk(SouthWest) end, gameRootPanel)
g_keyboard.bindKeyPress('Numpad4', function() smartWalk(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Numpad4', function() smartWalk(West) end, gameRootPanel)
g_keyboard.bindKeyPress('Numpad7', function() smartWalk(NorthWest) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Numpad7', function() smartWalk(NorthWest) end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+Up', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Ctrl+Up', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+Right', function() g_game.turn(East) changeWalkDir(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Ctrl+Right', function() g_game.turn(East) changeWalkDir(East) end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+Down', function() g_game.turn(South) changeWalkDir(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Ctrl+Down', function() g_game.turn(South) changeWalkDir(South) end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+Left', function() g_game.turn(West) changeWalkDir(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Ctrl+Left', function() g_game.turn(West) changeWalkDir(West) end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+Numpad8', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Ctrl+Numpad8', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+Numpad6', function() g_game.turn(East) changeWalkDir(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Ctrl+Numpad6', function() g_game.turn(East) changeWalkDir(East) end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+Numpad2', function() g_game.turn(South) changeWalkDir(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Ctrl+Numpad2', function() g_game.turn(South) changeWalkDir(South) end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+Numpad4', function() g_game.turn(West) changeWalkDir(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Ctrl+Numpad4', function() g_game.turn(West) changeWalkDir(West) end, gameRootPanel)
g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel, 250) g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel, 250) g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel)
@@ -111,13 +111,13 @@ function bindKeys()
end end
function terminate() function terminate()
save()
hide() hide()
stopSmartWalk() stopSmartWalk()
disconnect(g_game, { disconnect(g_game, {
onGameStart = onGameStart, onGameStart = onGameStart,
onGMActions = onGMActions,
onGameEnd = onGameEnd, onGameEnd = onGameEnd,
onLoginAdvice = onLoginAdvice onLoginAdvice = onLoginAdvice
}) })
@@ -137,6 +137,16 @@ function onGameStart()
else else
g_game.disableFeature(GameForceFirstAutoWalkStep) g_game.disableFeature(GameForceFirstAutoWalkStep)
end end
addEvent(function()
if not limitZoom or g_game.isGM() then
gameMapPanel:setMaxZoomOut(513)
gameMapPanel:setLimitVisibleRange(false)
else
gameMapPanel:setMaxZoomOut(11)
gameMapPanel:setLimitVisibleRange(true)
end
end)
end end
function onGameEnd() function onGameEnd()
@@ -150,8 +160,6 @@ function show()
gameRootPanel:show() gameRootPanel:show()
gameRootPanel:focus() gameRootPanel:focus()
gameMapPanel:followCreature(g_game.getLocalPlayer()) gameMapPanel:followCreature(g_game.getLocalPlayer())
gameMapPanel:setMaxZoomOut(11)
gameMapPanel:setLimitVisibleRange(true)
setupViewMode(0) setupViewMode(0)
updateStretchShrink() updateStretchShrink()
logoutButton:setTooltip(tr('Logout')) logoutButton:setTooltip(tr('Logout'))
@@ -177,11 +185,27 @@ function hide()
modules.client_background.show() modules.client_background.show()
end end
function save()
local settings = {}
settings.splitterMarginBottom = bottomSplitter:getMarginBottom()
g_settings.setNode('game_interface', settings)
end
function load()
local settings = g_settings.getNode('game_interface')
if settings then
if settings.splitterMarginBottom then
bottomSplitter:setMarginBottom(settings.splitterMarginBottom)
end
end
end
function onLoginAdvice(message) function onLoginAdvice(message)
displayInfoBox(tr("For Your Information"), message) displayInfoBox(tr("For Your Information"), message)
end end
function forceExit() function forceExit()
g_game.cancelLogin()
scheduleEvent(exit, 10) scheduleEvent(exit, 10)
return true return true
end end
@@ -214,6 +238,7 @@ end
function tryLogout() function tryLogout()
if not g_game.isOnline() then if not g_game.isOnline() then
exit() exit()
return
end end
if logoutWindow then if logoutWindow then
@@ -267,11 +292,16 @@ end
function smartWalk(dir) function smartWalk(dir)
if g_keyboard.getModifiers() == KeyboardNoModifier then if g_keyboard.getModifiers() == KeyboardNoModifier then
if smartWalkDir then local func = walkFunction
walkFunction(smartWalkDir) if not func then
else if modules.client_options.getOption('dashWalk') then
walkFunction(dir) func = g_game.dashWalk
else
func = g_game.walk
end
end end
local dire = smartWalkDir or dir
func(dire)
return true return true
end end
return false return false
@@ -574,7 +604,6 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
player:stopAutoWalk() player:stopAutoWalk()
if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then
player.onAutoWalkFail = function() modules.game_textmessage.displayFailureMessage(tr('There is no way.')) end
player:autoWalk(autoWalkPos) player:autoWalk(autoWalkPos)
return true return true
end end
@@ -718,6 +747,7 @@ function setupViewMode(mode)
gameMapPanel:setVisibleDimension({ width = 15, height = 11 }) gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
elseif mode == 2 then elseif mode == 2 then
local limit = limitZoom and not g_game.isGM() local limit = limitZoom and not g_game.isGM()
gameMapPanel:setKeepAspectRatio(false)
gameMapPanel:setLimitVisibleRange(limit) gameMapPanel:setLimitVisibleRange(limit)
gameMapPanel:setZoom(11) gameMapPanel:setZoom(11)
gameMapPanel:setVisibleDimension({ width = 15, height = 11 }) gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
@@ -744,9 +774,3 @@ end
function limitZoom() function limitZoom()
limitZoom = true limitZoom = true
end end
function onGMActions()
if not limitZoom then return end
gameMapPanel:setMaxZoomOut(513)
gameMapPanel:setLimitVisibleRange(false)
end

View File

@@ -76,6 +76,8 @@ currentItems = {}
lastCreatedOffer = 0 lastCreatedOffer = 0
fee = 0 fee = 0
loaded = false
local offerTableHeader = { local offerTableHeader = {
{['text'] = 'Player Name', ['width'] = 100}, {['text'] = 'Player Name', ['width'] = 100},
{['text'] = 'Amount', ['width'] = 60}, {['text'] = 'Amount', ['width'] = 60},
@@ -126,10 +128,7 @@ local function isItemValid(item, category, searchFilter)
return false return false
end end
if searchFilter then if searchFilter then
local checkString = marketData.name:lower() return marketData.name:lower():find(searchFilter)
if not checkString:find(searchFilter) then
return false
end
end end
return true return true
end end
@@ -580,22 +579,30 @@ local function onAmountChange()
end end
local function initMarketItems(category) local function initMarketItems(category)
-- initialize market category for c = MarketCategory.First, MarketCategory.Last do
marketItems[category] = {} marketItems[c] = {}
end
-- populate all market items -- populate all market items
local types = g_things.findThingTypeByAttr(ThingAttrMarket, 0) local types = g_things.findThingTypeByAttr(ThingAttrMarket, 0)
for i = 1, #types do for i = 1, #types do
local t = types[i] local t = types[i]
local newItem = Item.create(t:getId()) local newItem = Item.create(t:getId())
if newItem then if newItem then
local marketData = t:getMarketData() local marketData = t:getMarketData()
if not table.empty(marketData) and marketData.category == category then if not table.empty(marketData) then
local item = { if marketData.category == category or category == MarketCategory.All then
ptr = newItem,
marketData = marketData -- create new item block
} local item = {
marketItems[marketData.category][#marketItems[category]+1] = item ptr = newItem,
marketData = marketData
}
-- add new market item
table.insert(marketItems[marketData.category], item)
end
end end
end end
end end
@@ -733,9 +740,6 @@ function init()
marketWindow:hide() marketWindow:hide()
initInterface() -- build interface initInterface() -- build interface
for category = MarketCategory.First, MarketCategory.Last do
initMarketItems(category)
end
end end
function terminate() function terminate()
@@ -904,19 +908,14 @@ end
function Market.loadMarketItems(category) function Market.loadMarketItems(category)
if table.empty(marketItems[category]) then
initMarketItems(category)
end
clearItems() clearItems()
-- check search filter -- check search filter
local searchFilter = searchEdit:getText():lower() local searchFilter = searchEdit:getText()
if not searchFilter or searchFilter:len() < 3 then if searchFilter and searchFilter:len() > 2 then
searchFilter = nil if filterButtons[MarketFilters.SearchAll]:isChecked() then
end category = MarketCategory.All
local filterSearchAll = filterButtons[MarketFilters.SearchAll]:isChecked() end
if filterSearchAll and searchFilter then
category = MarketCategory.All
end end
if category == MarketCategory.All then if category == MarketCategory.All then
@@ -1070,6 +1069,11 @@ end
-- protocol callback functions -- protocol callback functions
function Market.onMarketEnter(depotItems, offers, balance, vocation) function Market.onMarketEnter(depotItems, offers, balance, vocation)
if not loaded then
initMarketItems(MarketCategory.All)
loaded = true
end
Market.clearSelectedItem() Market.clearSelectedItem()
updateBalance(balance) updateBalance(balance)
@@ -1078,7 +1082,7 @@ function Market.onMarketEnter(depotItems, offers, balance, vocation)
if player then if player then
information.player = player information.player = player
end end
if vocation < 0 then if vocation == -1 then
if player then if player then
information.vocation = player:getVocation() information.vocation = player:getVocation()
end end

View File

@@ -1,7 +1,7 @@
AmountWindow < MainWindow AmountWindow < MainWindow
id: amountWindow id: amountWindow
!text: tr('Amount') !text: tr('Amount')
size: 196 80 size: 270 80
Item Item
id: item id: item
@@ -21,7 +21,6 @@ AmountWindow < MainWindow
anchors.top: prev.top anchors.top: prev.top
margin-left: 10 margin-left: 10
margin-top: -2 margin-top: -2
focusable: false
Button Button
id: buttonCancel id: buttonCancel

View File

@@ -102,6 +102,7 @@ Panel
width: 75 width: 75
minimum: 1 minimum: 1
maximum: 999999999 maximum: 999999999
focusable: true
$disabled: $disabled:
color: #aaaaaa44 color: #aaaaaa44
@@ -123,6 +124,7 @@ Panel
width: 75 width: 75
minimum: 1 minimum: 1
maximum: 999999999 maximum: 999999999
focusable: true
$disabled: $disabled:
color: #aaaaaa44 color: #aaaaaa44
@@ -152,6 +154,7 @@ Panel
buttons: false buttons: false
minimum: 1 minimum: 1
maximum: 64000 maximum: 64000
focusable: true
NextButton NextButton
id: nextAmountButton id: nextAmountButton

View File

@@ -3,6 +3,9 @@ minimapButton = nil
minimapWindow = nil minimapWindow = nil
otmm = true otmm = true
preloaded = false preloaded = false
fullmapView = false
oldZoom = nil
oldPos = nil
function init() function init()
minimapButton = modules.client_topmenu.addRightGameToggleButton('minimapButton', tr('Minimap') .. ' (Ctrl+M)', '/images/topbuttons/minimap', toggle) minimapButton = modules.client_topmenu.addRightGameToggleButton('minimapButton', tr('Minimap') .. ' (Ctrl+M)', '/images/topbuttons/minimap', toggle)
@@ -19,6 +22,7 @@ function init()
g_keyboard.bindKeyPress('Alt+Up', function() minimapWidget:move(0,1) end, gameRootPanel) g_keyboard.bindKeyPress('Alt+Up', function() minimapWidget:move(0,1) end, gameRootPanel)
g_keyboard.bindKeyPress('Alt+Down', function() minimapWidget:move(0,-1) end, gameRootPanel) g_keyboard.bindKeyPress('Alt+Down', function() minimapWidget:move(0,-1) end, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+M', toggle) g_keyboard.bindKeyDown('Ctrl+M', toggle)
g_keyboard.bindKeyDown('Ctrl+Shift+M', toggleFullMap)
minimapWindow:setup() minimapWindow:setup()
@@ -27,6 +31,10 @@ function init()
onGameEnd = offline, onGameEnd = offline,
}) })
connect(LocalPlayer, {
onPositionChange = updateCameraPosition
})
if g_game.isOnline() then if g_game.isOnline() then
online() online()
end end
@@ -42,12 +50,17 @@ function terminate()
onGameEnd = offline, onGameEnd = offline,
}) })
disconnect(LocalPlayer, {
onPositionChange = updateCameraPosition
})
local gameRootPanel = modules.game_interface.getRootPanel() local gameRootPanel = modules.game_interface.getRootPanel()
g_keyboard.unbindKeyPress('Alt+Left', gameRootPanel) g_keyboard.unbindKeyPress('Alt+Left', gameRootPanel)
g_keyboard.unbindKeyPress('Alt+Right', gameRootPanel) g_keyboard.unbindKeyPress('Alt+Right', gameRootPanel)
g_keyboard.unbindKeyPress('Alt+Up', gameRootPanel) g_keyboard.unbindKeyPress('Alt+Up', gameRootPanel)
g_keyboard.unbindKeyPress('Alt+Down', gameRootPanel) g_keyboard.unbindKeyPress('Alt+Down', gameRootPanel)
g_keyboard.unbindKeyDown('Ctrl+M') g_keyboard.unbindKeyDown('Ctrl+M')
g_keyboard.unbindKeyDown('Ctrl+Shift+M')
minimapWindow:destroy() minimapWindow:destroy()
minimapButton:destroy() minimapButton:destroy()
@@ -74,7 +87,7 @@ end
function online() function online()
loadMap(not preloaded) loadMap(not preloaded)
minimapWidget:followLocalPlayer() updateCameraPosition()
end end
function offline() function offline()
@@ -114,6 +127,38 @@ function saveMap()
minimapWidget:save() minimapWidget:save()
end end
function getMinimap() function updateCameraPosition()
return minimapWidget local player = g_game.getLocalPlayer()
if not player then return end
local pos = player:getPosition()
if not pos then return end
if not minimapWidget:isDragging() then
if not fullmapView then
minimapWidget:setCameraPosition(player:getPosition())
end
minimapWidget:setCrossPosition(player:getPosition())
end
end
function toggleFullMap()
if not fullmapView then
fullmapView = true
minimapWindow:hide()
minimapWidget:setParent(modules.game_interface.getRootPanel())
minimapWidget:fill('parent')
minimapWidget:setAlternativeWidgetsVisible(true)
else
fullmapView = false
minimapWidget:setParent(minimapWindow:getChildById('contentsPanel'))
minimapWidget:fill('parent')
minimapWindow:show()
minimapWidget:setAlternativeWidgetsVisible(false)
end
local zoom = oldZoom or 0
local pos = oldPos or minimapWidget:getCameraPosition()
oldZoom = minimapWidget:getZoom()
oldPos = minimapWidget:getCameraPosition()
minimapWidget:setZoom(zoom)
minimapWidget:setCameraPosition(pos)
end end

View File

@@ -10,7 +10,7 @@ MiniWindow
text: ? text: ?
text-align: center text-align: center
phantom: false phantom: false
!tooltip: tr('Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks') !tooltip: tr('Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks\nPress Ctrl+Shift+M to view the entire game map')
anchors.top: minimizeButton.top anchors.top: minimizeButton.top
anchors.right: minimizeButton.left anchors.right: minimizeButton.left
margin-right: 3 margin-right: 3

View File

@@ -1,6 +1,7 @@
BUY = 1 BUY = 1
SELL = 2 SELL = 2
CURRENCY = 'gold' CURRENCY = 'gold'
CURRENCY_DECIMAL = false
WEIGHT_UNIT = 'oz' WEIGHT_UNIT = 'oz'
LAST_INVENTORY = 10 LAST_INVENTORY = 10
@@ -29,11 +30,12 @@ buyWithBackpack = nil
ignoreCapacity = nil ignoreCapacity = nil
ignoreEquipped = nil ignoreEquipped = nil
showAllItems = nil showAllItems = nil
sellAllButton = nil
playerFreeCapacity = nil playerFreeCapacity = 0
playerMoney = nil playerMoney = 0
tradeItems = {} tradeItems = {}
playerItems = nil playerItems = {}
selectedItem = nil selectedItem = nil
cancelNextRelease = nil cancelNextRelease = nil
@@ -60,6 +62,7 @@ function init()
ignoreCapacity = npcWindow:recursiveGetChildById('ignoreCapacity') ignoreCapacity = npcWindow:recursiveGetChildById('ignoreCapacity')
ignoreEquipped = npcWindow:recursiveGetChildById('ignoreEquipped') ignoreEquipped = npcWindow:recursiveGetChildById('ignoreEquipped')
showAllItems = npcWindow:recursiveGetChildById('showAllItems') showAllItems = npcWindow:recursiveGetChildById('showAllItems')
sellAllButton = npcWindow:recursiveGetChildById('sellAllButton')
buyTab = npcWindow:getChildById('buyTab') buyTab = npcWindow:getChildById('buyTab')
sellTab = npcWindow:getChildById('sellTab') sellTab = npcWindow:getChildById('sellTab')
@@ -124,13 +127,17 @@ function onItemBoxChecked(widget)
selectedItem = item selectedItem = item
refreshItem(item) refreshItem(item)
tradeButton:enable() tradeButton:enable()
if getCurrentTradeType() == SELL then
quantityScroll:setValue(quantityScroll:getMaximum())
end
end end
end end
function onQuantityValueChange(quantity) function onQuantityValueChange(quantity)
if selectedItem then if selectedItem then
weightLabel:setText(string.format('%.2f', selectedItem.weight*quantity) .. ' ' .. WEIGHT_UNIT) weightLabel:setText(string.format('%.2f', selectedItem.weight*quantity) .. ' ' .. WEIGHT_UNIT)
priceLabel:setText(getItemPrice(selectedItem) .. ' ' .. CURRENCY) priceLabel:setText(formatCurrency(getItemPrice(selectedItem)))
end end
end end
@@ -144,6 +151,8 @@ function onTradeTypeChange(radioTabs, selected, deselected)
ignoreCapacity:setVisible(currentTradeType == BUY) ignoreCapacity:setVisible(currentTradeType == BUY)
ignoreEquipped:setVisible(currentTradeType == SELL) ignoreEquipped:setVisible(currentTradeType == SELL)
showAllItems:setVisible(currentTradeType == SELL) showAllItems:setVisible(currentTradeType == SELL)
sellAllButton:setVisible(false)
--sellAllButton:setVisible(currentTradeType == SELL)
refreshTradeItems() refreshTradeItems()
refreshPlayerGoods() refreshPlayerGoods()
@@ -199,8 +208,9 @@ function onShowAllItemsChange()
refreshPlayerGoods() refreshPlayerGoods()
end end
function setCurrency(currency) function setCurrency(currency, decimal)
CURRENCY = currency CURRENCY = currency
CURRENCY_DECIMAL = decimal
end end
function setShowWeight(state) function setShowWeight(state)
@@ -220,7 +230,8 @@ function clearSelectedItem()
weightLabel:clearText() weightLabel:clearText()
priceLabel:clearText() priceLabel:clearText()
tradeButton:disable() tradeButton:disable()
quantityScroll:setMaximum(1) quantityScroll:setMinimum(0)
quantityScroll:setMaximum(0)
if selectedItem then if selectedItem then
radioItems:selectWidget(nil) radioItems:selectWidget(nil)
selectedItem = nil selectedItem = nil
@@ -254,60 +265,45 @@ function getItemPrice(item, single)
end end
function getSellQuantity(item) function getSellQuantity(item)
if not playerItems[item.ptr:getId()] then if not item or not playerItems[item:getId()] then return 0 end
return 0
end
local removeAmount = 0 local removeAmount = 0
if ignoreEquipped:isChecked() then if ignoreEquipped:isChecked() then
local localPlayer = g_game.getLocalPlayer() local localPlayer = g_game.getLocalPlayer()
for i=1,LAST_INVENTORY do for i=1,LAST_INVENTORY do
local inventoryItem = localPlayer:getInventoryItem(i) local inventoryItem = localPlayer:getInventoryItem(i)
if inventoryItem and inventoryItem:getId() == item.ptr:getId() then if inventoryItem and inventoryItem:getId() == item:getId() then
removeAmount = removeAmount + inventoryItem:getCount() removeAmount = removeAmount + inventoryItem:getCount()
end end
end end
end end
return playerItems[item.ptr:getId()] - removeAmount return playerItems[item:getId()] - removeAmount
end end
function canTradeItem(item) function canTradeItem(item)
if getCurrentTradeType() == BUY then if getCurrentTradeType() == BUY then
return (ignoreCapacity:isChecked() or (not ignoreCapacity:isChecked() and playerFreeCapacity >= item.weight)) and playerMoney >= getItemPrice(item, true) return (ignoreCapacity:isChecked() or (not ignoreCapacity:isChecked() and playerFreeCapacity >= item.weight)) and playerMoney >= getItemPrice(item, true)
else else
return getSellQuantity(item) > 0 return getSellQuantity(item.ptr) > 0
end end
end end
function refreshItem(item) function refreshItem(item)
nameLabel:setText(item.name) nameLabel:setText(item.name)
weightLabel:setText(string.format('%.2f', item.weight) .. ' ' .. WEIGHT_UNIT) weightLabel:setText(string.format('%.2f', item.weight) .. ' ' .. WEIGHT_UNIT)
priceLabel:setText(getItemPrice(item) .. ' ' .. CURRENCY) priceLabel:setText(formatCurrency(getItemPrice(item)))
if getCurrentTradeType() == BUY then if getCurrentTradeType() == BUY then
local capacityMaxCount = math.floor(playerFreeCapacity / item.weight) local capacityMaxCount = math.floor(playerFreeCapacity / item.weight)
if ignoreCapacity:isChecked() then if ignoreCapacity:isChecked() then
capacityMaxCount = 100 capacityMaxCount = 65535
end end
local priceMaxCount = math.floor(playerMoney / getItemPrice(item, true)) local priceMaxCount = math.floor(playerMoney / getItemPrice(item, true))
local finalCount = math.max(0, math.min(100, math.min(priceMaxCount, capacityMaxCount))) local finalCount = math.max(0, math.min(getMaxAmount(), math.min(priceMaxCount, capacityMaxCount)))
quantityScroll:setMinimum(1)
quantityScroll:setMaximum(finalCount) quantityScroll:setMaximum(finalCount)
if quantityScroll:getValue() > finalCount then
quantityScroll:setValue(finalCount)
end
else else
local removeAmount = 0 quantityScroll:setMinimum(1)
if ignoreEquipped:isChecked() then quantityScroll:setMaximum(math.max(0, math.min(getMaxAmount(), getSellQuantity(item.ptr))))
local localPlayer = g_game.getLocalPlayer()
for i=1,LAST_INVENTORY do
local inventoryItem = localPlayer:getInventoryItem(i)
if inventoryItem and inventoryItem:getId() == item.ptr:getId() then
removeAmount = removeAmount + inventoryItem:getCount()
end
end
end
quantityScroll:setMaximum(math.max(0, math.min(100, getSellQuantity(item))))
end end
setupPanel:enable() setupPanel:enable()
@@ -340,7 +336,7 @@ function refreshTradeItems()
local weight = string.format('%.2f', item.weight) .. ' ' .. WEIGHT_UNIT local weight = string.format('%.2f', item.weight) .. ' ' .. WEIGHT_UNIT
text = text .. '\n' .. weight text = text .. '\n' .. weight
end end
local price = item.price .. ' ' .. CURRENCY local price = formatCurrency(item.price)
text = text .. '\n' .. price text = text .. '\n' .. price
itemBox:setText(text) itemBox:setText(text)
@@ -358,7 +354,9 @@ end
function refreshPlayerGoods() function refreshPlayerGoods()
if not initialized then return end if not initialized then return end
moneyLabel:setText(playerMoney .. ' ' .. CURRENCY) checkSellAllTooltip()
moneyLabel:setText(formatCurrency(playerMoney))
capacityLabel:setText(string.format('%.2f', playerFreeCapacity) .. ' ' .. WEIGHT_UNIT) capacityLabel:setText(string.format('%.2f', playerFreeCapacity) .. ' ' .. WEIGHT_UNIT)
local currentTradeType = getCurrentTradeType() local currentTradeType = getCurrentTradeType()
@@ -372,6 +370,7 @@ function refreshPlayerGoods()
local canTrade = canTradeItem(item) local canTrade = canTradeItem(item)
itemWidget:setOn(canTrade) itemWidget:setOn(canTrade)
itemWidget:setEnabled(canTrade)
local searchCondition = (searchFilter == '') or (searchFilter ~= '' and string.find(item.name:lower(), searchFilter) ~= nil) local searchCondition = (searchFilter == '') or (searchFilter ~= '' and string.find(item.name:lower(), searchFilter) ~= nil)
local showAllItemsCondition = (currentTradeType == BUY) or (showAllItems:isChecked()) or (currentTradeType == SELL and not showAllItems:isChecked() and canTrade) local showAllItemsCondition = (currentTradeType == BUY) or (showAllItems:isChecked()) or (currentTradeType == SELL and not showAllItems:isChecked() and canTrade)
@@ -440,7 +439,7 @@ function onPlayerGoods(money, items)
playerItems[id] = playerItems[id] + item[2] playerItems[id] = playerItems[id] + item[2]
end end
end end
refreshPlayerGoods() refreshPlayerGoods()
end end
@@ -453,7 +452,86 @@ function onFreeCapacityChange(localPlayer, freeCapacity, oldFreeCapacity)
end end
function onInventoryChange(inventory, item, oldItem) function onInventoryChange(inventory, item, oldItem)
if selectedItem then refreshPlayerGoods()
refreshItem(selectedItem) end
function getTradeItemData(id, type)
if table.empty(tradeItems[type]) then
return false
end
if type then
for key,item in pairs(tradeItems[type]) do
if item.ptr and item.ptr:getId() == id then
return item
end
end
else
for _,items in pairs(tradeItems) do
for key,item in pairs(items) do
if item.ptr and item.ptr:getId() == id then
return item
end
end
end
end
return false
end
function checkSellAllTooltip()
sellAllButton:setEnabled(true)
sellAllButton:removeTooltip()
local total = 0
local info = ''
local first = true
for key, amount in pairs(playerItems) do
local data = getTradeItemData(key, SELL)
if data then
amount = getSellQuantity(data.ptr)
if amount > 0 then
if data and amount > 0 then
info = info..(not first and "\n" or "")..
amount.." "..
data.name.." ("..
data.price*amount.." gold)"
total = total+(data.price*amount)
if first then first = false end
end
end
end
end
if info ~= '' then
info = info.."\nTotal: "..total.." gold"
sellAllButton:setTooltip(info)
else
sellAllButton:setEnabled(false)
end
end
function formatCurrency(amount)
if CURRENCY_DECIMAL then
return string.format("%.02f", amount/100.0) .. ' ' .. CURRENCY
else
return amount .. ' ' .. CURRENCY
end
end
function getMaxAmount()
if getCurrentTradeType() == SELL and g_game.getFeature(GameDoubleShopSellAmount) then
return 10000
end
return 100
end
function sellAll()
for itemid,item in pairs(playerItems) do
local item = Item.create(itemid)
local amount = getSellQuantity(item)
if amount > 0 then
g_game.sellItem(item, amount, ignoreEquipped:isChecked())
end
end end
end end

View File

@@ -243,6 +243,17 @@ MainWindow
checked: true checked: true
@onCheckChange: modules.game_npctrade.onShowAllItemsChange() @onCheckChange: modules.game_npctrade.onShowAllItemsChange()
Button
id: sellAllButton
!text: tr('Sell All')
width: 64
anchors.right: next.left
anchors.bottom: parent.bottom
margin-right: 10
visible: false
@onClick: modules.game_npctrade.sellAll()
visible: false
Button Button
id: tradeButton id: tradeButton
!text: tr('Buy') !text: tr('Buy')

View File

@@ -33,7 +33,10 @@ function displayDeadMessage()
end end
function openWindow() function openWindow()
if deathWindow then return end if deathWindow then
deathWindow:destroy()
return
end
deathWindow = g_ui.createWidget('DeathWindow', rootWidget) deathWindow = g_ui.createWidget('DeathWindow', rootWidget)
local okButton = deathWindow:getChildById('buttonOk') local okButton = deathWindow:getChildById('buttonOk')
local cancelButton = deathWindow:getChildById('buttonCancel') local cancelButton = deathWindow:getChildById('buttonCancel')

View File

@@ -161,6 +161,10 @@ function init()
initialiseSpelllist() initialiseSpelllist()
resizeWindow() resizeWindow()
if g_game.isOnline() then
online()
end
end end
function terminate() function terminate()
@@ -201,7 +205,7 @@ function initialiseSpelllist()
tmpLabel:setHeight(SpelllistSettings[SpelllistProfile].iconSize.height + 4) tmpLabel:setHeight(SpelllistSettings[SpelllistProfile].iconSize.height + 4)
tmpLabel:setTextOffset(topoint((SpelllistSettings[SpelllistProfile].iconSize.width + 10) .. ' ' .. (SpelllistSettings[SpelllistProfile].iconSize.height - 32)/2 + 3)) tmpLabel:setTextOffset(topoint((SpelllistSettings[SpelllistProfile].iconSize.width + 10) .. ' ' .. (SpelllistSettings[SpelllistProfile].iconSize.height - 32)/2 + 3))
tmpLabel:setImageSource('/images/game/spells/' .. SpelllistSettings[SpelllistProfile].iconFile) tmpLabel:setImageSource(SpelllistSettings[SpelllistProfile].iconFile)
tmpLabel:setImageClip(Spells.getImageClip(iconId, SpelllistProfile)) tmpLabel:setImageClip(Spells.getImageClip(iconId, SpelllistProfile))
tmpLabel:setImageSize(tosize(SpelllistSettings[SpelllistProfile].iconSize.width .. ' ' .. SpelllistSettings[SpelllistProfile].iconSize.height)) tmpLabel:setImageSize(tosize(SpelllistSettings[SpelllistProfile].iconSize.width .. ' ' .. SpelllistSettings[SpelllistProfile].iconSize.height))
tmpLabel.onClick = updateSpellInformation tmpLabel.onClick = updateSpellInformation

View File

@@ -123,3 +123,7 @@ function clearMessages()
end end
end end
end end
function LocalPlayer:onAutoWalkFail(player)
modules.game_textmessage.displayFailureMessage(tr('There is no way.'))
end

View File

@@ -3,7 +3,8 @@ vipButton = nil
addVipWindow = nil addVipWindow = nil
function init() function init()
connect(g_game, { onGameEnd = clear, connect(g_game, { onGameStart = refresh,
onGameEnd = clear,
onAddVip = onAddVip, onAddVip = onAddVip,
onVipStateChange = onVipStateChange }) onVipStateChange = onVipStateChange })
@@ -20,7 +21,8 @@ end
function terminate() function terminate()
g_keyboard.unbindKeyDown('Ctrl+P') g_keyboard.unbindKeyDown('Ctrl+P')
disconnect(g_game, { onGameEnd = clear, disconnect(g_game, { onGameStart = refresh,
onGameEnd = clear,
onAddVip = onAddVip, onAddVip = onAddVip,
onVipStateChange = onVipStateChange }) onVipStateChange = onVipStateChange })
@@ -181,11 +183,14 @@ function onVipListLabelMousePress(widget, mousePos, mouseButton)
menu:addOption(tr('Add new VIP'), function() createAddWindow() end) menu:addOption(tr('Add new VIP'), function() createAddWindow() end)
menu:addOption(tr('Remove %s', widget:getText()), function() if widget then g_game.removeVip(widget:getId():sub(4)) vipList:removeChild(widget) end end) menu:addOption(tr('Remove %s', widget:getText()), function() if widget then g_game.removeVip(widget:getId():sub(4)) vipList:removeChild(widget) end end)
menu:addSeparator() menu:addSeparator()
menu:addOption(tr('Copy Name'), function() g_window.setClipboardText(widget:getText()) end) if modules.game_console.getOwnPrivateTab() then menu:addOption(tr('Copy Name'), function() g_window.setClipboardText(widget:getText()) end)
if modules.game_console.getOwnPrivateTab() then
menu:addSeparator() menu:addSeparator()
menu:addOption(tr('Invite to private chat'), function() g_game.inviteToOwnChannel(creatureName) end) menu:addOption(tr('Invite to private chat'), function() g_game.inviteToOwnChannel(widget:getText()) end)
menu:addOption(tr('Exclude from private chat'), function() g_game.excludeFromOwnChannel(creatureName) end) menu:addOption(tr('Exclude from private chat'), function() g_game.excludeFromOwnChannel(widget:getText()) end)
end end
if not isHiddingOffline() then if not isHiddingOffline() then
menu:addOption(tr('Hide Offline'), function() hideOffline(true) end) menu:addOption(tr('Hide Offline'), function() hideOffline(true) end)
else else

View File

@@ -80,6 +80,7 @@ GameLoginPending = 35
GameNewSpeedLaw = 36 GameNewSpeedLaw = 36
GameForceFirstAutoWalkStep = 37 GameForceFirstAutoWalkStep = 37
GameMinimapRemove = 38 GameMinimapRemove = 38
GameDoubleShopSellAmount = 39
TextColors = { TextColors = {
red = '#f55e5e', --'#c83200' red = '#f55e5e', --'#c83200'
@@ -91,7 +92,7 @@ TextColors = {
--blue1 = '#6e50dc', --blue1 = '#6e50dc',
--blue2 = '#3264c8', --blue2 = '#3264c8',
--blue3 = '#0096c8', --blue3 = '#0096c8',
white = '#ffffff' --'#bebebe' white = '#ffffff', --'#bebebe'
} }
MessageModes = { MessageModes = {
@@ -145,7 +146,7 @@ MessageModes = {
RVRAnswer = 47, RVRAnswer = 47,
RVRContinue = 48, RVRContinue = 48,
Last = 49, Last = 49,
Invalid = 255 Invalid = 255,
} }
OTSERV_RSA = "1091201329673994292788609605089955415282375029027981291234687579" .. OTSERV_RSA = "1091201329673994292788609605089955415282375029027981291234687579" ..
@@ -169,7 +170,7 @@ OsTypes = {
Flash = 3, Flash = 3,
OtclientLinux = 10, OtclientLinux = 10,
OtclientWindows = 11, OtclientWindows = 11,
OtclientMac = 12 OtclientMac = 12,
} }
PathFindResults = { PathFindResults = {
@@ -177,26 +178,31 @@ PathFindResults = {
Position = 1, Position = 1,
Impossible = 2, Impossible = 2,
TooFar = 3, TooFar = 3,
NoWay = 4 NoWay = 4,
} }
PathFindFlags = { PathFindFlags = {
AllowNullTiles = 1, AllowNullTiles = 1,
AllowCreatures = 2, AllowCreatures = 2,
AllowNonPathable = 4, AllowNonPathable = 4,
AllowNonWalkable = 8 AllowNonWalkable = 8,
} }
VipState = { VipState = {
Offline = 0, Offline = 0,
Online = 1, Online = 1,
Pending = 2 Pending = 2,
} }
ExtendedIds = { ExtendedIds = {
Activate = 0, Activate = 0,
Locale = 1, Locale = 1,
Ping = 2 Ping = 2,
Sound = 3,
Game = 4,
Particles = 5,
MapShader = 6,
NeedsUpdate = 7
} }
-- @} -- @}

View File

@@ -34,16 +34,18 @@ end
function g_game.getSupportedProtocols() function g_game.getSupportedProtocols()
return { return {
810, 853, 854, 860, 861, 862, 870, 810, 811, 840, 842, 850, 853, 854,
910, 940, 944, 953, 954, 960, 961, 860, 861, 862, 870, 910, 940, 944,
963, 970, 971, 973 953, 954, 960, 961, 963, 970, 971,
973, 974
} }
end end
function g_game.getSupportedClients(protocol) function g_game.getSupportedClients(protocol)
clients = { clients = {
[971] = {980}, [971] = {980},
[973] = {981} [973] = {981},
[974] = {982}
} }
return clients[protocol] or {protocol} return clients[protocol] or {protocol}
end end

View File

@@ -161,4 +161,4 @@ function Player:hasState(_state, states)
end end
end end
return false return false
end end

View File

@@ -10,13 +10,13 @@ LoginServerExtendedCharacterList = 101
function ProtocolLogin:login(host, port, accountName, accountPassword) function ProtocolLogin:login(host, port, accountName, accountPassword)
if string.len(host) == 0 or port == nil or port == 0 then if string.len(host) == 0 or port == nil or port == 0 then
signalcall(self.onError, self, tr("You must enter a valid server address and port.")) signalcall(self.onLoginError, self, tr("You must enter a valid server address and port."))
return return
end end
self.accountName = accountName self.accountName = accountName
self.accountPassword = accountPassword self.accountPassword = accountPassword
self.connectCallback = sendLoginPacket self.connectCallback = self.sendLoginPacket
self:connect(host, port) self:connect(host, port)
end end
@@ -25,7 +25,7 @@ function ProtocolLogin:cancelLogin()
self:disconnect() self:disconnect()
end end
function ProtocolLogin:sendLoginPacket(extended) function ProtocolLogin:sendLoginPacket()
local msg = OutputMessage.create() local msg = OutputMessage.create()
msg:addU8(ClientOpcodes.ClientEnterAccount) msg:addU8(ClientOpcodes.ClientEnterAccount)
@@ -85,7 +85,9 @@ function ProtocolLogin:sendLoginPacket(extended)
end end
function ProtocolLogin:onConnect() function ProtocolLogin:onConnect()
self:sendLoginPacket() self.gotConnection = true
self:connectCallback()
self.connectCallback = nil
end end
function ProtocolLogin:onRecv(msg) function ProtocolLogin:onRecv(msg)
@@ -96,7 +98,7 @@ function ProtocolLogin:onRecv(msg)
elseif opcode == LoginServerMotd then elseif opcode == LoginServerMotd then
self:parseMotd(msg) self:parseMotd(msg)
elseif opcode == LoginServerUpdateNeeded then elseif opcode == LoginServerUpdateNeeded then
signalcall(self.onError, self, tr("Client needs update.")) signalcall(self.onLoginError, self, tr("Client needs update."))
elseif opcode == LoginServerCharacterList then elseif opcode == LoginServerCharacterList then
self:parseCharacterList(msg) self:parseCharacterList(msg)
elseif opcode == LoginServerExtendedCharacterList then elseif opcode == LoginServerExtendedCharacterList then
@@ -113,7 +115,7 @@ end
function ProtocolLogin:parseError(msg) function ProtocolLogin:parseError(msg)
local errorMessage = msg:getString() local errorMessage = msg:getString()
signalcall(self.onError, self, errorMessage) signalcall(self.onLoginError, self, errorMessage)
end end
function ProtocolLogin:parseMotd(msg) function ProtocolLogin:parseMotd(msg)
@@ -130,12 +132,12 @@ function ProtocolLogin:parseCharacterList(msg)
character.worldName = msg:getString() character.worldName = msg:getString()
character.worldIp = iptostring(msg:getU32()) character.worldIp = iptostring(msg:getU32())
character.worldPort = msg:getU16() character.worldPort = msg:getU16()
characters[i] = character
-- ??
if g_game.getProtocolVersion() >= 971 then if g_game.getProtocolVersion() >= 971 then
msg:getU8() character.unknown = msg:getU8()
end end
characters[i] = character
end end
local account = {} local account = {}
@@ -153,3 +155,8 @@ end
function ProtocolLogin:parseOpcode(opcode, msg) function ProtocolLogin:parseOpcode(opcode, msg)
signalcall(self.onOpcode, self, opcode, msg) signalcall(self.onOpcode, self, opcode, msg)
end end
function ProtocolLogin:onError(msg, code)
local text = translateNetworkError(code, self:isConnecting(), msg)
signalcall(self.onLoginError, self, text)
end

View File

@@ -1,17 +1,17 @@
SpelllistSettings = { SpelllistSettings = {
['Default'] = { ['Default'] = {
iconFile = 'defaultspells', iconFile = '/images/game/spells/defaultspells',
iconSize = {width = 32, height = 32}, iconSize = {width = 32, height = 32},
spellListWidth = 210, spellListWidth = 210,
spellWindowWidth = 550, spellWindowWidth = 550,
spellOrder = {'Animate Dead', 'Annihilation', 'Avalanche', 'Berserk', 'Blood Rage', 'Brutal Strike', 'Cancel Invisibility', 'Challenge', 'Chameleon', 'Charge', 'Conjure Arrow', 'Conjure Bolt', 'Conjure Explosive Arrow', 'Conjure Piercing Bolt', 'Conjure Poisoned Arrow', 'Conjure Power Bolt', 'Conjure Sniper Arrow', 'Convince Creature', 'Creature Illusion', 'Cure Bleeding', 'Cure Burning', 'Cure Curse', 'Cure Electrification', 'Cure Poison', 'Cure Poison Rune', 'Curse', 'Death Strike', 'Desintegrate', 'Destroy Field', 'Divine Caldera', 'Divine Healing', 'Divine Missile', 'Electrify', 'Enchant Party', 'Enchant Spear', 'Enchant Staff', 'Energy Beam', 'Energy Field', 'Energy Strike', 'Energy Wall', 'Energy Wave', 'Energybomb', 'Envenom', 'Eternal Winter', 'Ethereal Spear', 'Explosion', 'Fierce Berserk', 'Find Person', 'Fire Field', 'Fire Wall', 'Fire Wave', 'Fireball', 'Firebomb', 'Flame Strike', 'Food', 'Front Sweep', 'Great Energy Beam', 'Great Fireball', 'Great Light', 'Groundshaker', 'Haste', 'Heal Friend', 'Heal Party', 'Heavy Magic Missile', 'Hells Core', 'Holy Flash', 'Holy Missile', 'Ice Strike', 'Ice Wave', 'Icicle', 'Ignite', 'Inflict Wound', 'Intense Healing', 'Intense Healing Rune', 'Intense Recovery', 'Intense Wound Cleansing', 'Invisibility', 'Levitate', 'Light', 'Light Healing', 'Light Magic Missile', 'Lightning', 'Magic Rope', 'Magic Shield', 'Magic Wall', 'Mass Healing', 'Paralyze', 'Physical Strike', 'Poison Bomb', 'Poison Field', 'Poison Wall', 'Protect Party', 'Protector', 'Rage of the Skies', 'Recovery', 'Salvation', 'Sharpshooter', 'Soulfire', 'Stalagmite', 'Stone Shower', 'Strong Energy Strike', 'Strong Ethereal Spear', 'Strong Flame Strike', 'Strong Haste', 'Strong Ice Strike', 'Strong Ice Wave', 'Strong Terra Strike', 'Sudden Death', 'Summon Creature', 'Swift Foot', 'Terra Strike', 'Terra Wave', 'Thunderstorm', 'Train Party', 'Ultimate Energy Strike', 'Ultimate Flame Strike', 'Ultimate Healing', 'Ultimate Healing Rune', 'Ultimate Ice Strike', 'Ultimate Light', 'Ultimate Terra Strike', 'Whirlwind Throw', 'Wild Growth', 'Wound Cleansing', 'Wrath of Nature'} spellOrder = {'Animate Dead', 'Annihilation', 'Avalanche', 'Berserk', 'Blood Rage', 'Brutal Strike', 'Cancel Invisibility', 'Challenge', 'Chameleon', 'Charge', 'Conjure Arrow', 'Conjure Bolt', 'Conjure Explosive Arrow', 'Conjure Piercing Bolt', 'Conjure Poisoned Arrow', 'Conjure Power Bolt', 'Conjure Sniper Arrow', 'Convince Creature', 'Creature Illusion', 'Cure Bleeding', 'Cure Burning', 'Cure Curse', 'Cure Electrification', 'Cure Poison', 'Cure Poison Rune', 'Curse', 'Death Strike', 'Desintegrate', 'Destroy Field', 'Divine Caldera', 'Divine Healing', 'Divine Missile', 'Electrify', 'Enchant Party', 'Enchant Spear', 'Enchant Staff', 'Energy Beam', 'Energy Field', 'Energy Strike', 'Energy Wall', 'Energy Wave', 'Energybomb', 'Envenom', 'Eternal Winter', 'Ethereal Spear', 'Explosion', 'Fierce Berserk', 'Find Person', 'Fire Field', 'Fire Wall', 'Fire Wave', 'Fireball', 'Firebomb', 'Flame Strike', 'Food', 'Front Sweep', 'Great Energy Beam', 'Great Fireball', 'Great Light', 'Groundshaker', 'Haste', 'Heal Friend', 'Heal Party', 'Heavy Magic Missile', 'Hells Core', 'Holy Flash', 'Holy Missile', 'Ice Strike', 'Ice Wave', 'Icicle', 'Ignite', 'Inflict Wound', 'Intense Healing', 'Intense Healing Rune', 'Intense Recovery', 'Intense Wound Cleansing', 'Invisibility', 'Levitate', 'Light', 'Light Healing', 'Light Magic Missile', 'Lightning', 'Magic Rope', 'Magic Shield', 'Magic Wall', 'Mass Healing', 'Paralyze', 'Physical Strike', 'Poison Bomb', 'Poison Field', 'Poison Wall', 'Protect Party', 'Protector', 'Rage of the Skies', 'Recovery', 'Salvation', 'Sharpshooter', 'Soulfire', 'Stalagmite', 'Stone Shower', 'Strong Energy Strike', 'Strong Ethereal Spear', 'Strong Flame Strike', 'Strong Haste', 'Strong Ice Strike', 'Strong Ice Wave', 'Strong Terra Strike', 'Sudden Death', 'Summon Creature', 'Swift Foot', 'Terra Strike', 'Terra Wave', 'Thunderstorm', 'Train Party', 'Ultimate Energy Strike', 'Ultimate Flame Strike', 'Ultimate Healing', 'Ultimate Healing Rune', 'Ultimate Ice Strike', 'Ultimate Light', 'Ultimate Terra Strike', 'Whirlwind Throw', 'Wild Growth', 'Wound Cleansing', 'Wrath of Nature'}
}, }--[[,
['Sample'] = { ['Sample'] = {
iconFile = 'sample', iconFile = '/images/game/spells/sample',
iconSize = {width = 64, height = 64}, iconSize = {width = 64, height = 64},
spellOrder = {'Critical Strike', 'Firefly', 'Fire Breath', 'Moonglaives', 'Wind Walk'} spellOrder = {'Critical Strike', 'Firefly', 'Fire Breath', 'Moonglaives', 'Wind Walk'}
} }]]
} }
SpellInfo = { SpellInfo = {
@@ -361,6 +361,27 @@ function Spells.getSpellByIcon(iconId)
return nil return nil
end end
function Spells.getSpellIconIds()
local ids = {}
for profile,data in pairs(SpellInfo) do
for k,spell in pairs(data) do
table.insert(ids, spell.id)
end
end
return ids
end
function Spells.getSpellProfileById(id)
for profile,data in pairs(SpellInfo) do
for k,spell in pairs(data) do
if spell.id == id then
return profile
end
end
end
return nil
end
function Spells.getSpellProfileByWords(words) function Spells.getSpellProfileByWords(words)
for profile,data in pairs(SpellInfo) do for profile,data in pairs(SpellInfo) do
for k,spell in pairs(data) do for k,spell in pairs(data) do

View File

@@ -1,43 +1,43 @@
function UIMinimap:onSetup() function UIMinimap:onSetup()
self.flagWindow = nil self.flagWindow = nil
self.flagsWidget = self:getChildById('flags')
self.floorUpWidget = self:getChildById('floorUp') self.floorUpWidget = self:getChildById('floorUp')
self.floorDownWidget = self:getChildById('floorDown') self.floorDownWidget = self:getChildById('floorDown')
self.zoomInWidget = self:getChildById('zoomIn') self.zoomInWidget = self:getChildById('zoomIn')
self.zoomOutWidget = self:getChildById('zoomOut') self.zoomOutWidget = self:getChildById('zoomOut')
self.dx = 0 self.flags = {}
self.dy = 0 self.alternatives = {}
self.autowalk = true self.autowalk = true
self.allowFollowLocalPlayer = true
self.onPositionChange = function() self:followLocalPlayer() end
self.onAddAutomapFlag = function(pos, icon, description) self:addFlag(pos, icon, description) end self.onAddAutomapFlag = function(pos, icon, description) self:addFlag(pos, icon, description) end
self.onRemoveAutomapFlag = function(pos, icon, description) self:removeFlag(pos, icon, description) end self.onRemoveAutomapFlag = function(pos, icon, description) self:removeFlag(pos, icon, description) end
connect(g_game, { connect(g_game, {
onAddAutomapFlag = self.onAddAutomapFlag, onAddAutomapFlag = self.onAddAutomapFlag,
onRemoveAutomapFlag = self.onRemoveAutomapFlag, onRemoveAutomapFlag = self.onRemoveAutomapFlag,
}) })
connect(LocalPlayer, { onPositionChange = self.onPositionChange })
end end
function UIMinimap:onDestroy() function UIMinimap:onDestroy()
disconnect(LocalPlayer, { onPositionChange = self.onPositionChange }) for _,widget in pairs(self.alternatives) do
widget:destroy()
end
self.alternatives = {}
disconnect(g_game, { disconnect(g_game, {
onAddAutomapFlag = self.onAddAutomapFlag, onAddAutomapFlag = self.onAddAutomapFlag,
onRemoveAutomapFlag = self.onRemoveAutomapFlag, onRemoveAutomapFlag = self.onRemoveAutomapFlag,
}) })
self:destroyFlagWindow() self:destroyFlagWindow()
self:destroyFullPanel() self.flags = {}
end end
function UIMinimap:onVisibilityChange() function UIMinimap:onVisibilityChange()
if not self:isVisible() then if not self:isVisible() then
self:destroyFlagWindow() self:destroyFlagWindow()
self:destroyFullPanel()
end end
end end
function UIMinimap:hideFlags() function UIMinimap:onCameraPositionChange(cameraPos)
self.flagsWidget:hide() if self.cross then
self:setCrossPosition(self.cross.pos)
end
end end
function UIMinimap:hideFloor() function UIMinimap:hideFloor()
@@ -54,33 +54,21 @@ function UIMinimap:disableAutoWalk()
self.autowalk = false self.autowalk = false
end end
function UIMinimap:disableFollowPlayer()
self.allowFollowLocalPlayer = false
end
function UIMinimap:enableFullPanel(image)
self.fullImage = image
end
function UIMinimap:load() function UIMinimap:load()
local settings = g_settings.getNode('Minimap') local settings = g_settings.getNode('Minimap')
if settings then if settings then
if settings.flags then if settings.flags then
for i=1,#settings.flags do for _,flag in pairs(settings.flags) do
local flag = settings.flags[i]
self:addFlag(flag.position, flag.icon, flag.description) self:addFlag(flag.position, flag.icon, flag.description)
end end
end end
self:setZoom(settings.zoom) self:setZoom(settings.zoom)
end end
self:updateFlags()
end end
function UIMinimap:save() function UIMinimap:save()
local settings = { flags={} } local settings = { flags={} }
local children = self.flagsWidget:getChildren() for _,flag in pairs(self.flags) do
for i=1,#children do
local flag = children[i]
table.insert(settings.flags, { table.insert(settings.flags, {
position = flag.pos, position = flag.pos,
icon = flag.icon, icon = flag.icon,
@@ -91,134 +79,116 @@ function UIMinimap:save()
g_settings.setNode('Minimap', settings) g_settings.setNode('Minimap', settings)
end end
function UIMinimap:addFlag(pos, icon, description) local function onFlagMouseRelease(widget, pos, button)
local flag = self:getFlag(pos, icon, description) if button == MouseRightButton then
if flag then local menu = g_ui.createWidget('PopupMenu')
return menu:addOption(tr('Delete mark'), function() widget:destroy() end)
menu:display(pos)
return true
end end
return false
flag = g_ui.createWidget('MinimapFlag', self.flagsWidget)
flag.pos = pos
flag.icon = icon
flag.description = description
flag:setIcon('/images/game/minimap/flag' .. icon)
flag:setTooltip(description)
flag.onMouseRelease = function(widget, pos, button)
if button == MouseRightButton then
local menu = g_ui.createWidget('PopupMenu')
menu:addOption(tr('Delete mark'), function() widget:destroy() end)
menu:display(pos)
return true
end
return false
end
self:updateFlag(flag)
end end
function UIMinimap:getFlag(pos, icon, description) function UIMinimap:setCrossPosition(pos)
local children = self.flagsWidget:getChildren() local cross = self.cross
for i=1,#children do if not self.cross then
local flag = children[i] cross = g_ui.createWidget('MinimapCross', self)
cross:setIcon('/images/game/minimap/cross')
self.cross = cross
end
pos.z = self:getCameraPosition().z
cross.pos = pos
if pos then
self:centerInPosition(cross, pos)
else
cross:breakAnchors()
end
end
function UIMinimap:addFlag(pos, icon, description)
if not pos or not icon then return end
local flag = self:getFlag(pos, icon, description)
if flag or not icon then
return
end
flag = g_ui.createWidget('MinimapFlag')
self:insertChild(1, flag)
flag.pos = pos
flag.description = description
flag.icon = icon
flag:setIcon('/images/game/minimap/flag' .. icon)
flag:setTooltip(description)
flag.onMouseRelease = onFlagMouseRelease
flag.onDestroy = function() table.removevalue(self.flags, flag) end
table.insert(self.flags, flag)
self:centerInPosition(flag, pos)
end
function UIMinimap:addAlternativeWidget(widget, pos, maxZoom)
widget.pos = pos
widget.maxZoom = maxZoom or 0
widget.minZoom = minZoom
table.insert(self.alternatives, widget)
end
function UIMinimap:setAlternativeWidgetsVisible(show)
local layout = self:getLayout()
layout:disableUpdates()
for _,widget in pairs(self.alternatives) do
if show then
self:insertChild(1, widget)
self:centerInPosition(widget, widget.pos)
else
self:removeChild(widget)
end
end
layout:enableUpdates()
layout:update()
end
function UIMinimap:onZoomChange(zoom)
for _,widget in pairs(self.alternatives) do
if (not widget.minZoom or widget.minZoom >= zoom) and widget.maxZoom <= zoom then
widget:show()
else
widget:hide()
end
end
end
function UIMinimap:getFlag(pos)
for _,flag in pairs(self.flags) do
if flag.pos.x == pos.x and flag.pos.y == pos.y and flag.pos.z == pos.z then if flag.pos.x == pos.x and flag.pos.y == pos.y and flag.pos.z == pos.z then
return flag return flag
end end
end end
return nil
end end
function UIMinimap:removeFlag(pos, icon, description) function UIMinimap:removeFlag(pos, icon, description)
local flag = self:getFlag(pos, icon, description) local flag = self:getFlag(pos)
if flag then if flag then
flag:destroy() flag:destroy()
end end
end end
function UIMinimap:updateFlag(flag)
local point = self:getPoint(flag.pos)
if self:containsPoint(point) and self:getZoom() >= 0 and flag.pos.z == self:getCameraPosition().z then
flag:setVisible(true)
flag:setMarginLeft(point.x - self:getX() - flag:getWidth()/2)
flag:setMarginTop(point.y - self:getY() - flag:getHeight()/2)
else
flag:setVisible(false)
end
end
function UIMinimap:updateFlags()
local children = self.flagsWidget:getChildren()
for i=1,#children do
self:updateFlag(children[i])
end
end
UIMinimap.realSetCameraPosition = UIMinimap.realSetCameraPosition or UIMinimap.setCameraPosition
function UIMinimap:setCameraPosition(pos)
self:realSetCameraPosition(pos)
self:updateFlags()
end
UIMinimap.realZoomIn = UIMinimap.realZoomIn or UIMinimap.zoomIn
function UIMinimap:zoomIn()
self:realZoomIn()
self:updateFlags()
end
UIMinimap.realZoomOut = UIMinimap.realZoomOut or UIMinimap.zoomOut
function UIMinimap:zoomOut()
self:realZoomOut()
self:updateFlags()
end
UIMinimap.realSetZoom = UIMinimap.realSetZoom or UIMinimap.setZoom
function UIMinimap:setZoom(zoom)
self:realSetZoom(zoom)
self:updateFlags()
end
function UIMinimap:floorUp(floors)
local pos = self:getCameraPosition()
pos.z = pos.z - floors
if pos.z >= FloorHigher then
self:setCameraPosition(pos)
end
self:updateFlags()
end
function UIMinimap:floorDown(floors)
local pos = self:getCameraPosition()
pos.z = pos.z + floors
if pos.z <= FloorLower then
self:setCameraPosition(pos)
end
self:updateFlags()
end
function UIMinimap:followLocalPlayer()
if not self:isDragging() and self.allowFollowLocalPlayer then
local player = g_game.getLocalPlayer()
self:followCreature(player)
self:updateFlags()
end
end
function UIMinimap:reset() function UIMinimap:reset()
self:followLocalPlayer()
self:setZoom(0) self:setZoom(0)
if self.cross then
self:setCameraPosition(self.cross.pos)
end
end end
function UIMinimap:move(x, y) function UIMinimap:move(x, y)
local topLeft, bottomRight = self:getArea()
self.dx = self.dx + ((bottomRight.x - topLeft.x) / self:getWidth() ) * x
self.dy = self.dy + ((bottomRight.y - topLeft.y) / self:getHeight()) * y
local dx = math.floor(self.dx)
local dy = math.floor(self.dy)
self.dx = self.dx - dx
self.dy = self.dy - dy
local cameraPos = self:getCameraPosition() local cameraPos = self:getCameraPosition()
local scale = self:getScale()
if scale > 1 then scale = 1 end
local dx = x/scale
local dy = y/scale
local pos = {x = cameraPos.x - dx, y = cameraPos.y - dy, z = cameraPos.z} local pos = {x = cameraPos.x - dx, y = cameraPos.y - dy, z = cameraPos.z}
self:setCameraPosition(pos) self:setCameraPosition(pos)
self:updateFlags()
end end
function UIMinimap:onMouseWheel(mousePos, direction) function UIMinimap:onMouseWheel(mousePos, direction)
@@ -232,7 +202,6 @@ function UIMinimap:onMouseWheel(mousePos, direction)
elseif direction == MouseWheelUp and keyboardModifiers == KeyboardCtrlModifier then elseif direction == MouseWheelUp and keyboardModifiers == KeyboardCtrlModifier then
self:floorDown(1) self:floorDown(1)
end end
self:updateFlags()
end end
function UIMinimap:onMousePress(pos, button) function UIMinimap:onMousePress(pos, button)
@@ -245,20 +214,18 @@ function UIMinimap:onMouseRelease(pos, button)
if not self.allowNextRelease then return true end if not self.allowNextRelease then return true end
self.allowNextRelease = false self.allowNextRelease = false
local mapPos = self:getPosition(pos) local mapPos = self:getTilePosition(pos)
if not mapPos then return end if not mapPos then return end
if button == MouseLeftButton then if button == MouseLeftButton then
local player = g_game.getLocalPlayer() local player = g_game.getLocalPlayer()
if self.autowalk then if self.autowalk then
player.onAutoWalkFail = function() modules.game_textmessage.displayFailureMessage(tr('There is no way.')) end
player:autoWalk(mapPos) player:autoWalk(mapPos)
end end
return true return true
elseif button == MouseRightButton then elseif button == MouseRightButton then
local menu = g_ui.createWidget('PopupMenu') local menu = g_ui.createWidget('PopupMenu')
menu:addOption(tr('Create mark'), function() self:createFlagWindow(mapPos) end) menu:addOption(tr('Create mark'), function() self:createFlagWindow(mapPos) end)
if self.fullImage then menu:addOption(tr('Full map'), function() self:createFullPanel() end) end
menu:display(pos) menu:display(pos)
return true return true
end end
@@ -266,11 +233,17 @@ function UIMinimap:onMouseRelease(pos, button)
end end
function UIMinimap:onDragEnter(pos) function UIMinimap:onDragEnter(pos)
self.dragReference = pos
self.dragCameraReference = self:getCameraPosition()
return true return true
end end
function UIMinimap:onDragMove(pos, moved) function UIMinimap:onDragMove(pos, moved)
self:move(moved.x, moved.y) local scale = self:getScale()
local dx = (self.dragReference.x - pos.x)/scale
local dy = (self.dragReference.y - pos.y)/scale
local pos = {x = self.dragCameraReference.x + dx, y = self.dragCameraReference.y + dy, z = self.dragCameraReference.z}
self:setCameraPosition(pos)
return true return true
end end
@@ -278,20 +251,6 @@ function UIMinimap:onDragLeave(widget, pos)
return true return true
end end
function UIMinimap:createFullPanel()
self.fullPanel = g_ui.createWidget('MinimapFullPanel', rootWidget)
self.fullPanel.onDestroy = function() self.fullPanel = nil end
local image = self.fullPanel:getChildById('image')
image:setImage(self.fullImage)
end
function UIMinimap:destroyFullPanel()
if self.fullPanel then
self.fullPanel:destroy()
self.fullPanel = nil
end
end
function UIMinimap:createFlagWindow(pos) function UIMinimap:createFlagWindow(pos)
if self.flagWindow then return end if self.flagWindow then return end
if not pos then return end if not pos then return end
@@ -311,16 +270,14 @@ function UIMinimap:createFlagWindow(pos)
checkbox.icon = i checkbox.icon = i
flagRadioGroup:addWidget(checkbox) flagRadioGroup:addWidget(checkbox)
end end
flagRadioGroup:selectWidget(flagRadioGroup:getFirstWidget()) flagRadioGroup:selectWidget(flagRadioGroup:getFirstWidget())
okButton.onClick = function() okButton.onClick = function()
self:addFlag(pos, flagRadioGroup:getSelectedWidget().icon, description:getText()) self:addFlag(pos, flagRadioGroup:getSelectedWidget().icon, description:getText())
self:destroyFlagWindow() self:destroyFlagWindow()
end end
cancelButton.onClick = function() cancelButton.onClick = function() self:destroyFlagWindow() end
self:destroyFlagWindow()
end
self.flagWindow.onDestroy = function() flagRadioGroup:destroy() end self.flagWindow.onDestroy = function() flagRadioGroup:destroy() end
end end
@@ -331,9 +288,3 @@ function UIMinimap:destroyFlagWindow()
self.flagWindow = nil self.flagWindow = nil
end end
end end
function UIMinimap:getArea()
local topLeft = self:getPosition({ x = self:getX() + 1, y = self:getY() + 1 })
local bottomRight = self:getPosition({ x = self:getX() + self:getWidth() - 2, y = self:getY() + self:getHeight() - 2 })
return topLeft, bottomRight
end

View File

@@ -2,4 +2,3 @@
-- you can place any custom user code here -- you can place any custom user code here
print 'Startup done :]' print 'Startup done :]'

View File

@@ -98,6 +98,8 @@ set(client_SOURCES ${client_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/uiminimap.h ${CMAKE_CURRENT_LIST_DIR}/uiminimap.h
${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.cpp ${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.cpp
${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.h ${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.h
${CMAKE_CURRENT_LIST_DIR}/uimapanchorlayout.cpp
${CMAKE_CURRENT_LIST_DIR}/uimapanchorlayout.h
# util # util
${CMAKE_CURRENT_LIST_DIR}/position.h ${CMAKE_CURRENT_LIST_DIR}/position.h

View File

@@ -352,6 +352,7 @@ namespace Otc
GameNewSpeedLaw = 36, GameNewSpeedLaw = 36,
GameForceFirstAutoWalkStep = 37, GameForceFirstAutoWalkStep = 37,
GameMinimapRemove = 38, GameMinimapRemove = 38,
GameDoubleShopSellAmount = 39,
// 51-100 reserved to be defined in lua // 51-100 reserved to be defined in lua
LastGameFeature = 101 LastGameFeature = 101
}; };

View File

@@ -36,7 +36,7 @@
#include <framework/core/clock.h> #include <framework/core/clock.h>
#include <framework/graphics/paintershaderprogram.h> #include <framework/graphics/paintershaderprogram.h>
#include <framework/graphics/painterogl2_shadersources.h> #include <framework/graphics/ogl/painterogl2_shadersources.h>
#include <framework/graphics/texturemanager.h> #include <framework/graphics/texturemanager.h>
#include <framework/graphics/framebuffermanager.h> #include <framework/graphics/framebuffermanager.h>
#include "spritemanager.h" #include "spritemanager.h"
@@ -334,10 +334,6 @@ void Creature::stopWalk()
if(!m_walking) if(!m_walking)
return; return;
// reset walk animation states
m_walkOffset = Point(0,0);
m_walkAnimationPhase = 0;
// stops the walk right away // stops the walk right away
terminateWalk(); terminateWalk();
} }
@@ -588,6 +584,10 @@ void Creature::terminateWalk()
m_walking = false; m_walking = false;
m_walkedPixels = 0; m_walkedPixels = 0;
// reset walk animation states
m_walkOffset = Point(0,0);
m_walkAnimationPhase = 0;
} }
void Creature::setName(const std::string& name) void Creature::setName(const std::string& name)
@@ -782,7 +782,7 @@ Point Creature::getDrawOffset()
return drawOffset; return drawOffset;
} }
int Creature::getStepDuration(bool ignoreDiagonal) int Creature::getStepDuration(bool ignoreDiagonal, Otc::Direction dir)
{ {
int speed = m_speed; int speed = m_speed;
if(speed < 1) if(speed < 1)
@@ -792,7 +792,13 @@ int Creature::getStepDuration(bool ignoreDiagonal)
speed *= 2; speed *= 2;
int groundSpeed = 0; int groundSpeed = 0;
Position tilePos = m_lastStepToPosition; Position tilePos;
if(dir == Otc::InvalidDirection)
tilePos = m_lastStepToPosition;
else
tilePos = m_position.translatedToDirection(dir);
if(!tilePos.isValid()) if(!tilePos.isValid())
tilePos = m_position; tilePos = m_position;
const TilePtr& tile = g_map.getTile(tilePos); const TilePtr& tile = g_map.getTile(tilePos);

View File

@@ -85,7 +85,7 @@ public:
uint8 getEmblem() { return m_emblem; } uint8 getEmblem() { return m_emblem; }
bool isPassable() { return m_passable; } bool isPassable() { return m_passable; }
Point getDrawOffset(); Point getDrawOffset();
int getStepDuration(bool ignoreDiagonal = false); int getStepDuration(bool ignoreDiagonal = false, Otc::Direction dir = Otc::InvalidDirection);
Point getWalkOffset() { return m_walkOffset; } Point getWalkOffset() { return m_walkOffset; }
Position getLastStepFromPosition() { return m_lastStepFromPosition; } Position getLastStepFromPosition() { return m_lastStepFromPosition; }
Position getLastStepToPosition() { return m_lastStepToPosition; } Position getLastStepToPosition() { return m_lastStepToPosition; }

View File

@@ -26,7 +26,6 @@
#include <framework/xml/tinyxml.h> #include <framework/xml/tinyxml.h>
#include <framework/core/resourcemanager.h> #include <framework/core/resourcemanager.h>
#include <boost/filesystem.hpp>
CreatureManager g_creatures; CreatureManager g_creatures;
@@ -50,7 +49,11 @@ void CreatureManager::terminate()
void Spawn::load(TiXmlElement* node) void Spawn::load(TiXmlElement* node)
{ {
Position centerPos = node->readPos("center"); Position centerPos;
centerPos.x = node->readType<uint16>("centerx");
centerPos.y = node->readType<uint16>("centery");
centerPos.z = node->readType<uint8>("centerz");
setCenterPos(centerPos); setCenterPos(centerPos);
setRadius(node->readType<int32>("radius")); setRadius(node->readType<int32>("radius"));
@@ -196,6 +199,8 @@ void CreatureManager::loadNpcs(const std::string& folder)
if(!stdext::ends_with(tmp, "/")) if(!stdext::ends_with(tmp, "/"))
tmp += "/"; tmp += "/";
// FIXME: filesystem is not supported anymore, rework the following code with g_resources
/*
boost::filesystem::path npcPath(boost::filesystem::current_path().generic_string() + tmp); boost::filesystem::path npcPath(boost::filesystem::current_path().generic_string() + tmp);
if(!boost::filesystem::exists(npcPath)) if(!boost::filesystem::exists(npcPath))
stdext::throw_exception(stdext::format("NPCs folder '%s' was not found.", folder)); stdext::throw_exception(stdext::format("NPCs folder '%s' was not found.", folder));
@@ -207,6 +212,7 @@ void CreatureManager::loadNpcs(const std::string& folder)
loadCreatureBuffer(g_resources.readFileContents(tmp + f)); loadCreatureBuffer(g_resources.readFileContents(tmp + f));
} }
*/
} }
void CreatureManager::loadSpawns(const std::string& fileName) void CreatureManager::loadSpawns(const std::string& fileName)

View File

@@ -94,11 +94,15 @@ class UICreature;
class UIMap; class UIMap;
class UIMinimap; class UIMinimap;
class UIProgressRect; class UIProgressRect;
class UIMapAnchorLayout;
class UIPositionAnchor;
typedef stdext::shared_object_ptr<UIItem> UIItemPtr; typedef stdext::shared_object_ptr<UIItem> UIItemPtr;
typedef stdext::shared_object_ptr<UICreature> UICreaturePtr; typedef stdext::shared_object_ptr<UICreature> UICreaturePtr;
typedef stdext::shared_object_ptr<UIMap> UIMapPtr; typedef stdext::shared_object_ptr<UIMap> UIMapPtr;
typedef stdext::shared_object_ptr<UIMinimap> UIMinimapPtr; typedef stdext::shared_object_ptr<UIMinimap> UIMinimapPtr;
typedef stdext::shared_object_ptr<UIProgressRect> UIProgressRectPtr; typedef stdext::shared_object_ptr<UIProgressRect> UIProgressRectPtr;
typedef stdext::shared_object_ptr<UIMapAnchorLayout> UIMapAnchorLayoutPtr;
typedef stdext::shared_object_ptr<UIPositionAnchor> UIPositionAnchorPtr;
#endif #endif

View File

@@ -47,6 +47,7 @@ Game::Game()
m_serverBeat = 50; m_serverBeat = 50;
m_seq = 0; m_seq = 0;
m_ping = -1; m_ping = -1;
m_pingDelay = 1000;
m_canReportBugs = false; m_canReportBugs = false;
m_fightMode = Otc::FightBalanced; m_fightMode = Otc::FightBalanced;
m_chaseMode = Otc::DontChase; m_chaseMode = Otc::DontChase;
@@ -79,6 +80,8 @@ void Game::resetGameStates()
m_followingCreature = nullptr; m_followingCreature = nullptr;
m_attackingCreature = nullptr; m_attackingCreature = nullptr;
m_localPlayer = nullptr; m_localPlayer = nullptr;
m_pingSent = 0;
m_pingReceived = 0;
for(auto& it : m_containers) { for(auto& it : m_containers) {
const ContainerPtr& container = it.second; const ContainerPtr& container = it.second;
@@ -176,14 +179,9 @@ void Game::processGameStart()
disableBotCall(); disableBotCall();
if(g_game.getFeature(Otc::GameClientPing) || g_game.getFeature(Otc::GameExtendedClientPing)) { if(g_game.getFeature(Otc::GameClientPing) || g_game.getFeature(Otc::GameExtendedClientPing)) {
m_protocolGame->sendPing(); m_pingEvent = g_dispatcher.scheduleEvent([this] {
m_pingEvent = g_dispatcher.cycleEvent([this] { g_game.ping();
if(m_protocolGame && m_protocolGame->isConnected()) { }, m_pingDelay);
enableBotCall();
m_protocolGame->sendPing();
disableBotCall();
}
}, 2000);
} }
} }
@@ -224,10 +222,20 @@ void Game::processPing()
disableBotCall(); disableBotCall();
} }
void Game::processPingBack(int elapsed) void Game::processPingBack()
{ {
m_ping = elapsed; m_pingReceived++;
g_lua.callGlobalField("g_game", "onPingBack", elapsed);
if(m_pingReceived == m_pingSent)
m_ping = m_pingTimer.elapsed_millis();
else
g_logger.error("got an invalid ping from server");
g_lua.callGlobalField("g_game", "onPingBack", m_ping);
m_pingEvent = g_dispatcher.scheduleEvent([this] {
g_game.ping();
}, m_pingDelay);
} }
void Game::processTextMessage(Otc::MessageMode mode, const std::string& text) void Game::processTextMessage(Otc::MessageMode mode, const std::string& text)
@@ -605,6 +613,70 @@ bool Game::walk(Otc::Direction direction)
return true; return true;
} }
bool Game::dashWalk(Otc::Direction direction)
{
if(!canPerformGameAction())
return false;
// must cancel follow before any new walk
if(isFollowing())
cancelFollow();
// must cancel auto walking
if(m_localPlayer->isAutoWalking()) {
m_protocolGame->sendStop();
m_localPlayer->stopAutoWalk();
}
if(m_localPlayer->isWalking() && m_dashTimer.ticksElapsed() < std::max<int>(m_localPlayer->getStepDuration(false, direction) - m_ping, 30))
return false;
Position toPos = m_localPlayer->getPosition().translatedToDirection(direction);
TilePtr toTile = g_map.getTile(toPos);
// only do prewalks to walkable tiles (like grounds and not walls)
if(toTile && toTile->isWalkable()) {
if(!m_localPlayer->isWalking() && m_localPlayer->getWalkTicksElapsed() >= m_localPlayer->getStepDuration() + 100)
m_localPlayer->preWalk(direction);
// check walk to another floor (e.g: when above 3 parcels)
} else {
// check if can walk to a lower floor
auto canChangeFloorDown = [&]() -> bool {
Position pos = toPos;
if(!pos.down())
return false;
TilePtr toTile = g_map.getTile(pos);
if(toTile && toTile->hasElevation(3))
return true;
return false;
};
// check if can walk to a higher floor
auto canChangeFloorUp = [&]() -> bool {
TilePtr fromTile = m_localPlayer->getTile();
if(!fromTile || !fromTile->hasElevation(3))
return false;
Position pos = toPos;
if(!pos.up())
return false;
TilePtr toTile = g_map.getTile(pos);
if(!toTile || !toTile->isWalkable())
return false;
return true;
};
if(canChangeFloorDown() || canChangeFloorUp() ||
(!toTile || toTile->isEmpty())) {
m_localPlayer->lockWalk();
} else
return false;
}
forceWalk(direction);
m_dashTimer.restart();
m_lastWalkDir = direction;
return true;
}
void Game::autoWalk(std::vector<Otc::Direction> dirs) void Game::autoWalk(std::vector<Otc::Direction> dirs)
{ {
if(!canPerformGameAction()) if(!canPerformGameAction())
@@ -1057,6 +1129,11 @@ void Game::removeVip(int playerId)
{ {
if(!canPerformGameAction()) if(!canPerformGameAction())
return; return;
auto it = m_vips.find(playerId);
if(it == m_vips.end())
return;
m_vips.erase(it);
m_protocolGame->sendRemoveVip(playerId); m_protocolGame->sendRemoveVip(playerId);
} }
@@ -1252,9 +1329,14 @@ void Game::ping()
if(!m_protocolGame || !m_protocolGame->isConnected()) if(!m_protocolGame || !m_protocolGame->isConnected())
return; return;
if(m_pingReceived != m_pingSent)
return;
m_denyBotCall = false; m_denyBotCall = false;
m_protocolGame->sendPing(); m_protocolGame->sendPing();
m_denyBotCall = true; m_denyBotCall = true;
m_pingSent++;
m_pingTimer.restart();
} }
void Game::changeMapAwareRange(int xrange, int yrange) void Game::changeMapAwareRange(int xrange, int yrange)
@@ -1297,20 +1379,23 @@ void Game::setProtocolVersion(int version)
if(isOnline()) if(isOnline())
stdext::throw_exception("Unable to change protocol version while online"); stdext::throw_exception("Unable to change protocol version while online");
if(version != 0 && (version < 810 || version > 973)) if(version != 0 && (version < 810 || version > 974))
stdext::throw_exception(stdext::format("Protocol version %d not supported", version)); stdext::throw_exception(stdext::format("Protocol version %d not supported", version));
m_features.reset(); m_features.reset();
enableFeature(Otc::GameFormatCreatureName); enableFeature(Otc::GameFormatCreatureName);
if(version >= 840) {
enableFeature(Otc::GameProtocolChecksum);
enableFeature(Otc::GameChallengeOnLogin);
enableFeature(Otc::GameAccountNames);
}
if(version <= 854) { if(version <= 854) {
enableFeature(Otc::GameChargeableItems); enableFeature(Otc::GameChargeableItems);
} }
if(version >= 854) { if(version >= 854) {
enableFeature(Otc::GameProtocolChecksum);
enableFeature(Otc::GameAccountNames);
enableFeature(Otc::GameChallengeOnLogin);
enableFeature(Otc::GameDoubleFreeCapacity); enableFeature(Otc::GameDoubleFreeCapacity);
enableFeature(Otc::GameCreatureEmblems); enableFeature(Otc::GameCreatureEmblems);
} }
@@ -1373,7 +1458,7 @@ void Game::setClientVersion(int version)
if(isOnline()) if(isOnline())
stdext::throw_exception("Unable to change client version while online"); stdext::throw_exception("Unable to change client version while online");
if(version != 0 && (version < 810 || version > 981)) if(version != 0 && (version < 810 || version > 982))
stdext::throw_exception(stdext::format("Client version %d not supported", version)); stdext::throw_exception(stdext::format("Client version %d not supported", version));
m_clientVersion = version; m_clientVersion = version;

View File

@@ -54,7 +54,7 @@ protected:
void processConnectionError(const boost::system::error_code& error); void processConnectionError(const boost::system::error_code& error);
void processDisconnect(); void processDisconnect();
void processPing(); void processPing();
void processPingBack(int elapsed); void processPingBack();
void processUpdateNeeded(const std::string& signature); void processUpdateNeeded(const std::string& signature);
void processLoginError(const std::string& error); void processLoginError(const std::string& error);
@@ -143,6 +143,7 @@ public:
// walk related // walk related
bool walk(Otc::Direction direction); bool walk(Otc::Direction direction);
bool dashWalk(Otc::Direction direction);
void autoWalk(std::vector<Otc::Direction> dirs); void autoWalk(std::vector<Otc::Direction> dirs);
void forceWalk(Otc::Direction direction); void forceWalk(Otc::Direction direction);
void turn(Otc::Direction direction); void turn(Otc::Direction direction);
@@ -252,6 +253,7 @@ public:
//void reportRuleViolation2(); //void reportRuleViolation2();
void ping(); void ping();
void setPingDelay(int delay) { m_pingDelay = delay; }
// otclient only // otclient only
void changeMapAwareRange(int xrange, int yrange); void changeMapAwareRange(int xrange, int yrange);
@@ -280,7 +282,7 @@ public:
bool isAttacking() { return !!m_attackingCreature; } bool isAttacking() { return !!m_attackingCreature; }
bool isFollowing() { return !!m_followingCreature; } bool isFollowing() { return !!m_followingCreature; }
int getPing() { return m_ping; } int getPing() { return m_ping >= 0 ? std::max(m_ping, m_pingTimer.elapsed_millis()) : -1; }
ContainerPtr getContainer(int index) { return m_containers[index]; } ContainerPtr getContainer(int index) { return m_containers[index]; }
std::map<int, ContainerPtr> getContainers() { return m_containers; } std::map<int, ContainerPtr> getContainers() { return m_containers; }
std::map<int, Vip> getVips() { return m_vips; } std::map<int, Vip> getVips() { return m_vips; }
@@ -320,8 +322,13 @@ private:
bool m_denyBotCall; bool m_denyBotCall;
bool m_dead; bool m_dead;
int m_serverBeat; int m_serverBeat;
int m_ping; ticks_t m_ping;
uint m_pingSent;
uint m_pingReceived;
stdext::timer m_pingTimer;
Timer m_dashTimer;
uint m_seq; uint m_seq;
int m_pingDelay;
Otc::FightModes m_fightMode; Otc::FightModes m_fightMode;
Otc::ChaseModes m_chaseMode; Otc::ChaseModes m_chaseMode;
Otc::Direction m_lastWalkDir; Otc::Direction m_lastWalkDir;

View File

@@ -65,7 +65,12 @@ void House::load(const TiXmlElement *elem)
setSize(elem->readType<uint32>("size")); setSize(elem->readType<uint32>("size"));
setTownId(elem->readType<uint32>("townid")); setTownId(elem->readType<uint32>("townid"));
m_isGuildHall = elem->readType<bool>("guildhall"); m_isGuildHall = elem->readType<bool>("guildhall");
setEntry(elem->readPos("entry"));
Position entryPos;
entryPos.x = elem->readType<uint16>("entryx");
entryPos.y = elem->readType<uint16>("entryy");
entryPos.z = elem->readType<uint8>("entryz");
setEntry(entryPos);
} }
void House::save(TiXmlElement*& elem) void House::save(TiXmlElement*& elem)

View File

@@ -179,7 +179,7 @@ void Item::serializeItem(const OutputBinaryTreePtr& out)
Position dest = m_attribs.get<Position>(ATTR_TELE_DEST); Position dest = m_attribs.get<Position>(ATTR_TELE_DEST);
if(dest.isValid()) { if(dest.isValid()) {
out->addU8(ATTR_TELE_DEST); out->addU8(ATTR_TELE_DEST);
out->addPos(dest); out->addPos(dest.x, dest.y, dest.z);
} }
if(isDepot()) { if(isDepot()) {
@@ -210,7 +210,7 @@ int Item::getSubType()
{ {
if(isSplash() || isFluidContainer()) if(isSplash() || isFluidContainer())
return m_countOrSubType; return m_countOrSubType;
if(g_game.getProtocolVersion() >= 860) if(g_game.getProtocolVersion() > 862)
return 0; return 0;
return 1; return 1;
} }

Some files were not shown because too many files have changed in this diff Show More