218 Commits

Author SHA1 Message Date
Eduardo Bart
28786a3570 Update make_snapshop.sh 2013-11-13 14:33:29 -02:00
Eduardo Bart
b07a77f705 Changes to compile for Win64 2013-11-13 13:55:34 -02:00
Eduardo Bart
0d44942e8e Version 0.6.4 2013-11-13 13:07:37 -02:00
Eduardo Bart
dd829395e3 Merge pull request #376 from dalkon/master
Item phases & Fix party "bug" & Additions
2013-11-12 15:56:54 -08:00
dalkon
18fa54181a Format fix 2013-11-13 00:50:46 +01:00
dalkon
5b8ff29fa3 Fix party "bug" & Additions 2013-11-13 00:48:41 +01:00
dalkon
59e90e8f1e Item phases 2013-11-13 00:18:15 +01:00
Sam
5db37857bf Fix game zoom issue 2013-11-12 23:35:19 +01:00
Eduardo Bart
fc0297d6db Fix compile errors in ubuntu 2013-11-12 20:07:46 -02:00
Eduardo Bart
1060c6f78c Compilation for MSVC2013, thanks @dalkon
OTclient now compiles in "Microsoft Visual Studio 2013 Express for Windows Desktop"
All the needed libraries you can download at https://www.dropbox.com/s/2yfb1c763io8efy/otclient-msvc13-libs.zip
NOTE: You have to change VC++ Directories to the properly directories
NOTE: Latested MSVC 2013 or greated is required
2013-11-12 16:32:39 -02:00
dalkon
c9597d6682 Visual Studio 2013 Compatibility 2013-11-12 16:32:39 -02:00
dalkon
d3e97d33c7 Update .gitignore 2013-11-12 16:32:39 -02:00
Ahmed Samy
2b015d49d7 don't set bits twice 2013-11-12 20:06:59 +02:00
Ahmed Samy
f04b4a0b42 small fix 2013-11-12 20:02:24 +02:00
Ahmed Samy
ff5c22d4c0 Tiny fix
Saving newly made houses by the map editor is not even supported, so this
is not a bug
2013-11-12 17:15:09 +02:00
Sam
d6105a98d1 Fixed issue with deathwindow 2013-11-12 15:21:10 +01:00
Eduardo Bart
0938e22eb9 Fixes in stdext::format 2013-11-11 23:07:25 -02:00
Eduardo Bart
1868b235cb Implement creature marks 2013-11-11 01:45:18 -02:00
Eduardo Bart
9a30050340 Fix typo 2013-11-10 23:40:29 -02:00
Eduardo Bart
9d689f0c43 Add missing changes for protocol > 1000 2013-11-10 23:31:59 -02:00
Eduardo Bart
2b34c0ea0a Fix #337
The sound buffer was not being fully preloaded because it's size was incorrect
2013-11-10 20:35:00 -02:00
Eduardo Bart
d32f71c2b9 Partial support for protocol 1020 and minimize lag
I am able to login in global Tibia however there are game protocol errors
* there is a new opcode 167, which I dont know what it is
* there are changes in opcode 147 which handles text messages that I don't know too

Connection writing was optimized, playing "lag" should improve by 10ms,
and improve much more in systems with low fps
2013-11-10 20:10:04 -02:00
Eduardo Bart
3cff331723 Merge github.com:BrunoDCC/otclient 2013-11-10 19:36:06 -02:00
Eduardo Bart
9894f0c0b9 Merge github.com:conde2/otclient 2013-11-10 19:31:24 -02:00
conde2
e60372fdea A little fix! 2013-11-10 03:17:49 -02:00
conde2
d2473fd424 Login support for 10.21 ~ 10.22
Please someone test more it !
Not tested in real Tibia !
2013-11-10 03:13:51 -02:00
BrunoDCC
7d7bd00a63 minor fix :3 2013-11-09 22:48:29 -02:00
BrunoDCC
c81a623c43 Fixes for creatures name
fixes on save houses (Now open most generate some error)
First 10.22 commit (open dat to edit)
Add server id for new versions
2013-11-09 20:04:48 -02:00
Eduardo Bart
8b165b95fd non relevant change 2013-11-05 21:32:27 -02:00
Sam
6f9436dd60 UISprite widget added
Display single sprites
2013-10-30 21:35:29 +01:00
Henrique Santiago
ae95f51346 Merge pull request #367 from shdpl/patch-1
Polish locale update
2013-10-26 09:46:15 -07:00
shdpl
9b84570372 Polish locale update
UTF-8 or UTF-16 pls
2013-10-25 19:27:19 +02:00
Eduardo Bart
38dec168ee Fix boost::asio misuse that would cause lag
io_service::reset was not called before io_service::poll, meaning that new events would be really polled in the next Connection::poll call, this could lead to network lag in computers with low framerate (ie: a user with 10 fps would have 100ms lag just because of that)
2013-10-22 21:42:35 -02:00
Henrique Santiago
84b722f8c7 Merge pull request #365 from conde2/master
Fix - Writeable / Readable items Issues: #362 and #364
2013-10-21 17:29:13 -07:00
Joao Pasqualini Costa
b3717ceb93 Fix - Writeable / Readable items 2013-10-21 22:25:12 -02:00
Henrique Santiago
3340e06da6 Merge pull request #363 from conde2/master
Fix protocol error #362
2013-10-20 17:24:19 -07:00
Joao Pasqualini Costa
084ee45650 A little mistake 2013-10-20 20:33:44 -02:00
Joao Pasqualini Costa
7290ec3334 Some work on container pagination
Bind lua functions for containers
Update onAddItem now it have the pagination slot
Note: getSize as i see is equal to getItemsCount, but not sure thats why
I've added !
2013-10-20 20:21:20 -02:00
Joao Pasqualini Costa
971d90a596 Fix protocol error #362
TODO:
Handle the helpers in LUA, it could be added into Battle Window i think,
if someone know where should this be comment here !
2013-10-20 18:31:20 -02:00
Sam
8230bf2af4 Merge branch 'master' of https://github.com/edubart/otclient 2013-10-20 17:15:30 +02:00
Sam
241b54262a Updated lua consts 2013-10-20 17:15:24 +02:00
Ahmed Samy
63ce68b449 mapio: make sure we read the house tile flag 2013-10-12 11:38:30 +02:00
Ahmed Samy
f47ea05abc Merge https://github.com/BrunoDCC/otclient
# By BrunoDCC
# Via BrunoDCC
* https://github.com/BrunoDCC/otclient:
  Save houses and spawns fix
2013-10-11 11:38:03 +02:00
BrunoDCC
de3160c90d Save houses and spawns fix 2013-10-11 02:35:31 -03:00
Sam
67bd00556d Re-added "Don't stretch/shrink" option
Closes #345
2013-10-09 18:17:50 +02:00
Sam
778559c7b9 Protocol 10.10 fixed containers 2013-10-09 17:58:58 +02:00
Sam
3aac0ac0ec Reverting mapio.cpp change
Should not have been commited.
2013-10-07 21:38:55 +02:00
Sam
4adfafc67e Fix for Client 8.5 2013-10-07 21:32:13 +02:00
Sam
1b27a095a9 Hotkeys for Fluid Containers
Hotkeys now save subType for fluid containers instead of always trying
to use item with subType 0.
2013-10-05 18:08:49 +02:00
Sam
e6977b1b43 Improvement / Fix hotkeys
- Hotkeys now check items in inventory
- Fixed USEONETARGET hotkey bug
2013-10-05 02:31:44 +02:00
Sam
5843b78e87 Support for client version 7.6
Tell me if there are parts which I should change.

- Not everything is tested yet, feel free to report bugs in 7.6
- the data send in between login opcode and account data might not be
correct, but I could not find any documents showing the right protocol
yet
- Hotkeys working
2013-10-04 04:09:54 +02:00
Ahmed Samy
7cf645e715 Woops, fix operator less than 2013-09-02 19:12:12 +00:00
Ahmed Samy
537508021e Make g_map.findItemsById return a map instead of a vector 2013-09-02 17:53:32 +00:00
Ahmed Samy
e741a62ce9 g_map.findItemsByid 2013-08-31 01:18:17 +00:00
Ahmed Samy
56d6ef6642 Introduce 4 new functions:
- g_map.beginGhostMode(float opacity)
- g_map.endGhostMode()
- UIMap::movePixels(int x, int y)
- MapView::move(int x, int y)
2013-08-30 01:54:36 +00:00
Ahmed Samy
3db8f54aa9 Introduce 2 new functions to g_things
- g_things.findItemTypesByName
- g_things.findItemTypesByString
2013-08-29 17:53:21 +00:00
Ahmed Samy
9234030c1b Zone colors: add more tile flags to be checked for 2013-08-27 15:49:48 +00:00
Ahmed Samy
520baa28ea Move "getNPC" that was introduced in commit
00729bbc2e
from Spawn to CreatureType

I didn't have a closer look at how his code was structured, what he
basically did
is that he set all creatures in a spawn as NPC's even if it's a monster
which is
so erroneous.

Highlights:
- Add branch prediction macros
- Minor code style fixes & some others

Hopefully the branch prediction thing will speed up OTB since it's
awfully slow.
2013-08-27 03:40:18 +02:00
Ben Dol
bbdeac2e33 Merge pull request #353 from KnopersPL/master
Fix for protocol 850 errors, thanks @KnopersPL
2013-08-25 03:54:39 -07:00
KnopersPL
1f914351bb Update protocolcodes.cpp
Fix for server messages on 850
2013-08-25 12:24:18 +02:00
KnopersPL
eb68504dc1 Update protocolgameparse.cpp
Fix the slow animation move effect, some opcodes error and logging in as GM
2013-08-25 12:20:54 +02:00
Ahmed Samy
32647f11bf Introduce 2 new functions to Map
- g_map.colorizeThing
- g_map.removeThingColor
2013-08-24 00:09:56 +02:00
Ahmed Samy
644d4daeea More cleanups 2013-08-23 02:12:36 +02:00
Ahmed Samy
b27352c321 Merge branch 'master' of https://github.com/BrunoDCC/otclient
* 'master' of https://github.com/BrunoDCC/otclient:
  Add full npc read (it not cause bug)
  Fixed a npcs save Fixed a spawns and npcs load
2013-08-23 02:03:40 +02:00
BrunoDCC
a6be9ae525 Add full npc read (it not cause bug) 2013-08-22 21:00:48 -03:00
Ahmed Samy
5df3ec8cf2 More cleanups
Also, bind map descriptions auxiliar functions
2013-08-23 01:55:15 +02:00
BrunoDCC
00729bbc2e Fixed a npcs save
Fixed a spawns and npcs load
2013-08-22 20:54:09 -03:00
Ahmed Samy
3b2d8a2b5e Fix build 2013-08-22 23:20:44 +02:00
Ahmed Samy
d5298c1011 Cleanups 2013-08-22 21:15:17 +02:00
Allan Ference
aaad8ab8a0 Fix spawn loading and saving, thanks to @BrunoDCC 2013-08-20 12:14:52 +02:00
Allan Ference
efbd9ab693 Attempt to fix spawn loader 2013-08-19 18:57:25 +02:00
Allan Ference
092209c0bb Attempt to fix houses and spawns save 2013-08-19 10:38:22 +02:00
Allan Ference
05f7f6a4cf Introduce Item::getName() 2013-08-18 18:29:20 +02:00
Ben Dol
2c36ca7215 Merge pull request #350 from conde2/master
Fix Keyboard unbind, WASD walk, Mount Frames, Fix #349, #344, #304, #253 Thanks @conde2!
2013-08-17 19:23:06 -07:00
Joao Pasqualini Costa
926eb9f01e Fix #253
Message Mode 12
2013-08-17 22:57:38 -03:00
Joao Pasqualini Costa
96bb28e806 Fix Mount frame issue
This will fix mount for all protocols
2013-08-17 22:19:24 -03:00
Joao Pasqualini Costa
e15995e1eb Fix walk with WASD
This should be an alone bind, so any other control will not affect the
keys.
2013-08-17 21:56:37 -03:00
Joao Pasqualini Costa
719debfeae Fix keyboard unbind
Now this will unbind the right widget
2013-08-17 21:54:16 -03:00
Allan Ference
e7137c2535 Rework NPCs loader with g_resources (Untested) 2013-08-17 23:36:44 +02:00
Allan Ference
5eabf6f518 Optional and configurable zone colors 2013-08-17 23:06:58 +02:00
Allan Ference
5849136526 Introduce g_things.findItemTypeByName 2013-08-17 15:09:10 +02:00
Allan Ference
0451fd6b58 OTBM saver: don't escape version check for waypoints 2013-08-15 11:20:22 +02:00
Allan Ference
9cf878335a Minor changes
Mainly code style
2013-08-14 18:58:53 +02:00
BeniS
529b646316 Forgot to provide the widget for walk key bind, thanks conde2! 2013-08-13 10:22:34 +12:00
Allan Ference
1ea2b380ca Disregard progressbar 2013-08-09 17:35:56 +02:00
Allan Ference
914fe249ab Merge branch 'master' of https://github.com/BrunoDCC/otclient
* 'master' of https://github.com/BrunoDCC/otclient:
  Fix OTBM save Remove if(version > 1) { (it causes bug)
2013-08-09 14:54:09 +02:00
BrunoDCC
4d498ed0d8 Fix OTBM save
Remove if(version > 1) { (it causes bug)
2013-08-07 20:04:21 -03:00
Allan Ference
9aa667da26 MapEditor: more changes for ease of use 2013-08-04 14:21:12 +02:00
Allan Ference
e6db43ac3a MapEditor specific: Use colors for tile states 2013-08-04 14:19:10 +02:00
Eduardo Bart
b5911cf1de Use client version instead of entergame 2013-08-03 19:26:38 -03:00
BeniS
5fbb71157d Added enable/disable chat mode (allows for alphabetical key controls), battle window anchoring fixed (thank you River) & more:
* Added better walk key binding (for other uses, like the sample given WASD).
* Made string.ends part of the string meta table rather than parameter based.
2013-07-29 10:42:18 +12:00
Allan Ference
0ff36a1a0a Merge https://github.com/marksamman/otclient
* https://github.com/marksamman/otclient:
  Fix login with 9.83-10.10
2013-07-28 07:10:44 +02:00
Mark Samman
4a04a18835 Fix login with 9.83-10.10
This only adds protocol compatibility, the features aren't actually
implemented yet
2013-07-28 07:05:46 +02:00
Allan Ference
6fa9631d6a Merge https://github.com/marksamman/otclient
* https://github.com/marksamman/otclient:
  Fix compiling on OS X
2013-07-28 04:42:31 +02:00
Mark Samman
261642190b Fix compiling on OS X 2013-07-28 04:30:52 +02:00
BeniS
95abf2a1d2 Fix a bug with autowalking & add prompt param for tryLogout.
(We don't want to be prompted when pressing Ctrl + Q or  Ctrl + L).
2013-07-07 05:36:56 +12:00
Sam
c4adf2d817 Added whitelist
- Checkboxes to turn ignore/whitelist off
- Allow VIP messages
2013-07-04 18:03:21 +02:00
Sam
c7c259ef80 Game Menu / Attacking fixes
- No more "Attack" / "Follow" for creatures on different floor
- No rule violation for monsters, only players now
- Alt + Click to target works through roofs -> fixes #203
- Fixed battle list issue (check position when trying to attack)
2013-07-03 14:25:18 +02:00
Sam
987c6d6c91 Mount display issue
fixes #275
Not really needed but enables some cool stuff
2013-07-02 23:16:11 +02:00
Sam
c8185474de Implements battlelist sorting
Features:
Sort by age, name, health or distance
Sort ascending or descending
Button to toggle filters and sort options
http://i.imgur.com/cSCBwr4.png

closes 213
2013-07-02 22:43:52 +02:00
Sam
be071c7103 Fix deathwindow issue 2013-07-02 22:40:19 +02:00
Sam
2f9e2c3e33 Sorting VIP list by name
@ #209
What should sorting by type do?
2013-07-01 22:59:51 +02:00
Sam
b81590f297 Fixed Alt + F4 keycombo on Windows 2013-06-29 16:53:15 +02:00
BeniS
e062562888 Added sublime text 2 project file.
* Changed the order of the dofiles params.
2013-05-12 21:16:43 +12:00
BeniS
18d23653c4 Added some control params to dofiles lua method.
* File name contains string.
* Recursive file checking for deep searches.
2013-05-12 17:00:52 +12:00
Henrique Santiago
6c119627bb Merge pull request #330 from conde2/master
Improvement on styles
2013-04-30 13:26:56 -07:00
Joao Pasqualini Costa
d847a78a4d Improvement on styles
Added VerticalList
2013-04-30 17:21:04 -03:00
Eduardo Bart
0dccc870b5 Merge pull request #324 from TiagoTdA/master
Update/Refresh modules on unload
2013-04-13 18:11:47 -07:00
Tiago T. de Araujo
e4c7ca604b Fix update on unload module 2013-04-12 21:27:10 -03:00
Sam
d427560b98 Countwindow Fix [YAH]
Fixed typing amount in count window. Should be hidden again.
2013-04-12 19:15:28 +02:00
Sam
cc12db0d1f Reverted getTopMultiUseThing() change 2013-04-09 23:54:10 +02:00
Henrique Santiago
1ce6df99ac Merge pull request #318 from conde2/master
Fix #316
2013-04-09 14:21:15 -07:00
Joao Pasqualini Costa
57bb6ff974 Fix #315 by @pacmanis
Credits go to @pacmanis
2013-04-09 18:02:43 -03:00
Joao Pasqualini Costa
9bae1b9e25 Fix #316
It still have a bug when using string like this:

" teste {{}} teste"
2013-04-09 17:54:57 -03:00
Sam
1415de222c Merge pull request #313 from sn3ejk/sn3ejk
Fix extended opcodes for forgottenserver.
2013-04-05 18:50:02 -07:00
Kamil W
34ceb3c95e Fix extended opcodes for forgottenserver. 2013-04-05 22:03:17 +02:00
Eduardo Bart
b43a196eac Minor fixes and add auto resize for images 2013-03-15 21:59:22 -03:00
Eduardo Bart
a3a65d40ce Merge pull request #303 from conde2/master
Properly Fix #301
2013-03-15 08:35:04 -07:00
Joao Pasqualini Costa
6ef3508362 Properly Fix #301 2013-03-14 20:57:02 -03:00
Eduardo Bart
a71e07f063 Restore walk optimization 2013-03-14 00:16:57 -03:00
Eduardo Bart
4bdd1e79fd Fix compile error for win32 2013-03-13 21:18:17 -03:00
Eduardo Bart
e9e4dcd71b Improve walk when lagging 2013-03-13 20:55:20 -03:00
Eduardo Bart
0891e2b30a Add C++ traceback to errors 2013-03-12 01:36:36 -03:00
Eduardo Bart
24664714bd Fix rare but serious bug in Connection
* Implement output pooling for writing data in connection,
this should fix rare cases where sending would fail
2013-03-12 00:18:47 -03:00
Eduardo Bart
da51dd467e Minor fix 2013-03-11 15:00:31 -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
260 changed files with 9884 additions and 3344 deletions

73
.gitignore vendored
View File

@@ -1,4 +1,3 @@
/modules/.project
build* build*
CMakeCache.txt CMakeCache.txt
CMakeFiles CMakeFiles
@@ -37,3 +36,75 @@ otclient.layout
LOCALTODO LOCALTODO
tags tags
Thumbs.db Thumbs.db
.directory
src/framework/graphics/dx/
modules/.project/modules.sublime-workspace
#################
## Visual Studio
#################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
build/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper

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.4")
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: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 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

@@ -1,36 +1,31 @@
-- by Don Daniello
-- 09 June 2012
-- http://DonDaniello.com
-- http://otland.net/members/Don+Daniello
locale = { locale = {
name = "pl", name = "pl",
languageName = "Polski", languageName = "Polski",
translation = { translation = {
["1a) Offensive Name"] = false, ["1a) Offensive Name"] = "1a) Obrazliwe Imie",
["1b) Invalid Name Format"] = false, ["1b) Invalid Name Format"] = "1b) Niepoprawny Format Imienia",
["1c) Unsuitable Name"] = false, ["1c) Unsuitable Name"] = "1c) Nieodpowiednie Imie",
["1d) Name Inciting Rule Violation"] = false, ["1d) Name Inciting Rule Violation"] = "1d) Imie Nawolujace Do Lamania Regulaminu",
["2a) Offensive Statement"] = false, ["2a) Offensive Statement"] = "2a) Obrazliwa wypowiedz",
["2b) Spamming"] = false, ["2b) Spamming"] = "2b) Spamowanie",
["2c) Illegal Advertising"] = false, ["2c) Illegal Advertising"] = "2c) Nielegalne Reklamy",
["2d) Off-Topic Public Statement"] = false, ["2d) Off-Topic Public Statement"] = "2d) Publiczne Wypowiadanie Sie Nie Na Temat",
["2e) Non-English Public Statement"] = false, ["2e) Non-English Public Statement"] = "2e) Publiczne wypowiadanie Sie W Jezyku Innym Niz Angielski",
["2f) Inciting Rule Violation"] = false, ["2f) Inciting Rule Violation"] = "2f) Nawolywanie Do Lamania Regulaminu ",
["3a) Bug Abuse"] = false, ["3a) Bug Abuse"] = "3a) Wykorzystywanie Bledow",
["3b) Game Weakness Abuse"] = false, ["3b) Game Weakness Abuse"] = "3b) Wykorzystanie Slabosci Gry",
["3c) Using Unofficial Software to Play"] = false, ["3c) Using Unofficial Software to Play"] = "3c) Gra Przy Uzyciu Nieoficjalnego Oprogramowania",
["3d) Hacking"] = false, ["3d) Hacking"] = "3d) Wlamywanie Sie",
["3e) Multi-Clienting"] = false, ["3e) Multi-Clienting"] = "3e) Uzycie Multi-Klienta",
["3f) Account Trading or Sharing"] = false, ["3f) Account Trading or Sharing"] = "3f) Handel Lub Udostepnianie Kont",
["4a) Threatening Gamemaster"] = false, ["4a) Threatening Gamemaster"] = "4a) Grozby Pod Adresem Mistrza Gry",
["4b) Pretending to Have Influence on Rule Enforcement"] = false, ["4b) Pretending to Have Influence on Rule Enforcement"] = "4b) Udawanie Wplywu na Ustanawianie Regul Gry",
["4c) False Report to Gamemaster"] = false, ["4c) False Report to Gamemaster"] = "4c) Wyslanie Falszywego Raportu Mistrzowi Gry",
["Accept"] = false, ["Accept"] = "Akceptuj",
["Account name"] = "Numer konta", ["Account name"] = "Numer konta",
["Account Status:"] = false, ["Account Status:"] = "Status Konta:",
["Action:"] = false, ["Action:"] = "Akcja:",
["Add"] = "Dodaj", ["Add"] = "Dodaj",
["Add new VIP"] = "Nowy VIP", ["Add new VIP"] = "Nowy VIP",
["Addon 1"] = "Addon 1", ["Addon 1"] = "Addon 1",
@@ -39,15 +34,15 @@ locale = {
["Add to VIP list"] = "Dodaj do VIPow", ["Add to VIP list"] = "Dodaj do VIPow",
["Adjust volume"] = "Zmien glosnosc", ["Adjust volume"] = "Zmien glosnosc",
["Alas! Brave adventurer, you have met a sad fate.\nBut do not despair, for the gods will bring you back\ninto this world in exchange for a small sacrifice\n\nSimply click on Ok to resume your journeys!"] = false, ["Alas! Brave adventurer, you have met a sad fate.\nBut do not despair, for the gods will bring you back\ninto this world in exchange for a small sacrifice\n\nSimply click on Ok to resume your journeys!"] = false,
["All"] = false, ["All"] = "Wszystkie",
["All modules and scripts were reloaded."] = "Wszystkie moduly ", ["All modules and scripts were reloaded."] = "Wszystkie moduly ",
["Allow auto chase override"] = false, ["Allow auto chase override"] = false,
["Also known as dash in tibia community, recommended\nfor playing characters with high speed"] = false, ["Also known as dash in tibia community, recommended\nfor playing characters with high speed"] = false,
["Ambient light: %s%%"] = false, ["Ambient light: %s%%"] = "Swiatlo tla: %s%%",
["Amount:"] = "Ilosc:", ["Amount:"] = "Ilosc:",
["Amount"] = false, ["Amount"] = "Ilosc",
["Anonymous"] = false, ["Anonymous"] = "Anonimowy",
["Are you sure you want to logout?"] = false, ["Are you sure you want to logout?"] = "Czy jestes pewien, ze sie chcesz wylogowac?",
["Attack"] = "Atak", ["Attack"] = "Atak",
["Author"] = "Autor", ["Author"] = "Autor",
["Autoload"] = "Autoladowanie", ["Autoload"] = "Autoladowanie",
@@ -59,17 +54,17 @@ locale = {
["Banishment"] = false, ["Banishment"] = false,
["Banishment + Final Warning"] = false, ["Banishment + Final Warning"] = false,
["Battle"] = "Bitwa", ["Battle"] = "Bitwa",
["Browse"] = false, ["Browse"] = "Przegladaj",
["Bug report sent."] = false, ["Bug report sent."] = "Raport o bledzie zostal wyslany.",
["Button Assign"] = "Przypisanie Klawisza", ["Button Assign"] = "Przypisanie Klawisza",
["Buy"] = "Kup", ["Buy"] = "Kup",
["Buy Now"] = false, ["Buy Now"] = "Kup Teraz",
["Buy Offers"] = false, ["Buy Offers"] = "Oferty Kupna",
["Buy with backpack"] = "Kupuj z plecakami", ["Buy with backpack"] = "Kupuj z plecakami",
["Cancel"] = "Anuluj", ["Cancel"] = "Anuluj",
["Cannot login while already in game."] = false, ["Cannot login while already in game."] = "Nie mozna zalogowac gdy juz w grze",
["Cap"] = false, ["Cap"] = false,
["Capacity"] = "Capacidad", ["Capacity"] = "Ladownosc",
["Center"] = false, ["Center"] = false,
["Channels"] = "Kanaly", ["Channels"] = "Kanaly",
["Character List"] = "Lista postaci", ["Character List"] = "Lista postaci",
@@ -82,65 +77,64 @@ locale = {
["Close this channel"] = "Zamknij kanal", ["Close this channel"] = "Zamknij kanal",
["Club Fighting"] = "Walka obuchem", ["Club Fighting"] = "Walka obuchem",
["Combat Controls"] = "Kontrola walki", ["Combat Controls"] = "Kontrola walki",
["Comment:"] = false, ["Comment:"] = "Komentarz:",
["Connecting to game server..."] = "Laczenie z serwerem gry...", ["Connecting to game server..."] = "Laczenie z serwerem gry...",
["Connecting to login server..."] = "Laczenie z serwerem logowania...", ["Connecting to login server..."] = "Laczenie z serwerem logowania...",
["Console"] = false, ["Console"] = "Konsola",
["Cooldowns"] = false, ["Cooldowns"] = false,
["Copy message"] = false, ["Copy message"] = "Kopiuj wiadomosc",
["Copy name"] = false, ["Copy name"] = "Kopiuj imie",
["Copy Name"] = "Kopiuj Nick", ["Copy Name"] = "Kopiuj Imie",
["Create Map Mark"] = false, ["Create Map Mark"] = "Utworz Znacznik na Mapie",
["Create mark"] = false, ["Create mark"] = "Utworz znacznik",
["Create New Offer"] = false, ["Create New Offer"] = "Utworz Nowa Oferte",
["Create Offer"] = false, ["Create Offer"] = "Utworz Oferte",
["Current hotkeys:"] = "Aktualny hotkey:", ["Current hotkeys:"] = "Aktualny hotkey:",
["Current hotkey to add: %s"] = "Aktualny hotkey do dodania: %s", ["Current hotkey to add: %s"] = "Aktualny hotkey do dodania: %s",
["Current Offers"] = false, ["Current Offers"] = "Obecne Oferty",
["Default"] = "Domyslny", ["Default"] = "Domyslny",
["Delete mark"] = false, ["Delete mark"] = "Usun znacznik",
["Description:"] = false, ["Description:"] = "Opis:",
["Description"] = "Opis", ["Description"] = "Opis",
["Destructive Behaviour"] = false, ["Destructive Behaviour"] = "Destrukcyjne Zachowanie",
["Detail"] = "Szczegoly", ["Detail"] = "Szczegoly",
["Details"] = false, ["Details"] = "Szczegoly",
["Disable Shared Experience"] = "Wylacz Dzielenie Doswiadczenia", ["Disable Shared Experience"] = "Wylacz Dzielenie Doswiadczenia",
["Dismount"] = false, ["Dismount"] = false,
["Display connection speed to the server (milliseconds)"] = false, ["Display connection speed to the server (milliseconds)"] = "Wyswietl ping do serwera (ms)",
["Distance Fighting"] = "Walka na odleglosc", ["Distance Fighting"] = "Walka na odleglosc",
["Don't stretch/shrink Game Window"] = false, ["Don't stretch/shrink Game Window"] = "Nie rozszerzaj/zwezaj Okna Gry",
["Edit hotkey text:"] = "Edytuj tresc hotkeya:", ["Edit hotkey text:"] = "Edytuj tresc hotkeya:",
["Edit List"] = false, ["Edit List"] = "Lista Edycji",
["Edit Text"] = "Edytuj tekst", ["Edit Text"] = "Edytuj tekst",
["Enable music"] = false, ["Enable music"] = "Odtwarzaj muzyke",
["Enable Shared Experience"] = "Wlacz dzielenie doswiadczenia", ["Enable Shared Experience"] = "Wlacz dzielenie doswiadczenia",
["Enable smart walking"] = false, ["Enable smart walking"] = false,
["Enable vertical synchronization"] = "Wlacz synchronizacje pionowa", ["Enable vertical synchronization"] = "Wlacz synchronizacje pionowa",
["Enable walk booster"] = false, ["Enable walk booster"] = false,
["Enter Game"] = "Wejdz do gry", ["Enter Game"] = "Wejdz do gry",
["Enter one name per line."] = false, ["Enter one name per line."] = "Wprowadz jedno imie na linie",
["Enter with your account again to update your client."] = false, ["Enter with your account again to update your client."] = "Zaloguj sie ponownie by zaktualizowac klienta",
["Error"] = "Blad", ["Error"] = "Blad",
["Error"] = "Blad", ["Excessive Unjustified Player Killing"] = "Nadmierne Nieusprawiedliwione Zabijanie Graczy",
["Excessive Unjustified Player Killing"] = false,
["Exclude from private chat"] = "Wyrzuc w prywatnej konwersacji", ["Exclude from private chat"] = "Wyrzuc w prywatnej konwersacji",
["Exit"] = false, ["Exit"] = false,
["Experience"] = "Doswiadczenie", ["Experience"] = "Doswiadczenie",
["Filter list to match your level"] = false, ["Filter list to match your level"] = "Wyswietl tylko odpowiednie dla mojego poziomu",
["Filter list to match your vocation"] = false, ["Filter list to match your vocation"] = "Wyswietl tylko odpowiednie dla mojej klasy",
["Find:"] = false, ["Find:"] = "Szukaj:",
["Fishing"] = "Wedkarstwo", ["Fishing"] = "Wedkarstwo",
["Fist Fighting"] = "Walka wrecz", ["Fist Fighting"] = "Walka wrecz",
["Follow"] = "Podazaj", ["Follow"] = "Podazaj",
["Force Exit"] = false, ["Force Exit"] = "Wymus Zamkniecie",
["For Your Information"] = false, ["For Your Information"] = false,
["Free Account"] = false, ["Free Account"] = "Darmowe Konto",
["Fullscreen"] = "Pelen ekran", ["Fullscreen"] = "Pelen ekran",
["Game"] = false, ["Game"] = "Gra",
["Game framerate limit: %s"] = false, ["Game framerate limit: %s"] = "Limit FPS: %s",
["Graphics"] = "Grafika", ["Graphics"] = "Grafika",
["Graphics card driver not detected"] = false, ["Graphics card driver not detected"] = "Nie wykryto karty graficznej",
["Graphics Engine:"] = false, ["Graphics Engine:"] = "Silnik graficzny:",
["Head"] = "Glowa", ["Head"] = "Glowa",
["Healing"] = false, ["Healing"] = false,
["Health Info"] = false, ["Health Info"] = false,
@@ -148,43 +142,43 @@ locale = {
["Hide monsters"] = "Ukryj potwory", ["Hide monsters"] = "Ukryj potwory",
["Hide non-skull players"] = "Ukryj graczy bez skulla", ["Hide non-skull players"] = "Ukryj graczy bez skulla",
["Hide Npcs"] = "Ukryj NPCe", ["Hide Npcs"] = "Ukryj NPCe",
["Hide Offline"] = false, ["Hide Offline"] = "Ukryj Niedostepnych",
["Hide party members"] = "Ukryj czlonkow zabawy", ["Hide party members"] = "Ukryj czlonkow druzyny",
["Hide players"] = "Ukryj graczy", ["Hide players"] = "Ukryj graczy",
["Hide spells for higher exp. levels"] = false, ["Hide spells for higher exp. levels"] = "Ukryj zaklecia wyzszych poziomow postaci",
["Hide spells for other vocations"] = false, ["Hide spells for other vocations"] = "Ukryj zaklecia innych klas",
["Hit Points"] = "Punkty uderzen", ["Hit Points"] = "Punkty uderzen",
["Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks"] = false, ["Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks"] = false,
["Hotkeys"] = "Hotkeye", ["Hotkeys"] = "Hotkeye",
["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."] = false, ["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."] = false,
["Ignore"] = false, ["Ignore"] = "Ignoruj",
["Ignore capacity"] = "Ignoruj pojemnosc", ["Ignore capacity"] = "Ignoruj pojemnosc",
["Ignored players:"] = false, ["Ignored players:"] = "Ignorowani gracze:",
["Ignore equipped"] = "Ignoruj ekwipunek", ["Ignore equipped"] = "Ignoruj ekwipunek",
["Ignore List"] = false, ["Ignore List"] = "Lista Ignorowanych",
["Ignore players"] = false, ["Ignore players"] = "Ignoruj graczy",
["Ignore Private Messages"] = false, ["Ignore Private Messages"] = "Ignoruj Prywatne Wiadomosci",
["Ignore Yelling"] = false, ["Ignore Yelling"] = "Ignoruj Krzyki",
["Interface framerate limit: %s"] = false, ["Interface framerate limit: %s"] = "Limit FPS interfejsu: %s",
["Inventory"] = "Inwentarz", ["Inventory"] = "Ekwipunek",
["Invite to Party"] = "Zapros do zabawy", ["Invite to Party"] = "Zapros do druzyny",
["Invite to private chat"] = "Zapros do prywatnej konwersacji", ["Invite to private chat"] = "Zapros do prywatnej konwersacji",
["IP Address Banishment"] = false, ["IP Address Banishment"] = "Blokada adresu IP",
["Item Offers"] = false, ["Item Offers"] = "Oferty Przedmiotow",
["It is empty."] = false, ["It is empty."] = "To jest puste.",
["Join %s's Party"] = false, ["Join %s's Party"] = "Dolacz do druzyny gracza %s",
["Leave Party"] = "Opusc zabawe", ["Leave Party"] = "Opusc druzyne",
["Level"] = "Poziom", ["Level"] = "Poziom",
["Lifetime Premium Account"] = false, ["Lifetime Premium Account"] = "Konto Premium na Stale",
["Limits FPS to 60"] = "Ogranicz FPS do 60", ["Limits FPS to 60"] = "Ogranicz FPS do 60",
["List of items that you're able to buy"] = "Lista przedmiotow, ktore mozesz kupic", ["List of items that you're able to buy"] = "Lista przedmiotow, ktore mozesz kupic",
["List of items that you're able to sell"] = "Lista przedmiotow, ktore mozesz sprzedac", ["List of items that you're able to sell"] = "Lista przedmiotow, ktore mozesz sprzedac",
["Load"] = "Wczytaj", ["Load"] = "Wczytaj",
["Logging out..."] = false, ["Logging out..."] = "Wylogowuje...",
["Login"] = "Zaloguj", ["Login"] = "Zaloguj",
["Login Error"] = "Blad Logowania", ["Login Error"] = "Blad Logowania",
["Login Error"] = "Blad Logowania", ["Login Error"] = "Blad Logowania",
["Logout"] = false, ["Logout"] = "Wyloguj",
["Look"] = "Spojrz", ["Look"] = "Spojrz",
["Magic Level"] = "Poziom Magiczny", ["Magic Level"] = "Poziom Magiczny",
["Make sure that your client uses\nthe correct game protocol version"] = "Upewnij sie, ze twoj klient\nuzywa wlasciwego protokolu gry.", ["Make sure that your client uses\nthe correct game protocol version"] = "Upewnij sie, ze twoj klient\nuzywa wlasciwego protokolu gry.",
@@ -193,7 +187,7 @@ locale = {
["Market"] = false, ["Market"] = false,
["Market Offers"] = false, ["Market Offers"] = false,
["Message of the day"] = "Wiadomosc dnia", ["Message of the day"] = "Wiadomosc dnia",
["Message to "] = false, ["Message to "] = "Wiadomosc do ",
["Message to %s"] = "Wiadomosc do %s", ["Message to %s"] = "Wiadomosc do %s",
["Minimap"] = "Minimapa", ["Minimap"] = "Minimapa",
["Module Manager"] = "Menedzer modulow", ["Module Manager"] = "Menedzer modulow",
@@ -201,32 +195,32 @@ locale = {
["Mount"] = false, ["Mount"] = false,
["Move Stackable Item"] = "Przenies przedmiot", ["Move Stackable Item"] = "Przenies przedmiot",
["Move up"] = "Przenies wyzej", ["Move up"] = "Przenies wyzej",
["My Offers"] = false, ["My Offers"] = "Moje Oferty",
["Name:"] = "Nazwa:", ["Name:"] = "Nazwa:",
["Name Report"] = false, ["Name Report"] = false,
["Name Report + Banishment"] = false, ["Name Report + Banishment"] = false,
["Name Report + Banishment + Final Warning"] = false, ["Name Report + Banishment + Final Warning"] = false,
["No"] = false, ["No"] = "Nie",
["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."] = false, ["No item selected."] = "Nie wybrano przedmiotu.",
["No Mount"] = false, ["No Mount"] = "Brak wierzchowca",
["No Outfit"] = false, ["No Outfit"] = "Brak stroju",
["No statement has been selected."] = false, ["No statement has been selected."] = false,
["Notation"] = false, ["Notation"] = false,
["NPC Trade"] = "Handel NPC", ["NPC Trade"] = "Handel NPC",
["Offer History"] = false, ["Offer History"] = "Historia Ofert",
["Offers"] = false, ["Offers"] = "Oferty",
["Offer Type:"] = false, ["Offer Type:"] = "Typ Oferty:",
["Offline Training"] = false, ["Offline Training"] = "Trening Offline",
["Ok"] = "Ok", ["Ok"] = "Ok",
["on %s.\n"] = false, ["on %s.\n"] = false,
["Open"] = "Otworz", ["Open"] = "Otworz",
["Open a private message channel:"] = "Otworz prywatny kanal:", ["Open a private message channel:"] = "Otworz prywatny kanal:",
["Open charlist automatically when starting client"] = false, ["Open charlist automatically when starting client"] = "Automatycznie otworz liste postaci przy starcie gry",
["Open in new window"] = "Otworz w nowym oknie", ["Open in new window"] = "Otworz w nowym oknie",
["Open new channel"] = "Otworz nowy kanal", ["Open new channel"] = "Otworz nowy kanal",
["Options"] = "Opcje", ["Options"] = "Opcje",
["Overview"] = false, ["Overview"] = "Podsumowanie",
["Pass Leadership to %s"] = "Przekaz przywodztwo %s", ["Pass Leadership to %s"] = "Przekaz przywodztwo %s",
["Password"] = "Haslo", ["Password"] = "Haslo",
["Piece Price:"] = false, ["Piece Price:"] = false,
@@ -236,79 +230,79 @@ locale = {
["Please use this dialog to only report bugs. Do not report rule violations here!"] = false, ["Please use this dialog to only report bugs. Do not report rule violations here!"] = false,
["Please wait"] = "Prosze czekac", ["Please wait"] = "Prosze czekac",
["Port"] = "Port", ["Port"] = "Port",
["Position:"] = false, ["Position:"] = "Pozycja:",
["Position: %i %i %i"] = false, ["Position: %i %i %i"] = "Pozycja: %i %i %i",
["Premium Account (%s) days left"] = false, ["Premium Account (%s) days left"] = "Konto Premium (%s) dni",
["Price:"] = "Cena:", ["Price:"] = "Cena:",
["Primary"] = "Podstawowy", ["Primary"] = "Podstawowy",
["Protocol"] = false, ["Protocol"] = "Protokol",
["Quest Log"] = false, ["Quest Log"] = "Dziennik Misji",
["Randomize"] = false, ["Randomize"] = false,
["Randomize characters outfit"] = false, ["Randomize characters outfit"] = false,
["Reason:"] = false, ["Reason:"] = "Powod:",
["Refresh"] = "Odswiez", ["Refresh"] = "Odswiez",
["Refresh Offers"] = false, ["Refresh Offers"] = "Odswiez Oferty",
["Regeneration Time"] = false, ["Regeneration Time"] = "Czas Regeneracji",
["Reject"] = false, ["Reject"] = "Odrzuc",
["Reload All"] = "Przeladuj Wszystko", ["Reload All"] = "Przeladuj Wszystko",
["Remember account and password when starts client"] = false, ["Remember account and password when starts client"] = "Zapamietaj identyfikator konta oraz haslo",
["Remember password"] = "Zapamietaj haslo", ["Remember password"] = "Zapamietaj haslo",
["Remove"] = "Usun", ["Remove"] = "Usun",
["Remove %s"] = "Usun %s", ["Remove %s"] = "Usun %s",
["Report Bug"] = false, ["Report Bug"] = "Zglos Blad",
["Reserved for more functionality later."] = false, ["Reserved for more functionality later."] = "Zarezerowane dla przyszlych funkcjonalnosci.",
["Reset Market"] = false, ["Reset Market"] = false,
["Revoke %s's Invitation"] = false, ["Revoke %s's Invitation"] = "Odmow na zaproszenie gracza %s",
["Rotate"] = "Obroc", ["Rotate"] = "Obroc",
["Rule Violation"] = false, ["Rule Violation"] = "Zlamanie Regul",
["Save"] = false, ["Save"] = "Zapisz",
["Save Messages"] = false, ["Save Messages"] = "Zapisz Wiadomosci",
["Search:"] = "Szukaj:", ["Search:"] = "Szukaj:",
["Search all items"] = false, ["Search all items"] = "Znajdz wszystkie przedmioty",
["Secondary"] = "Drugorzedny", ["Secondary"] = "Drugorzedny",
["Select object"] = "Wybierz obiekt", ["Select object"] = "Wybierz obiekt",
["Select Outfit"] = "Wybierz outfit", ["Select Outfit"] = "Wybierz outfit",
["Select your language"] = false, ["Select your language"] = "Wybierz jezyk",
["Sell"] = "Sprzedaj", ["Sell"] = "Sprzedaj",
["Sell Now"] = false, ["Sell Now"] = "Sprzedaj Teraz",
["Sell Offers"] = false, ["Sell Offers"] = "Oferty Sprzedazy",
["Send"] = false, ["Send"] = "Wyslij",
["Send automatically"] = "Wyslij automatycznie", ["Send automatically"] = "Wyslij automatycznie",
["Send Message"] = false, ["Send Message"] = "Wyslij Wiadomosc",
["Server"] = "Serwer", ["Server"] = "Serwer",
["Server Log"] = "Log Serwera", ["Server Log"] = "Log Serwera",
["Set Outfit"] = "Ustaw outfit", ["Set Outfit"] = "Ustaw outfit",
["Shielding"] = "Obrona tarcza", ["Shielding"] = "Obrona tarcza",
["Show all items"] = "Pokaz wszystkie przedmioty", ["Show all items"] = "Pokaz wszystkie przedmioty",
["Show connection ping"] = false, ["Show connection ping"] = "Wyswietl ping",
["Show Depot Only"] = false, ["Show Depot Only"] = false,
["Show event messages in console"] = "Pokaz wydarzenia w konsoli", ["Show event messages in console"] = "Pokaz wydarzenia w konsoli",
["Show frame rate"] = "Pokaz ilosc FPS", ["Show frame rate"] = "Pokaz FPS",
["Show info messages in console"] = "Pokaz informacje w konsoli", ["Show info messages in console"] = "Pokaz informacje w konsoli",
["Show left panel"] = false, ["Show left panel"] = "Pokaz lewy panel",
["Show levels in console"] = "Pokaz poziomy w konsoli", ["Show levels in console"] = "Pokaz poziomy w konsoli",
["Show Offline"] = false, ["Show Offline"] = "Pokaz Niedostepnych",
["Show private messages in console"] = "Pokaz prywatne wiadomosci w konsoli", ["Show private messages in console"] = "Pokaz prywatne wiadomosci w konsoli",
["Show private messages on screen"] = false, ["Show private messages on screen"] = "Pokaz prywatne wiadomosci na ekranie",
["Show Server Messages"] = false, ["Show Server Messages"] = "Pokaz Wiadomosci Serwera",
["Show status messages in console"] = "Pokaz status w konsoli", ["Show status messages in console"] = "Pokaz status w konsoli",
["Show Text"] = false, ["Show Text"] = "Pokaz Tekst",
["Show timestamps in console"] = "Pokaz znaczniki czasu w konsoli", ["Show timestamps in console"] = "Pokaz znaczniki czasu w konsoli",
["Show your depot items only"] = false, ["Show your depot items only"] = false,
["Skills"] = "Umiejetnosci", ["Skills"] = "Umiejetnosci",
["Soul"] = false, ["Soul"] = "Dusze",
["Soul Points"] = "Punkty Duszy", ["Soul Points"] = "Punkty Duszy",
["Special"] = false, ["Special"] = false,
["Speed"] = false, ["Speed"] = "Predkosc",
["Spell Cooldowns"] = false, ["Spell Cooldowns"] = false,
["Spell List"] = false, ["Spell List"] = "Lista Zaklec",
["Stamina"] = "Wytrzymalosc", ["Stamina"] = "Wytrzymalosc",
["Statement:"] = false, ["Statement:"] = false,
["Statement Report"] = false, ["Statement Report"] = false,
["Statistics"] = false, ["Statistics"] = "Statystki",
["Stop Attack"] = "Zatrzymaj atak", ["Stop Attack"] = "Anuluj atak",
["Stop Follow"] = "Zatrzymaj podazanie", ["Stop Follow"] = "Przestan podazac",
["Support"] = false, ["Support"] = "Wsparcie",
["%s: (use object)"] = "%s: (uzyj obiekt)", ["%s: (use object)"] = "%s: (uzyj obiekt)",
["%s: (use object on target)"] = "%s: (uzyj obiektu na celu)", ["%s: (use object on target)"] = "%s: (uzyj obiektu na celu)",
["%s: (use object on yourself)"] = "%s: (uzyj obiektu na sobie)", ["%s: (use object on yourself)"] = "%s: (uzyj obiektu na sobie)",
@@ -316,15 +310,15 @@ locale = {
["Sword Fighting"] = "Atak mieczem", ["Sword Fighting"] = "Atak mieczem",
["Terminal"] = "Terminal", ["Terminal"] = "Terminal",
["There is no way."] = "Nie ma drogi.", ["There is no way."] = "Nie ma drogi.",
["Title"] = false, ["Title"] = "Tytul",
["Total Price:"] = false, ["Total Price"] = "Cena sumaryczna",
["Trade"] = "Handel", ["Trade"] = "Handel",
["Trade with ..."] = "Handluj z ...", ["Trade with ..."] = "Handluj z ...",
["Trying to reconnect in %s seconds."] = false, ["Trying to reconnect in %s seconds."] = "Ponowna proba laczenia za %s sekund.",
["Unable to load dat file, please place a valid dat in '%s'"] = false, ["Unable to load dat file, please place a valid dat in '%s'"] = "Nie mozna zaladowac pliku .dat z '%s'",
["Unable to load spr file, please place a valid spr in '%s'"] = false, ["Unable to load spr file, please place a valid spr in '%s'"] = "Nie mozna zaladowac pliku .spr z '%s'",
["Unable to logout."] = "Nie mozna sie wylogowac.", ["Unable to logout."] = "Nie mozna sie wylogowac.",
["Unignore"] = false, ["Unignore"] = "Anuluj Ignorowanie",
["Unload"] = "Wylacz", ["Unload"] = "Wylacz",
["Update needed"] = false, ["Update needed"] = false,
["Use"] = "Uzyj", ["Use"] = "Uzyj",
@@ -334,42 +328,87 @@ locale = {
["Version"] = "Wersja", ["Version"] = "Wersja",
["VIP List"] = "Lista VIP", ["VIP List"] = "Lista VIP",
["Voc."] = false, ["Voc."] = false,
["Vocation"] = false, ["Vocation"] = "Klasa",
["Waiting List"] = false, ["Waiting List"] = "Lista Oczekujacych",
["Website"] = "Strona:", ["Website"] = "Strona:",
["Weight:"] = "Waga:", ["Weight:"] = "Waga:",
["Will detect when to use diagonal step based on the\nkeys you are pressing"] = false, ["Will detect when to use diagonal step based on the\nkeys you are pressing"] = false,
["With crosshair"] = "Z celownikiem", ["With crosshair"] = "Z celownikiem",
["Yes"] = false, ["Yes"] = "Tak",
["You are bleeding"] = false, ["You are bleeding"] = "Krwawisz",
["You are burning"] = "Palisz sie", ["You are burning"] = "Palisz sie",
["You are cursed"] = "Jestes przeklety", ["You are cursed"] = "Jestes przeklety",
["You are dazzled"] = "Jestes oslepiony", ["You are dazzled"] = "Jestes oslepiony",
["You are dead."] = "Zginales marnie.", ["You are dead."] = "Zginales marnie.",
["You are dead"] = false, ["You are dead"] = "Jestes martwy",
["You are drowning"] = "Topisz sie", ["You are drowning"] = "Topisz sie",
["You are drunk"] = false, ["You are drunk"] = "Caly swiat wiruje",
["You are electrified"] = "Jestes porazony pradem", ["You are electrified"] = "Jestes porazony pradem",
["You are freezing"] = "Marzniesz", ["You are freezing"] = "Marzniesz",
["You are hasted"] = "Zapieprzasz", ["You are hasted"] = "Zapieprzasz",
["You are hungry"] = false, ["You are hungry"] = "Burczy ci w brzuchu",
["You are paralysed"] = "Jestes sparalizowany", ["You are paralysed"] = "Jestes sparalizowany",
["You are poisoned"] = "Jestes zatruty", ["You are poisoned"] = "Jestes zatruty",
["You are protected by a magic shield"] = "Jestes chroniony magiczna tarcza", ["You are protected by a magic shield"] = "Jestes chroniony magiczna tarcza",
["You are strengthened"] = "Jestes wzmocniony", ["You are strengthened"] = "Jestes wzmocniony",
["You are within a protection zone"] = "Jestes w strefie ochronnej", ["You are within a protection zone"] = "Jestes w strefie ochronnej",
["You can enter new text."] = false, ["You can enter new text."] = "Mozesz wprowadzic nowy tekst.",
["You have %s percent"] = "Masz %s procent", ["You have %s percent"] = "Masz %s procent",
["You have %s percent to go"] = "Brakuje Ci %s procent", ["You have %s percent to go"] = "Brakuje Ci %s procent",
["You may not logout during a fight"] = "Nie mozesz sie wylogowac w trakcie walki", ["You may not logout during a fight"] = "Nie mozesz sie wylogowac w trakcie walki",
["You may not logout or enter a protection zone"] = "Nie mozesz sie wylogowac ani wejsc do strefy ochronnej", ["You may not logout or enter a protection zone"] = "Nie mozesz sie wylogowac ani wejsc do strefy ochronnej",
["You must enter a comment."] = false, ["You must enter a comment."] = "Prosze wprowadzic komentarz",
["You must enter a valid server address and port."] = false, ["You must enter a valid server address and port."] = "Prosze wprowadzic poprawny adres i port.",
["You must select a character to login!"] = "Musisz wybrac postac aby sie zalogowac!", ["You must select a character to login!"] = "Musisz wybrac postac aby sie zalogowac!",
["Your Capacity:"] = false, ["Your Capacity:"] = "Twoja Ladownosc:",
["You read the following, written by \n%s\n"] = false, ["You read the following, written by \n%s\n"] = false,
["You read the following, written on \n%s.\n"] = false, ["You read the following, written on \n%s.\n"] = false,
["Your Money:"] = false, ["Your Money:"] = false,
["Enable dash walking"] = false,
["Will boost your walk on high speed characters"] = "Przyspieszy poruszanie sie postaci o wysokiej predkosci",
["Display creature names"] = "Wyswietlaj nazwy potworow",
["Display creature health bars"] = "Wyswietlaj paski zycia potworow",
["Display text messages"] = "Wyswietlaj wiadomosci tekstowe",
["Change language"] = "Zmien jezyk",
["Enable lights"] = "Odblokuj oswietlenie",
["Enable audio"] = "Odblokuj dzwiek",
["Enable music sound"] = "Odblokuj muzyke",
["Music volume: %d"] = "Glosnosc muzyki: %d",
["Audio"] = "Dzwiek",
["Server List"] = "Lista serwerow",
["Server list"] = "Lista serwerow",
["Client Version"] = "Wersja klienta",
["Add new server"] = "Dodaj nowy serwer",
["Select"] = "Wybierz",
["New Server"] = "Nowy serwer",
["Host"] = false,
["Reset All"] = "Ustaw domyslne",
["Disable chat mode, allow to walk using ASDW"] = "Zablokuj tryb rozmow, zezwol na poruszanie sie za pomoca klawiszy ADSW",
["Name"] = "Imie",
["Price"] = "Cena",
["Your Money"] = "Twoje fundusze",
["Weight"] = "Waga",
["Your Capacity"] = "Twoj udzwig",
["Search"] = "Szukaj",
["Sell All"] = "Sprzedaj wszystko",
["Statement"] = false,
["Reason"] = "Powod",
["Action"] = "Akcja",
["Comment"] = "Komentarz",
["Balance"] = false,
["Offer Type"] = "Typ oferty",
["Piece Price"] = false,
["Find"] = "Szukaj",
["Formula"] = "Formula",
["Group"] = "Groupa",
["Type"] = "Typ",
["Cooldown"] = false,
["Premium"] = false,
["Any"] = "Dowolny",
["Sorcerer"] = "Czarodziej",
["Druid"] = false,
["Paladin"] = "Paladyn",
["Knight"] = "Rycerz"
} }
} }

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

@@ -67,3 +67,17 @@ PreviousButton < UIButton
$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

@@ -11,3 +11,9 @@ HorizontalList < UIScrollArea
border-width: 1 border-width: 1
border-color: #1d222b border-color: #1d222b
background-color: #222833 background-color: #222833
VerticalList < UIScrollArea
layout: verticalBox
border-width: 1
border-color: #1d222b
background-color: #222833

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

@@ -0,0 +1,10 @@
{
"folders":
[
{
"path": "..",
"folder_exclude_patterns": [".*", "*.*~"],
"file_exclude_patterns": [".*", "*.*~"]
}
]
}

View File

@@ -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'
@@ -104,11 +104,6 @@ function terminate()
g_settings.set('window-size', g_window.getUnmaximizedSize()) g_settings.set('window-size', g_window.getUnmaximizedSize())
g_settings.set('window-pos', g_window.getUnmaximizedPos()) g_settings.set('window-pos', g_window.getUnmaximizedPos())
g_settings.set('window-maximized', g_window.isMaximized()) g_settings.set('window-maximized', g_window.isMaximized())
local protocolVersion = g_game.getProtocolVersion()
if protocolVersion ~= 0 then
g_settings.set('protocol-version', protocolVersion)
end
end end
function exit() function exit()

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_stats - client_serverlist
- 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

@@ -6,8 +6,9 @@ local enterGame
local motdWindow local motdWindow
local motdButton local motdButton
local enterGameButton local enterGameButton
local protocolBox local clientBox
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)
if motdEnabled then
motdButton:show() 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,6 +62,7 @@ local function onCharacterList(protocol, characters, account, otui)
CharacterList.create(characters, account, otui) CharacterList.create(characters, account, otui)
CharacterList.show() CharacterList.show()
if motdEnabled then
local lastMotdNumber = g_settings.getNumber("motd") local lastMotdNumber = g_settings.getNumber("motd")
if G.motdNumber and G.motdNumber ~= lastMotdNumber then if G.motdNumber and G.motdNumber ~= lastMotdNumber then
g_settings.set("motd", motdNumber) g_settings.set("motd", motdNumber)
@@ -53,10 +71,6 @@ local function onCharacterList(protocol, characters, account, otui)
CharacterList.hide() CharacterList.hide()
end end
end end
local function onChangeProtocol(combobox, option)
local clients = g_game.getSupportedClients(option)
protocolBox:setTooltip("Supports Client" .. (#clients > 1 and "s" or "") .. ": " .. table.tostring(clients))
end end
local function onUpdateNeeded(protocol, signature) local function onUpdateNeeded(protocol, signature)
@@ -81,36 +95,32 @@ 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')
local protocolVersion = g_settings.getInteger('protocol-version') local clientVersion = g_settings.getInteger('client-version')
if clientVersion == 0 then clientVersion = 860 end
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') clientBox = enterGame:getChildById('clientComboBox')
protocolBox.onOptionChange = onChangeProtocol for _, proto in pairs(g_game.getSupportedClients()) do
for _i, proto in pairs(g_game.getSupportedProtocols()) do clientBox:addOption(proto)
protocolBox:addOption(proto)
end
if protocolVersion then
protocolBox:setCurrentOption(protocolVersion)
end end
clientBox:setCurrentOption(clientVersion)
enterGame:hide() enterGame:hide()
@@ -127,18 +137,20 @@ 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()
enterGameButton = nil enterGameButton = nil
protocolBox = nil clientBox = nil
if motdWindow then if motdWindow then
motdWindow:destroy() motdWindow:destroy()
motdWindow = nil motdWindow = nil
@@ -177,6 +189,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,13 +210,11 @@ 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()
G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText()) G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText())
local protocolVersion = tonumber(protocolBox:getText()) local clientVersion = tonumber(clientBox:getText())
local clientVersions = g_game.getSupportedClients(protocolVersion)
EnterGame.hide() EnterGame.hide()
if g_game.isOnline() then if g_game.isOnline() then
@@ -203,9 +225,10 @@ function EnterGame.doLogin()
g_settings.set('host', G.host) g_settings.set('host', G.host)
g_settings.set('port', G.port) g_settings.set('port', G.port)
g_settings.set('client-version', clientVersion)
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
@@ -218,10 +241,8 @@ function EnterGame.doLogin()
end }) end })
g_game.chooseRsa(G.host) g_game.chooseRsa(G.host)
g_game.setProtocolVersion(protocolVersion) g_game.setClientVersion(clientVersion)
if #clientVersions > 0 then g_game.setProtocolVersion(g_game.getProtocolVersionForClient(clientVersion))
g_game.setClientVersion(clientVersions[#clientVersions])
end
if modules.game_things.isLoaded() then if modules.game_things.isLoaded() then
protocolLogin:login(G.host, G.port, G.account, G.password) protocolLogin:login(G.host, G.port, G.account, G.password)
@@ -242,20 +263,16 @@ end
function EnterGame.setDefaultServer(host, port, protocol) function EnterGame.setDefaultServer(host, port, protocol)
local hostTextEdit = enterGame:getChildById('serverHostTextEdit') local hostTextEdit = enterGame:getChildById('serverHostTextEdit')
local portTextEdit = enterGame:getChildById('serverPortTextEdit') local portTextEdit = enterGame:getChildById('serverPortTextEdit')
local protocolLabel = enterGame:getChildById('protocolLabel') local clientLabel = enterGame:getChildById('clientLabel')
local accountTextEdit = enterGame:getChildById('accountNameTextEdit') local accountTextEdit = enterGame:getChildById('accountNameTextEdit')
local passwordTextEdit = enterGame:getChildById('accountPasswordTextEdit') local passwordTextEdit = enterGame:getChildById('accountPasswordTextEdit')
if hostTextEdit:getText() ~= host then if hostTextEdit:getText() ~= host then
hostTextEdit:setText(host) hostTextEdit:setText(host)
portTextEdit:setText(port) portTextEdit:setText(port)
protocolBox:setCurrentOption(protocol) clientBox:setCurrentOption(protocol)
accountTextEdit:setText('') accountTextEdit:setText('')
passwordTextEdit:setText('') passwordTextEdit:setText('')
if autoLoginEvent then
autoLoginEvent:cancel()
end
end end
end end
@@ -269,9 +286,9 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
portTextEdit:setVisible(false) portTextEdit:setVisible(false)
portTextEdit:setHeight(0) portTextEdit:setHeight(0)
protocolBox:setCurrentOption(protocol) clientBox:setCurrentOption(protocol)
protocolBox:setVisible(false) clientBox:setVisible(false)
protocolBox:setHeight(0) clientBox:setHeight(0)
local serverLabel = enterGame:getChildById('serverLabel') local serverLabel = enterGame:getChildById('serverLabel')
serverLabel:setVisible(false) serverLabel:setVisible(false)
@@ -279,9 +296,14 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
local portLabel = enterGame:getChildById('portLabel') local portLabel = enterGame:getChildById('portLabel')
portLabel:setVisible(false) portLabel:setVisible(false)
portLabel:setHeight(0) portLabel:setHeight(0)
local protocolLabel = enterGame:getChildById('protocolLabel') local clientLabel = enterGame:getChildById('clientLabel')
protocolLabel:setVisible(false) clientLabel:setVisible(false)
protocolLabel:setHeight(0) clientLabel: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 +319,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,17 +58,26 @@ EnterGameWindow
margin-top: 8 margin-top: 8
text-auto-resize: true text-auto-resize: true
TextEdit ServerListButton
id: serverHostTextEdit id: serverListButton
!tooltip: tr('Make sure that your client uses\nthe correct game protocol version') !tooltip: tr('Server list')
anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: serverLabel.bottom anchors.top: serverLabel.bottom
margin-top: 3
@onClick: ServerList.show()
TextEdit
id: serverHostTextEdit
!tooltip: tr('Make sure that your client uses\nthe correct game client version')
anchors.left: parent.left
anchors.right: serverListButton.left
anchors.top: serverLabel.bottom
margin-top: 2 margin-top: 2
margin-right: 4
MenuLabel MenuLabel
id: protocolLabel id: clientLabel
!text: tr('Protocol') !text: tr('Client Version')
anchors.left: parent.left anchors.left: parent.left
anchors.top: serverHostTextEdit.bottom anchors.top: serverHostTextEdit.bottom
text-auto-resize: true text-auto-resize: true
@@ -59,10 +85,10 @@ EnterGameWindow
margin-top: 8 margin-top: 8
ComboBox ComboBox
id: protocolComboBox id: clientComboBox
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.horizontalCenter anchors.right: parent.horizontalCenter
anchors.top: protocolLabel.bottom anchors.top: clientLabel.bottom
margin-top: 2 margin-top: 2
margin-right: 3 margin-right: 3
width: 90 width: 90
@@ -80,7 +106,7 @@ EnterGameWindow
text: 7171 text: 7171
anchors.right: parent.right anchors.right: parent.right
anchors.left: parent.horizontalCenter anchors.left: parent.horizontalCenter
anchors.top: protocolComboBox.top anchors.top: clientComboBox.top
margin-left: 3 margin-left: 3
CheckBox CheckBox
@@ -103,9 +129,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

@@ -137,7 +137,7 @@ function unloadCurrentModule()
local module = g_modules.getModule(focusedChild:getText()) local module = g_modules.getModule(focusedChild:getText())
if module then if module then
module:unload() module:unload()
if ModuleManager == nil then return end if modules.client_modulemanager == nil then return end
updateModuleInfo(module:getName()) updateModuleInfo(module:getName())
refreshLoadedModules() refreshLoadedModules()
end end

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
@@ -49,13 +40,17 @@ Panel
!text: tr('Fullscreen') !text: tr('Fullscreen')
tooltip: Ctrl+Shift+F tooltip: Ctrl+Shift+F
OptionCheckBox
id: dontStretchShrink
!text: tr('Don\'t stretch/shrink Game Window')
Label Label
id: backgroundFrameRateLabel id: backgroundFrameRateLabel
!text: tr('Game framerate limit: %s', 'max') !text: tr('Game framerate limit: %s', 'max')
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: prev.bottom anchors.top: prev.bottom
margin-top: 6 margin-top: 12
@onSetup: | @onSetup: |
local value = modules.client_options.getOption('backgroundFrameRate') local value = modules.client_options.getOption('backgroundFrameRate')
local text = value local text = value
@@ -65,7 +60,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 +84,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 +103,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,
@@ -24,7 +25,8 @@ local defaultOptions = {
ambientLight = 25, ambientLight = 25,
displayNames = true, displayNames = true,
displayHealth = true, displayHealth = true,
displayText = true displayText = true,
dontStretchShrink = false
} }
local optionsWindow local optionsWindow
@@ -81,45 +83,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 +109,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 +172,74 @@ 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'
value = 0
end
if graphicsPanel then
graphicsPanel:getChildById('backgroundFrameRateLabel'):setText(tr('Game framerate limit: %s', text)) graphicsPanel:getChildById('backgroundFrameRateLabel'):setText(tr('Game framerate limit: %s', text))
end g_app.setBackgroundPaneMaxFps(v)
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'
value = 0
end
if graphicsPanel then
graphicsPanel:getChildById('foregroundFrameRateLabel'):setText(tr('Interface framerate limit: %s', text)) graphicsPanel:getChildById('foregroundFrameRateLabel'):setText(tr('Interface framerate limit: %s', text))
end g_app.setForegroundPaneMaxFps(v)
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()
map:setDrawLights(value and options['ambientLight'] < 100)
if graphicsPanel then
graphicsPanel:getChildById('ambientLight'):setEnabled(value) graphicsPanel:getChildById('ambientLight'):setEnabled(value)
graphicsPanel:getChildById('ambientLightLabel'):setEnabled(value) graphicsPanel:getChildById('ambientLightLabel'):setEnabled(value)
end
end)
elseif key == 'ambientLight' then elseif key == 'ambientLight' then
addEvent(function()
local map = modules.game_interface.getMapPanel()
if graphicsPanel then
graphicsPanel:getChildById('ambientLightLabel'):setText(tr('Ambient light: %s%%', value)) graphicsPanel:getChildById('ambientLightLabel'):setText(tr('Ambient light: %s%%', value))
end gameMapPanel:setMinimumAmbientLight(value/100)
map:setMinimumAmbientLight(value/100) gameMapPanel:setDrawLights(options['enableLights'] and 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 elseif key == 'dontStretchShrink' then
addEvent(function()
modules.game_interface.updateStretchShrink()
end)
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
if widget:getStyle().__class == 'UICheckBox' then
widget:setChecked(value) 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.getSupportedClients()) 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
local child = widget:getChildByIndex(i)
if child:isVisible() then
local name = child:getId()
if name:match('widget%d+') == nil then
print(string.rep(' ', level) .. name)
end end
if child:getId() ~= 'terminalBuffer' then
dumpWidgets(child, level+1) function draw_debug_boxes()
g_ui.setDebugBoxesDrawing(not g_ui.isDrawingDebugBoxes())
end end
function hide_map()
modules.game_interface.getMapPanel():hide()
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
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)
if newtime > time then
pcolored('Reloading ' .. name, 'green')
modules.client_terminal.flushLines()
module:reload()
files[filepath] = newtime
if name == 'client_terminal' then
modules.client_terminal.show()
end
break
end
end
end, 1000)
end end
function showMap() function live_sprites_reload()
local map = rootWidget:recursiveGetChildById('gameMapPanel') local files = {}
if map then map:show() end 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
function debugContainersItems() if not hasFile then
function UIItem:onHoverChange(hovered) pcolored('ERROR: unable to find things file for module', 'red')
if hovered then return
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
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
local pinging = false
local function pingBack(ping)
if ping < 300 then color = 'green'
elseif ping < 600 then color = 'yellow'
else color = 'red' end
pcolored(g_game.getWorldName() .. ' => ' .. ping .. ' ms', color)
end
function ping()
if pinging then
pcolored('Ping stopped.')
g_game.setPingDelay(1000)
disconnect(g_game, 'onPingBack', pingBack)
else else
g_tooltip.hide() if not (g_game.getFeature(GameClientPing) or g_game.getFeature(GameExtendedClientPing)) then
end pcolored('this server does not support ping', 'red')
end return
elseif not g_game.isOnline() then
pcolored('ping command is only allowed when online', 'red')
return
end end
function debugPosition(enable) pcolored('Starting ping...')
if enable == nil then enable = true end g_game.setPingDelay(0)
local label = rootWidget:getChildById('debugPositionLabel') connect(g_game, 'onPingBack', pingBack)
if not label then
label = g_ui.createWidget('GameLabel', rootWidget)
label:setColor('pink')
label:setFont('terminus-14px-bold')
label:setId('debugPositionLabel')
label:setPosition({x= 10, y = 40 })
label:setPhantom(true)
label:setTextAutoResize(true)
end end
if enable then pinging = not pinging
label.event = cycleEvent(function() end
local player = g_game.getLocalPlayer()
if player then function clear()
local pos = g_game.getLocalPlayer():getPosition() modules.client_terminal.clear()
label:show() end
label:setText('x: ' .. pos.x .. '\ny: ' .. pos.y .. '\nz: ' .. pos.z)
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 else
label:hide() pcolored(path .. v)
end end
end, 100) end
end
function about_version()
pcolored(g_app.getName() .. ' ' .. g_app.getVersion() .. '\n' ..
'Rev ' .. g_app.getBuildRevision() .. ' ('.. g_app.getBuildCommit() .. ')\n' ..
'Built on ' .. g_app.getBuildDate())
end
function about_graphics()
pcolored('Vendor ' .. g_graphics.getVendor() )
pcolored('Renderer' .. g_graphics.getRenderer())
pcolored('Version' .. g_graphics.getVersion())
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 else
removeEvent(label.event) pcolored(m:getName() .. ' => not loaded', 'red')
label.event = nil
label:hide()
end end
end end
function autoReloadModule(name)
local function reloadEvent()
reloadModule(name)
scheduleEvent(reloadEvent, 1000)
end
reloadEvent()
end
function createDebugUIItem(id)
local uiitem = g_ui.createWidget('Item', rootWidget)
uiitem:setPosition({x= 200, y = 200 })
uiitem:setItemId(id)
uiitem:show()
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)
if not g_app.isRunning() then
g_logger.fireOldMessages() 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,56 @@ 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 firstChild = terminalBuffer:getChildByIndex(1)
if firstChild then
local len = #firstChild:getText()
firstChild:destroy()
table.remove(allLines, 1)
fulltext = string.sub(fulltext, len)
end
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 text = string.gsub(text, '\t', ' ')
local label = g_ui.createWidget('TerminalLabel', terminalBuffer) table.insert(cachedLines, {text=text, color=color})
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 +309,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 +346,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, arg1, arg2)
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, arg1, arg2)
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

@@ -20,8 +20,8 @@ function string:starts(start)
return string.sub(self, 1, #start) == start return string.sub(self, 1, #start) == start
end end
function string.ends(s, test) function string:ends(test)
return test =='' or string.sub(s,-string.len(test)) == test return test =='' or string.sub(self,-string.len(test)) == test
end end
function string:trim() function string:trim()

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
@@ -172,6 +171,9 @@ 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

@@ -110,8 +110,10 @@ function UITabBar:selectTab(tab)
tab:setOn(false) tab:setOn(false)
local parent = tab:getParent() local parent = tab:getParent()
if parent then
parent:focusChild(tab, MouseFocusReason) parent:focusChild(tab, MouseFocusReason)
end end
end
function UITabBar:selectNextTab() function UITabBar:selectNextTab()
if self.currentTab == nil then return end if self.currentTab == nil then return end
@@ -144,3 +146,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,15 +19,16 @@ 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
end
return true return true
end end
end
function UITextEdit:onTextAreaUpdate(virtualOffset, virtualSize, totalSize) function UITextEdit:onTextAreaUpdate(virtualOffset, virtualSize, totalSize)
self:updateScrollBars() self:updateScrollBars()

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

@@ -1,11 +1,16 @@
battleWindow = nil battleWindow = nil
battleButton = nil battleButton = nil
battlePanel = nil battlePanel = nil
filterPanel = nil
toggleFilterButton = nil
lastBattleButtonSwitched = nil lastBattleButtonSwitched = nil
battleButtonsByCreaturesList = {} battleButtonsByCreaturesList = {}
creatureAgeList = {}
mouseWidget = nil mouseWidget = nil
sortTypeBox = nil
sortOrderBox = nil
hidePlayersButton = nil hidePlayersButton = nil
hideNPCsButton = nil hideNPCsButton = nil
hideMonstersButton = nil hideMonstersButton = nil
@@ -25,6 +30,15 @@ function init()
battlePanel = battleWindow:recursiveGetChildById('battlePanel') battlePanel = battleWindow:recursiveGetChildById('battlePanel')
filterPanel = battleWindow:recursiveGetChildById('filterPanel')
toggleFilterButton = battleWindow:recursiveGetChildById('toggleFilterButton')
if isHidingFilters() then
hideFilterPanel()
end
sortTypeBox = battleWindow:recursiveGetChildById('sortTypeBox')
sortOrderBox = battleWindow:recursiveGetChildById('sortOrderBox')
hidePlayersButton = battleWindow:recursiveGetChildById('hidePlayers') hidePlayersButton = battleWindow:recursiveGetChildById('hidePlayers')
hideNPCsButton = battleWindow:recursiveGetChildById('hideNPCs') hideNPCsButton = battleWindow:recursiveGetChildById('hideNPCs')
hideMonstersButton = battleWindow:recursiveGetChildById('hideMonsters') hideMonstersButton = battleWindow:recursiveGetChildById('hideMonsters')
@@ -38,6 +52,18 @@ function init()
battleWindow:setContentMinimumHeight(80) battleWindow:setContentMinimumHeight(80)
sortTypeBox:addOption('Name', 'name')
sortTypeBox:addOption('Distance', 'distance')
sortTypeBox:addOption('Age', 'age')
sortTypeBox:addOption('Health', 'health')
sortTypeBox:setCurrentOptionByData(getSortType())
sortTypeBox.onOptionChange = onChangeSortType
sortOrderBox:addOption('Asc.', 'asc')
sortOrderBox:addOption('Desc.', 'desc')
sortOrderBox:setCurrentOptionByData(getSortOrder())
sortOrderBox.onOptionChange = onChangeSortOrder
connect(Creature, { connect(Creature, {
onSkullChange = updateCreatureSkull, onSkullChange = updateCreatureSkull,
onEmblemChange = updateCreatureEmblem, onEmblemChange = updateCreatureEmblem,
@@ -48,6 +74,10 @@ function init()
onDisappear = onCreatureDisappear onDisappear = onCreatureDisappear
}) })
connect(LocalPlayer, {
onPositionChange = onCreaturePositionChange
})
connect(g_game, { connect(g_game, {
onAttackingCreatureChange = onAttack, onAttackingCreatureChange = onAttack,
onFollowingCreatureChange = onFollow, onFollowingCreatureChange = onFollow,
@@ -75,6 +105,10 @@ function terminate()
onDisappear = onCreatureDisappear onDisappear = onCreatureDisappear
}) })
disconnect(LocalPlayer, {
onPositionChange = onCreaturePositionChange
})
disconnect(g_game, { disconnect(g_game, {
onAttackingCreatureChange = onAttack, onAttackingCreatureChange = onAttack,
onFollowingCreatureChange = onFollow, onFollowingCreatureChange = onFollow,
@@ -96,6 +130,93 @@ function onMiniWindowClose()
battleButton:setOn(false) battleButton:setOn(false)
end end
function getSortType()
local settings = g_settings.getNode('BattleList')
if not settings then
return 'name'
end
return settings['sortType']
end
function setSortType(state)
settings = {}
settings['sortType'] = state
g_settings.mergeNode('BattleList', settings)
checkCreatures()
end
function getSortOrder()
local settings = g_settings.getNode('BattleList')
if not settings then
return 'asc'
end
return settings['sortOrder']
end
function setSortOrder(state)
settings = {}
settings['sortOrder'] = state
g_settings.mergeNode('BattleList', settings)
checkCreatures()
end
function isSortAsc()
return getSortOrder() == 'asc'
end
function isSortDesc()
return getSortOrder() == 'desc'
end
function isHidingFilters()
local settings = g_settings.getNode('BattleList')
if not settings then
return false
end
return settings['hidingFilters']
end
function setHidingFilters(state)
settings = {}
settings['hidingFilters'] = state
g_settings.mergeNode('BattleList', settings)
end
function hideFilterPanel()
filterPanel.originalHeight = filterPanel:getHeight()
filterPanel:setHeight(0)
toggleFilterButton:getParent():setMarginTop(0)
toggleFilterButton:setImageClip(torect("0 0 21 12"))
setHidingFilters(true)
filterPanel:setVisible(false)
end
function showFilterPanel()
toggleFilterButton:getParent():setMarginTop(5)
filterPanel:setHeight(filterPanel.originalHeight)
toggleFilterButton:setImageClip(torect("21 0 21 12"))
setHidingFilters(false)
filterPanel:setVisible(true)
end
function toggleFilterPanel()
if filterPanel:isVisible() then
hideFilterPanel()
else
showFilterPanel()
end
end
function onChangeSortType(comboBox, option)
setSortType(option:lower())
end
function onChangeSortOrder(comboBox, option)
setSortOrder(option:lower():gsub('[.]', '')) -- Replace dot in option name
end
function checkCreatures() function checkCreatures()
removeAllCreatures() removeAllCreatures()
@@ -151,15 +272,42 @@ end
function onCreatureHealthPercentChange(creature, health) function onCreatureHealthPercentChange(creature, health)
local battleButton = battleButtonsByCreaturesList[creature:getId()] local battleButton = battleButtonsByCreaturesList[creature:getId()]
if battleButton then if battleButton then
if getSortType() == 'health' then
removeCreature(creature)
addCreature(creature)
return
end
battleButton:setLifeBarPercent(creature:getHealthPercent()) battleButton:setLifeBarPercent(creature:getHealthPercent())
end end
end end
local function getDistanceBetween(p1, p2)
return math.max(math.abs(p1.x - p2.x), math.abs(p1.y - p2.y))
end
function onCreaturePositionChange(creature, newPos, oldPos) function onCreaturePositionChange(creature, newPos, oldPos)
if creature:isLocalPlayer() then if creature:isLocalPlayer() then
if oldPos and newPos and newPos.z ~= oldPos.z then if oldPos and newPos and newPos.z ~= oldPos.z then
checkCreatures() checkCreatures()
else else
-- Distance will change when moving, recalculate and move to correct index
if getSortType() == 'distance' then
local distanceList = {}
for id, creatureButton in pairs(battleButtonsByCreaturesList) do
table.insert(distanceList, {distance = getDistanceBetween(newPos, creatureButton.creature:getPosition()), widget = creatureButton})
end
if isSortAsc() then
table.sort(distanceList, function(a, b) return a.distance < b.distance end)
else
table.sort(distanceList, function(a, b) return a.distance > b.distance end)
end
for i = 1, #distanceList do
battlePanel:moveChildToIndex(distanceList[i].widget, i)
end
end
for id, creatureButton in pairs(battleButtonsByCreaturesList) do for id, creatureButton in pairs(battleButtonsByCreaturesList) do
addCreature(creatureButton.creature) addCreature(creatureButton.creature)
end end
@@ -170,6 +318,9 @@ function onCreaturePositionChange(creature, newPos, oldPos)
if has and not fit then if has and not fit then
removeCreature(creature) removeCreature(creature)
elseif fit then elseif fit then
if has and getSortType() == 'distance' then
removeCreature(creature)
end
addCreature(creature) addCreature(creature)
end end
end end
@@ -201,8 +352,13 @@ function addCreature(creature)
local creatureId = creature:getId() local creatureId = creature:getId()
local battleButton = battleButtonsByCreaturesList[creatureId] local battleButton = battleButtonsByCreaturesList[creatureId]
-- Register when creature is added to battlelist for the first time
if not creatureAgeList[creatureId] then
creatureAgeList[creatureId] = os.time()
end
if not battleButton then if not battleButton then
battleButton = g_ui.createWidget('BattleButton', battlePanel) battleButton = g_ui.createWidget('BattleButton')
battleButton:setup(creature) battleButton:setup(creature)
battleButton.onHoverChange = onBattleButtonHoverChange battleButton.onHoverChange = onBattleButtonHoverChange
@@ -217,6 +373,77 @@ function addCreature(creature)
if creature == g_game.getFollowingCreature() then if creature == g_game.getFollowingCreature() then
onFollow(creature) onFollow(creature)
end end
local inserted = false
local nameLower = creature:getName():lower()
local healthPercent = creature:getHealthPercent()
local playerPosition = g_game.getLocalPlayer():getPosition()
local distance = getDistanceBetween(playerPosition, creature:getPosition())
local age = creatureAgeList[creatureId]
local childCount = battlePanel:getChildCount()
for i = 1, childCount do
local child = battlePanel:getChildByIndex(i)
local childName = child:getCreature():getName():lower()
local equal = false
if getSortType() == 'age' then
local childAge = creatureAgeList[child:getCreature():getId()]
if (age < childAge and isSortAsc()) or (age > childAge and isSortDesc()) then
battlePanel:insertChild(i, battleButton)
inserted = true
break
elseif age == childAge then
equal = true
end
elseif getSortType() == 'distance' then
local childDistance = getDistanceBetween(child:getCreature():getPosition(), playerPosition)
if (distance < childDistance and isSortAsc()) or (distance > childDistance and isSortDesc()) then
battlePanel:insertChild(i, battleButton)
inserted = true
break
elseif childDistance == distance then
equal = true
end
elseif getSortType() == 'health' then
local childHealth = child:getCreature():getHealthPercent()
if (healthPercent < childHealth and isSortAsc()) or (healthPercent > childHealth and isSortDesc()) then
battlePanel:insertChild(i, battleButton)
inserted = true
break
elseif healthPercent == childHealth then
equal = true
end
end
-- If any other sort type is selected and values are equal, sort it by name also
if getSortType() == 'name' or equal then
local length = math.min(childName:len(), nameLower:len())
for j=1,length do
if (nameLower:byte(j) < childName:byte(j) and isSortAsc()) or (nameLower:byte(j) > childName:byte(j) and isSortDesc()) then
battlePanel:insertChild(i, battleButton)
inserted = true
break
elseif (nameLower:byte(j) > childName:byte(j) and isSortAsc()) or (nameLower:byte(j) < childName:byte(j) and isSortDesc()) then
break
elseif j == nameLower:len() and isSortAsc() then
battlePanel:insertChild(i, battleButton)
inserted = true
elseif j == childName:len() and isSortDesc() then
battlePanel:insertChild(i, battleButton)
inserted = true
end
end
end
if inserted then
break
end
end
-- Insert at the end if no other place is found
if not inserted then
battlePanel:insertChild(childCount + 1, battleButton)
end
else else
battleButton:setLifeBarPercent(creature:getHealthPercent()) battleButton:setLifeBarPercent(creature:getHealthPercent())
end end
@@ -226,6 +453,7 @@ function addCreature(creature)
end end
function removeAllCreatures() function removeAllCreatures()
creatureAgeList = {}
for i, v in pairs(battleButtonsByCreaturesList) do for i, v in pairs(battleButtonsByCreaturesList) do
removeCreature(v.creature) removeCreature(v.creature)
end end

View File

@@ -45,11 +45,12 @@ MiniWindow
&save: true &save: true
Panel Panel
id: filterPanel
margin-top: 26 margin-top: 26
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: miniwindowScrollBar.left anchors.right: miniwindowScrollBar.left
height: 20 height: 45
Panel Panel
anchors.top: parent.top anchors.top: parent.top
@@ -85,16 +86,56 @@ MiniWindow
!tooltip: tr('Hide party members') !tooltip: tr('Hide party members')
@onCheckChange: modules.game_battle.checkCreatures() @onCheckChange: modules.game_battle.checkCreatures()
HorizontalSeparator Panel
anchors.top: prev.bottom
anchors.horizontalCenter: parent.horizontalCenter
height: 20
width: 128
margin-top: 6
ComboBox
id: sortTypeBox
width: 74
anchors.top: parent.top
anchors.left: prev.right
anchors.horizontalCenter: parent.horizontalCenter
margin-left: -28
ComboBox
id: sortOrderBox
width: 54
anchors.top: parent.top
anchors.left: prev.right
margin-left: 4
Panel
height: 18
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: miniwindowScrollBar.left anchors.right: miniwindowScrollBar.left
margin-top: 5
UIWidget
id: toggleFilterButton
anchors.top: prev.top
width: 21
anchors.horizontalCenter: parent.horizontalCenter
image-source: /images/ui/arrow_vertical
image-rect: 0 0 21 12
image-clip: 21 0 21 12
@onClick: modules.game_battle.toggleFilterPanel()
phantom: false
HorizontalSeparator
anchors.top: prev.top
anchors.left: parent.left
anchors.right: miniwindowScrollBar.left
margin-right: 1 margin-right: 1
margin-top: 4 margin-top: 11
MiniWindowContents MiniWindowContents
anchors.top: prev.bottom anchors.top: prev.bottom
margin-top: 0 margin-top: 6
Panel Panel
id: battlePanel id: battlePanel

View File

@@ -0,0 +1,206 @@
IgnoreListLabel < Label
font: verdana-11px-monochrome
background-color: alpha
text-offset: 2 0
focusable: true
phantom: false
$focus:
background-color: #ffffff22
color: #ffffff
WhiteListLabel < Label
font: verdana-11px-monochrome
background-color: alpha
text-offset: 2 0
focusable: true
phantom: false
$focus:
background-color: #ffffff22
color: #ffffff
MainWindow
id: communicationWindow
!text: tr('Ignore List')
size: 515 410
@onEscape: self:destroy()
CheckBox
id: checkboxUseIgnoreList
!text: tr('Activate ignorelist')
anchors.left: parent.left
anchors.top: parent.top
width: 180
Label
!text: tr('Ignored Players:')
anchors.left: parent.left
anchors.top: prev.bottom
margin-top: 10
TextList
id: ignoreList
vertical-scrollbar: ignoreListScrollBar
anchors.left: parent.left
anchors.top: prev.bottom
height: 150
width: 230
margin-bottom: 10
margin-top: 3
padding: 1
focusable: false
TextEdit
id: ignoreNameEdit
anchors.top: prev.bottom
anchors.left: parent.left
width: 110
margin-top: 5
Button
id: buttonIgnoreAdd
!text: tr('Add')
width: 48
height: 20
margin-left: 5
anchors.top: prev.top
anchors.left: prev.right
Button
id: buttonIgnoreRemove
!text: tr('Remove')
width: 64
height: 20
margin-left: 5
anchors.top: prev.top
anchors.left: prev.right
Label
!text: tr('Global ignore settings')
anchors.left: parent.left
anchors.top: prev.bottom
margin-top: 20
CheckBox
id: checkboxIgnorePrivateMessages
!text: tr('Ignore Private Messages')
anchors.left: parent.left
anchors.top: prev.bottom
width: 180
margin-top: 5
CheckBox
id: checkboxIgnoreYelling
!text: tr('Ignore Yelling')
anchors.left: parent.left
anchors.top: prev.bottom
width: 180
margin-top: 5
CheckBox
id: checkboxUseWhiteList
!text: tr('Activate whitelist')
anchors.top: parent.top
anchors.left: ignoreList.right
margin-left: 20
width: 180
Label
!text: tr('Allowed Players:')
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 10
TextList
id: whiteList
vertical-scrollbar: whiteListScrollBar
anchors.left: prev.left
anchors.top: prev.bottom
height: 150
width: 230
margin-bottom: 10
margin-top: 3
padding: 1
focusable: false
TextEdit
id: whitelistNameEdit
anchors.top: prev.bottom
anchors.left: prev.left
width: 110
margin-top: 5
Button
id: buttonWhitelistAdd
!text: tr('Add')
width: 48
height: 20
margin-left: 5
anchors.top: prev.top
anchors.left: prev.right
Button
id: buttonWhitelistRemove
!text: tr('Remove')
width: 64
height: 20
margin-left: 5
anchors.top: prev.top
anchors.left: prev.right
Label
!text: tr('Global whitelist settings')
anchors.left: whiteList.left
anchors.top: prev.bottom
margin-top: 20
CheckBox
id: checkboxAllowVIPs
!text: tr('Allow VIPs to message you')
anchors.left: prev.left
anchors.top: prev.bottom
width: 180
margin-top: 5
Panel
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
height: 30
Panel
size: 160 30
anchors.horizontalCenter: parent.horizontalCenter
Button
id: buttonSave
!text: tr('Save')
width: 75
anchors.top: parent.top
anchors.left: parent.left
Button
id: buttonCancel
!text: tr('Cancel')
width: 75
anchors.top: parent.top
anchors.left: prev.right
margin-left: 10
VerticalScrollBar
id: ignoreListScrollBar
anchors.top: ignoreList.top
anchors.bottom: ignoreList.bottom
anchors.right: ignoreList.right
step: 14
pixels-scroll: true
VerticalScrollBar
id: whiteListScrollBar
anchors.top: whiteList.top
anchors.bottom: whiteList.bottom
anchors.right: whiteList.right
step: 14
pixels-scroll: true

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
@@ -61,7 +61,7 @@ consoleTabBar = nil
consoleTextEdit = nil consoleTextEdit = nil
channels = nil channels = nil
channelsWindow = nil channelsWindow = nil
ignoreWindow = nil communicationWindow = nil
ownPrivateName = nil ownPrivateName = nil
messageHistory = {} messageHistory = {}
currentMessageIndex = 0 currentMessageIndex = 0
@@ -72,15 +72,21 @@ violationsChannelId = nil
violationWindow = nil violationWindow = nil
violationReportTab = nil violationReportTab = nil
ignoredChannels = {} ignoredChannels = {}
filters = {}
local ignoreSettings = { local communicationSettings = {
useIgnoreList = true,
useWhiteList = true,
privateMessages = false, privateMessages = false,
yelling = false, yelling = false,
players = {} allowVIPs = false,
ignoredPlayers = {},
whitelistedPlayers = {}
} }
function init() function init()
connect(g_game, { onTalk = onTalk, connect(g_game, {
onTalk = onTalk,
onChannelList = onChannelList, onChannelList = onChannelList,
onOpenChannel = onOpenChannel, onOpenChannel = onOpenChannel,
onOpenPrivateChannel = onOpenPrivateChannel, onOpenPrivateChannel = onOpenPrivateChannel,
@@ -91,7 +97,8 @@ function init()
onRuleViolationCancel = onRuleViolationCancel, onRuleViolationCancel = onRuleViolationCancel,
onRuleViolationLock = onRuleViolationLock, onRuleViolationLock = onRuleViolationLock,
onGameStart = online, onGameStart = online,
onGameEnd = offline }) 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,12 +144,62 @@ 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 consoleToggleChat = consolePanel:getChildById('toggleChat')
loadIgnoreSettings() load()
end
function toggleChat()
if consoleToggleChat:isChecked() then
disableChat()
else
enableChat()
end
end
function enableChat()
local gameInterface = modules.game_interface
consoleTextEdit:setVisible(true)
consoleTextEdit:setText("")
g_keyboard.unbindKeyUp("Space")
g_keyboard.unbindKeyUp("Enter")
gameInterface.unbindWalkKey("W")
gameInterface.unbindWalkKey("D")
gameInterface.unbindWalkKey("S")
gameInterface.unbindWalkKey("A")
consoleToggleChat:setTooltip(tr("Disable chat mode, allow to walk using ASDW"))
end
function disableChat()
local gameInterface = modules.game_interface
consoleTextEdit:setVisible(false)
consoleTextEdit:setText("")
local quickFunc = function()
if consoleToggleChat:isChecked() then
consoleToggleChat:setChecked(false)
end
enableChat()
end
g_keyboard.bindKeyUp("Space", quickFunc)
g_keyboard.bindKeyUp("Enter", quickFunc)
gameInterface.bindWalkKey("W", North)
gameInterface.bindWalkKey("D", East)
gameInterface.bindWalkKey("S", South)
gameInterface.bindWalkKey("A", West)
consoleToggleChat:setTooltip(tr("Enable chat mode"))
end end
function terminate() function terminate()
disconnect(g_game, { onTalk = onTalk, save()
disconnect(g_game, {
onTalk = onTalk,
onChannelList = onChannelList, onChannelList = onChannelList,
onOpenChannel = onOpenChannel, onOpenChannel = onOpenChannel,
onOpenPrivateChannel = onOpenPrivateChannel, onOpenPrivateChannel = onOpenPrivateChannel,
@@ -153,7 +210,8 @@ function terminate()
onRuleViolationCancel = onRuleViolationCancel, onRuleViolationCancel = onRuleViolationCancel,
onRuleViolationLock = onRuleViolationLock, onRuleViolationLock = onRuleViolationLock,
onGameStart = online, onGameStart = online,
onGameEnd = offline }) onGameEnd = offline
})
if g_game.isOnline() then clear() end if g_game.isOnline() then clear() end
@@ -161,14 +219,14 @@ function terminate()
g_keyboard.unbindKeyDown('Ctrl+E') g_keyboard.unbindKeyDown('Ctrl+E')
g_keyboard.unbindKeyDown('Ctrl+H') g_keyboard.unbindKeyDown('Ctrl+H')
saveIgnoreSettings() saveCommunicationSettings()
if channelsWindow then if channelsWindow then
channelsWindow:destroy() channelsWindow:destroy()
end end
if ignoreWindow then if communicationWindow then
ignoreWindow:destroy() communicationWindow:destroy()
end end
if violationWindow then if violationWindow then
@@ -181,6 +239,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
loadCommunicationSettings()
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 +315,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 +342,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 +367,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 +390,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,21 +506,20 @@ 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
local highlightData = getHighlightedText(text)
if #highlightData > 0 then
local labelHighlight = g_ui.createWidget('ConsolePhantomLabel', label)
labelHighlight:fill('parent')
labelHighlight:setId('consoleLabelHighlight' .. consoleBuffer:getChildCount())
labelHighlight:setColor("#1f9ffe") 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)
if #highlightData == 0 then
labelHighlight:setText("")
else
-- 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] }
text = text:gsub("{"..dataBlock.words.."}", dataBlock.words) text = text:gsub("%{(.-)%}", dataBlock.words, 1)
-- Recalculate positions as braces are removed -- Recalculate positions as braces are removed
highlightData[(i-1)*3+1] = dataBlock._start - ((i-1) * 2) highlightData[(i-1)*3+1] = dataBlock._start - ((i-1) * 2)
@@ -482,8 +554,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 +564,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 +645,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 +671,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 +727,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 +748,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
@@ -730,7 +832,11 @@ function onTalk(name, level, mode, message, channelId, creaturePos)
return return
end end
if name ~= g_game.getCharacterName() then local localPlayer = g_game.getLocalPlayer()
if name ~= g_game.getCharacterName()
and isUsingIgnoreList()
and not(isUsingWhiteList()) or (isUsingWhiteList() and not(isWhitelisted(name)) and not(isAllowingVIPs() and localPlayer:hasVip(name))) then
if mode == MessageModes.Yell and isIgnoringYelling() then if mode == MessageModes.Yell and isIgnoringYelling() then
return return
elseif speaktype.private and isIgnoringPrivate() and mode ~= MessageModes.NpcFrom then elseif speaktype.private and isIgnoringPrivate() and mode ~= MessageModes.NpcFrom then
@@ -857,6 +963,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
@@ -907,107 +1014,221 @@ function onChannelList(channelList)
end end
end end
function loadIgnoreSettings() function loadCommunicationSettings()
communicationSettings.whitelistedPlayers = {}
communicationSettings.ignoredPlayers = {}
local ignoreNode = g_settings.getNode('IgnorePlayers') local ignoreNode = g_settings.getNode('IgnorePlayers')
if ignoreNode then if ignoreNode then
for i = 1, #ignoreNode do for i = 1, #ignoreNode do
table.insert(ignoreSettings.players, ignoreNode[i]) table.insert(communicationSettings.ignoredPlayers, ignoreNode[i])
end end
end end
ignoreSettings.privateMessages = g_settings.getBoolean('IgnorePrivateMessages')
ignoreSettings.yelling = g_settings.getBoolean('IgnoreYelling')
end
function saveIgnoreSettings() local whitelistNode = g_settings.getNode('WhitelistedPlayers')
local tmpSettings = {} if whitelistNode then
for i = 1, #ignoreSettings.players do for i = 1, #whitelistNode do
table.insert(tmpSettings, ignoreSettings.players[i]) table.insert(communicationSettings.whitelistedPlayers, whitelistNode[i])
end end
g_settings.set('IgnorePrivateMessages', ignoreSettings.privateMessages)
g_settings.set('IgnoreYelling', ignoreSettings.yelling)
g_settings.setNode('IgnorePlayers', tmpSettings)
end end
communicationSettings.useIgnoreList = g_settings.getBoolean('UseIgnoreList')
communicationSettings.useWhiteList = g_settings.getBoolean('UseWhiteList')
communicationSettings.privateMessages = g_settings.getBoolean('IgnorePrivateMessages')
communicationSettings.yelling = g_settings.getBoolean('IgnoreYelling')
communicationSettings.allowVIPs = g_settings.getBoolean('AllowVIPs')
end
function saveCommunicationSettings()
local tmpIgnoreList = {}
local ignoredPlayers = getIgnoredPlayers()
for i = 1, #ignoredPlayers do
table.insert(tmpIgnoreList, ignoredPlayers[i])
end
local tmpWhiteList = {}
local whitelistedPlayers = getWhitelistedPlayers()
for i = 1, #whitelistedPlayers do
table.insert(tmpWhiteList, whitelistedPlayers[i])
end
g_settings.set('UseIgnoreList', communicationSettings.useIgnoreList)
g_settings.set('UseWhiteList', communicationSettings.useWhiteList)
g_settings.set('IgnorePrivateMessages', communicationSettings.privateMessages)
g_settings.set('IgnoreYelling', communicationSettings.yelling)
g_settings.setNode('IgnorePlayers', tmpIgnoreList)
g_settings.setNode('WhitelistedPlayers', tmpWhiteList)
end
function getIgnoredPlayers()
return communicationSettings.ignoredPlayers
end
function getWhitelistedPlayers()
return communicationSettings.whitelistedPlayers
end
function isUsingIgnoreList()
return communicationSettings.useIgnoreList
end
function isUsingWhiteList()
return communicationSettings.useWhiteList
end
function isIgnored(name) function isIgnored(name)
return table.find(ignoreSettings.players, name, true) return table.find(communicationSettings.ignoredPlayers, name, true)
end end
function addIgnoredPlayer(name) function addIgnoredPlayer(name)
if not isIgnored(name) then if isIgnored(name) then return end
table.insert(ignoreSettings.players, name) table.insert(communicationSettings.ignoredPlayers, name)
end
end end
function removeIgnoredPlayer(name) function removeIgnoredPlayer(name)
table.removevalue(ignoreSettings.players, name) table.removevalue(communicationSettings.ignoredPlayers, name)
end
function isWhitelisted(name)
return table.find(communicationSettings.whitelistedPlayers, name, true)
end
function addWhitelistedPlayer(name)
if isWhitelisted(name) then return end
table.insert(communicationSettings.whitelistedPlayers, name)
end
function removeWhitelistedPlayer(name)
table.removevalue(communicationSettings.whitelistedPlayers, name)
end end
function isIgnoringPrivate() function isIgnoringPrivate()
return ignoreSettings.privateMessages return communicationSettings.privateMessages
end end
function isIgnoringYelling() function isIgnoringYelling()
return ignoreSettings.yelling return communicationSettings.yelling
end
function isAllowingVIPs()
return communicationSettings.allowVIPs
end end
function onClickIgnoreButton() function onClickIgnoreButton()
if ignoreWindow then return end if communicationWindow then return end
ignoreWindow = g_ui.displayUI('ignorewindow') communicationWindow = g_ui.displayUI('communicationwindow')
local ignoreListPanel = ignoreWindow:getChildById('ignoreList') local ignoreListPanel = communicationWindow:getChildById('ignoreList')
ignoreWindow.onDestroy = function() ignoreWindow = nil end local whiteListPanel = communicationWindow:getChildById('whiteList')
communicationWindow.onDestroy = function() communicationWindow = nil end
local removeButton = ignoreWindow:getChildById('buttonRemove') local useIgnoreListBox = communicationWindow:getChildById('checkboxUseIgnoreList')
removeButton:disable() useIgnoreListBox:setChecked(communicationSettings.useIgnoreList)
ignoreListPanel.onChildFocusChange = function() removeButton:enable() end local useWhiteListBox = communicationWindow:getChildById('checkboxUseWhiteList')
removeButton.onClick = function() useWhiteListBox:setChecked(communicationSettings.useWhiteList)
local removeIgnoreButton = communicationWindow:getChildById('buttonIgnoreRemove')
removeIgnoreButton:disable()
ignoreListPanel.onChildFocusChange = function() removeIgnoreButton:enable() end
removeIgnoreButton.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 removeIgnoreButton:disable()
removeButton:disable()
end end
local removeWhitelistButton = communicationWindow:getChildById('buttonWhitelistRemove')
removeWhitelistButton:disable()
whiteListPanel.onChildFocusChange = function() removeWhitelistButton:enable() end
removeWhitelistButton.onClick = function()
local selection = whiteListPanel:getFocusedChild()
if selection then
whiteListPanel:removeChild(selection)
selection:destroy()
end
removeWhitelistButton:disable()
end end
local newlyIgnoredPlayers = {} local newlyIgnoredPlayers = {}
local addName = ignoreWindow:getChildById('ignoreNameEdit') local addIgnoreName = communicationWindow:getChildById('ignoreNameEdit')
local addButton = ignoreWindow:getChildById('buttonAdd') local addIgnoreButton = communicationWindow:getChildById('buttonIgnoreAdd')
local addFunction = function() local addIgnoreFunction = function()
if addName:getText() == '' then return end local newEntry = addIgnoreName:getText()
if table.find(ignoreSettings.players, addName:getText()) then return end if newEntry == '' then return end
if table.find(newlyIgnoredPlayers, addName:getText()) then return end if table.find(getIgnoredPlayers(), newEntry) then return end
if table.find(newlyIgnoredPlayers, newEntry) then return end
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel) local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
label:setText(addName:getText()) label:setText(newEntry)
table.insert(newlyIgnoredPlayers, addName:getText()) table.insert(newlyIgnoredPlayers, newEntry)
label:setPhantom(false) addIgnoreName:setText('')
addName:setText('')
end end
addButton.onClick = addFunction addIgnoreButton.onClick = addIgnoreFunction
ignoreWindow.onEnter = addFunction
local ignorePrivateMessageBox = ignoreWindow:getChildById('checkboxIgnorePrivateMessages') local newlyWhitelistedPlayers = {}
ignorePrivateMessageBox:setChecked(ignoreSettings.privateMessages) local addWhitelistName = communicationWindow:getChildById('whitelistNameEdit')
local ignoreYellingBox = ignoreWindow:getChildById('checkboxIgnoreYelling') local addWhitelistButton = communicationWindow:getChildById('buttonWhitelistAdd')
ignoreYellingBox:setChecked(ignoreSettings.yelling) local addWhitelistFunction = function()
local newEntry = addWhitelistName:getText()
if newEntry == '' then return end
if table.find(getWhitelistedPlayers(), newEntry) then return end
if table.find(newlyWhitelistedPlayers, newEntry) then return end
local label = g_ui.createWidget('WhiteListLabel', whiteListPanel)
label:setText(newEntry)
table.insert(newlyWhitelistedPlayers, newEntry)
addWhitelistName:setText('')
end
addWhitelistButton.onClick = addWhitelistFunction
local saveButton = ignoreWindow:getChildById('buttonSave') communicationWindow.onEnter = function()
if addWhitelistName:isFocused() then
addWhitelistFunction()
elseif addIgnoreName:isFocused() then
addIgnoreFunction()
end
end
local ignorePrivateMessageBox = communicationWindow:getChildById('checkboxIgnorePrivateMessages')
ignorePrivateMessageBox:setChecked(communicationSettings.privateMessages)
local ignoreYellingBox = communicationWindow:getChildById('checkboxIgnoreYelling')
ignoreYellingBox:setChecked(communicationSettings.yelling)
local allowVIPsBox = communicationWindow:getChildById('checkboxAllowVIPs')
allowVIPsBox:setChecked(communicationSettings.allowVIPs)
local saveButton = communicationWindow:recursiveGetChildById('buttonSave')
saveButton.onClick = function() saveButton.onClick = function()
ignoreSettings.players = {} communicationSettings.ignoredPlayers = {}
for i = 1, ignoreListPanel:getChildCount() do for i = 1, ignoreListPanel:getChildCount() do
addIgnoredPlayer(ignoreListPanel:getChildByIndex(i):getText()) addIgnoredPlayer(ignoreListPanel:getChildByIndex(i):getText())
--table.insert(ignoreSettings.players, ignoreListPanel:getChildByIndex(i):getText())
end end
ignoreSettings.yelling = ignoreYellingBox:isChecked() communicationSettings.whitelistedPlayers = {}
ignoreSettings.privateMessages = ignorePrivateMessageBox:isChecked() for i = 1, whiteListPanel:getChildCount() do
ignoreWindow:destroy() addWhitelistedPlayer(whiteListPanel:getChildByIndex(i):getText())
end end
for _, name in pairs(ignoreSettings.players) do communicationSettings.useIgnoreList = useIgnoreListBox:isChecked()
communicationSettings.useWhiteList = useWhiteListBox:isChecked()
communicationSettings.yelling = ignoreYellingBox:isChecked()
communicationSettings.privateMessages = ignorePrivateMessageBox:isChecked()
communicationSettings.allowVIPs = allowVIPsBox:isChecked()
communicationWindow:destroy()
end
local cancelButton = communicationWindow:recursiveGetChildById('buttonCancel')
cancelButton.onClick = function()
communicationWindow:destroy()
end
local ignoredPlayers = getIgnoredPlayers()
for i = 1, #ignoredPlayers do
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel) local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
label:setText(name) label:setText(ignoredPlayers[i])
label:setPhantom(false) end
local whitelistedPlayers = getWhitelistedPlayers()
for i = 1, #whitelistedPlayers do
local label = g_ui.createWidget('WhiteListLabel', whiteListPanel)
label:setText(whitelistedPlayers[i])
end end
end end

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
@@ -78,17 +56,25 @@ Panel
id: consolePanel id: consolePanel
anchors.fill: parent anchors.fill: parent
CheckBox
id: toggleChat
!tooltip: tr('Disable chat mode, allow to walk using ASDW')
anchors.left: parent.left
anchors.top: parent.top
margin-left: 13
margin-top: 8
@onCheckChange: toggleChat()
TabButton TabButton
id: prevChannelButton id: prevChannelButton
icon: /images/game/console/leftarrow icon: /images/game/console/leftarrow
anchors.left: parent.left anchors.left: toggleChat.right
anchors.top: parent.top anchors.top: parent.top
margin-left: 6 margin-left: 3
margin-top: 6 margin-top: 6
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

@@ -1,98 +0,0 @@
IgnoreListLabel < Label
font: verdana-11px-monochrome
background-color: alpha
text-offset: 2 0
focusable: true
$focus:
background-color: #ffffff22
color: #ffffff
MainWindow
id: ignoreWindow
!text: tr('Ignore List')
size: 500 240
@onEscape: self:destroy()
Label
!text: tr('Ignored players:')
anchors.left: parent.left
anchors.top: parent.top
TextList
id: ignoreList
vertical-scrollbar: ignoreListScrollBar
anchors.left: parent.left
anchors.top: prev.bottom
height: 150
width: 230
margin-bottom: 10
margin-top: 3
padding: 1
focusable: false
Button
id: buttonRemove
!text: tr('Remove')
width: 64
anchors.right: prev.right
anchors.bottom: parent.bottom
TextEdit
id: ignoreNameEdit
anchors.left: ignoreList.right
anchors.top: ignoreList.top
width: 180
margin-left: 8
margin-right: 3
Button
id: buttonAdd
!text: tr('Add')
width: 48
height: 20
anchors.right: parent.right
anchors.top: prev.top
CheckBox
id: checkboxIgnorePrivateMessages
!text: tr('Ignore Private Messages')
anchors.left: ignoreList.right
anchors.top: ignoreList.top
width: 180
margin-top: 25
margin-left: 8
CheckBox
id: checkboxIgnoreYelling
!text: tr('Ignore Yelling')
anchors.left: ignoreList.right
anchors.top: prev.top
width: 180
margin-top: 25
margin-left: 8
Button
id: buttonSave
!text: tr('Save')
width: 64
anchors.right: next.left
anchors.bottom: parent.bottom
margin-right: 10
@onClick: self:getParent():onEnter()
Button
id: buttonCancel
!text: tr('Cancel')
width: 64
anchors.right: parent.right
anchors.bottom: parent.bottom
@onClick: self:getParent():destroy()
VerticalScrollBar
id: ignoreListScrollBar
anchors.top: ignoreList.top
anchors.bottom: ignoreList.bottom
anchors.right: ignoreList.right
step: 14
pixels-scroll: true

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,13 +29,17 @@ end
function clean() function clean()
for containerid,container in pairs(g_game.getContainers()) do for containerid,container in pairs(g_game.getContainers()) do
destroy(container)
end
end
function destroy(container)
if container.window then if container.window then
container.window:destroy() container.window:destroy()
container.window = nil container.window = nil
container.itemsPanel = nil container.itemsPanel = nil
end end
end end
end
function refreshContainerItems(container) function refreshContainerItems(container)
for slot=0,container:getCapacity()-1 do for slot=0,container:getCapacity()-1 do
@@ -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,11 +97,17 @@ 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:setParent(content)
end
end
function loadIcon(bitChanged)
local icon = g_ui.createWidget('ConditionWidget', content)
icon:setId(Icons[bitChanged].id) icon:setId(Icons[bitChanged].id)
icon:setImageSource(Icons[bitChanged].path) icon:setImageSource(Icons[bitChanged].path)
icon:setTooltip(Icons[bitChanged].tooltip) icon:setTooltip(Icons[bitChanged].tooltip)
end return icon
end end
function offline() function offline()
@@ -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,31 +192,39 @@ 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
if not hotkeys[G.host] then
hotkeys[G.host] = {} 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 end
hotkeys = hotkeys[char]
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,
itemId = child.itemId, itemId = child.itemId,
subType = child.subType,
useType = child.useType, useType = child.useType,
value = child.value value = child.value
} }
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()
@@ -250,6 +267,9 @@ function onChooseItemMouseRelease(self, mousePosition, mouseButton)
if item and currentHotkeyLabel then if item and currentHotkeyLabel then
currentHotkeyLabel.itemId = item:getId() currentHotkeyLabel.itemId = item:getId()
if item:isFluidContainer() then
currentHotkeyLabel.subType = item:getSubType()
end
if item:isMultiUse() then if item:isMultiUse() then
currentHotkeyLabel.useType = HOTKEY_MANAGER_USEWITH currentHotkeyLabel.useType = HOTKEY_MANAGER_USEWITH
else else
@@ -258,7 +278,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()
@@ -277,11 +297,12 @@ end
function clearObject() function clearObject()
currentHotkeyLabel.itemId = nil currentHotkeyLabel.itemId = nil
currentHotkeyLabel.subType = nil
currentHotkeyLabel.useType = nil currentHotkeyLabel.useType = nil
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 +315,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 +343,30 @@ 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.subType = tonumber(keySettings.subType)
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.subType = 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,15 +382,42 @@ 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) if g_game.getProtocolVersion() < 780 or hotKey.subType then
local item = g_game.findPlayerItem(hotKey.itemId, hotKey.subType or -1)
if item then
g_game.use(item)
end
else
g_game.useInventoryItem(hotKey.itemId)
end
elseif hotKey.useType == HOTKEY_MANAGER_USEONSELF then elseif hotKey.useType == HOTKEY_MANAGER_USEONSELF then
if g_game.getProtocolVersion() < 780 or hotKey.subType then
local item = g_game.findPlayerItem(hotKey.itemId, hotKey.subType or -1)
if item then
g_game.useWith(item, g_game.getLocalPlayer())
end
else
g_game.useInventoryItemWith(hotKey.itemId, g_game.getLocalPlayer()) g_game.useInventoryItemWith(hotKey.itemId, g_game.getLocalPlayer())
end
elseif hotKey.useType == HOTKEY_MANAGER_USEONTARGET then elseif hotKey.useType == HOTKEY_MANAGER_USEONTARGET then
local attackingCreature = g_game.getAttackingCreature() local attackingCreature = g_game.getAttackingCreature()
if not attackingCreature then return end if not attackingCreature then return end
if not attackingCreature:getTile() then return end
if g_game.getProtocolVersion() < 780 or hotKey.subType then
local item = g_game.findPlayerItem(hotKey.itemId, hotKey.subType or -1)
if item then
g_game.useWith(item, attackingCreature)
end
else
g_game.useInventoryItemWith(hotKey.itemId, attackingCreature) g_game.useInventoryItemWith(hotKey.itemId, attackingCreature)
end
elseif hotKey.useType == HOTKEY_MANAGER_USEWITH then elseif hotKey.useType == HOTKEY_MANAGER_USEWITH then
local item = Item.create(hotKey.itemId) local item = Item.create(hotKey.itemId)
if g_game.getProtocolVersion() < 780 or hotKey.subType then
local tmpItem = g_game.findPlayerItem(hotKey.itemId, hotKey.subType or -1)
if not tmpItem then return true end
item = tmpItem
end
modules.game_interface.startUseWith(item) modules.game_interface.startUseWith(item)
end end
end end
@@ -398,7 +450,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
@@ -410,6 +462,9 @@ function updateHotkeyForm()
selectObjectButton:disable() selectObjectButton:disable()
clearObjectButton:enable() clearObjectButton:enable()
currentItemPreview:setItemId(currentHotkeyLabel.itemId) currentItemPreview:setItemId(currentHotkeyLabel.itemId)
if currentHotkeyLabel.subType then
currentItemPreview:setItemSubType(currentHotkeyLabel.subType)
end
if currentItemPreview:getItem():isMultiUse() then if currentItemPreview:getItem():isMultiUse() then
useOnSelf:enable() useOnSelf:enable()
useOnTarget:enable() useOnTarget:enable()
@@ -435,8 +490,10 @@ function updateHotkeyForm()
hotkeyText:enable() hotkeyText:enable()
hotkeyText:focus() hotkeyText:focus()
hotKeyTextLabel:enable() hotKeyTextLabel:enable()
hotkeyText:setText(currentHotkeyLabel.value) if reset then
hotkeyText:setCursorPos(-1) hotkeyText:setCursorPos(-1)
end
hotkeyText:setText(currentHotkeyLabel.value)
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 +518,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 +562,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
@@ -12,20 +11,19 @@ countWindow = nil
logoutWindow = nil logoutWindow = nil
exitWindow = nil exitWindow = nil
bottomSplitter = nil bottomSplitter = nil
limitZoom = false limitedZoom = 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')
@@ -44,11 +42,13 @@ function init()
gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel') gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel')
connect(gameLeftPanel, { onVisibilityChange = onLeftPanelVisibilityChange }) connect(gameLeftPanel, { onVisibilityChange = onLeftPanelVisibilityChange })
logoutButton = modules.client_topmenu.addLeftButton('logoutButton', tr('Exit'), '/images/topbuttons/logout', tryLogout, true) logoutButton = modules.client_topmenu.addLeftButton('logoutButton', tr('Exit'),
'/images/topbuttons/logout', tryLogout, true)
setupViewMode(0) setupViewMode(0)
bindKeys() bindKeys()
load()
if g_game.isOnline() then if g_game.isOnline() then
show() show()
@@ -56,68 +56,58 @@ function init()
end end
function bindKeys() function bindKeys()
g_keyboard.bindKeyDown('Up', function() changeWalkDir(North) end, gameRootPanel, true) gameRootPanel:setAutoRepeatDelay(250)
g_keyboard.bindKeyDown('Right', function() changeWalkDir(East) end, gameRootPanel, true)
g_keyboard.bindKeyDown('Down', function() changeWalkDir(South) end, gameRootPanel, true)
g_keyboard.bindKeyDown('Left', function() changeWalkDir(West) end, gameRootPanel, true)
g_keyboard.bindKeyDown('Numpad8', function() changeWalkDir(North) end, gameRootPanel, true)
g_keyboard.bindKeyDown('Numpad9', function() changeWalkDir(NorthEast) end, gameRootPanel, true)
g_keyboard.bindKeyDown('Numpad6', function() changeWalkDir(East) end, gameRootPanel, true)
g_keyboard.bindKeyDown('Numpad3', function() changeWalkDir(SouthEast) end, gameRootPanel, true)
g_keyboard.bindKeyDown('Numpad2', function() changeWalkDir(South) end, gameRootPanel, true)
g_keyboard.bindKeyDown('Numpad1', function() changeWalkDir(SouthWest) end, gameRootPanel, true)
g_keyboard.bindKeyDown('Numpad4', function() changeWalkDir(West) end, gameRootPanel, true)
g_keyboard.bindKeyDown('Numpad7', function() changeWalkDir(NorthWest) end, gameRootPanel, true)
g_keyboard.bindKeyUp('Up', function() changeWalkDir(North, true) end, gameRootPanel, true)
g_keyboard.bindKeyUp('Right', function() changeWalkDir(East, true) end, gameRootPanel, true)
g_keyboard.bindKeyUp('Down', function() changeWalkDir(South, true) end, gameRootPanel, true)
g_keyboard.bindKeyUp('Left', function() changeWalkDir(West, true) end, gameRootPanel, true)
g_keyboard.bindKeyUp('Numpad8', function() changeWalkDir(North, true) end, gameRootPanel, true)
g_keyboard.bindKeyUp('Numpad9', function() changeWalkDir(NorthEast, true) end, gameRootPanel, true)
g_keyboard.bindKeyUp('Numpad6', function() changeWalkDir(East, true) end, gameRootPanel, true)
g_keyboard.bindKeyUp('Numpad3', function() changeWalkDir(SouthEast, true) end, gameRootPanel, true)
g_keyboard.bindKeyUp('Numpad2', function() changeWalkDir(South, 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('Numpad7', function() changeWalkDir(NorthWest, true) end, gameRootPanel, true)
g_keyboard.bindKeyPress('Up', function() smartWalk(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Right', function() smartWalk(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Down', function() smartWalk(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Left', function() smartWalk(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad8', function() smartWalk(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad9', function() smartWalk(NorthEast) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad6', function() smartWalk(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad3', function() smartWalk(SouthEast) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad2', function() smartWalk(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad1', function() smartWalk(SouthWest) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad4', function() smartWalk(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Numpad7', function() smartWalk(NorthWest) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY)
g_keyboard.bindKeyPress('Ctrl+Up', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) bindWalkKey('Up', North)
g_keyboard.bindKeyPress('Ctrl+Right', function() g_game.turn(East) changeWalkDir(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) bindWalkKey('Right', East)
g_keyboard.bindKeyPress('Ctrl+Down', function() g_game.turn(South) changeWalkDir(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) bindWalkKey('Down', South)
g_keyboard.bindKeyPress('Ctrl+Left', function() g_game.turn(West) changeWalkDir(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) bindWalkKey('Left', West)
g_keyboard.bindKeyPress('Ctrl+Numpad8', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) bindWalkKey('Numpad8', North)
g_keyboard.bindKeyPress('Ctrl+Numpad6', function() g_game.turn(East) changeWalkDir(East) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) bindWalkKey('Numpad9', NorthEast)
g_keyboard.bindKeyPress('Ctrl+Numpad2', function() g_game.turn(South) changeWalkDir(South) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) bindWalkKey('Numpad6', East)
g_keyboard.bindKeyPress('Ctrl+Numpad4', function() g_game.turn(West) changeWalkDir(West) end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) bindWalkKey('Numpad3', SouthEast)
g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel, WALK_AUTO_REPEAT_DELAY) bindWalkKey('Numpad2', South)
g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel, 250) bindWalkKey('Numpad1', SouthWest)
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel, 250) bindWalkKey('Numpad4', West)
g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel) bindWalkKey('Numpad7', NorthWest)
g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel)
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)
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)
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)
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)
g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel)
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+Q', function() tryLogout(false) end, gameRootPanel)
g_keyboard.bindKeyDown('Ctrl+L', function() tryLogout(false) end, 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)
g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel) g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel)
end end
function bindWalkKey(key, dir)
g_keyboard.bindKeyDown(key, function() changeWalkDir(dir) end, gameRootPanel, true)
g_keyboard.bindKeyUp(key, function() changeWalkDir(dir, true) end, gameRootPanel, true)
g_keyboard.bindKeyPress(key, function() smartWalk(dir) end, gameRootPanel)
end
function unbindWalkKey(key)
g_keyboard.unbindKeyDown(key, gameRootPanel)
g_keyboard.unbindKeyUp(key, gameRootPanel)
g_keyboard.unbindKeyPress(key, gameRootPanel)
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
}) })
@@ -150,11 +140,19 @@ 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'))
addEvent(function()
if not limitedZoom or g_game.isGM() then
gameMapPanel:setMaxZoomOut(513)
gameMapPanel:setLimitVisibleRange(false)
else
gameMapPanel:setMaxZoomOut(11)
gameMapPanel:setLimitVisibleRange(true)
end
end)
end end
function hide() function hide()
@@ -177,11 +175,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
@@ -191,8 +205,8 @@ function tryExit()
return true return true
end end
local exitFunc = function() logout() forceExit() end local exitFunc = function() g_game.safeLogout() forceExit() end
local logoutFunc = function() logout() exitWindow:destroy() exitWindow = nil end local logoutFunc = function() g_game.safeLogout() exitWindow:destroy() exitWindow = nil end
local cancelFunc = function() exitWindow:destroy() exitWindow = nil end local cancelFunc = function() exitWindow:destroy() exitWindow = nil end
exitWindow = displayGeneralBox(tr('Exit'), tr("If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character."), exitWindow = displayGeneralBox(tr('Exit'), tr("If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character."),
@@ -204,29 +218,55 @@ function tryExit()
return true return true
end end
function logout() function tryLogout(prompt)
if g_game.isOnline() then if type(prompt) ~= "boolean" then
g_game.safeLogout() prompt = true
return true
end end
end
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
return return
end end
local yesCallback = function() logout() logoutWindow:destroy() logoutWindow=nil end local msg, yesCallback
local noCallback = function() logoutWindow:destroy() logoutWindow=nil end if not g_game.isConnectionOk() then
msg = 'Your connection is failing, if you logout now your character will be still online, do you want to force logout?'
logoutWindow = displayGeneralBox(tr('Logout'), tr('Are you sure you want to logout?'), { yesCallback = function()
g_game.forceLogout()
if logoutWindow then
logoutWindow:destroy()
logoutWindow=nil
end
end
else
msg = 'Are you sure you want to logout?'
yesCallback = function()
g_game.safeLogout()
if logoutWindow then
logoutWindow:destroy()
logoutWindow=nil
end
end
end
local noCallback = function()
logoutWindow:destroy()
logoutWindow=nil
end
if prompt then
logoutWindow = displayGeneralBox(tr('Logout'), tr(msg), {
{ text=tr('Yes'), callback=yesCallback }, { text=tr('Yes'), callback=yesCallback },
{ text=tr('No'), callback=noCallback }, { text=tr('No'), callback=noCallback },
anchor=AnchorHorizontalCenter}, yesCallback, noCallback) anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
else
yesCallback()
end
end end
function stopSmartWalk() function stopSmartWalk()
@@ -267,11 +307,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
if modules.client_options.getOption('dashWalk') then
func = g_game.dashWalk
else else
walkFunction(dir) func = g_game.walk
end end
end
local dire = smartWalkDir or dir
func(dire)
return true return true
end end
return false return false
@@ -433,7 +478,9 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
end end
else else
local localPosition = localPlayer:getPosition()
if not classic then shortcut = '(Alt)' else shortcut = nil end if not classic then shortcut = '(Alt)' else shortcut = nil end
if creatureThing:getPosition().z == localPosition.z then
if g_game.getAttackingCreature() ~= creatureThing then if g_game.getAttackingCreature() ~= creatureThing then
menu:addOption(tr('Attack'), function() g_game.attack(creatureThing) end, shortcut) menu:addOption(tr('Attack'), function() g_game.attack(creatureThing) end, shortcut)
else else
@@ -445,6 +492,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
else else
menu:addOption(tr('Stop Follow'), function() g_game.cancelFollow() end) menu:addOption(tr('Stop Follow'), function() g_game.cancelFollow() end)
end end
end
if creatureThing:isPlayer() then if creatureThing:isPlayer() then
menu:addSeparator() menu:addSeparator()
@@ -489,7 +537,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
end end
end end
if modules.game_ruleviolation.hasWindowAccess() then if modules.game_ruleviolation.hasWindowAccess() and creatureThing:isPlayer() then
menu:addSeparator() menu:addSeparator()
menu:addOption(tr('Rule Violation'), function() modules.game_ruleviolation.show(creatureThing:getName()) end) menu:addOption(tr('Rule Violation'), function() modules.game_ruleviolation.show(creatureThing:getName()) end)
end end
@@ -501,7 +549,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
menu:display(menuPosition) menu:display(menuPosition)
end end
function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing) function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing, attackCreature)
local keyboardModifiers = g_keyboard.getModifiers() local keyboardModifiers = g_keyboard.getModifiers()
if not modules.client_options.getOption('classicControl') then if not modules.client_options.getOption('classicControl') then
@@ -527,7 +575,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
return true return true
end end
return true return true
elseif creatureThing and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then elseif attackCreature and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
g_game.attack(attackCreature)
return true
elseif creatureThing and creatureThing:getPosition().z == autoWalkPos.z and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
g_game.attack(creatureThing) g_game.attack(creatureThing)
return true return true
end end
@@ -536,7 +587,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
else else
if useThing and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then if useThing and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
local player = g_game.getLocalPlayer() local player = g_game.getLocalPlayer()
if creatureThing and creatureThing ~= player then if attackCreature and attackCreature ~= player then
g_game.attack(attackCreature)
return true
elseif creatureThing and creatureThing ~= player and creatureThing:getPosition().z == autoWalkPos.z then
g_game.attack(creatureThing) g_game.attack(creatureThing)
return true return true
elseif useThing:isContainer() then elseif useThing:isContainer() then
@@ -564,7 +618,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
elseif useThing and keyboardModifiers == KeyboardCtrlModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then elseif useThing and keyboardModifiers == KeyboardCtrlModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
createThingMenu(menuPosition, lookThing, useThing, creatureThing) createThingMenu(menuPosition, lookThing, useThing, creatureThing)
return true return true
elseif creatureThing and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then elseif attackCreature and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
g_game.attack(attackCreature)
return true
elseif creatureThing and creatureThing:getPosition().z == autoWalkPos.z and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
g_game.attack(creatureThing) g_game.attack(creatureThing)
return true return true
end end
@@ -574,7 +631,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
@@ -626,6 +682,8 @@ function moveStackableItem(item, toPos)
end end
g_keyboard.bindKeyPress("Up", function() check() spinbox:up() end, spinbox) g_keyboard.bindKeyPress("Up", function() check() spinbox:up() end, spinbox)
g_keyboard.bindKeyPress("Down", function() check() spinbox:down() end, spinbox) g_keyboard.bindKeyPress("Down", function() check() spinbox:down() end, spinbox)
g_keyboard.bindKeyPress("Right", function() check() spinbox:up() end, spinbox)
g_keyboard.bindKeyPress("Left", function() check() spinbox:down() end, spinbox)
g_keyboard.bindKeyPress("PageUp", function() check() spinbox:setValue(spinbox:getValue()+10) end, spinbox) g_keyboard.bindKeyPress("PageUp", function() check() spinbox:setValue(spinbox:getValue()+10) end, spinbox)
g_keyboard.bindKeyPress("PageDown", function() check() spinbox:setValue(spinbox:getValue()-10) end, spinbox) g_keyboard.bindKeyPress("PageDown", function() check() spinbox:setValue(spinbox:getValue()-10) end, spinbox)
@@ -717,7 +775,7 @@ function setupViewMode(mode)
gameMapPanel:setZoom(11) gameMapPanel:setZoom(11)
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 = limitedZoom and not g_game.isGM()
gameMapPanel:setLimitVisibleRange(limit) gameMapPanel:setLimitVisibleRange(limit)
gameMapPanel:setZoom(11) gameMapPanel:setZoom(11)
gameMapPanel:setVisibleDimension({ width = 15, height = 11 }) gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
@@ -742,11 +800,5 @@ function setupViewMode(mode)
end end
function limitZoom() function limitZoom()
limitZoom = true limitedZoom = true
end
function onGMActions()
if not limitZoom then return end
gameMapPanel:setMaxZoomOut(513)
gameMapPanel:setLimitVisibleRange(false)
end end

View File

@@ -6,11 +6,11 @@ CountWindow < MainWindow
SpinBox SpinBox
id: spinBox id: spinBox
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.bottom anchors.top: parent.top
width: 0 width: 1
height: 0 height: 1
phantom: true phantom: true
padding-bottom: -40 margin-top: 2
focusable: true focusable: true
Item Item

View File

@@ -78,6 +78,7 @@ function UIGameMap:onMouseRelease(mousePosition, mouseButton)
local useThing local useThing
local creatureThing local creatureThing
local multiUseThing local multiUseThing
local attackCreature
local tile = self:getTile(mousePosition) local tile = self:getTile(mousePosition)
if tile then if tile then
@@ -86,7 +87,12 @@ function UIGameMap:onMouseRelease(mousePosition, mouseButton)
creatureThing = tile:getTopCreature() creatureThing = tile:getTopCreature()
end end
local ret = modules.game_interface.processMouseAction(mousePosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing) local autoWalkTile = g_map.getTile(autoWalkPos)
if autoWalkTile then
attackCreature = autoWalkTile:getTopCreature()
end
local ret = modules.game_interface.processMouseAction(mousePosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing, attackCreature)
if ret then if ret then
self.allowNextRelease = false self.allowNextRelease = false
end end

View File

@@ -86,7 +86,7 @@ function UIItem:onMouseRelease(mousePosition, mouseButton)
g_game.look(item) g_game.look(item)
self.cancelNextRelease = true self.cancelNextRelease = true
return true return true
elseif modules.game_interface.processMouseAction(mousePosition, mouseButton, nil, item, item, nil, item) then elseif modules.game_interface.processMouseAction(mousePosition, mouseButton, nil, item, item, nil, nil) then
return true return true
end end
return false return false

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
if marketData.category == category or category == MarketCategory.All then
-- create new item block
local item = { local item = {
ptr = newItem, ptr = newItem,
marketData = marketData marketData = marketData
} }
marketItems[marketData.category][#marketItems[category]+1] = item
-- 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,20 +908,15 @@ 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
local filterSearchAll = filterButtons[MarketFilters.SearchAll]:isChecked()
if filterSearchAll and searchFilter then
category = MarketCategory.All category = MarketCategory.All
end end
end
if category == MarketCategory.All then if category == MarketCategory.All then
-- loop all categories -- loop all categories
@@ -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,7 @@ 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(currentTradeType == SELL)
refreshTradeItems() refreshTradeItems()
refreshPlayerGoods() refreshPlayerGoods()
@@ -199,8 +207,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 +229,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 +264,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 +335,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 +353,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 +369,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)
@@ -453,7 +451,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,16 @@ 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()
Button Button
id: tradeButton id: tradeButton
!text: tr('Buy') !text: tr('Buy')

View File

@@ -17,6 +17,7 @@ end
function reset() function reset()
if deathWindow then if deathWindow then
deathWindow:destroy() deathWindow:destroy()
deathWindow = nil
end end
end end
@@ -33,7 +34,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')
@@ -44,7 +48,7 @@ function openWindow()
deathWindow = nil deathWindow = nil
end end
local cancelFunc = function() local cancelFunc = function()
modules.game_interface.logout() g_game.safeLogout()
cancelButton:getParent():destroy() cancelButton:getParent():destroy()
deathWindow = nil deathWindow = nil
end end

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

@@ -28,6 +28,8 @@ MessageTypes = {
[MessageModes.Blue] = MessageSettings.consoleBlue, [MessageModes.Blue] = MessageSettings.consoleBlue,
[MessageModes.PrivateFrom] = MessageSettings.consoleBlue, [MessageModes.PrivateFrom] = MessageSettings.consoleBlue,
[MessageModes.GamemasterBroadcast] = MessageSettings.consoleRed,
[MessageModes.DamageDealed] = MessageSettings.status, [MessageModes.DamageDealed] = MessageSettings.status,
[MessageModes.DamageReceived] = MessageSettings.status, [MessageModes.DamageReceived] = MessageSettings.status,
[MessageModes.Heal] = MessageSettings.status, [MessageModes.Heal] = MessageSettings.status,
@@ -123,3 +125,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

@@ -18,7 +18,7 @@ function isLoaded()
end end
function load() function load()
local version = g_game.getProtocolVersion() local version = g_game.getClientVersion()
local datPath, sprPath local datPath, sprPath
if filename then if filename then

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