Compare commits

...

410 Commits

Author SHA1 Message Date
divinity76
dab86e6109
Make OutputMessage::addRawString available in Lua (#1218) 2024-09-14 17:26:54 +02:00
vfjpl
e6861d79c9
Use float literals where applicable (#1210) 2023-08-14 04:47:12 +02:00
diath
52475761cd
Save the minimap on a per server basis
Co-authored-by: Xagul <eixim@hotmail.com>
2022-12-10 10:52:03 +01:00
diath
a3fdf073b9
Use lambdas instead of std::bind (#1200) 2022-11-26 19:15:38 +01:00
Marcin Michalski
77f05b9476
Run CI on ubuntu 20.04 (#1199) 2022-11-26 01:50:42 +01:00
Marcin Michalski
0e5de3383e
Prevent luaL_newlib macro redefinition (#1198) 2022-11-26 01:28:21 +01:00
Marcin Michalski
4a39d49fc1
Update workflow actions (#1197)
* Update workflow actions

* Update actions/checkout to v3
2022-11-26 01:06:57 +01:00
Marcin Michalski
725c200c9f
Update vcpkg (#1196) 2022-11-26 00:12:00 +01:00
diath
da4bb92c33
Fix UIWidget::propagateOnMouseMove repeatedly adding the mouse receiver to the list (#1195) 2022-11-25 18:03:51 +01:00
diath
77c844d006
Fix building with newest Boost.Asio (#1194) 2022-11-25 18:00:45 +01:00
Marcin Michalski
fc39ee4adb
Correctly include vcpkg LuaJIT in Visual Studio (#1174) 2022-05-26 13:45:13 +02:00
Kacper
b098210c6a move big functions from .h to .cpp 2022-05-26 13:40:01 +02:00
Marcin Michalski
f0d7963883 Fix compilation with GMP 2022-04-28 14:09:08 +02:00
Marcin Michalski
836ea2bdc6 Update vcpkg 2022-04-28 14:09:08 +02:00
Marcin Michalski
45afb65b90
Remove client stats module (#1170) 2022-01-26 20:13:18 +01:00
diath
d3e12b5d44
Make UIWidget::resizeToText() respect widget padding and text offset like text-auto-resize does (#1167) 2021-11-24 20:10:13 +01:00
Marcin Michalski
3092b5b2d5
Update physfs repo in Dockerfile (#1165) 2021-11-15 23:13:41 +01:00
diath
e73f6df221
Fix process hang on fatal errors (#1163) 2021-09-29 21:03:12 +02:00
diath
9eb13494f9
Fix ghost item border when dropping non-item objects (#1164) 2021-09-29 21:03:01 +02:00
vfjpl
1d614e294c
Fix std::istream::streampos deprecation warning (#1154) 2021-08-25 19:24:08 +02:00
Marcin Michalski
e0d5b7d7fd
Update vcpkg & switch back to ubuntu 18.04 in workflow (#1161) 2021-08-22 01:21:17 +02:00
Marcin Michalski
10100342b9
Fix opening "https://"-prefixed links on Windows (#1160) 2021-08-22 00:51:18 +02:00
Marcin Michalski
302748b2f3
Fix opening URLs on macOS (#1159) 2021-08-22 00:48:34 +02:00
Marcin Michalski
f173b03dbd
Map option to alt and command to meta keys on macOS (#1158) 2021-08-22 00:38:58 +02:00
vfjpl
89dc0f87eb
Fix stamina minutes check in the skills window (#1155) 2021-07-22 00:02:27 +02:00
vfjpl
9ce2cab9ae
Fix uninitialized oldMaxMana variable in Player::setMana (#1152) 2021-06-16 23:25:43 +02:00
TheSumm
1e29b5cb01 Remove unused source file 2021-06-12 19:40:21 +02:00
Samuel
8eb01df240
Fix vcpkg compiling (#1153) 2021-06-12 18:07:18 +02:00
diath
6cd5eb3e22
Add clickable NPC keywords (#1148) 2021-04-29 18:06:48 +02:00
Ranieri Althoff
5cc9319a94
Optimize XTEA encryption (#1143)
https://dev.to/rsa/making-an-algorithm-15x-faster-without-parallelism-38k5
2021-04-02 21:48:58 +02:00
vfjpl
3600a9b40b
Fix Lua errors when the client is built without the sound framework (#1142) 2021-04-02 21:35:34 +02:00
diath
b37623cd86
Fix the use of deprecated C++ functions (#1138) 2021-04-01 00:38:36 +02:00
vfjpl
67b7dbfcfe
Keep log messages in a deque instead of a list and remove unnecessary copy
Co-authored-by: Kacper Piwiński <kacper.piwinski@arex.pl>
2021-04-01 00:38:02 +02:00
vfjpl
7752add8aa
Use float literals where applicable (#1140)
Use float literals to perform more calculation in float instead of performing implicit conversion to double and back to float.

Co-authored-by: Kacper Piwiński <kacper.piwinski@arex.pl>
2021-04-01 00:06:50 +02:00
diath
7c528be73e
Cleanup CMake project (#1137)
* Updated the minimum required standard from C++11 to C++14 (https://en.wikipedia.org/wiki/C%2B%2B14).
* Fixed -g0 and -Os flags being passed to luafunctions.cpp when building with MSVC.
* Fixed case mismatch in FIND_PACKAGE_HANDLE_STANDARD_ARGS argument in a number of CMake files.
2021-03-31 07:30:09 +02:00
vfjpl
4d055913dc
Clean up BitmapFont code (#1129) 2021-03-30 17:03:02 +02:00
Marcin Michalski
4edb1eb3ad
Fix adding executable icon on windows with non-msvc compiler (#1136) 2021-03-30 08:58:32 +02:00
Marcin Michalski
69e44a3722
Fix & enable by default static linking on macOS (#1133) 2021-03-29 17:22:04 +02:00
Marcin Michalski
ba706fc5c3
Remove travis (#1135)
Replaced by GitHub workflows.
2021-03-29 16:58:38 +02:00
Marcin Michalski
975d138a57
Run windows workflow with luajit only (#1134) 2021-03-29 16:54:02 +02:00
Marcin Michalski
c4530a6d17
Bump minimum required CMake version to 3.1 (#1131)
* Removed Ubuntu Clang workflow
* Removed FindCXX.cmake (in favor of native feature)
* Added support for building Windows binaries with CMake when using MSVC
* Cleaned up a number of Find*.cmake modules
2021-03-27 01:04:59 +01:00
Marcin Michalski
b6399a8ad9
Update workflow (#1130) 2021-03-26 14:37:02 +01:00
Kamil Chojnowski
9c9b85ac5e Fix UITextEdit::setTextHidden ignoring the hidden param and always setting the member variable to true 2021-03-14 21:12:59 +01:00
Martin Nylind
872abf05f4
Add Missile:setPath to Lua interface (#1125)
Add Missile:setPath(fromPos, toPos) method to Lua interface.
2021-02-10 05:40:39 +01:00
peonso
d07e7fcce7
Correct messageModsMap for version 10.41 (#1119) 2021-01-04 17:33:04 +01:00
vfjpl
f521737b26
Return Tile walking creatures and things by const ref instead of copy (#1117) 2020-11-23 17:26:15 +01:00
reyhammer
18dd9c2d2d
Fix TPoint::distanceFrom() calling TPoint::getLength() instead of TPoint::length() (#1116) 2020-11-23 15:59:50 +01:00
vfjpl
72cc4b2fb0
Fix out-of-bounds access in Platform::getCPUName (#1115) 2020-11-22 22:08:37 +01:00
vfjpl
c6d0fc0f71
Fix laggy diagonal movement (#1108) 2020-10-07 03:14:00 +02:00
vfjpl
b3d947d4c3
Use std::deque for queues (#1112) 2020-10-07 03:12:04 +02:00
bakasuradbl
83959e5e23
Fix window position when entering fullscreen mode on Windows platform (#1099) 2020-10-05 19:59:36 +02:00
Source61
70400bc83e
Add optional format string for stdext::date_time_string() (#1110) 2020-09-15 18:58:47 +02:00
vfjpl
9c1f519f8a
resourcemanager:[bug fix] directoryExists method should resolvePath before checking (#1102) 2020-08-29 17:35:42 +02:00
diath
88d0ea34bf
Fix UITabBar and UIMoveableTabBar bricking when removing first tabs in (#1101) collapsed view
Co-authored-by: Xagul <eixim@hotmail.com>
2020-08-26 09:54:56 +02:00
diath
b3aaa10646
Remove stdext::packed_vector (#1106)
Co-authored-by: Kacper Piwiński <cosiekvfj@o2.pl>
2020-08-26 09:54:05 +02:00
diath
59059321a6
Fix an issue with pathfinding not respecting the PathFindAllowCreatures flag properly (#1090) 2020-06-13 09:00:01 +02:00
4drik
b0a73e5525
Fix an issue with the VIP list data not being stored properly (#1083)
The VIP IDs aren't guaranteed to be stable.
2020-05-27 21:41:25 +02:00
Oscar
307a618591
Spanish language revised (#1088)
* Spanish language revised
2020-05-22 02:11:37 +02:00
Oscar
28c2f46f13
Fix comma_value result treated as an int (#1087) 2020-05-09 16:32:19 +02:00
slavidodo
190131a1b8
Update project version to celebrate github workflows 2020-05-09 09:06:53 +02:00
slavi
de97869384
Adding build with vcpkg github workflow
- updated gitignore
- build-vcpkg
2020-05-09 08:55:33 +02:00
slavidodo
eb031e8584
removing datapack preparing 2020-05-09 08:54:02 +02:00
slavidodo
0f78727db5
remove mysql removal step 2020-05-09 08:52:27 +02:00
slavidodo
dcd3573e16
Building with vcpkg 2020-05-09 08:46:31 +02:00
slavidodo
48c3a8992f
Update gitignore 2020-05-09 08:45:00 +02:00
slavidodo
d95bde1c77
fixing some unused variables and hiding previous/class members warnings 2020-05-07 19:05:16 +02:00
slavidodo
e3caaacc55
Use vcpkg & drop OTClient SDK for windows
additionaly, the project has been updated to Visual Studio 2019!
2020-05-07 19:02:20 +02:00
Ascuas Funkeln
714c6b8fc0
Add comma_value function for pretty formatting big numbers (#1085)
This also applies the function to a number of labels in the skills window.
2020-05-05 18:39:11 +02:00
Konrad Kuśnierz
63f5351016
Merge pull request #1021 from edubart/openssl-gmp
Support for OpenSSL with a fallback to GMP
2020-03-31 17:09:45 +02:00
Konrad Kuśnierz
066df4dd52
Merge pull request #1070 from Ochmar/master
Getting rid of redraw on lying corpse
2020-02-03 10:23:42 +01:00
OchmanM
e1c3fac974
Getting rid of redraw on lying corpse
In https://github.com/edubart/otclient/issues/1040#issuecomment-581173589 we had a discussion if tile:draw() redrawing in case of lying corpse either is needed or not. We came to conclusion that there are way too many downsides of this resolution and therefore we opt against redrawing. Both performance-wise and gameplay-wise it is better without redrawing.
2020-02-03 10:07:19 +01:00
Konrad Kuśnierz
a0abcbb54e
Merge pull request #1065 from Sposito/update-copyright-year-2020
Update Copyright year for 2020
2019-12-31 11:44:26 +01:00
Sposito
fbcf0a3eea Update copyright year for 2020 2019-12-31 10:07:29 +00:00
Zbizu
fe6bbd6c21 fix initial language selection
fix language selection bug

steps to reproduce:
- go to c:/users/username/otclient and remove settings file
- launch otclient
- select english
- restart otclient

expected behaviour: no more startup prompts for language selection when selecting default language
observed behaviour: everytime client gets restarted and you click the default language, it doesn't get saved if it didn't exist in config file previously
2019-12-19 19:20:12 +01:00
Zbizu
be7a7d365f fixing typo in PL translation
punkt -> plural: punkty
2019-12-15 17:53:01 +01:00
Zbizu
45b14060f6 allow using up/down arrows in modalWindow
QoL change, that's how it works in the official client
2019-12-14 04:27:52 +01:00
Zbizu
a7785a3029 removing duplicate 2019-12-13 04:14:47 +01:00
Zbizu
451075516d focus first choice in modalWindow by default (QoL)
selecting first modalwindow choice by default like in cip client
2019-12-13 04:14:47 +01:00
4drik
49e3ded63c Update console.lua
I was wrong, still need it for multireturn unpack
2019-11-21 13:47:15 +01:00
4drik
14a93a13c8 Update battle.lua
Indentation
2019-11-21 13:47:15 +01:00
4drik
3019e88293 Update uiitem.lua
Indentation
2019-11-21 13:47:15 +01:00
4drik
91a80017b4 Fix for moving creatures/items far out of reach
Fix to https://github.com/edubart/otclient/issues/1055
2019-11-21 13:47:15 +01:00
4drik
656dff45f1 Fix for moving creatures/items far out of reach
Fix to https://github.com/edubart/otclient/issues/1055
2019-11-21 13:47:15 +01:00
4drik
11b006c356 Fix for container miniWindow
A fix for container miniWindow that should be able to move.
2019-11-21 13:47:15 +01:00
4drik
62d84d13d0 Delete unused variable. 2019-11-21 13:47:15 +01:00
4drik
521e87ca00 Fix target square
The target square disappeared when using filters in the battle window.
2019-11-21 13:47:15 +01:00
Leonardo Dias
6217d8805b Update dockerfile to use physfs stable 3.0 2019-10-22 22:51:01 +02:00
Konrad Kuśnierz
23bc0ab4b7
Merge pull request #1052 from diath/fix_demangle_name
Fix a possible missing null terminator in the demangle_name output buffer
2019-10-14 08:10:08 +02:00
Konrad Kuśnierz
0b0c8191dd
Merge pull request #1048 from diath/fix_static_linkage
Fix an issue with Connection class linkage
2019-10-14 08:09:54 +02:00
Kamil Chojnowski
7a57acd646 Fix a possible missing null terminator in the demangle_name output buffer 2019-10-14 07:56:06 +02:00
Kamil Chojnowski
80b35b8308 Fix an issue with Connection class linkage 2019-10-14 07:54:39 +02:00
Konrad Kuśnierz
ca868b9b61
Merge pull request #1049 from diath/update_resourcemanager
Move isDirectory logic from an anonymous namespace to ResourceManager::directoryExists
2019-10-11 08:47:49 +02:00
Konrad Kuśnierz
9a0abb1452
Merge pull request #1047 from diath/update_travis
Update Travis build file to use physfs stable 3.0 branch
2019-10-11 08:46:53 +02:00
Kamil Chojnowski
ba12f55fe4 Move isDirectory logic from an anonymous namespace to ResourceManager::directoryExists 2019-10-11 03:23:01 +02:00
Kamil Chojnowski
cd7b09e27e Update Travis build file to use physfs stable 3.0 branch 2019-10-11 03:15:22 +02:00
Konrad Kuśnierz
1ab18788e6
Merge pull request #1039 from slavidodo/master
Correcting text offset
2019-10-10 08:14:47 +02:00
Konrad Kuśnierz
dd0303feee
Merge pull request #1046 from diath/fix_deprecated_physfs_funcs
Fix use of deprecated PhysFS functions
2019-10-10 08:14:08 +02:00
Konrad Kuśnierz
2f76fe1c3c
Merge pull request #1045 from diath/dft_cpy_mov_ctor
Add default copy constructors to Color and Position classes
2019-10-10 08:13:50 +02:00
Konrad Kuśnierz
831a87abc9
Merge pull request #1044 from diath/tidy_up
Tidy up the source code
2019-10-10 08:13:36 +02:00
Konrad Kuśnierz
f048b0e414
Merge pull request #1042 from f0rmiga/improve-docker-support
Improved Docker support
2019-10-10 08:12:52 +02:00
Kamil Chojnowski
6f13914a92 Fix use of deprecated PhysFS functions 2019-10-10 06:30:31 +02:00
Kamil Chojnowski
6a2d12ce27 Add default copy constructors to Color and Position classes 2019-10-10 01:47:34 +02:00
Kamil Chojnowski
869de6886f Tidy up the source code
* Replaced push_back calls with emplace_back where applicable.
* Replaced size() == 0 and size() != 0 with empty() and !empty().
* Replaced C style loops for range for loops where applicable.
* Fixed mismatching arg names between function declarations and definitions.
* Replaced NULL and 0 (in the context of pointers) with nullptr.
* Remove unnecessary calls to string::c_str() where applicable.
* Replaced deprecated C headers with proper C++ headers.
* Removed unnecessary null pointer checks when deleting pointers
(deleting a null pointer has no effect).
* Fixed a potential memory leak in apngloader.cpp file.
* Replaced unsafe strcpy with strncpy in the demangle_name function.
2019-10-10 00:59:24 +02:00
Thulio Ferraz Assis
5bde14d6ba Improved concurrency for building on CI 2019-09-26 20:19:46 -07:00
Thulio Ferraz Assis
9bb251e14a Refactored before_script for TravisCI 2019-09-26 20:19:37 -07:00
Thulio Ferraz Assis
22a23ee977 Used MAKE_BUILD_TYPE=Release instead of strip 2019-09-26 19:59:40 -07:00
Thulio Ferraz Assis
f6358492a5 Removed unnecessary mv for libphysfs.a 2019-09-26 19:59:07 -07:00
Thulio Ferraz Assis
272867e56e Used nproc instead of grepping /proc/cpuinfo 2019-09-26 19:58:19 -07:00
Thulio Ferraz Assis
0f69f11b78 Improved Docker support 2019-09-26 18:23:08 -07:00
Nickolas Coppem
17738dfdea
Correcting text offset 2019-07-06 19:41:39 +02:00
Konrad Kuśnierz
caae18dbce
Merge pull request #1038 from diath/fix_tooltip_move
Fix tooltip position updating
2019-07-02 09:08:01 +02:00
Kamil Chojnowski
09593e3382 Fix tooltip position updating 2019-07-02 01:58:40 +02:00
Konrad Kuśnierz
15d8793a93
Merge pull request #1037 from diath/improve_mouse_move_propagation
Improve mouse move event propagation
2019-07-01 19:16:22 +02:00
Kamil Chojnowski
da564e86cf Improve mouse move event propagation 2019-07-01 17:36:25 +02:00
Konrad Kuśnierz
7922f8238e
Merge pull request #1032 from diath/fix_config_setvalue
Fix clearing a config key
2019-06-03 00:53:12 +02:00
Kamil Chojnowski
501552dc23 Fix clearing a config key 2019-06-02 20:05:34 +02:00
Konrad Kuśnierz
83ae66e6ae
Merge pull request #1026 from divinity76/patch-3
urlencode stuff
2019-04-29 01:13:52 +02:00
Konrad Kuśnierz
fdba9d5e9c
Merge pull request #1030 from Shawak/patch-1
don't call getChildren() thrice
2019-04-28 10:40:20 +02:00
Maximilian
833f029335
don't call getChildren() thrice 2019-04-27 19:21:38 +02:00
divinity76
97d2be8187
urlencode stuff
for example spaces should be %20 encoded and the @ in `Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz` should be encoded to %40

but the real problem is the possibility that these stings may include the `&` character, which should be encoded as %25 (but wasn't prior to this commit)
2019-04-14 13:54:30 +02:00
Konrad Kuśnierz
e244ba4775
Merge pull request #1025 from diath/fix_ignore_list
Fix saving ignore list and whitelist
2019-03-31 10:29:42 +02:00
Kamil Chojnowski
e5ec5ff6c8 Fix saving ignore list and whitelist 2019-03-31 08:34:32 +02:00
Konrad Kuśnierz
88e271c4ad Minor GMP typos 2019-03-09 23:55:07 +01:00
Konrad Kuśnierz
779eb56068
Fix setBuffer of InputMessage class 2019-03-09 23:35:52 +01:00
Konrad Kuśnierz
c9845a36fc Support for OpenSSL with a fallback to GMP 2019-03-09 23:21:02 +01:00
Konrad Kuśnierz
322c6fde3e Change default AVX instructions to SSE2 as mentioned in #1019 2019-03-09 00:34:35 +01:00
Konrad Kuśnierz
1c8cea513c
Fix setBuffer of the OutputMessage class 2019-03-06 14:48:46 +01:00
Konrad Kuśnierz
92532a958e
Merge pull request #967 from EgzoT/EgzoT-OutputMessage_setBuffer_2
Add setBuffer() method to OutputMessage class
2019-03-06 14:46:24 +01:00
Konrad Kuśnierz
53f57dfcf7
Merge pull request #929 from vamo89/vamo89-patch-2
Update translations
2019-03-06 14:36:15 +01:00
Konrad Kuśnierz
ef8fa2472c
Merge pull request #1001 from divinity76/patch-2
OpenSSL >= 1.1.0 compatibility
2019-03-06 14:30:20 +01:00
Konrad Kuśnierz
8b8e7312ea
Fix code style 2019-03-06 09:41:37 +01:00
Konrad Kuśnierz
fd3db800fe
Fix default init of BIGNUM to nullptr 2019-03-05 09:29:13 +01:00
Konrad Kuśnierz
9186ac5321
Follow OTClient code style 2019-03-05 00:44:18 +01:00
Konrad Kuśnierz
d2a68ea301
Merge pull request #1008 from Arkamek/vs-settings
Fix glew32/zlib debug build.
2019-01-30 22:13:05 +01:00
Arkamek
b231725294 Fix glew32/zlib debug mode 2019-01-30 16:19:56 +01:00
Konrad Kuśnierz
62a48a94ff
Merge pull request #919 from EgzoT/EgzoT-VS_OTC_upd_ver
Update OTClient outdated version in VS project
2019-01-16 14:16:20 +01:00
Konrad Kuśnierz
68872dd02c
Merge pull request #950 from codetriage-readme-bot/codetriage-badge
Add CodeTriage badge to edubart/otclient
2019-01-16 14:14:11 +01:00
Konrad Kuśnierz
c1369a7c92
Merge branch 'master' into codetriage-badge 2019-01-16 14:13:18 +01:00
Konrad Kuśnierz
c4dce79b15
Update README.md 2019-01-16 14:08:50 +01:00
Konrad Kuśnierz
c58bf46f5e
Merge pull request #954 from DavidUser/feature/docker-support
Docker support
2019-01-16 14:08:09 +01:00
Konrad Kuśnierz
8b2bb127b0
Merge pull request #951 from EgzoT/EgzoT-setupViewMode_2_fix
Fix problem with display text in setupViewMode_2
2019-01-16 14:03:17 +01:00
Konrad Kuśnierz
33b60e842f
Merge pull request #966 from diath/msvc_fixes
Silence Windows SDK warnings when building with MSVC
2019-01-16 13:57:30 +01:00
Konrad Kuśnierz
70a95b2f04
Merge pull request #972 from EgzoT/EgzoT-UIComboBox_fix_getOption_to_isOption
Fixed getOption and rename to isOption
2019-01-16 13:56:20 +01:00
Konrad Kuśnierz
e3b02a7c5d
Merge pull request #986 from okk3/patch-1
Function updateJump() fix
2019-01-16 13:53:14 +01:00
Konrad Kuśnierz
74d328206b
Merge pull request #1002 from diath/fix_magic_effects
Fix magic effect animations in newer client versions
2019-01-16 13:50:51 +01:00
Konrad Kuśnierz
db3ba0f679
Merge pull request #1006 from diath/improve_scrollbar_navigation
Improve scrollbar navigation
2019-01-16 13:36:33 +01:00
Konrad Kuśnierz
d563aafbc9
Merge pull request #990 from EgzoT/EgzoT-Show_more_information_in_stamina_bar_2
Show more information in stamina bar
2019-01-16 13:35:05 +01:00
Konrad Kuśnierz
7e31980ba3
Merge pull request #965 from diath/fix_tab_blink
Fix tab blink
2019-01-16 13:32:39 +01:00
Konrad Kuśnierz
f7ceb788e8
Merge pull request #1004 from diath/add_channel_events
Add support for channel events
2019-01-16 13:30:09 +01:00
Konrad Kuśnierz
710212c23a
Merge pull request #1003 from diath/fix_keyboard_desc
Fix an issue with key combo desc not working properly with integer keys
2019-01-16 13:25:37 +01:00
Samuel Gros
d1500746c0
Merge pull request #981 from DSpeichert/vcpkg-fixes
Compilation & linking fixes
2019-01-07 12:50:39 +01:00
Samuel Gros
a6c7269f78
Merge pull request #1005 from diath/message_prefixes
Don't apply message prefixes to messages with empty name
2019-01-06 14:32:59 +01:00
Kamil Chojnowski
a40130d79b Fix magic effect animations in newer client versions 2019-01-06 06:17:25 +01:00
Kamil Chojnowski
8301bc74f3 Add support for channel events 2019-01-05 22:22:01 +01:00
Kamil Chojnowski
c4be084516 Fix an issue with key combo desc not working properly with integer keys 2019-01-05 19:31:19 +01:00
Kamil Chojnowski
b8228ac6eb Don't apply message prefixes to messages with empty name 2019-01-05 18:14:38 +01:00
Kamil Chojnowski
57a1f5eebe Improve scrollbar navigation 2019-01-05 18:13:36 +01:00
divinity76
79e31cb041
OpenSSL >= 1.1.0 compatibility
OpenSSL did some otclient-breaking changes around 1.1.0, 
this patch should work on both < and >= 1.1.0
2018-12-06 00:51:16 +01:00
EgzoT
0e8464bd42
Show more information in stamina bar
1. Change colors on certain values, when stamina time was change.
2. Change tooltip on certain values, when stamina time was change.
3. Work with most protocols, including the most popular (8.54 - 10.98).
4. In protocols >= 1031 use information about premium account to show if player have premium stamina time.
2018-09-03 16:33:07 +02:00
Okke
a93333ddbf
Function updateJump() fix
nextT should cast double as it's a second degree equation and results in a double type. -> Bhaskara.
2018-08-06 00:08:37 +02:00
Daniel Speichert
dc729d9846
Fix formatting 2018-07-16 08:47:31 -04:00
Daniel Speichert
271790d22e Upgrade vcxproj + fix path to OpenAL from vcpkg 2018-07-15 17:37:36 -04:00
Daniel Speichert
ad769d6614 Fix compilation errors (READ_TIMEOUT, READ_TIMEOUT) 2018-07-15 17:03:21 -04:00
Samuel Gros
07b4b785fc
Merge pull request #934 from diath/fix_login_protocol
Fix parsing the premium status in newer login protocol versions
2018-07-13 00:11:40 +02:00
EgzoT
95ce65d8cc
Fixed getOption and rename to isOption
Fixed getOption who always return nil.
Rename getOption to isOption.
2018-06-09 18:08:56 +02:00
Samuel Gros
1addf3e176
Merge pull request #971 from rmalizia44/patch-1
Fixing a typo
2018-05-09 14:31:32 +02:00
Malizia R
b813508eb7
Fixing a typo 2018-05-09 06:56:14 -03:00
EgzoT
9e9d88f184 Add setBuffer() method to OutputMessage class 2018-04-24 23:21:58 +02:00
Kamil Chojnowski
1bd392aba9 Silence Windows SDK warnings when building with MSVC 2018-04-23 14:33:08 +02:00
Kamil Chojnowski
ba558404d3 Fix tab blink 2018-04-23 14:29:39 +02:00
David Kennedy S. A
d03ffc1f26 Enable any client connect to X host 2018-03-28 11:57:59 -03:00
David Kennedy S. A
251c937b7e Disable SE Linux when running the client on container 2018-03-21 01:56:38 -03:00
David Kennedy S. A
934513df80 Build and run with docker container 2018-03-21 01:55:51 -03:00
David Kennedy S. A
9142a096df Add dockerfile to build ubuntu version 2018-03-21 01:54:10 -03:00
EgzoT
9daec49212
Fix problem with display text in setupViewMode_2
Fix problem with display text messages in setupViewMode - 2 ([CTRL + .] x 2).
Status messages was display in other place (higher than player character).
2018-03-05 11:43:38 +01:00
EgzoT
4007980c0c Change outdated compiler name for VS (#920)
Change "msvc12" compiler name to "Visual Studio [13-17]" for Visual Studio compiler. 
Name based on "_MSC_VER" parameter.
2018-02-28 21:48:27 +01:00
EgzoT
b58c438015 UIMiniWindowContainer small improve (#938)
Change type of checking whether window have on drop possibility.

Reason:
Previously this parameter was checking by class name, so it blocking creating similar objects to miniwindow or inheritance from miniwindow object without changing sources. So it block creating modules with new UI objects working with miniwindowcontainer.
2018-02-28 21:46:27 +01:00
EgzoT
e6f273d5e1 Add functionality to minimap flags system (#931)
- Add parameter 'temporary' to method 'UIMinimap:addFlag', who prevents saving flag with this parameter (look 'UIMinimap:save' method), add flag only at game session time. Old parameters list work the same at previous - backward compatibility.
- Add possibility to add icon from outside (for example from module folder) using link to this file. Old system with choose flag name by number work the same at previous, now method check if paramether is number then use old system otherwise get icon from path - backward compatibility. 'Mods' friendly.
2018-02-28 21:45:59 +01:00
diath
7967bd4385 Fix vertical tooltip clamping (#942) 2018-02-28 21:44:49 +01:00
diath
cb508c6b9f Fix write dir missing a trailing slash (#947) 2018-02-28 21:44:17 +01:00
codetriage-readme-bot
2b1feb1586 Add CodeTriage badge to edubart/otclient
Adds a badge showing the number of people helping this repo on CodeTriage.

[![Open Source Helpers](https://www.codetriage.com/edubart/otclient/badges/users.svg)](https://www.codetriage.com/edubart/otclient)

## What is CodeTriage?

CodeTriage is an Open Source app that is designed to make contributing to Open Source projects easier. It works by sending subscribers a few open issues in their inbox. If subscribers get busy, there is an algorithm that backs off issue load so they do not get overwhelmed

[Read more about the CodeTriage project](https://www.codetriage.com/what).

## Why am I getting this PR?

Your project was picked by the human, @schneems. They selected it from the projects submitted to https://www.codetriage.com and hand edited the PR. How did your project get added to [CodeTriage](https://www.codetriage.com/what)? Roughly about 1 year ago, [Tarjei400](https://github.com/Tarjei400) added this project to CodeTriage in order to start contributing. Since then, 5 people have subscribed to help this repo.

## What does adding a badge accomplish?

Adding a badge invites people to help contribute to your project. It also lets developers know that others are invested in the longterm success and maintainability of the project.

You can see an example of a CodeTriage badge on these popular OSS READMEs:

- [![Email clients like GMAIL do not render SVG images](https://www.codetriage.com/rails/rails/badges/users.svg)](https://www.codetriage.com/rails/rails) https://github.com/rails/rails
- [![Email clients like GMAIL do not render SVG images](https://www.codetriage.com/crystal-lang/crystal/badges/users.svg)](https://www.codetriage.com/crystal-lang/crystal) https://github.com/crystal-lang/crystal

## Have a question or comment?

While I am a bot, this PR was manually reviewed and monitored by a human - @schneems. My job is writing commit messages and handling PR logistics.

If you have any questions, you can reply back to this PR and they will be answered by @schneems. If you do not want a badge right now, no worries, close the PR, you will not hear from me again.

Thanks for making your project Open Source! Any feedback is greatly appreciated.
2018-02-27 14:13:10 -06:00
Victor Oliveira
e1e0ee5cb5 Updating neededtranslations and some pt translations 2018-01-03 20:42:00 -02:00
Victor Oliveira
a725de55f2 Updating translation string. 'in' and 'out' were outside translation. 2018-01-03 20:40:56 -02:00
Victor Oliveira
edd54cc5f6 Updating translation strings. Don't use ':' as last char. 2018-01-03 20:38:53 -02:00
Kamil Chojnowski
2bb9fdc82b Fix parsing the premium status in newer login protocol versions
Closes #933
2018-01-01 05:36:51 +01:00
Henrique Santiago
a7b910a755
Merge pull request #921 from EgzoT/EgzoT-compiler_info_on_start_screen
Add compiler info to version label in start screen
2017-12-22 02:43:15 -02:00
EgzoT
78ca89d2b4
Add compiler info to version label in start screen
Add compiler name and version to start screen (client_background module).
It would help distinguish OTClient problems on different compilations.
2017-11-29 00:42:15 +01:00
EgzoT
1eda9b441f
Update OTClient outdated version in VS project
Change OTClient version from 0.6.3 to 0.6.6 in Visual Studio project.
2017-11-28 22:17:06 +01:00
Eduardo Bart
47766685d9
Merge pull request #907 from diath/topbar_visibility_toggle
Add a keyboard shortcut to toggle topmenu visibility
2017-11-20 12:04:11 -02:00
Eduardo Bart
8e639ea338
Merge pull request #913 from andersonfaaria/icons-branch
Fix minimap icons
2017-11-20 12:03:23 -02:00
Eduardo Bart
425b3bfdda
Merge pull request #915 from diath/add_summon_indicator
Add creature type icons for summons
2017-11-20 12:03:09 -02:00
Henrique Santiago
034a152668
Merge pull request #916 from diath/fix_defunct_link
Replace a defunct otclient.info link with a link to this repo
2017-11-20 11:55:08 -02:00
Kamil Chojnowski
0e0f194df6 Replace a defunct otclient.info link with a link to this repo (closes #821) 2017-11-19 20:09:31 +01:00
Kamil Chojnowski
3b23b787f3 Add creature type icons for summons 2017-11-19 20:02:34 +01:00
Kamil Chojnowski
68371c98d4 Add a button to show the top menu when it's hidden 2017-11-19 02:00:02 +01:00
Henrique Santiago
81a705096a
Merge pull request #914 from andersonfaaria/outfit-src
Fix wrong parameter name in source
2017-11-17 15:27:39 -03:00
Anderson Chaves Faria
2e3bf66502 Fix wrong parameter name in source
This will fix missing t in outfit parameter
2017-11-17 14:26:23 -02:00
Anderson Chaves Faria
885cc90fb5 Fix minimap icons
This commit will change the flagid to fit the correct id on the source code of tfs.
2017-11-17 14:22:40 -02:00
Eduardo Bart
0a6e7dd74e
Merge pull request #898 from EgzoT/EgzoT-setPathable
Add setPathable() function
2017-11-16 23:51:15 -02:00
EgzoT
c1a5a661e7
Fixed indentation and changed function location 2017-11-17 02:32:31 +01:00
Eduardo Bart
a9c59526e0
Merge pull request #904 from ninjalulz/FixModalWindowId
Fix data type for Modal Dialog ID
2017-11-16 22:56:28 -02:00
Eduardo Bart
fe1ca3d329
Merge pull request #909 from diath/player_mana_bar
Add player mana bar
2017-11-16 22:47:54 -02:00
Eduardo Bart
38e9e7c1ed
Merge pull request #910 from diath/hotkey_turn_delay
Add turn and hotkey delay
2017-11-16 22:46:37 -02:00
Eduardo Bart
ac21f6772d
Merge pull request #908 from diath/fix_market_focus
Fix game interface not gaining focus after exitting the market
2017-11-16 22:44:11 -02:00
Kamil Chojnowski
483988f814 Add a keyboard shortcut to toggle topmenu visibility 2017-11-16 19:06:50 +01:00
Kamil Chojnowski
93f51fe127 Add player mana bar 2017-11-16 19:06:40 +01:00
Kamil Chojnowski
d889b5aaf2 Add turn and hotkey delay 2017-11-16 19:06:31 +01:00
Kamil Chojnowski
74caa132c5 Fix game interface not gaining focus after exitting the market (closes #869) 2017-11-16 19:06:15 +01:00
Daniel Björkholm
408e9b4239 Fix data type for Modal Dialog ID 2017-11-16 14:50:12 +01:00
EgzoT
5650db7ba2
Move definition to thingtype.cpp file
Move definition from thingtype.h to thingtype.cpp file
2017-11-15 02:20:33 +01:00
EgzoT
c51df93e3e
Add setPathable() function
Adding function who changing item attribute (ThingAttrNotPathable).
Allows to walk on not pathable items (ThingAttrNotPathable -> true) like parcels, fire fields etc. and vice versa.
Modifying item attribute without editing items sources files. Temporary action for the duration of the client session.

Usage:
print(g_things.getThingType(3504):isNotPathable()) -> true

g_things.getThingType(3504):setPathable(true)

print(g_things.getThingType(3504):isNotPathable()) -> false

Helpful for highter levels players to ignoring "avoiding" fire/energy/poison fields etc. when using map click.
2017-11-15 01:02:06 +01:00
Eduardo Bart
2095951e07 Add missing include 2017-11-14 13:59:19 -02:00
Eduardo Bart
8bbc8c09a5
Update README.md 2017-11-04 12:33:51 -02:00
Sportacus
a9f6f7662f Log file saves specific to server and character
Changed it so when you save a log file, the log file name includes the
server name and the characters name, in the file name.

This is to improve organization, to separate logs based off the server
you are on, and the character you are logged in.
2017-11-04 11:34:33 -02:00
Marcin Michalski
13789c5612 Properly check tile elevation in older protocols 2017-11-04 11:24:12 -02:00
Eduardo Bart
7046fa1cdb
Merge pull request #874 from EgzoT/EgzoT-useWith_fix
Fixed problem with function "useWith" on creatures
2017-11-04 11:13:11 -02:00
Eduardo Bart
aeb98810ed
Merge pull request #878 from EgzoT/EgzoT-map_missile_bug
[Probable bug] Double use function onAppear
2017-11-04 11:08:37 -02:00
Eduardo Bart
aa19f45d94 Fixes to compile on mingw32 2017-11-04 11:05:25 -02:00
Eduardo Bart
c9bc9e327d
Merge pull request #867 from fluidsonic/clang-9
fixed clang 9 compile errors in shared_object_ptr
2017-11-04 10:53:46 -02:00
Eduardo Bart
8309fee510 Fix build for mingw-w64 2017-11-04 10:43:57 -02:00
Eduardo Bart
e6bec115ae Try to fix travis build script 2017-11-04 10:32:23 -02:00
Eduardo Bart
8b161e1a07 Priorize OpenSSL 1.0 in cmake, warning fixes 2017-11-04 09:03:57 -02:00
Eduardo Bart
696610bba7
Merge pull request #880 from diath/fix_missing_include
Fix a missing include in unix crash handler
2017-10-31 12:48:15 -02:00
Kamil Chojnowski
f33a44643f Fix a missing include 2017-10-31 13:44:38 +01:00
EgzoT
f4f3219d61 [Probable bug] Double use function onAppear
Method Map::addThing uses two times function onAppear for object Missile.
First used in line 119, but then used again the same function in line 165.
Without first function onAppear method Map::addThing work the same.
2017-10-25 23:25:02 +02:00
EgzoT
1950d8ec26 Fixed problem with function "useWith" on creatures 2017-10-23 02:33:51 +02:00
Henrique Santiago
4e9e1555f4 Merge pull request #872 from EgzoT/EgzoT-trade_request_ui
Sending trade request using "UICreatureButton"
2017-10-22 20:21:16 -03:00
Henrique Santiago
a4a40426bf Merge pull request #873 from EgzoT/EgzoT-getBackground
Add function getBackground
2017-10-22 20:18:53 -03:00
EgzoT
d44733ff3e Add function getBackground
Add function getBackground 
Function getBackground return background value, who contain background UI (login screen).
2017-10-22 23:31:45 +02:00
EgzoT
bc507fd98b Sending trade request using "UICreatureButton"
Extending the possibilities of "UICreatureButton" widget.
Adding possibility sending trade request in battle list (game_battle module) and other modules who use widget "UICreatureButton".
2017-10-22 23:21:02 +02:00
Marc Knaup
a604ea7153
fixed clang 9 compile errors in shared_object_ptr 2017-09-29 23:39:27 +02:00
Konrad Kuśnierz
8c731ac016 Merge pull request #844 from gesior/iptostring_fix
Fix iptostring in LUA
2017-05-13 14:08:25 +02:00
Jerzy Skalski
1d77d202e6 Change uint to uint32 2017-05-13 13:14:25 +02:00
Jerzy Skalski
90de0dec04 Fix iptostring
Fix iptostring bug that blocks access to half of OTSes
2017-05-12 15:47:44 +02:00
Konrad Kuśnierz
c87c450905 Fix #703 2017-05-01 18:15:16 +02:00
Henrique Santiago
8871659b07 Fix image read 2017-04-27 18:47:08 -03:00
Henrique Santiago
42df56a98d Merge pull request #831 from ranisalt/master
Fix misleading indentation
2017-03-27 08:06:45 -03:00
Ranieri Althoff
88d0a0a879
Fix misleading indentation 2017-03-27 01:54:35 -03:00
A-Syntax
df422c0991 Update protocolgameparse.cpp (#777)
The vocation id was not being received by the client.
https://github.com/otland/forgottenserver/issues/1982
2017-02-04 13:05:03 +02:00
Joao Pasqualini Costa
837f461bb1 Update README (#817)
Remove all broken links and fix MSVC link
2017-02-02 10:00:03 +02:00
Joao Pasqualini Costa
af92792d4a Fix Login problem and use removeEvent (#816)
When trying to logout in battle the player would not logout and tryLogin
would be called, so the next time you tryed to login it will still be
trying to login
2017-02-02 09:59:41 +02:00
Joao Pasqualini Costa
2292df922d Fix Look (#818)
sendLookCreature should only be called in battleList
2017-02-02 09:59:20 +02:00
Joao Pasqualini Costa
0676b68493 Include Issue Template (#819) 2017-02-02 09:58:48 +02:00
Ahmed Samy
fdec018186 Merge pull request #808 from GustavoBlaze/patch-1
Bug idle animations of the creatures solved
2017-01-24 23:42:49 +02:00
GustavoBlaze
743e73d755 Applying the otclient code style 2017-01-24 15:27:58 -02:00
GustavoBlaze
bc20e16584 Applying the otclient code style
changing the variables names
2017-01-24 14:58:11 -02:00
GustavoBlaze
a4400a4ff1 applying the otclient code style
changing the variables names
2017-01-24 14:56:21 -02:00
GustavoBlaze
2927ed29d8 Bug idle animations of the creatures solved
These changes we join the idle animations with the walking animations
2017-01-23 22:39:16 -02:00
Ahmed Samy
15483a395f Merge pull request #805 from brunominervino/some-changes
Change LICENSE Copyright Year
2017-01-18 23:41:13 +02:00
Ahmed Samy
e44b33fc67 Merge pull request #807 from conde2/otclient-locales
Show missing translation on console
2017-01-18 23:40:51 +02:00
Ahmed Samy
af09a91d64 Merge pull request #806 from conde2/otclient-vs
Update Visual Studio Project
2017-01-18 23:40:36 +02:00
conde2
a644dff043 Show missing translation on console 2017-01-18 11:31:40 -02:00
conde2
664ef6bcad Update Visual Studio Project
Update Visual Studio to work with PATH system variables in Windows
systems. Credits go to @Radseq for changing the project and to me for
update to Visual Studio 2015

Closes
#795
#746
#718
#724
#713
2017-01-18 11:20:09 -02:00
Bruno Minervino
deeb80dd67 Revert Extension 2017-01-17 09:42:31 -02:00
Bruno Minervino
9d3f3d8aec Change LICENSE Copyright Year and Extension 2017-01-16 10:38:58 -02:00
Ahmed Samy
deee6ed8c9 Completion for #764
Thanks to @conde2 for pointer it out.
2017-01-13 18:46:04 +02:00
Ahmed Samy
94d60432f3 Merge pull request #766 from TibiaFun/patch-1
Update protocolcodes.cpp
2017-01-13 18:31:41 +02:00
Ahmed Samy
b6140a03b4 Merge pull request #764 from elderapo/patch-1
Fix typo
2017-01-13 18:31:33 +02:00
Ahmed Samy
7845238918 Merge pull request #802 from brunominervino/vs-version
Update Visual Studio build files
2017-01-13 18:30:44 +02:00
Samuel Gros
e870110875 Merge pull request #801 from brunominervino/copyright-year-2017
Update copyright year for 2017
2017-01-13 13:09:11 +01:00
Bruno Minervino
8eacaa8e80 Fix EOF (again) 2017-01-13 09:01:42 -02:00
Bruno Minervino
21d9bf059e Remove new line 2017-01-13 08:59:56 -02:00
Bruno Minervino
23b6c8e839 Fix EOF 2017-01-13 08:58:50 -02:00
Bruno Minervino
a793cab751 Update Visual Studio build files 2017-01-13 08:55:24 -02:00
Bruno Minervino
882be286d9 Update copyright year for 2017 2017-01-13 08:47:07 -02:00
Ahmed Samy
d5858092ca Merge pull request #799 from zygzagZ/master
Fixed inconsistences between const.lua and const.h causing messagetypes not to work
Fixed talking with npc for 8.54
2017-01-13 01:05:57 +02:00
zygzagZ
8486f6c867 Fixed talking with npc for 8.54 2017-01-12 15:40:13 +01:00
zygzagZ
9d2298037e Fixed inconsistences between const.lua and const.h causing messagetypes not to work 2017-01-12 15:30:24 +01:00
Konrad Kuśnierz
42e0b0a025 Merge pull request #771 from jo3bingham/coding-style
Fix inconsistent coding style
2016-11-08 18:57:52 +01:00
Joseph Bingham
e5d28e00e2 Fixes inconsistent coding style 2016-11-08 12:54:31 -05:00
Joseph Bingham
56a641e516 Merge pull request #1 from edubart/master
Rebase with original master
2016-11-08 12:50:22 -05:00
Samuel Gros
7cd01714fc Merge pull request #770 from jo3bingham/update-1099
10.96, 10.97, 10.98, 10.99 support
2016-11-08 09:22:23 +01:00
Joseph Bingham
9148d412e5 Replace tabs with spaces (again) 2016-11-08 00:00:21 -05:00
Joseph Bingham
5a5adc4ed6 Replace tabs with spaces 2016-11-07 23:58:42 -05:00
Joseph Bingham
344146ba2d 10.96, 10.97, 10.98, 10.99 support
Adds basic support for the latest client version
2016-11-07 23:52:42 -05:00
TibiaFun
0870fda2ac Update protocolcodes.cpp 2016-10-23 13:31:02 +02:00
Tomasz Martyński
8ffacefb04 Fix typo
change "getOufitColor" to "getOutfitColor"
2016-10-10 02:16:40 +02:00
Eduardo Bart
a6a50fa162 Merge pull request #744 from ranisalt/copyright-year
Update copyright year for 2016
2016-07-10 11:10:43 -03:00
Eduardo Bart
a5f4545168 Merge pull request #745 from ranisalt/cxx11
Replace deprecated c++11 test with cmake script
2016-07-10 11:09:47 -03:00
Ranieri Althoff
551f30d32f
Replace deprecated c++11 test with cmake script 2016-07-09 22:51:32 -03:00
Ranieri Althoff
2f1f62a916
Update copyright year for 2016 2016-07-09 22:11:34 -03:00
Sam
1ec3b65a3a 10.94, 10.95 support 2016-07-03 00:50:08 +02:00
Sam
8992d40e37 Update PIC signature 2016-05-23 03:26:17 +02:00
Sam
1c09c3770b Protocol 10.93 2016-05-23 02:48:32 +02:00
Henrique Santiago
0dfdb22509 Merge pull request #728 from dalvorsn/master
Fixed issue in function fitAll
2016-05-01 16:21:04 -03:00
dalvorsn
a165bef741 Fixed issue in function fitAll: mini windows containers was exceeding the size of the panels. 2016-04-24 18:25:21 -03:00
Henrique Santiago
fa3068f6e6 Merge pull request #725 from ottools/master
Fix 'getTopMultiUseThing' returning border items. Closes #644
2016-04-11 14:49:51 -03:00
Nailson
d1b26781d3 Fix 'getTopMultiUseThing' returning border items. 2016-04-11 09:42:37 -03:00
Sam
7a8e605704 Minimal 10.91 support 2016-03-03 08:44:26 +01:00
Ahmed Samy
5913cc0fd7 vc12: restore path as I thought they were originally like that 2016-02-08 10:35:00 +02:00
Ahmed Samy
c6f5c5c725 vc12: Fix compilation and also give the compiler more options to use
This gives the compiler the opportunity to SSE2 instead of FPU
Also added some options that were necessary.
2016-02-08 10:34:13 +02:00
Sam
2b7e2a45ea Fix 7.4 walking over items with elevation 2016-01-25 22:19:39 +01:00
BenDol
f024e30753 Fix NPC chat when ignoring private messages. 2016-01-22 16:15:35 +13:00
Sam
408b3c5125 Fix npc message mode 2016-01-20 02:44:13 +01:00
TheSumm
90deb067a6 Added missing message types 2015-12-22 13:06:36 +01:00
Ahmed Samy
39d4a7d842 Merge branch 'master' of https://github.com/Crypton33/otclient 2015-12-15 03:26:43 +02:00
TheSumm
37f563d3d5 Replaced some tabs with spaces 2015-12-11 01:51:55 +01:00
TheSumm
80184a1249 Initial 10.90 support
Basic support, I did not check for further protocol changes yet.
2015-12-08 18:25:18 +01:00
Konrad Kuśnierz
ec9dafcfdf Fix #696 2015-12-05 16:23:09 +01:00
Henrique Santiago
b1a290981c Merge pull request #695 from ottools/master
Small optimization.
2015-11-30 21:47:47 -02:00
Nailson
2f3540c996 Small optimization. 2015-11-30 19:49:21 -03:00
TheSumm
0d8791e1a7 Protocol updates up to 10.82 2015-10-24 17:46:53 +02:00
Sam
d9e8bfff4c Merge pull request #690 from ottools/master
Add 'GameKeepUnawareTiles' feature.
2015-10-06 15:12:37 +02:00
Nailson
d41fe195f4 Add 'GameKeepUnawareTiles' feature.
Remove tiles that we are not aware anymore by default.
2015-10-06 00:37:50 -03:00
Konrad Kuśnierz
1686d8081b Merge pull request #680 from ottools/master
Add a flag for idle animation game feature.
2015-08-28 10:07:14 +02:00
Nailson
f1fdbd56e9 Add a flag for idle animation game feature. 2015-08-26 19:49:43 -03:00
Konrad Kuśnierz
ae25dbf6a5 Merge pull request #678 from ranisalt/fix-deprecated-openssl
Replace deprecated function
2015-07-25 02:37:50 -05:00
Ranieri Althoff
058b926a94 Replace deprecated function 2015-07-24 20:52:31 -03:00
Konrad Kuśnierz
4591a37844 My bad, wrong function name. 2015-07-19 10:33:55 +02:00
Konrad Kuśnierz
8abefb1505 Fix #601, fix #599 2015-07-19 10:27:06 +02:00
BenDol
0afbfd58ce Proper gameinterface load sequence, thanks @Quintinon
https://github.com/edubart/otclient/pull/677
2015-07-19 07:08:21 +12:00
BenDol
6c5549dd46 This was already fixed. 2015-07-19 06:48:05 +12:00
Ben Dol
0e0da9ecbf Merge pull request #654 from crackcomm/market-myoffers
Market myoffers + NPC start block
2015-07-19 06:46:33 +12:00
BenDol
7a7f63586f Fix serverlist issues from previous commit.
Was referencing a 'global' variable so a simple check will do.
2015-07-19 06:34:21 +12:00
BenDol
07a2995285 Fix NPC static text and missing SpeakType. 2015-07-19 06:03:19 +12:00
TheSumm
b822e92c0e Fixed serverlist to ignore invalid settings when loading 2015-07-17 11:22:31 +02:00
Henrique Santiago
0ecf2229e6 Merge pull request #674 from kenfal/master
Fix missing loop counter, fixes #673
2015-07-10 21:45:48 -03:00
kenfal
47272519b5 Fix missing loop counter 2015-07-10 21:41:53 -03:00
Konrad Kuśnierz
481adcdc21 Merge pull request #672 from diath/patch-motd
Fix last motd number saving
2015-07-06 09:53:50 +02:00
Kamil Chojnowski
78bdf20603 Fix last motd number saving 2015-07-06 07:38:01 +02:00
Sam
0642fb66cd Merge pull request #671 from ottools/master
Fix #664
2015-07-05 18:34:54 +02:00
Nailson
5ef55307f5 Fix #664 2015-07-05 13:05:12 -03:00
Konrad Kuśnierz
b9848f360c Check for Otc::GameAttackSeq feature 2015-06-21 12:44:19 +02:00
Konrad Kuśnierz
b5a14ddb68 Add context menu option "Select all" for channel 2015-06-04 22:10:05 +02:00
Eduardo Bart
e4302562ff Change new line from CR LF to LF when copying console text 2015-06-04 12:10:32 -03:00
Konrad Kuśnierz
471b8362e2 ConsoleLabel should not be focusable
Avoid scrolling by ensureChildVisible of UIScrollArea
2015-06-04 15:31:15 +02:00
Konrad Kuśnierz
a33fcd19b4 Improve multi-line selection (find bouding children) 2015-06-03 23:00:39 +02:00
Konrad Kuśnierz
7f2f70e1a6 Change signalcall to protectedcall in console
Even though they kind of do the same (calling function in protected
mode), @edubart suggested to use a different function for the sake of
readability.
2015-06-03 17:03:49 +02:00
Konrad Kuśnierz
f9d183837a Add option to save messages from channel 2015-06-03 16:46:49 +02:00
Eduardo Bart
02c6b1b6c7 Missing changes for multiline text 2015-06-03 10:59:28 -03:00
Eduardo Bart
0c1540e531 Improve multiline text selection, closes #507 2015-06-03 10:51:39 -03:00
Konrad Kuśnierz
6893a5e98a Optimize UITextEdit rendering 2015-06-03 14:56:43 +02:00
Konrad Kuśnierz
559e545e36 Few more minor fixes to selection in game console 2015-06-02 22:46:33 +02:00
Konrad Kuśnierz
cf90bb9807 Fix selection
Perhaps it would be wise to move widget local variables to some sort of
global variable for each tab.
2015-06-02 20:04:34 +02:00
Konrad Kuśnierz
f35c939fc3 Start working on multi-line selection for console
Unfortunately UITextEdit is really bad in terms of performance. It
cannot be used as overlying widget (just like in terminal). On the other
hand we could optimize it by rewriting (unfortunately) the whole widget.

There still is a lot of things to do, but for now it is possible to
select several lines of text and copy it using CTRL + C. In order to
make text copyable in context menu it will be required to override
onMousePress (return true).
2015-06-02 19:16:41 +02:00
Konrad Kuśnierz
34e2fa1d49 Merge pull request #665 from ranisalt/master
Use native optimizations instead of hardcoded defaults
2015-05-27 11:12:12 -05:00
Ranieri Althoff
944b220c90 Use native optimizations instead of hardcoded defaults 2015-05-25 00:59:39 -03:00
Konrad Kuśnierz
c5ea8c98fb Add cn option to struct
"cn" a sequence of exactly n chars corresponding to a single lua string.
2015-05-19 18:50:02 +02:00
Konrad Kuśnierz
02ab50d8dd Minor mistake in unpacking string 2015-05-19 13:41:40 +02:00
Konrad Kuśnierz
48fefb03cb Add float and double support for struct
@edubart suggested it would be still better to have it done within C as
extra module (just like lbitlib).

"f" a float (4 bytes).
"d" a double (8 bytes).

http://en.wikipedia.org/wiki/IEEE_floating_point
2015-05-19 13:13:14 +02:00
Konrad Kuśnierz
7ea6c46b2c Add binary operations for lua
This is something I was always missing - posibbility to operate on
binary files or streams in pure lua. In most cases we do only need to
read simple variables from files such as integers with different amount
of bytes. This "class" will provide that ability.

It's a simple implementation of following C module for lua:
http://www.inf.puc-rio.br/~roberto/struct/

It has much less, though. Following elements have been implemented:

">" flag to set mode to big endian.
"<" flag to set mode to little endian.
"b" a signed char.
"B" an unsigned char.
"h" a signed short (2 bytes).
"H" an unsigned short (2 bytes).
"i" a signed int (4 bytes).
"I" an unsigned int (4 bytes).
"l" a signed long (8 bytes).
"L" an unsigned long (8 bytes).
"s" a zero-terminated string.

An example how to use it:

```lua
local packed = Struct.pack('<LIhBsb', 123456789123456789, 123456789,
-3200, 255, 'Test message', -1)
-- packed is now a lua string we can save to file as binary data
local L, I, h, B, s, b = Struct.unpack('<LIhBsb', packed)
print(L, I, h, B, s, b)
```

You can use g_resources.readFileContents as function to read binary
files and parse them via this class.
2015-05-18 21:38:05 +02:00
Konrad Kuśnierz
0597ded1d3 Merge pull request #648 from Shawak/Shawak-b_vc12
fix visual studio include paths
2015-05-13 06:32:47 -05:00
Konrad Kuśnierz
c3c2ac80e7 Fix drawing creatures in UICreature
I will leave this ugly hack for the time being, but I do encourage to change it later on. The whole "resize" boolean makes no sense since the outfit is resized by the destination rectangle anyway. I believe we should give it a try with a real size of the object defined in dat by the user for creatures bigger than 32x32.

Please keep in mind that we did cut bigger creatures to 48x48 (2*Otc::TILE_PIXELS*0.75f) before as well, so nothing really changed besides ability to properly draw bigger creatures than 64x64 on battlelist.
2015-05-12 23:44:10 +02:00
Konrad Kuśnierz
6bd0e37670 Correctly draw creatures bigger than 64x64
Battlelist icon
2015-05-12 10:16:14 +02:00
Konrad Kuśnierz
11990815a6 Correctly load corrupted otmm file, should fix #606 2015-05-10 22:31:10 +02:00
Konrad Kuśnierz
ded8fef16b Change bitter badge and made it inline with travis 2015-05-10 22:25:46 +02:00
Konrad Kuśnierz
53dbbd2ba3 Decrease RAM usage by at least 200MB
This was quite ridiculous.

TILESTATE_LAST = 1 << 24

Basically we were creating 2^24 Color structures within the array, each
of them has 4 floats (16 bytes) resulting in about 256 MB of extra
wasted memory.
2015-05-09 20:27:04 +02:00
Eduardo Bart
e4cdb3834b Merge pull request #661 from gitter-badger/gitter-badge
Add a Gitter chat badge to README.md
2015-05-08 11:28:17 -03:00
The Gitter Badger
86dd7958e1 Added Gitter badge 2015-05-07 21:42:02 +00:00
TheSumm
fe98efdc21 Fix modal dialog auto sizing, fixes #556 2015-04-20 19:22:50 +02:00
TheSumm
8e5bbcd3a1 Add tab-spacing tag to MoveableTabBars 2015-04-20 03:32:32 +02:00
TheSumm
f936ab9aab fix #638 2015-04-19 13:59:45 +02:00
TheSumm
84f6cdec86 Fix #576, PopupMenus close when leaving the game 2015-04-19 13:56:03 +02:00
TheSumm
ab5bed456b Fix warning 2015-04-19 13:54:55 +02:00
Łukasz Kurowski
01c107ba62 Market my offers 2015-04-07 01:24:39 +02:00
Łukasz Kurowski
ff0947c270 NPC start talk 2015-03-31 10:37:49 +02:00
Shawak
a3e6cc54b5 fix visual studio include paths 2015-03-22 20:11:41 +01:00
TheSumm
fcd481ee15 Added missing message mode 2015-03-09 23:26:39 +01:00
TheSumm
b237b713ef Fix 10.76 login protocol, added missing lua consts 2015-03-09 16:46:26 +01:00
TheSumm
3bffa6b04a Terminal new line (Shift+Enter) functionality 2015-03-07 16:32:45 +01:00
TheSumm
83dc129f03 Protocol 10.76, fixed death window & death packet 2015-03-07 06:10:10 +01:00
Konrad Kuśnierz
ca60efd786 Merge pull request #645 from gpedro/master
Update copyright for 2015
2015-03-04 16:43:38 +01:00
Gabriel Pedro
04b516a1a0 Update copyright for 2015 2015-03-04 10:36:51 -04:00
Eduardo Bart
5387f8fe83 Merge pull request #632 from SuggestName/master
Minor change in statusLabel anchor for Ctrl + .
2015-02-23 11:49:05 -03:00
Suggest Name
b5c7374890 Update textmessage.otui 2015-02-21 20:40:16 -02:00
TheSumm
f51a160bde Remove unintentionally added files 2015-02-15 03:27:32 +01:00
TheSumm
cbf70c1d63 Enable protocol 10.75 2015-02-15 03:25:43 +01:00
Henrique Santiago
28ff65be5a Merge pull request #640 from Mignari/master
Added support for enhanced animations for items.
2015-02-13 16:07:07 -02:00
Nailson
74af47f4d6 Added support for enhanced animations for items.
Thanks to @conde2, @BenDol
2015-02-13 08:19:45 -03:00
TheSumm
4c4e0b9d07 Fix error showing after relogging with containers being open 2015-02-12 14:48:56 +01:00
Mateusz Pawlica
af0819f454 Changed rule violation window default focus 2015-01-31 22:31:58 +01:00
Mateusz Pawlica
27f7871a08 Minimap widget is now horizontally resizeable 2015-01-31 22:30:14 +01:00
TheSumm
6961492e00 Fix console tabs not blinking, closes #627 2015-01-30 19:56:56 +01:00
TheSumm
1c3cfddab0 Removed tr() from UIHeader 2015-01-28 00:01:53 +01:00
TheSumm
71931b961a Full protocol 10.74 support (session key), entergame style fixes 2015-01-27 23:44:37 +01:00
TheSumm
64e9406488 Fixed 'widget destroyed but still have 1 reference left' related to console module 2015-01-27 21:14:38 +01:00
BenDol
900ebbd985 Fixes #181 and fixes #551 2015-01-27 22:11:52 +13:00
TheSumm
cb7cea6809 Tiny signalcall fix 2015-01-25 21:20:48 +01:00
TheSumm
4e2ded571e Fixed not being able to relog after reloading gamelib 2015-01-25 14:17:16 +01:00
TheSumm
da2762dac3 Market now highlights offers which differ from the average price 2015-01-25 13:41:00 +01:00
TheSumm
eb3c244023 More Market fixes
* Fixed NextButton and PreviousButton style
* Little update to SpinBox including dontSignal
* Market cleanup and more check to be safe
* Limit Market amountWindow by player balance
* Set proper maximum amount when creating offers
* Fixed fee label not calculating the correct fee sometimes
2015-01-25 02:28:53 +01:00
TheSumm
3157e7924f Market updates, now using showAs / tradeAs so every items works properly, some cleanup / bug fixing 2015-01-23 02:52:05 +01:00
TheSumm
92e2e8224f Added market message, reworked text messages a little 2015-01-22 20:38:28 +01:00
TheSumm
1d022905ab Fix button style (closes #607) 2015-01-22 11:49:04 +01:00
TheSumm
607dab01d6 Added Market column sorting (fixes #429), updated UITable and fixed not working methods 2015-01-21 23:40:15 +01:00
TheSumm
6edc73a8ba Fix Enter Game window not being centered on startup 2015-01-21 18:58:30 +01:00
TheSumm
596717bf32 Added locale number formatting to locale files 2015-01-20 16:18:04 +01:00
TheSumm
b5cea41f87 Market fixes
- Market now works after reloading
- Fixed button / tab styles
- MarketRightTabBarButton now inherits the base style
- Fixed amountWindow buttons being hardly clickable
- "All" search filter is now on by default
2015-01-20 14:34:45 +01:00
TheSumm
8542f8bfd4 Protocol 10.73 support 2015-01-20 11:07:38 +01:00
TheSumm
fc76ca4523 Updated advernturer blessing inventory style to be more robust 2015-01-19 01:52:49 +01:00
TheSumm
63f95317a2 Fixed baseSpeed not being parsed (10.59+) 2015-01-19 01:08:18 +01:00
TheSumm
26fb35fd4d Fixed major bug 2015-01-18 23:57:19 +01:00
TheSumm
a8f2bb19db Little polishing of Unjustified Points module 2015-01-18 23:56:44 +01:00
TheSumm
ddec9627b8 Protocol 10.72 (Authenticator) Support, Unjustified Points diplay
- Unjustified Points (Better topbar icon would be nice)
![Unjustified Points](http://i.gyazo.com/81286f46d9b4d56b3fe864140173cf34.png)
- Authenticator token support
- adjusted 'can change pvp frame' to 1054
- ...
2015-01-18 15:14:07 +01:00
TheSumm
24b1526534 Fixed sending wrong OS 2015-01-11 18:50:58 +01:00
Konrad
bf30fc0dc3 Add QEZC for diagonal walking as well as broadcast/red talk for gamemasters 2015-01-06 18:23:36 +01:00
TheSumm
4b7770361d Fix parseLogin packet 2014-12-30 19:25:20 +01:00
TheSumm
50c36bb2ba Fix for adventurer blessing style 2014-12-30 16:40:20 +01:00
BenDol
16f6a0019c Fix dat loading issue with 10.00 & minor outfit window fix. 2014-12-30 17:27:53 +13:00
TheSumm
7f3f18f991 Support for Protocols up to 10.71, Adventurer Blessing 2014-12-29 18:08:33 +01:00
Ben Dol
6ab69b499d Merge pull request #567 from cymruu/master
A tool which generates empty locales template
2014-12-26 23:54:42 -08:00
Konrad Kuśnierz
f724506550 Merge pull request #614 from gpedro/patch-1
Add OSX Compiling Wiki
2014-12-26 21:35:22 +01:00
Gabriel Pedro
1eb2bbd389 Add OSX Wiki 2014-12-25 11:10:03 -03:00
Konrad Kusnierz
5ada7eb5ec Fix #600 2014-11-20 21:14:25 +01:00
Konrad Kusnierz
c49a6f3bf2 Fix for #596 2014-11-19 07:25:36 +01:00
Eduardo Bart
aa924dc348 Fixes in CMake for building snapshots 2014-11-05 11:25:11 -02:00
Eduardo Bart
f6fb785cea Use -O2 in release build 2014-11-05 10:45:28 -02:00
BenDol
25e7b1d7a3 Fix logging in with 760 (until a better solution is found). 2014-11-04 13:27:21 +13:00
BenDol
bdfb77166e Reuse code by merging dash functionality with walk method. 2014-11-03 15:12:14 +13:00
cymruu
ac23b8e624 made a tool which generates empty locales template 2014-09-15 19:43:05 +02:00
505 changed files with 8364 additions and 4505 deletions

2
.dockerignore Normal file
View File

@ -0,0 +1,2 @@
/build/
Dockerfile

133
.github/workflows/build-vcpkg.yml vendored Normal file
View File

@ -0,0 +1,133 @@
name: Build with vcpkg
on:
push:
branches:
- master
- v*
tags:
- v*
paths:
- .github/workflows/**
- cmake/**
- src/**
- CMakeLists.txt
pull_request:
paths:
- .github/workflows/**
- cmake/**
- src/**
- CMakeLists.txt
jobs:
job:
name: ${{ matrix.os }}-${{ matrix.cxx }}-${{ matrix.buildtype }}-luajit=${{ matrix.luajit }}
runs-on: ${{ matrix.os }}-${{ matrix.os-version }}
strategy:
fail-fast: false
max-parallel: 8
matrix:
name: [ubuntu-gcc, macos-clang, windows-msvc]
buildtype: [Debug, Release]
luajit: [on, off]
include:
- name: windows-msvc
os: windows
os-version: latest
cxx: cl.exe
cc: cl.exe
triplet: x64-windows
packages: >
boost-iostreams boost-asio boost-system boost-variant boost-lockfree boost-filesystem boost-uuid
glew luajit libogg libvorbis openal-soft opengl openssl physfs zlib
- name: ubuntu-gcc
os: ubuntu
os-version: 20.04
cxx: g++
cc: gcc
triplet: x64-linux
packages: >
boost-iostreams boost-asio boost-system boost-variant boost-lockfree glew
boost-filesystem boost-uuid physfs openal-soft libogg libvorbis zlib opengl
- name: macos-clang
os: macos
os-version: latest
cxx: clang++
cc: clang
triplet: x64-osx
packages: >
boost-iostreams boost-asio boost-system boost-variant boost-lockfree glew
boost-filesystem boost-uuid libogg libvorbis zlib opengl
exclude:
- name: windows-msvc
luajit: off
steps:
- uses: actions/checkout@v3
with:
submodules: true
- name: Unshallow
run: git fetch --prune --unshallow
- name: Get latest CMake
# Using 'latest' branch, the latest CMake is installed.
uses: lukka/get-cmake@latest
- name: Ubuntu - install opengl lua5.1 luajit
# vcpkg has lua 5.3+
run: sudo apt-get install libglew-dev liblua5.1-0-dev libluajit-5.1-dev
if: contains( matrix.os, 'ubuntu')
- name: MacOS - install physfs pkgconfig lua5.1 luajit xquartz
run: brew install physfs pkgconfig lua@5.1 luajit xquartz
if: contains( matrix.os, 'macos')
- name: Set Environment vars
run: |
echo "CXX=${{ matrix.cxx }}" >> $GITHUB_ENV
echo "CC=${{ matrix.cc }}" >> $GITHUB_ENV
- name: Run vcpkg
uses: lukka/run-vcpkg@v7
with:
vcpkgArguments: ${{ matrix.packages }}
vcpkgDirectory: ${{ runner.workspace }}/vcpkg/
vcpkgTriplet: ${{ matrix.triplet }}
vcpkgGitCommitId: 6f7ffeb18f99796233b958aaaf14ec7bd4fb64b2
- name: Build with CMake
uses: lukka/run-cmake@v3
with:
buildDirectory: ${{ runner.workspace }}/build
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
cmakeAppendedArgs: '-G Ninja -DCMAKE_BUILD_TYPE="${{ matrix.buildtype }}" -DLUAJIT="${{ matrix.luajit }}"'
useVcpkgToolchainFile: true
- name: dir
run: find $RUNNER_WORKSPACE
shell: bash
- name: Upload artifact binary
uses: actions/upload-artifact@v3
with:
name: otclient-${{ matrix.name }}-${{ matrix.buildtype }}-luajit=${{ matrix.luajit }}-${{ github.sha }}
path: ${{ runner.workspace }}/build/otclient
if: "! contains( matrix.os, 'windows')"
- name: Upload artifact binary (exe)
uses: actions/upload-artifact@v3
with:
name: otclient-${{ matrix.name }}-${{ matrix.buildtype }}-luajit=${{ matrix.luajit }}-${{ github.sha }}
path: ${{ runner.workspace }}/build/otclient.exe
if: contains( matrix.os, 'windows')
- name: Upload artifact binary (dlls)
uses: actions/upload-artifact@v3
with:
name: otclient-${{ matrix.name }}-${{ matrix.buildtype }}-luajit=${{ matrix.luajit }}-${{ github.sha }}
path: ${{ runner.workspace }}/build/*.dll
if: contains( matrix.os, 'windows')

231
.gitignore vendored
View File

@ -1,45 +1,3 @@
build*
CMakeCache.txt
CMakeFiles
cmake_install.cmake
Makefile
/otclient
/*.h
/*.cxx
*.o
*.gch
*.a
*.exe
*.spr
*.dat
*.kdev*
*.cbp
*~
*.kate-swap
*.autosave
CMakeLists.txt.user*
*.xml
*.otb
*.otbm
*.log
*.bak
*.swp
*.pic
.lvimrc
.clang_complete
config.otml
/modules/otclientrc.lua
/doc
!.gitignore
otclient.map
otclient.layout
LOCALTODO
tags
Thumbs.db
.directory
src/framework/graphics/dx/
modules/.project/modules.sublime-workspace
#################
## Visual Studio
#################
@ -51,6 +9,8 @@ modules/.project/modules.sublime-workspace
*.suo
*.user
*.sln.docstates
.idea/
.vscode/
# Build results
@ -60,6 +20,7 @@ x64/
build/
[Bb]in/
[Oo]bj/
cmake-build-*/
# MSTest test Results
[Tt]est[Rr]esult*/
@ -86,16 +47,19 @@ build/
*.vssscc
.builds
*.pidb
*.log
*.scc
*.dll
*.exe
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.opendb
*.sdf
*.cachefile
*.VC.db
# Visual Studio profiler
*.psess
@ -108,3 +72,184 @@ ipch/
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
#############
## Windows detritus
#############
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
.DS_Store
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg
# Vim files
*~
.*.swp
.*.swo
#################
## OTClient
#################
/otclient
/modules/otclientrc.lua
src/framework/graphics/dx/
*.o
*.gch
*.a
*.kdev*
*.cbp
*~
*.kate-swap
*.autosave
*.bak
*.swp
.lvimrc
.clang_complete
LOCALTODO
tags
# user-specific files
*.xml
*.otb
*.otbm
*.spr
*.dat
*.pic
config.otml
## Cmake cache
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
## Sublime
# Cache files for Sublime Text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# Workspace files are user-specific
*.sublime-workspace
# Project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using Sublime Text
# *.sublime-project
# SFTP configuration file
sftp-config.json
sftp-config-alt*.json
# Package control specific files
Package Control.last-run
Package Control.ca-list
Package Control.ca-bundle
Package Control.system-ca-bundle
Package Control.cache/
Package Control.ca-certs/
Package Control.merged-ca-bundle
Package Control.user-ca-bundle
oscrypto-ca-bundle.crt
bh_unicode_properties.cache
# Sublime-github package stores a github token in this file
# https://packagecontrol.io/packages/sublime-github
GitHub.sublime-settings

View File

@ -1,14 +0,0 @@
language: cpp
compiler:
- gcc
before_script:
- sudo apt-get install libboost1.48-all-dev libphysfs-dev libssl-dev liblua5.1-dev libglew1.6-dev libvorbis-dev libopenal-dev libz-dev -y
script: |
cmake . -DCMAKE_BUILD_TYPE=Release
make
notifications:
irc:
channels:
- "irc.freenode.org#otclient"
on_success: change
skip_join: true

View File

@ -1,8 +1,7 @@
cmake_minimum_required(VERSION 2.6)
cmake_minimum_required(VERSION 3.1)
project(otclient)
set(VERSION "0.6.6")
set(LIB_NAME "otc_framework")
set(VERSION "1.0.0")
option(FRAMEWORK_SOUND "Use SOUND " ON)
option(FRAMEWORK_GRAPHICS "Use GRAPHICS " ON)
@ -24,32 +23,40 @@ set(executable_SOURCES
src/main.cpp
)
# add executable icon for win32 platforms
if(WIN32)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/otcicon.o
COMMAND ${CMAKE_RC_COMPILER}
-I${CMAKE_CURRENT_SOURCE_DIR}/src
-i${CMAKE_CURRENT_SOURCE_DIR}/src/otcicon.rc
-o ${CMAKE_CURRENT_BINARY_DIR}/otcicon.o)
if(MSVC)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/otcicon.o
COMMAND ${CMAKE_RC_COMPILER}
-I${CMAKE_CURRENT_SOURCE_DIR}/src
-fo${CMAKE_CURRENT_BINARY_DIR}/otcicon.o
${CMAKE_CURRENT_SOURCE_DIR}/src/otcicon.rc
)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
else()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/otcicon.o
COMMAND ${CMAKE_RC_COMPILER}
-I${CMAKE_CURRENT_SOURCE_DIR}/src
-i${CMAKE_CURRENT_SOURCE_DIR}/src/otcicon.rc
-o ${CMAKE_CURRENT_BINARY_DIR}/otcicon.o
)
endif()
set(executable_SOURCES ${executable_SOURCES} otcicon.o)
endif()
add_definitions(-D"VERSION=\\"${VERSION}\\"")
# we want framework to be a library for faster compilation/linking
if(USE_STATIC_LIBS)
add_library(${LIB_NAME} ${framework_SOURCES})
else()
add_library(${LIB_NAME} SHARED ${framework_SOURCES})
message(STATUS "Linking to shared ${LIB_NAME}, make sure you copy the DLL/SO/dylib with the executable!")
endif()
target_link_libraries(${LIB_NAME} ${framework_LIBRARIES})
# add client executable
add_executable(${PROJECT_NAME} ${client_SOURCES} ${executable_SOURCES})
add_executable(${PROJECT_NAME} ${framework_SOURCES} ${client_SOURCES} ${executable_SOURCES})
# target link libraries
target_link_libraries(${PROJECT_NAME} ${LIB_NAME})
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 14)
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD_REQUIRED ON)
target_link_libraries(${PROJECT_NAME} ${framework_LIBRARIES})
if(APPLE AND USE_STATIC_LIBS)
target_link_libraries(${PROJECT_NAME} "-framework Foundation" "-framework IOKit")
endif()
if(USE_PCH)
include(cotire)
@ -61,7 +68,7 @@ endif()
# installation
set(DATA_INSTALL_DIR share/${PROJECT_NAME})
install(TARGETS ${PROJECT_NAME} ${LIB_NAME}
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)

48
Dockerfile Normal file
View File

@ -0,0 +1,48 @@
FROM ubuntu@sha256:b88f8848e9a1a4e4558ba7cfc4acc5879e1d0e7ac06401409062ad2627e6fb58 AS builder
RUN apt-get update; \
apt-get install -y \
build-essential \
cmake \
git-core \
libboost-atomic1.65-dev \
libboost-chrono1.65-dev \
libboost-date-time1.65-dev \
libboost-filesystem1.65-dev \
libboost-system1.65-dev \
libboost-thread1.65-dev \
libglew-dev \
liblua5.1-0-dev \
libncurses5-dev \
libopenal-dev \
libssl-dev \
libvorbis-dev \
zlib1g-dev; \
apt-get clean && apt-get autoclean
WORKDIR /
RUN git clone --branch release-3.0.2 --depth 1 https://github.com/icculus/physfs.git
WORKDIR /physfs/build/
RUN cmake ..
RUN make -j$(nproc)
RUN make install
COPY ./src/ /otclient/src/.
COPY CMakeLists.txt /otclient/.
WORKDIR /otclient/build/
RUN cmake -DCMAKE_CXX_LINK_FLAGS=-no-pie -DCMAKE_BUILD_TYPE=Release ..
RUN make -j$(nproc)
FROM ubuntu@sha256:b88f8848e9a1a4e4558ba7cfc4acc5879e1d0e7ac06401409062ad2627e6fb58
RUN apt-get update; \
apt-get install -y \
libglew2.0 \
libopenal1; \
apt-get clean && apt-get autoclean
COPY --from=builder /otclient/build/otclient /otclient/bin/otclient
COPY ./data/ /otclient/data/.
COPY ./mods/ /otclient/mods/.
COPY ./modules/ /otclient/modules/.
COPY ./init.lua /otclient/.
WORKDIR /otclient
CMD ["./bin/otclient"]

22
ISSUE_TEMPLATE.md Normal file
View File

@ -0,0 +1,22 @@
<!-- Welcome to the issues section if it's your first time! -->
### Before creating an issue, please ensure:
- [ ] This is a bug in the software that resides in this repository, and not a
support matter (use https://otland.net/forums/otclient.494/ for support)
- [ ] This issue is reproducible without changes to the code in this repository
### Steps to reproduce (include any configuration/script required to reproduce)
1.
2.
3.
### Expected behaviour
<!-- Tell us what should happen -->
### Actual behaviour
<!-- Tell us what happens instead -->
### Environment
<!-- Please tell which client version are you using (E.g 10.98 OTClient 0.6.6)
If the issue is environment specific (e.g. compiling errors), include
name and version of the operating system and compiler you are using. -->

View File

@ -1,6 +1,6 @@
OTClient is made available under the MIT License
Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
Copyright (c) 2010-2020 OTClient <https://github.com/edubart/otclient>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,4 +1,5 @@
[![Build Status](https://secure.travis-ci.org/edubart/otclient.svg?branch=master)](http://travis-ci.org/edubart/otclient)
[![Build Status](https://github.com/edubart/otclient/actions/workflows/build-vcpkg.yml/badge.svg)](https://github.com/edubart/otclient/actions/workflows/build-vcpkg.yml) [![Join the chat at https://gitter.im/edubart/otclient](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/edubart/otclient?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Open Source Helpers](https://www.codetriage.com/edubart/otclient/badges/users.svg)](https://www.codetriage.com/edubart/otclient)
### What is otclient?
Otclient is an alternative Tibia client for usage with otserv. It aims to be complete and flexible,
@ -6,21 +7,17 @@ for that it uses LUA scripting for all game interface functionality and configur
similar to CSS for the client interface design. Otclient works with a modular system, this means
that each functionality is a separated module, giving the possibility to users modify and customize
anything easily. Users can also create new mods and extend game interface for their own purposes.
Otclient is written in C++2011, the upcoming C++ standard and heavily scripted in lua.
Otclient is written in C++11 and heavily scripted in lua.
For a server to connect to, you can build your own with the [forgottenserver](https://github.com/otland/forgottenserver)
or connect to one listed on [otservlist](https://otservlist.org/).
### Where do I download?
The latest commits compiled for Windows can be found here.
Compiled for Windows can be found here (but can be outdated):
* [Windows Builds](http://otland.net/threads/otclient-builds-windows.217977/)
Here is the latest v0.6.5 release compiled for both i686(32 bit) and x86_64(64 bit) machines, with OpenGL renderer.
This release is compatible with protocols ranges from 7.60 up to 10.31.
* [For Windows](https://www.dropbox.com/sh/se1okacemoqzjve/XFqFoSKLCg/otclient-win-0.6.5.zip)
* [For Linux](https://www.dropbox.com/sh/se1okacemoqzjve/xKJL7j6vEo/otclient-linux-0.6.5.tar.gz)
**NOTE:** You will need to download spr/dat files on your own and place them in `data/things/VERSION/` (i.e: `data/things/1041/Tibia.spr`)
Older releases can be downloaded from [here](https://www.dropbox.com/sh/se1okacemoqzjve/-oWK4YFm03)
**NOTE:** You will need to download spr/dat files on your own and place them in `data/things/VERSION/` (i.e: `data/things/1098/Tibia.spr`)
### Features
@ -34,20 +31,40 @@ client, instead otclient was designed to be a combination of a framework and tib
### Compiling
A package with all required libraries for compiling OTClient on Windows can be found here:
* [For MSVC 2013](https://www.dropbox.com/sh/se1okacemoqzjve/dI4ODbq7OT/otclient-msvc13-libs.zip)
* [For MingW32](https://www.dropbox.com/sh/se1okacemoqzjve/UAkRCiGXXR/otclient-libs_mingw32-dwarf2.zip)
In short, if you need to compile OTClient, follow these tutorials:
* [Compiling on Windows](https://github.com/edubart/otclient/wiki/Compiling-on-Windows)
* [Compiling on Linux](https://github.com/edubart/otclient/wiki/Compiling-on-Linux)
* [Compiling on OS X](https://github.com/edubart/otclient/wiki/Compiling-on-Mac-OS-X)
### Build and run with Docker
To build the image:
```sh
docker build -t edubart/otclient .
```
To run the built image:
```sh
# Disable access control for the X server.
xhost +
# Run the container image with the required bindings to the host devices and volumes.
docker run -it --rm \
--env DISPLAY \
--volume /tmp/.X11-unix:/tmp/.X11-unix \
--device /dev/dri \
--device /dev/snd edubart/otclient /bin/bash
# Enable access control for the X server.
xhost -
```
### Need help?
Try to ask questions in [otland](http://otland.net/f494/), now we have a board for the project there,
or talk with us at #otclient irc.freenode.net
or talk with us at the gitter chat.
### Bugs
@ -59,7 +76,7 @@ We encourage you to contribute to otclient! You can make pull requests of any im
### Contact
Talk directly with us at #otclient irc.freenode.net or send an email directly to the project leader edub4rt@gmail.com
Talk directly with us at the gitter chat [![Join the chat at https://gitter.im/edubart/otclient](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/edubart/otclient?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge).
### License

View File

Before

Width:  |  Height:  |  Size: 283 B

After

Width:  |  Height:  |  Size: 283 B

View File

Before

Width:  |  Height:  |  Size: 283 B

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 B

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 373 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 444 B

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 B

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 373 B

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 B

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 418 B

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 B

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 B

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 B

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -4,6 +4,10 @@ locale = {
charset = "cp1252",
languageName = "Deutsch",
formatNumbers = true,
decimalSeperator = ',',
thousandsSeperator = ' ',
translation = {
["1a) Offensive Name"] = false,
["1b) Invalid Name Format"] = false,
@ -26,7 +30,7 @@ locale = {
["4c) False Report to Gamemaster"] = false,
["Accept"] = "Annehmen",
["Account name"] = "Benutzername",
["Account Status:"] = false,
["Account Status"] = false,
["Action:"] = false,
["Add"] = "Hinzufügen",
["Add new VIP"] = "Neuen Freund hinzufügen",
@ -227,7 +231,7 @@ locale = {
["Pass Leadership to %s"] = "%s zum Anführer ernennen",
["Password"] = "Passwort",
["Piece Price:"] = "Stückpreis",
["Please enter a character name:"] = "Bitte gib einen Charakternamen an:",
["Please enter a character name"] = "Bitte gib einen Charakternamen an",
["Please, press the key you wish to add onto your hotkeys manager"] = "Bitte die gewünschte Taste drücken",
["Please Select"] = false,
["Please use this dialog to only report bugs. Do not report rule violations here!"] = false,

View File

@ -3,6 +3,10 @@ locale = {
charset = "cp1252",
languageName = "English",
formatNumbers = true,
decimalSeperator = '.',
thousandsSeperator = ',',
-- translations are not needed because everything is already in english
translation = {}
}

View File

@ -7,16 +7,20 @@ locale = {
charset = "cp1252",
languageName = "Español",
formatNumbers = true,
decimalSeperator = ',',
thousandsSeperator = '.',
translation = {
["1a) Offensive Name"] = "1a) Nombre ofensivo",
["1b) Invalid Name Format"] = "1b) Formato invalido para nombre",
["1b) Invalid Name Format"] = "1b) Formato inválido para el nombre",
["1c) Unsuitable Name"] = "1c) Nombre no adecuado",
["1d) Name Inciting Rule Violation"] = "1d) Nombre que incita una violación al reglamento",
["2a) Offensive Statement"] = "2a) Comentario ofensivo",
["2b) Spamming"] = "2b) Spamming",
["2c) Illegal Advertising"] = "2c) Publicidad ilícita",
["2d) Off-Topic Public Statement"] = "2d) Publicación fuera de lugar",
["2e) Non-English Public Statement"] = "2e) Publicación fuera del ingles",
["2e) Non-English Public Statement"] = "2e) Publicación fuera del inglés",
["2f) Inciting Rule Violation"] = "2f) Incitar a una violación al reglamento",
["3a) Bug Abuse"] = "3a) Abuso de error",
["3b) Game Weakness Abuse"] = "3b) Abuso de debilidad del juego",
@ -24,12 +28,12 @@ locale = {
["3d) Hacking"] = "3d) Hackeo",
["3e) Multi-Clienting"] = "3e) Uso de múltiples clientes",
["3f) Account Trading or Sharing"] = "3f) Intercambio de cuenta",
["4a) Threatening Gamemaster"] = "4a) Amenzar a un Gamemaster",
["4a) Threatening Gamemaster"] = "4a) Amenazar a un Gamemaster",
["4b) Pretending to Have Influence on Rule Enforcement"] = "4b) Pretender tener influencia en una parte del reglamento",
["4c) False Report to Gamemaster"] = "4c) Reporte falso a un Gamemaster",
["Accept"] = "Aceptar",
["Account name"] = "Nombre de cuenta",
["Account Status:"] = "Estado de cuenta:",
["Account name"] = "Nombre de la cuenta",
["Account Status"] = "Estado de la cuenta",
["Action:"] = "Acción:",
["Add"] = "Añadir",
["Add new VIP"] = "Añadir nuevo VIP",
@ -40,14 +44,14 @@ locale = {
["Adjust volume"] = "Ajustar volumen",
["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!"] = "¡Ay! Aventurero valiente, has conocido un triste destino. \nPero no se desespere, porque los dioses te llevarán de vuelta \na este mundo a cambio de un pequeño sacrificio \n\nSimplemente haga clic en Aceptar para continuar con sus viajes!",
["All"] = "Todo",
["All modules and scripts were reloaded."] = "Todos los módulos y scripts se vuelven a cargar.",
["Allow auto chase override"] = "Permitur auto persecución override",
["Also known as dash in tibia community, recommended\nfor playing characters with high speed"] = "Conocido por la comunidad de tibia como dash.\nRecomenada para jugadores de alto nivel.",
["Ambient light: %s%%"] = "Ambiente de luz: %s%%",
["All modules and scripts were reloaded."] = "Todos los módulos y scripts se volvieron a cargar.",
["Allow auto chase override"] = "Desactivar auto persecución al andar",
["Also known as dash in tibia community, recommended\nfor playing characters with high speed"] = "Conocido por la comunidad de tibia como \"dash\".\nRecomenada para jugadores de alto nivel.",
["Ambient light: %s%%"] = "Luz de ambiente: %s%%",
["Amount:"] = "Cantidad:",
["Amount"] = "Cantidad",
["Anonymous"] = "Anónimo",
["Are you sure you want to logout?"] = "¿Estas seguro de que deseas salir?",
["Are you sure you want to logout?"] = "¿Estás seguro de que deseas salir?",
["Attack"] = "Atacar",
["Author"] = "Autor",
["Autoload"] = "Auto carga",
@ -56,26 +60,26 @@ locale = {
["Auto login selected character on next charlist load"] = "Ingresar la siguiente vez que aparece el charlist con el personaje seleccionado",
["Axe Fighting"] = "Combate con hacha",
["Balance:"] = "Saldo:",
["Banishment"] = "Banishment",
["Banishment + Final Warning"] = "Banishment + Final Warning",
["Banishment"] = "Baneo",
["Banishment + Final Warning"] = "Baneo + Último Aviso",
["Battle"] = "Batalla",
["Browse"] = "Navegar",
["Bug report sent."] = "Reporte de error enviado.",
["Button Assign"] = "Botón asignado",
["Button Assign"] = "Asignar botón",
["Buy"] = "Compra",
["Buy Now"] = "Compra ahora",
["Buy Offers"] = "Comprar oferta",
["Buy Offers"] = "Comprar ofertas",
["Buy with backpack"] = "Comprar con mochila",
["Cancel"] = "Cancelar",
["Cannot login while already in game."] = "No se puede iniciar sesión, mientras que estés en el juego.",
["Cannot login while already in game."] = "No se puede iniciar sesión, mientras ya estés en el juego.",
["Cap"] = "Cap",
["Capacity"] = "Capacidad",
["Center"] = "Centrar",
["Channels"] = "Canales",
["Character List"] = "Lista de carácter",
["Classic control"] = "Controles Clásicos",
["Clear current message window"] = "Limpiar mensaje actual en ventana",
["Clear Messages"] = "Limpiar mensaje",
["Character List"] = "Lista de caracteres",
["Classic control"] = "Controles clásicos",
["Clear current message window"] = "Limpiar ventana de mensajes actual",
["Clear Messages"] = "Limpiar mensajes",
["Clear object"] = "Limpiar objeto",
["Client needs update."] = "El cliente necesita una actualización.",
["Close"] = "Cerrar",
@ -83,10 +87,10 @@ locale = {
["Club Fighting"] = "Combate con mazo",
["Combat Controls"] = "Controles de combate",
["Comment:"] = "Comentario:",
["Connecting to game server..."] = "Conectando a servidor game...",
["Connecting to login server..."] = "Conectando a servidor login...",
["Connecting to game server..."] = "Conectando a servidor de juego...",
["Connecting to login server..."] = "Conectando a servidor de login...",
["Console"] = "Consola",
["Cooldowns"] = "Descansos",
["Cooldowns"] = "Enfriamientos",
["Copy message"] = "Copiar mensaje",
["Copy name"] = "Copiar nombre",
["Copy Name"] = "Copiar nombre",
@ -118,7 +122,7 @@ locale = {
["Enable vertical synchronization"] = "Habilitar sincronización vertical",
["Enable walk booster"] = "Habilitar caminado turbo",
["Enter Game"] = "Entrar al juego",
["Enter one name per line."] = "Introducir un nombre por linea.",
["Enter one name per line."] = "Introducir un nombre por línea.",
["Enter with your account again to update your client."] = "Ingrese con su cuenta nuevamente para actualizar el cliente.",
["Error"] = "Error",
["Error"] = "Error",
@ -126,18 +130,18 @@ locale = {
["Exclude from private chat"] = "Ejecutar desde un canal privado",
["Exit"] = "Salir",
["Experience"] = "Experiencia",
["Filter list to match your level"] = "Lista de filtros que coincida con el nivel",
["Filter list to match your vocation"] = "Lista de filtros que coincida con el vocación",
["Filter list to match your level"] = "Filtrar lista para coincidir con el nivel",
["Filter list to match your vocation"] = "Filtrar lsta para coincidir con la vocación",
["Find:"] = "Encontrar:",
["Fishing"] = "Pesca",
["Fist Fighting"] = "Combate con puños",
["Fist Fighting"] = "Combate a puños",
["Follow"] = "Seguir",
["Force Exit"] = "Forzar salida",
["Force Exit"] = "Forzar Salir", -- "Forzar Salida" is almost too big for a button
["For Your Information"] = "Para tu información",
["Free Account"] = "Cuenta gratis",
["Fullscreen"] = "Pantalla completa",
["Game"] = "Juego",
["Game framerate limit: %s"] = "Limite de cuadros por segundo en el juego: %s",
["Game framerate limit: %s"] = "Límite de cuadros por segundo en el juego: %s",
["Graphics"] = "Gráficos",
["Graphics card driver not detected"] = "Controlador de tarjeta gráfica de video no detectado",
["Graphics Engine:"] = "Motor Gráfico:",
@ -151,32 +155,32 @@ locale = {
["Hide Offline"] = "Ocultar fuera de linea",
["Hide party members"] = "Ocultar miembros del party",
["Hide players"] = "Ocultar players",
["Hide spells for higher exp. levels"] = "Ocultar hechizos para niveles mas altos que tu experiencia.",
["Hide spells for higher exp. levels"] = "Ocultar hechizos para niveles más altos que tu experiencia.",
["Hide spells for other vocations"] = "Ocultar hechizos que sean para otra vocación",
["Hit Points"] = "Puntos de vida",
["Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks"] = "Mantenga presionado el botón derecho del ratón para navegar\nDezplaze la rueda central del ratón para ampliar\nbotón derecho del mouse para crear marcas del mapa",
["Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks"] = "Mantenga presionado el botón derecho del ratón para navegar\nDesplace la rueda central del ratón para ampliar\nbotón derecho del ratón para crear marcas del mapa",
["Hotkeys"] = "Hotkeys",
["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."] = "Si se cierra el programa, tu personaje puede permanecer en el juego.\nHaga clic en 'Salir' para asegurarse de que personaje deja el juego correctamente.\nHaga click en 'Salir' si desea salir del programa sin tener que salir de tu personaje.",
["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."] = "Si se cierra el programa, su personaje puede permanecer en el juego.\nHaga clic en 'Desconectar' para asegurarse de que el personaje deja el juego correctamente.\nHaga clic en 'Forzar Salir' si desea salir del programa igualmente, pudiendo mantener el personaje en el juego.",
["Ignore"] = "Ignorar",
["Ignore capacity"] = "Ignorar Capacidad",
["Ignore capacity"] = "Ignorar capacidad",
["Ignored players:"] = "Jugadores ignorados:",
["Ignore equipped"] = "Ignorar lo equipado",
["Ignore List"] = "Ignorar lista",
["Ignore players"] = "Ignorar jugadores",
["Ignore Private Messages"] = "Ignorar mensajes privados",
["Ignore Yelling"] = "Ignorar gritos",
["Interface framerate limit: %s"] = "Interface de cuadros por segundo: %s",
["Interface framerate limit: %s"] = "Interfaz de cuadros por segundo: %s",
["Inventory"] = "Inventario",
["Invite to Party"] = "Ivitar al party",
["Invite to Party"] = "Invitar a party",
["Invite to private chat"] = "Invitar a canal privado",
["IP Address Banishment"] = "Banishment - Dirección IP",
["IP Address Banishment"] = "Dirección IP Baneada",
["Item Offers"] = "Ofertas de objetos",
["It is empty."] = "Está vac.",
["Join %s\'s Party"] = "Unirse al party de %s ",
["It is empty."] = "Está vacío.",
["Join %s\'s Party"] = "Unirse al party de %s",
["Leave Party"] = "Dejar el party",
["Level"] = "Nivel",
["Lifetime Premium Account"] = "Tiempo de Premium Account infinito",
["Limits FPS to 60"] = "Limites FPS a 60",
["Limits FPS to 60"] = "Límites FPS a 60",
["List of items that you're able to buy"] = "Lista de objetos que puedes de comprar",
["List of items that you're able to sell"] = "Lista de objetos que puedes de vender",
["Load"] = "Cargar",
@ -184,44 +188,44 @@ locale = {
["Login"] = "Ingresar",
["Login Error"] = "Error de ingreso",
["Login Error"] = "Error de ingreso",
["Logout"] = "Salir",
["Logout"] = "Desconectar",
["Look"] = "Mirar",
["Magic Level"] = "Nivel mágico",
["Make sure that your client uses\nthe correct game protocol version"] = "Asegúrese de que el cliente este utilizando\nes el versión del protocolo adecuado",
["Make sure that your client uses\nthe correct game protocol version"] = "Asegúrese de que el cliente este utilizando\nla versión del protocolo correcta",
["Mana"] = "Mana",
["Manage hotkeys:"] = "Administrador de hotkeys:",
["Market"] = "Mercado",
["Market Offers"] = "Ofertas en mercado",
["Market Offers"] = "Ofertas del mercado",
["Message of the day"] = "Mensaje del día",
["Message to "] = "Mensaje a",
["Message to "] = "Mensaje a ",
["Message to %s"] = "Mensaje a %s",
["Minimap"] = "Minimapa",
["Module Manager"] = "Administrador de módulos",
["Module name"] = "Nombre del modulo",
["Mount"] = "Montar", --Unique name?
["Module name"] = "Nombre del módulo",
["Mount"] = "Montar", --"Montura" if it doesn't refers to the verb
["Move Stackable Item"] = "Mover objeto apilable",
["Move up"] = "Mover arriba",
["My Offers"] = "Mis ofertas",
["Name:"] = "Nombre:",
["Name Report"] = "Name Report",
["Name Report + Banishment"] = "Name Report + Banishment",
["Name Report + Banishment + Final Warning"] = "Name Report + Banishment + Final Warning",
["Name Report"] = "Reportar nombre",
["Name Report + Banishment"] = "Reportar nombre + Baneo",
["Name Report + Banishment + Final Warning"] = "Reportar nombre + Baneo + Último Aviso",
["No"] = "No",
["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."] = "No se ha detectado una tarjeta gráfica y todo sera procesado por tu procesador,\npor lo tanto el rendimiento va a ser muy malo.\nPor favor, actualice su controlador de gráficos para tener un rendimiento optimo.",
["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."] = "No se ha detectado una tarjeta gráfica y todo sera procesado por tu procesador,\npor lo tanto el rendimiento va a ser muy malo.\nPor favor, actualice su controlador de la gráfica para tener un rendimiento óptimo.",
["No item selected."] = "No hay elemento seleccionado.",
["No Mount"] = "No montura",
["No Mount"] = "No montura", --probably "Sin" instead of "No" is more fitting?
["No Outfit"] = "No outfit",
["No statement has been selected."] = "No hay comentario seleccionado.",
["Notation"] = "Notation",
["No statement has been selected."] = "No se ha seleccionado ningún comentario.",
["Notation"] = "Notación",
["NPC Trade"] = "Intercambio con NPC",
["Offer History"] = "Historial de oferta",
["Offer History"] = "Historial de ofertas",
["Offers"] = "Ofertas",
["Offer Type:"] = "Tipo de oferta:",
["Offline Training"] = "Entrenamiento offLine",
["Ok"] = "OK",
["on %s.\n"] = "en %s.\n",
["Open"] = "Abierto",
["Open a private message channel:"] = "Abrir mensaje en canal privado:",
["Open"] = "Abrir",
["Open a private message channel:"] = "Abrir canal privado:",
["Open charlist automatically when starting client"] = "Abrir lista de jugadores automáticamente al iniciar el cliente",
["Open in new window"] = "Abrir en nueva ventana",
["Open new channel"] = "Abrir nuevo canal",
@ -230,21 +234,21 @@ locale = {
["Pass Leadership to %s"] = "Pasar liderazgo a %s",
["Password"] = "Contraseña",
["Piece Price:"] = "Precio por pieza:",
["Please enter a character name:"] = "Por favor ingresar nombre del jugador:",
["Please enter a character name"] = "Por favor ingresa nombre del jugador",
["Please, press the key you wish to add onto your hotkeys manager"] = "Por favor, presiona la tecla que desees para que sea registrada en\nel administrador de hotkeys",
["Please Select"] = "Por favor seleccione",
["Please use this dialog to only report bugs. Do not report rule violations here!"] = "Por favor usa este diálogo solo para reportar errores.\n¡No reportar violaciones del reglamento aquí!",
["Please use this dialog to only report bugs. Do not report rule violations here!"] = "Por favor usa este diálogo sólo para reportar errores.\n¡No reportar violaciones del reglamento aquí!",
["Please wait"] = "Por favor espere",
["Port"] = "Puerto",
["Position:"] = "Posición:",
["Position: %i %i %i"] = "Posición: %i %i %i",
["Premium Account (%s) days left"] = "Tienes (%s) días de Premium Account restantes",
["Premium Account (%s) days left"] = "Quedan (%s) días de Premium Account",
["Price:"] = "Precio:",
["Primary"] = "Primario",
["Protocol"] = "Protocolo",
["Quest Log"] = "Quest Log", --Unique name
["Randomize"] = "Combinar",
["Randomize characters outfit"] = "Combinar vestimenta del jugador",
["Randomize"] = "Aleatorio",
["Randomize characters outfit"] = "Crear vestimenta del jugador aleatoriamente",
["Reason:"] = "Razón:",
["Refresh"] = "Refrescar",
["Refresh Offers"] = "Refrescar ofertas",
@ -253,10 +257,10 @@ locale = {
["Reload All"] = "Cargar todo de nuevo",
["Remember account and password when starts client"] = "Recordar cuenta y contraseña al iniciar el cliente",
["Remember password"] = "Recordar contraseña",
["Remove"] = "Remover",
["Remove %s"] = "Remover %s",
["Remove"] = "Eliminar",
["Remove %s"] = "Eliminar %s",
["Report Bug"] = "Reportar error",
["Reserved for more functionality later."] = "Reservado para una función futura.",
["Reserved for more functionality later."] = "Reservado para una funcionalidad futura.",
["Reset Market"] = "Reiniciar mercado",
["Revoke %s\'s Invitation"] = "Anular %s\'s invitación",
["Rotate"] = "Rotar",
@ -268,7 +272,7 @@ locale = {
["Secondary"] = "Secundario",
["Select object"] = "Seleccionar objeto",
["Select Outfit"] = "Seleccionar outfit",
["Select your language"] = "Selectionar tu lenguaje",
["Select your language"] = "Seleccionar tu idioma",
["Sell"] = "Vender",
["Sell Now"] = "Vender ahora",
["Sell Offers"] = "Ofertas de venta",
@ -296,82 +300,85 @@ locale = {
["Show timestamps in console"] = "Mostrar marcas de tiempo en consola",
["Show your depot items only"] = "Mostrar solo tus objetos en depot",
["Skills"] = "Habilidades",
["Soul"] = "Soul",
["Soul Points"] = "Puntos de Soul", --I'm leaving these as is because its a unique name, if you want to change it it can be "Alma" or "Espíritu"
["Sort by name"] = "Ordenar por nombre",
["Sort by status"] = "Ordenar por estado",
["Sort by type"] = "Ordernar por tipo",
["Soul"] = "Soul", --I'm leaving these as is because its a unique name, if you want to change it it can be "Alma" or "Espíritu"
["Soul Points"] = "Puntos de Soul",
["Special"] = "Especial",
["Speed"] = "Velocidad",
["Spell Cooldowns"] = "Spells Cooldowns", --Could be "Tiempo de recarga para los hechizos".
["Spell Cooldowns"] = "Enfriamiento de hechizos", --Should 'spells'? be an unique name?
["Spell List"] = "Lista de hechizos",
["Stamina"] = "Resistencia",
["Statement:"] = "Comentario:",
["Statement Report"] = "Statement Report", --Could be "reporte del comentario"
["Statement Report"] = "Statement Report", --Could be "reporte del comentario"/Not sure how to translate it correctly.. When is it used in the game?
["Statistics"] = "Estadísticas",
["Stop Attack"] = "Detener ataque",
["Stop Follow"] = "Detener persecución",
["Support"] = "Soporte",
["%s: (use object)"] = "%s: (usar objeto)",
["%s: (use object on target)"] = "%s: (usar objeto en un objetivo)",
["%s: (use object on yourself)"] = "%s: (usar objeto en mi mismo)",
["%s: (use object on yourself)"] = "%s: (usar objeto en ti mismo)",
["%s: (use object with crosshair)"] = "%s: (usar objeto con punto de mira)",
["Sword Fighting"] = "Combate de espada",
["Sword Fighting"] = "Combate con espada",
["Terminal"] = "Terminal",
["There is no way."] = "No hay ninguna manera.",
["Title"] = "Titulo",
["Total Price:"] = "Total total:",
["There is no way."] = "No hay forma de llegar.",
["Title"] = "Título",
["Total Price:"] = "Precio total:",
["Trade"] = "Intercambio",
["Trade with ..."] = "Intercambiar con ...",
["Trying to reconnect in %s seconds."] = "",
["Trying to reconnect in %s seconds."] = "Intentando reconectar en %s segundos.",
["Unable to load dat file, please place a valid dat in '%s'"] = "No se puede cargar el archivo dat, por favor coloque un dat válido en '%s'",
["Unable to load spr file, please place a valid spr in '%s'"] = "No se puede cargar el archivo spr, por favor coloque un spr válido en '%s'",
["Unable to logout."] = "No se puede cerrar sesión-",
["Unable to logout."] = "No se puede cerrar sesión.",
["Unignore"] = "Dejar de ignorar",
["Unload"] = "No cargado",
["Unload"] = "Desactivar", -- Should be "Descargar", but not used to prevent misunderstandings with "Download".
["Update needed"] = "Es necesario actualizar",
["Use"] = "Uso",
["Use"] = "Usar",
["Use on target"] = "Usar en un objetivo",
["Use on yourself"] = "Usar en mi mismo",
["Use with ..."] = "Usar en ...",
["Version"] = "Versión",
["VIP List"] = "Lista Vip",
["VIP List"] = "Lista VIP",
["Voc."] = "Voc.",
["Vocation"] = "Vocación",
["Waiting List"] = "Lista de espera",
["Website"] = "Sitio Web",
["Weight:"] = "Peso:",
["Will detect when to use diagonal step based on the\nkeys you are pressing"] = "Detectara cuando se camina en diagonal usando las flechas",
["Will detect when to use diagonal step based on the\nkeys you are pressing"] = "Detectará cuando caminar en diagonal en base\n a las teclas pulsadas",
["With crosshair"] = "Con punto de mira",
["Yes"] = "Si",
["You are bleeding"] = "Te estas desangrando",
["You are burning"] = "Te estas quemando",
["You are cursed"] = "Tu estas maldecido",
["You are dazzled"] = "Tu estas deslumbrado",
["You are dead."] = "Tu estas muerto.",
["You are dead"] = "Tu estas muerto",
["You are drowning"] = "Te estas ahogando",
["You are drunk"] = "Tu estas ebrio",
["You are electrified"] = "Tu estas electrocutado",
["You are freezing"] = "Te estas congelando",
["You are hasted"] = "Tu estas rápido", --I dont know what is the best way to translate this so I'm leaving it as I found it.
["You are hungry"] = "Tu estas hambriento",
["You are paralysed"] = "Tu estas paralizado",
["You are poisoned"] = "Tu estas envenedado",
["You are protected by a magic shield"] = "Tu estas protegido por un escudo mágico",
["You are strengthened"] = "Tu estas reforzado",
["You are within a protection zone"] = "Tu estas dentro de una zona de protección",
["You can enter new text."] = "Tu puedes ingresar un texto nuevo.",
["You have %s percent"] = "Tu tienes %s por ciento",
["You have %s percent to go"] = "Tu tienes %s por ciento para ir",
["You may not logout during a fight"] = "No puedes salir durante una pelea",
["You may not logout or enter a protection zone"] = "No puedes salir o entrar en una zona de protección",
["You must enter a comment."] = "Debes ingresar un comentario.",
["Yes"] = "Sí",
["You are bleeding"] = "Te estás desangrando",
["You are burning"] = "Te estás quemando",
["You are cursed"] = "Estás maldecido",
["You are dazzled"] = "Estás deslumbrado",
["You are dead."] = "Has muerto.",
["You are dead"] = "Has muerto",
["You are drowning"] = "Te estás ahogando",
["You are drunk"] = "Estás ebrio",
["You are electrified"] = "Estás electrocutado",
["You are freezing"] = "Te estás congelando",
["You are hasted"] = "Tienes la velocidad incrementada", --The best translation I could thing of ("You have increased speed")
["You are hungry"] = "Tienes hambre",
["You are paralysed"] = "Estás paralizado",
["You are poisoned"] = "Estás envenedado",
["You are protected by a magic shield"] = "Estás protegido por un escudo mágico",
["You are strengthened"] = "Estás reforzado", --"fortificado" maybe?
["You are within a protection zone"] = "Estás dentro de una zona de protección",
["You can enter new text."] = "Puedes escribir texto nuevo.",
["You have %s percent"] = "Tienes el %s por ciento",
["You have %s percent to go"] = "Tienes el %s por ciento para avanzar",
["You may not logout during a fight"] = "No te puedes desconectar durante una pelea",
["You may not logout or enter a protection zone"] = "No te puedes desconectar o entrar en una zona de protección",
["You must enter a comment."] = "Debes escribir un comentario.",
["You must enter a valid server address and port."] = "Debes ingresar una dirección válida de servidor y el puerto.",
["You must select a character to login!"] = "¡Debes seleccionar un personaje para ingresar!",
["You must select a character to login!"] = "¡Debes seleccionar un personaje para ingresar!", -- I would use "conectarte" but it's Ok
["Your Capacity:"] = "Tu capacidad:",
["You read the following, written by \n%s\n"] = "Lees lo siguiente, escrito por \n%s\n",
["You read the following, written on \n%s.\n"] = "Lees lo siguiente, escrito en \n%s\n",
["Your Money:"] = "Tu dinero:",
["Change language"] = "Cambiar idioma",
["Don't stretch or shrink Game Window"] = "No estirar o encoger Ventana de Juego"
["Don't stretch or shrink Game Window"] = "No estirar ni encoger la ventana de juego"
}
}

View File

@ -2,6 +2,10 @@ locale = {
name = "pl",
languageName = "Polski",
formatNumbers = true,
decimalSeperator = '.',
thousandsSeperator = ' ',
translation = {
["1a) Offensive Name"] = "1a) Obrazliwe Imie",
["1b) Invalid Name Format"] = "1b) Niepoprawny Format Imienia",
@ -24,7 +28,7 @@ locale = {
["4c) False Report to Gamemaster"] = "4c) Wyslanie Falszywego Raportu Mistrzowi Gry",
["Accept"] = "Akceptuj",
["Account name"] = "Numer konta",
["Account Status:"] = "Status Konta:",
["Account Status"] = "Status Konta",
["Action:"] = "Akcja:",
["Add"] = "Dodaj",
["Add new VIP"] = "Nowy VIP",
@ -224,7 +228,7 @@ locale = {
["Pass Leadership to %s"] = "Oddaj przywodztwo %s",
["Password"] = "Haslo",
["Piece Price:"] = "Cena jednego przedmiotu",
["Please enter a character name:"] = "Podaj nazwe postaci:",
["Please enter a character name"] = "Podaj nazwe postaci",
["Please, press the key you wish to add onto your hotkeys manager"] = "Nacisnij klawisz, ktory chcesz dodac do menedzera skrotow klawiszowych",
["Please Select"] = "Prosze wybrac",
["Please use this dialog to only report bugs. Do not report rule violations here!"] = "Zglaszaj tylko bledy gry, nie lamanie zasad",
@ -291,7 +295,7 @@ locale = {
["Show your depot items only"] = "Pokaz tylko przedmioty z depozytu",
["Skills"] = "Umiejetnosci",
["Soul"] = "Dusze",
["Soul Points"] = "Punktey Duszy",
["Soul Points"] = "Punkty Duszy",
["Special"] = "Specialne",
["Speed"] = "Predkosc",
["Spell Cooldowns"] = "Czas odnowienia czaru",

View File

@ -3,14 +3,22 @@ locale = {
charset = "cp1252",
languageName = "Português",
formatNumbers = true,
decimalSeperator = ',',
thousandsSeperator = '.',
-- As traduções devem vir sempre em ordem alfabética.
translation = {
["%d of experience per hour"] = "%d de experiência por hora",
["%s has finished the request"] = "%s finalizou o pedido",
["%s has logged in."] = "%s entrou.",
["%s has logged out."] = "%s saiu.",
["%s of experience left"] = "%s de experiência faltando",
["%s: (use object on target)"] = "%s: (usar objeto no alvo)",
["%s: (use object on yourself)"] = "%s: (usar objeto em si)",
["%s: (use object with crosshair)"] = "%s: (usar objeto com mira)",
["%s: (use object)"] = "%s: (usar objeto)",
["(ERROR %d)"] = "(ERRO %d)",
["1a) Offensive Name"] = "1a) Nome ofensivo",
["1b) Invalid Name Format"] = "1b) Nome com formato inválido",
["1c) Unsuitable Name"] = "1c) Nome não adequado",
@ -34,6 +42,8 @@ locale = {
["Account name"] = "Nome da conta",
["Account Status"] = "Estado da Conta",
["Action"] = "Ação",
["Activate ignorelist"] = "Ativar lista ignorada",
["Activate whitelist"] = "Ativar lista branca",
["Add new server"] = "Adicionar novo servidor",
["Add new VIP"] = "Adicionar nova VIP",
["Add to VIP list"] = "Adicionar a lista VIP",
@ -42,17 +52,18 @@ locale = {
["Addon 2"] = "Addon 2",
["Addon 3"] = "Addon 3",
["Adjust volume"] = "Ajustar volume",
["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 modules and scripts were reloaded."] = "Todos módulos e scripts foram recarregados.",
["All"] = "Todos",
["Allow auto chase override"] = "Permitir sobrescrever o modo de perseguição",
["Allow VIPs to message you"] = "Permitir que VIPs te mandem mensagem",
["Allowed Players"] = "Jogadores com permissão",
["Also known as dash in tibia community, recommended\nfor playing characters with high speed"] = "Também conhecido como dash na comunidade tibiana, recomendado\npara jogar com personagem que possuam velocidade alta",
["Ambient light: %s%%"] = "Luz ambiente: %s%%",
["Amount"] = "Quantidade",
["Anonymous"] = "Anônimo",
["Any"] = "Qualquer",
["Are you sure you want to logout?"] = "Você tem certeza que quer sair?",
["Attack"] = "Atacar",
["Auction End"] = "Fim do Leilão",
["Audio"] = "Áudio",
["Author"] = "Autor",
["Auto login selected character on next charlist load"] = "Entrar automaticamente com o personagem quando reabrir a lista de personagens",
@ -64,6 +75,7 @@ locale = {
["Banishment + Final Warning"] = "Banimento + Aviso final",
["Banishment"] = "Banimento",
["Battle"] = "Batalha",
["Browse Field"] = "Navegar Campo",
["Browse"] = "Navegar",
["Bug report sent."] = "Reporte de bug enviado.",
["Button Assign"] = "Selecionar botão",
@ -71,12 +83,14 @@ locale = {
["Buy Offers"] = "Ofertas de compra",
["Buy with backpack"] = "Comprar com mochila",
["Buy"] = "Comprar",
["Buyer Name"] = "Nome do Comprador",
["Cancel"] = "Cancelar",
["Cannot login while already in game."] = "Não é possivel logar enquanto já estiver jogando.",
["Cap"] = "Cap",
["Capacity"] = "Capacidade",
["Center"] = "Centro",
["Change language"] = "Trocar língua",
["Channel appended to %s"] = "Canais acrescentados a %s",
["Channels"] = "Canais",
["Character List"] = "Lista de personagens",
["Classic control"] = "Controle clássico",
@ -84,6 +98,7 @@ locale = {
["Clear Messages"] = "Limpar mensagens",
["Clear object"] = "Limpar objeto",
["Client needs update."] = "O client do jogo precisa ser atualizado",
["Client Version"] = "Versão do Client",
["Close this channel"] = "Fechar esse canal",
["Close"] = "Fechar",
["Club Fighting"] = "Combate com Porrete",
@ -92,35 +107,44 @@ locale = {
["Connecting to game server..."] = "Conectando no servidor do jogo...",
["Connecting to login server..."] = "Conectando no servidor de autenticação...",
["Connection Error"] = "Erro de Conexão",
["Connection failed the server address does not exist."] = "Conexão falhou, servidor não existe.",
["Connection failed."] = "Conexão falhou.",
["Connection refused the server might be offline or restarting.\nPlease try again later."] = "Conexão recusada, servidor pode estar offline ou reiniciando. Por favor, tente novamente mais tarde.",
["Connection timed out. Either your network is failing or the server is offline."] = "Conexão encerrada por tempo limite. Sua rede está falhando, ou o servidor está offline.",
["Console"] = "Console",
["Cooldown"] = "Cooldown",
["Cooldowns"] = "Cooldowns",
["Copy message"] = "Copiar mensagem",
["Copy name"] = "Copiar nome",
["Copy Name"] = "Copiar Nome",
["Copy"] = "Copiar",
["Create Map Mark"] = "Criar marca no mapa",
["Create mark"] = "Criar marca",
["Create New Offer"] = "Criar nova oferta",
["Create Offer"] = "Criar oferta",
["Current hotkey to add: %s"] = "Atalho atual para adicionar: %s",
["Current hotkeys:"] = "Atalhos atuais",
["Critical Hit Chance"] = "Chance de acerto crítico",
["Critical Hit Damage"] = "Dano de acerto crítico",
["Current hotkeys"] = "Atalhos atuais",
["Current Offers"] = "Ofertas atuais",
["Default"] = "Padrão",
["Delete mark"] = "Deletar marca",
["Description"] = "Descrição",
["Description:"] = "Descrição",
["Destructive Behaviour"] = "Comportamento destrutivo",
["Detail"] = "Detalhe",
["Details"] = "Detalhes",
["Disable chat mode allow to walk using ASDW"] = "Desativar modo de chat permite andar usando ASDW",
["Disable Shared Experience"] = "Desativar experiência compartilhada",
["Dismount"] = "Desmontar",
["Display connection speed to the server (milliseconds)"] = "Exibir a velocidade de conexão com o servidor (milisegundos)",
["Display creature health bars"] = "Exibir barras de vida das criaturas",
["Display creature names"] = "Exibir nomes das criaturas",
["Display player mana bar"] = "Exibir barra de mana",
["Display text messages"] = "Exibir mensagens de texto",
["Distance Fighting"] = "Combate a Distância",
["Don't stretch or shrink Game Window"] = "Não esticar ou contrair a janela do game",
["Don\'t stretch or shrink Game Window"] = "Não esticar ou contrair a janela do game",
["Druid"] = "Druid",
["Edit %s"] = "Editar %s",
["Edit hotkey text:"] = "Editar texto do atalho",
["Edit List"] = "Editar lista",
["Edit Text"] = "Editar Texto",
@ -253,7 +277,7 @@ locale = {
["Pass Leadership to %s"] = "Passar liderança para %s",
["Password"] = "Senha",
["Piece Price"] = "Preço por peça",
["Please enter a character name:"] = "Por favor, entre com o nome do personagem:",
["Please enter a character name"] = "Por favor, entre com o nome do personagem",
["Please Select"] = "Por favor, selecione algo",
["Please use this dialog to only report bugs. Do not report rule violations here!"] = "Por favor, use este campo apenas para reportar defeitos. Não reporte violação de regras aqui!",
["Please wait"] = "Por favor, espere",

View File

@ -5,6 +5,10 @@ locale = {
charset = "cp1252",
languageName = "Svenska",
formatNumbers = true,
decimalSeperator = ',',
thousandsSeperator = ' ',
translation = {
["1a) Offensive Name"] = "1a) Offensivt Namn",
["1b) Invalid Name Format"] = "1b) Ogiltigt Namnformat",
@ -27,7 +31,7 @@ locale = {
["4c) False Report to Gamemaster"] = "4c) Falsk rapport till gamemaster",
["Accept"] = "Acceptera",
["Account name"] = "Konto namn",
["Account Status:"] = false,
["Account Status"] = false,
["Action:"] = "Handling:",
["Add"] = "Lägg till",
["Add new VIP"] = "Ny VIP",
@ -228,7 +232,7 @@ locale = {
["Pass Leadership to %s"] = "Ge ledarskap till %s",
["Password"] = "Lösenord",
["Piece Price:"] = "Per Styck:",
["Please enter a character name:"] = "Skriv in ett karaktärsnamn:",
["Please enter a character name"] = "Skriv in ett karaktärsnamn",
["Please, press the key you wish to add onto your hotkeys manager"] = "Tryck på knappen som du\nvill lägga till som snabbtangent",
["Please Select"] = "Välj",
["Please use this dialog to only report bugs. Do not report rule violations here!"] = "Använd den här dialogrutan endast för att rapportera buggar. Rapportera inte regelbrott här!",

View File

@ -8,6 +8,7 @@ Button < UIButton
image-clip: 0 0 22 23
image-border: 3
padding: 5 10 5 10
opacity: 1.0
$hover !disabled:
image-clip: 0 23 22 23
@ -45,6 +46,7 @@ NextButton < UIButton
size: 12 21
image-source: /images/ui/arrow_horizontal
image-clip: 12 0 12 21
image-color: #ffffff
$hover !disabled:
image-clip: 12 21 12 21
@ -53,12 +55,13 @@ NextButton < UIButton
image-clip: 12 21 12 21
$disabled:
image-color: #dfdfdf55
image-color: #dfdfdf88
PreviousButton < UIButton
size: 12 21
image-source: /images/ui/arrow_horizontal
image-clip: 0 0 12 21
image-color: #ffffff
$hover !disabled:
image-clip: 0 21 12 21
@ -67,7 +70,7 @@ PreviousButton < UIButton
image-clip: 0 21 12 21
$disabled:
image-color: #dfdfdf55
image-color: #dfdfdf88
AddButton < UIButton
size: 20 20

View File

@ -27,7 +27,7 @@ MoveableTabBarButton < UIButton
color: #dfdfdf
$on !checked:
color: #dfdfdf
color: #de6f6f
TabBar < UITabBar
size: 80 21
@ -36,10 +36,11 @@ TabBar < UITabBar
anchors.fill: parent
TabBarPanel < Panel
TabBarButton < UIButton
size: 22 23
size: 20 21
image-source: /images/ui/tabbutton_square
image-source: /images/ui/tabbutton_square
image-color: #dfdfdf
image-clip: 0 0 22 23
image-clip: 0 0 20 21
image-border: 3
image-border-bottom: 0
icon-color: #dfdfdf
@ -55,7 +56,7 @@ TabBarButton < UIButton
margin-left: 5
$hover !checked:
image-clip: 0 23 22 23
image-clip: 0 21 20 21
color: #dfdfdf
$disabled:
@ -63,7 +64,7 @@ TabBarButton < UIButton
icon-color: #dfdfdf
$checked:
image-clip: 0 46 22 23
image-clip: 0 42 20 21
color: #dfdfdf
$on !checked:
@ -73,6 +74,14 @@ TabBarRounded < TabBar
TabBarRoundedPanel < TabBarPanel
TabBarRoundedButton < TabBarButton
image-source: /images/ui/tabbutton_rounded
size: 22 23
image-clip: 0 0 22 23
$hover !checked:
image-clip: 0 23 22 23
$checked:
image-clip: 0 46 22 23
TabBarVertical < UITabBar
width: 96

View File

@ -1,26 +1,62 @@
Table < UITable
layout: verticalBox
header-column-style: HeaderTableColumn
header-row-style: HeaderTableRow
header-column-style: TableHeaderColumn
header-row-style: TableHeaderRow
column-style: TableColumn
row-style: TableRow
TableData < UIScrollArea
layout: verticalBox
TableRow < Label
TableRow < UITableRow
layout: horizontalBox
height: 10
text-wrap: true
focusable: true
even-background-color: alpha
odd-background-color: #00000022
$focus:
background-color: #294f6d
color: #ffffff
TableColumn < Label
width: 30
text-wrap: true
focusable: false
TableHeaderRow < Label
layout: horizontalBox
focusable: false
height: 10
text-wrap: true
TableHeaderColumn < Button
width: 30
TableHeaderColumn < UITableHeaderColumn
font: verdana-11px-antialised
background-color: alpha
color: #dfdfdfff
height: 23
focusable: true
text-offset: 0 0
image-source: /images/ui/button
image-color: #dfdfdf
image-clip: 0 0 22 23
image-border: 3
padding: 5 10 5 10
enabled: false
focusable: false
$hover !disabled:
image-clip: 0 23 22 23
$pressed:
image-clip: 0 46 22 23
text-offset: 1 1
$disabled:
color: #dfdfdf88
opacity: 0.8
SortableTableHeaderColumn < TableHeaderColumn
enabled: true
focusable: true

View File

@ -22,7 +22,7 @@ end
g_resources.addSearchPath(g_resources.getWorkDir() .. "mods", true)
-- setup directory for saving configurations
g_resources.setupUserWriteDir(g_app.getCompactName())
g_resources.setupUserWriteDir(('%s/'):format(g_app.getCompactName()))
-- search all packages
g_resources.searchAndAddPackages('/', '.otpkg', true)
@ -52,4 +52,4 @@ local script = '/' .. g_app.getCompactName() .. 'rc.lua'
if g_resources.fileExists(script) then
dofile(script)
end
end

View File

@ -1,5 +1,8 @@
local musicFilename = "/sounds/startup"
local musicChannel = g_sounds.getChannel(1)
local musicChannel = nil
if g_sounds then
musicChannel = g_sounds.getChannel(SoundChannels.Music)
end
function setMusic(filename)
musicFilename = filename
@ -27,12 +30,14 @@ end
function startup()
-- Play startup music (The Silver Tree, by Mattias Westlund)
musicChannel:enqueue(musicFilename, 3)
connect(g_game, { onGameStart = function() musicChannel:stop(3) end })
connect(g_game, { onGameEnd = function()
g_sounds.stopAll()
musicChannel:enqueue(musicFilename, 3)
end })
if musicChannel then
musicChannel:enqueue(musicFilename, 3)
connect(g_game, { onGameStart = function() musicChannel:stop(3) end })
connect(g_game, { onGameEnd = function()
g_sounds.stopAll()
musicChannel:enqueue(musicFilename, 3)
end })
end
-- Check for startup errors
local errtitle = nil
@ -57,7 +62,9 @@ function init()
onExit = exit })
g_window.setMinimumSize({ width = 600, height = 480 })
g_sounds.preload(musicFilename)
if musicChannel then
g_sounds.preload(musicFilename)
end
-- initialize in fullscreen mode on mobile devices
if g_window.getPlatformType() == "X11-EGL" then

View File

@ -2,7 +2,7 @@ Module
name: client
description: Initialize the client and setups its main window
author: edubart
website: www.otclient.info
website: https://github.com/edubart/otclient
reloadable: false
sandboxed: true
scripts: [ client ]
@ -19,4 +19,3 @@ Module
- client_terminal
- client_modulemanager
- client_serverlist
- client_stats

View File

@ -10,7 +10,7 @@ function init()
clientVersionLabel = background:getChildById('clientVersionLabel')
clientVersionLabel:setText(g_app.getName() .. ' ' .. g_app.getVersion() .. '\n' ..
'Rev ' .. g_app.getBuildRevision() .. ' ('.. g_app.getBuildCommit() .. ')\n' ..
'Built on ' .. g_app.getBuildDate())
'Built on ' .. g_app.getBuildDate() .. '\n' .. g_app.getBuildCompiler())
if not g_game.isOnline() then
addEvent(function() g_effects.fadeIn(clientVersionLabel, 1500) end)
@ -45,3 +45,7 @@ end
function setVersionText(text)
clientVersionLabel:setText(text)
end
function getBackground()
return background
end

View File

@ -2,7 +2,7 @@ Module
name: client_background
description: Handles the background of the login screen
author: edubart
website: www.otclient.info
website: https://github.com/edubart/otclient
sandboxed: true
scripts: [ background ]
dependencies: [ client_topmenu ]

View File

@ -8,6 +8,7 @@ local errorBox
local waitingWindow
local updateWaitEvent
local resendWaitEvent
local loginEvent
-- private functions
local function tryLogin(charInfo, tries)
@ -21,13 +22,13 @@ local function tryLogin(charInfo, tries)
if tries == 1 then
g_game.safeLogout()
end
scheduleEvent(function() tryLogin(charInfo, tries+1) end, 100)
loginEvent = scheduleEvent(function() tryLogin(charInfo, tries+1) end, 100)
return
end
CharacterList.hide()
g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName)
g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName, G.authenticatorToken, G.sessionKey)
loadBox = displayCancelBox(tr('Please wait'), tr('Connecting to game server...'))
connect(loadBox, { onCancel = function()
@ -109,6 +110,16 @@ function onGameLoginError(message)
end
end
function onGameLoginToken(unknown)
CharacterList.destroyLoadBox()
-- TODO: make it possible to enter a new token here / prompt token
errorBox = displayErrorBox(tr("Two-Factor Authentification"), 'A new authentification token is required.\nPlease login again.')
errorBox.onOk = function()
errorBox = nil
EnterGame.show()
end
end
function onGameConnectionError(message, code)
CharacterList.destroyLoadBox()
local text = translateNetworkError(code, g_game.getProtocolGame() and g_game.getProtocolGame():isConnecting(), message)
@ -131,6 +142,7 @@ end
-- public functions
function CharacterList.init()
connect(g_game, { onLoginError = onGameLoginError })
connect(g_game, { onLoginToken = onGameLoginToken })
connect(g_game, { onUpdateNeeded = onGameUpdateNeeded })
connect(g_game, { onConnectionError = onGameConnectionError })
connect(g_game, { onGameStart = CharacterList.destroyLoadBox })
@ -144,6 +156,7 @@ end
function CharacterList.terminate()
disconnect(g_game, { onLoginError = onGameLoginError })
disconnect(g_game, { onLoginToken = onGameLoginToken })
disconnect(g_game, { onUpdateNeeded = onGameUpdateNeeded })
disconnect(g_game, { onConnectionError = onGameConnectionError })
disconnect(g_game, { onGameStart = CharacterList.destroyLoadBox })
@ -168,15 +181,20 @@ function CharacterList.terminate()
end
if updateWaitEvent then
updateWaitEvent:cancel()
removeEvent(updateWaitEvent)
updateWaitEvent = nil
end
if resendWaitEvent then
resendWaitEvent:cancel()
removeEvent(resendWaitEvent)
resendWaitEvent = nil
end
if loginEvent then
removeEvent(loginEvent)
loginEvent = nil
end
CharacterList = nil
end
@ -236,12 +254,21 @@ function CharacterList.create(characters, account, otui)
end
-- account
if account.premDays > 0 and account.premDays < 65535 then
accountStatusLabel:setText(tr("Premium Account (%s) days left", account.premDays))
elseif account.premDays >= 65535 then
accountStatusLabel:setText(tr("Lifetime Premium Account"))
else
accountStatusLabel:setText(tr('Free Account'))
local status = ''
if account.status == AccountStatus.Frozen then
status = tr(' (Frozen)')
elseif account.status == AccountStatus.Suspended then
status = tr(' (Suspended)')
end
if account.subStatus == SubscriptionStatus.Free then
accountStatusLabel:setText(('%s%s'):format(tr('Free Account'), status))
elseif account.subStatus == SubscriptionStatus.Premium then
if account.premDays == 0 or account.premDays == 65535 then
accountStatusLabel:setText(('%s%s'):format(tr('Gratis Premium Account'), status))
else
accountStatusLabel:setText(('%s%s'):format(tr('Premium Account (%s) days left', account.premDays), status))
end
end
if account.premDays > 0 and account.premDays <= 7 then
@ -298,6 +325,10 @@ function CharacterList.doLogin()
worldName = selected.worldName,
characterName = selected.characterName }
charactersWindow:hide()
if loginEvent then
removeEvent(loginEvent)
loginEvent = nil
end
tryLogin(charInfo)
else
displayErrorBox(tr('Error'), tr('You must select a character to login!'))
@ -318,12 +349,12 @@ function CharacterList.cancelWait()
end
if updateWaitEvent then
updateWaitEvent:cancel()
updateWaitEvent = nil
removeEvent(updateWaitEvent)
updateWaitEvent = nil
end
if resendWaitEvent then
resendWaitEvent:cancel()
removeEvent(resendWaitEvent)
resendWaitEvent = nil
end

View File

@ -16,7 +16,7 @@ CharacterWidget < UIWidget
Label
id: name
color: #aaaaaa
color: #bbbbbb
anchors.top: parent.top
anchors.left: parent.left
font: verdana-11px-monochrome
@ -29,8 +29,7 @@ CharacterWidget < UIWidget
Label
id: worldName
color: #ffffff
color: #aaaaaa
color: #bbbbbb
anchors.top: parent.top
anchors.right: parent.right
margin-right: 5
@ -45,16 +44,21 @@ CharacterWidget < UIWidget
MainWindow
id: charactersWindow
!text: tr('Character List')
size: 250 248
visible: false
@onEnter: CharacterList.doLogin()
@onEscape: CharacterList.hide(true)
@onSetup: |
g_keyboard.bindKeyPress('Up', function() self:getChildById('characters'):focusPreviousChild(KeyboardFocusReason) end, self)
g_keyboard.bindKeyPress('Down', function() self:getChildById('characters'):focusNextChild(KeyboardFocusReason) end, self)
if g_game.getFeature(GamePreviewState) then
self:setSize({width = 350, height = 400})
else
self:setSize({width = 250, height = 248})
end
TextList
id: characters
background-color: #565656
anchors.top: parent.top
anchors.left: parent.left
anchors.right: characterListScrollBar.left

View File

@ -33,10 +33,17 @@ local function onMotd(protocol, motd)
end
end
local function onSessionKey(protocol, sessionKey)
G.sessionKey = sessionKey
end
local function onCharacterList(protocol, characters, account, otui)
-- Try add server to the server list
ServerList.add(G.host, G.port, g_game.getClientVersion())
-- Save 'Stay logged in' setting
g_settings.set('staylogged', enterGame:getChildById('stayLoggedBox'):isChecked())
if enterGame:getChildById('rememberPasswordBox'):isChecked() then
local account = g_crypt.encrypt(G.account)
local password = g_crypt.encrypt(G.password)
@ -59,13 +66,19 @@ local function onCharacterList(protocol, characters, account, otui)
loadBox:destroy()
loadBox = nil
for _, characterInfo in pairs(characters) do
if characterInfo.previewState and characterInfo.previewState ~= PreviewState.Default then
characterInfo.worldName = characterInfo.worldName .. ', Preview'
end
end
CharacterList.create(characters, account, otui)
CharacterList.show()
if motdEnabled then
local lastMotdNumber = g_settings.getNumber("motd")
if G.motdNumber and G.motdNumber ~= lastMotdNumber then
g_settings.set("motd", motdNumber)
g_settings.set("motd", G.motdNumber)
motdWindow = displayInfoBox(tr('Message of the day'), G.motdMessage)
connect(motdWindow, { onOk = function() CharacterList.show() motdWindow = nil end })
CharacterList.hide()
@ -103,9 +116,10 @@ function EnterGame.init()
local password = g_settings.get('password')
local host = g_settings.get('host')
local port = g_settings.get('port')
local stayLogged = g_settings.getBoolean('staylogged')
local autologin = g_settings.getBoolean('autologin')
local clientVersion = g_settings.getInteger('client-version')
if clientVersion == 0 then clientVersion = 860 end
if clientVersion == 0 then clientVersion = 1074 end
if port == nil or port == 0 then port = 7171 end
@ -115,6 +129,7 @@ function EnterGame.init()
enterGame:getChildById('serverHostTextEdit'):setText(host)
enterGame:getChildById('serverPortTextEdit'):setText(port)
enterGame:getChildById('autoLoginBox'):setChecked(autologin)
enterGame:getChildById('stayLoggedBox'):setChecked(stayLogged)
clientBox = enterGame:getChildById('clientComboBox')
for _, proto in pairs(g_game.getSupportedClients()) do
@ -122,6 +137,10 @@ function EnterGame.init()
end
clientBox:setCurrentOption(clientVersion)
EnterGame.toggleAuthenticatorToken(clientVersion, true)
EnterGame.toggleStayLoggedBox(clientVersion, true)
connect(clientBox, { onOptionChange = EnterGame.onClientVersionChange })
enterGame:hide()
if g_app.isRunning() and not g_game.isOnline() then
@ -146,6 +165,7 @@ end
function EnterGame.terminate()
g_keyboard.unbindKeyDown('Ctrl+G')
disconnect(clientBox, { onOptionChange = EnterGame.onClientVersionChange })
enterGame:destroy()
enterGame = nil
enterGameButton:destroy()
@ -204,14 +224,80 @@ end
function EnterGame.clearAccountFields()
enterGame:getChildById('accountNameTextEdit'):clearText()
enterGame:getChildById('accountPasswordTextEdit'):clearText()
enterGame:getChildById('authenticatorTokenTextEdit'):clearText()
enterGame:getChildById('accountNameTextEdit'):focus()
g_settings.remove('account')
g_settings.remove('password')
end
function EnterGame.toggleAuthenticatorToken(clientVersion, init)
local enabled = (clientVersion >= 1072)
if enabled == enterGame.authenticatorEnabled then
return
end
enterGame:getChildById('authenticatorTokenLabel'):setOn(enabled)
enterGame:getChildById('authenticatorTokenTextEdit'):setOn(enabled)
local newHeight = enterGame:getHeight()
local newY = enterGame:getY()
if enabled then
newY = newY - enterGame.authenticatorHeight
newHeight = newHeight + enterGame.authenticatorHeight
else
newY = newY + enterGame.authenticatorHeight
newHeight = newHeight - enterGame.authenticatorHeight
end
if not init then
enterGame:breakAnchors()
enterGame:setY(newY)
enterGame:bindRectToParent()
end
enterGame:setHeight(newHeight)
enterGame.authenticatorEnabled = enabled
end
function EnterGame.toggleStayLoggedBox(clientVersion, init)
local enabled = (clientVersion >= 1074)
if enabled == enterGame.stayLoggedBoxEnabled then
return
end
enterGame:getChildById('stayLoggedBox'):setOn(enabled)
local newHeight = enterGame:getHeight()
local newY = enterGame:getY()
if enabled then
newY = newY - enterGame.stayLoggedBoxHeight
newHeight = newHeight + enterGame.stayLoggedBoxHeight
else
newY = newY + enterGame.stayLoggedBoxHeight
newHeight = newHeight - enterGame.stayLoggedBoxHeight
end
if not init then
enterGame:breakAnchors()
enterGame:setY(newY)
enterGame:bindRectToParent()
end
enterGame:setHeight(newHeight)
enterGame.stayLoggedBoxEnabled = enabled
end
function EnterGame.onClientVersionChange(comboBox, text, data)
local clientVersion = tonumber(text)
EnterGame.toggleAuthenticatorToken(clientVersion)
EnterGame.toggleStayLoggedBox(clientVersion)
end
function EnterGame.doLogin()
G.account = enterGame:getChildById('accountNameTextEdit'):getText()
G.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
G.authenticatorToken = enterGame:getChildById('authenticatorTokenTextEdit'):getText()
G.stayLogged = enterGame:getChildById('stayLoggedBox'):isChecked()
G.host = enterGame:getChildById('serverHostTextEdit'):getText()
G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText())
local clientVersion = tonumber(clientBox:getText())
@ -230,6 +316,7 @@ function EnterGame.doLogin()
protocolLogin = ProtocolLogin.create()
protocolLogin.onLoginError = onError
protocolLogin.onMotd = onMotd
protocolLogin.onSessionKey = onSessionKey
protocolLogin.onCharacterList = onCharacterList
protocolLogin.onUpdateNeeded = onUpdateNeeded
@ -240,12 +327,12 @@ function EnterGame.doLogin()
EnterGame.show()
end })
g_game.chooseRsa(G.host)
g_game.setClientVersion(clientVersion)
g_game.setProtocolVersion(g_game.getClientProtocolVersion(clientVersion))
g_game.chooseRsa(G.host)
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, G.authenticatorToken, G.stayLogged)
else
loadBox:destroy()
loadBox = nil
@ -266,6 +353,7 @@ function EnterGame.setDefaultServer(host, port, protocol)
local clientLabel = enterGame:getChildById('clientLabel')
local accountTextEdit = enterGame:getChildById('accountNameTextEdit')
local passwordTextEdit = enterGame:getChildById('accountPasswordTextEdit')
local authenticatorTokenTextEdit = enterGame:getChildById('authenticatorTokenTextEdit')
if hostTextEdit:getText() ~= host then
hostTextEdit:setText(host)
@ -273,6 +361,7 @@ function EnterGame.setDefaultServer(host, port, protocol)
clientBox:setCurrentOption(protocol)
accountTextEdit:setText('')
passwordTextEdit:setText('')
authenticatorTokenTextEdit:setText('')
end
end
@ -286,6 +375,16 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
portTextEdit:setVisible(false)
portTextEdit:setHeight(0)
local authenticatorTokenTextEdit = enterGame:getChildById('authenticatorTokenTextEdit')
authenticatorTokenTextEdit:setText('')
authenticatorTokenTextEdit:setOn(false)
local authenticatorTokenLabel = enterGame:getChildById('authenticatorTokenLabel')
authenticatorTokenLabel:setOn(false)
local stayLoggedBox = enterGame:getChildById('stayLoggedBox')
stayLoggedBox:setChecked(false)
stayLoggedBox:setOn(false)
clientBox:setCurrentOption(protocol)
clientBox:setVisible(false)
clientBox:setHeight(0)
@ -306,11 +405,11 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
serverListButton:setWidth(0)
local rememberPasswordBox = enterGame:getChildById('rememberPasswordBox')
rememberPasswordBox:setMarginTop(-5)
rememberPasswordBox:setMarginTop(-8)
if not windowWidth then windowWidth = 236 end
enterGame:setWidth(windowWidth)
if not windowHeight then windowHeight = 200 end
if not windowHeight then windowHeight = 210 end
enterGame:setHeight(windowHeight)
end

View File

@ -2,7 +2,7 @@ Module
name: client_entergame
description: Manages enter game and character list windows
author: edubart
website: www.otclient.info
website: https://github.com/edubart/otclient
dependencies:
- client_topmenu

View File

@ -1,6 +1,6 @@
EnterGameWindow < MainWindow
!text: tr('Enter Game')
size: 236 274
size: 236 298
EnterGameButton < Button
width: 64
@ -21,6 +21,10 @@ ServerListButton < UIButton
EnterGameWindow
id: enterGame
&authenticatorEnabled: false
&authenticatorHeight: 44
&stayLoggedBoxEnabled: false
&stayLoggedBoxHeight: 24
@onEnter: EnterGame.doLogin()
MenuLabel
@ -50,6 +54,52 @@ EnterGameWindow
anchors.top: prev.bottom
margin-top: 2
MenuLabel
id: authenticatorTokenLabel
!text: tr('Authenticator Token')
anchors.left: prev.left
anchors.top: prev.bottom
text-auto-resize: true
margin-top: -12
visible: false
$on:
visible: true
margin-top: 8
TextEdit
id: authenticatorTokenTextEdit
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: -22
visible: false
max-length: 8
$on:
visible: true
margin-top: 2
CheckBox
id: stayLoggedBox
!text: tr('Stay logged during session')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 6
margin-top: -16
visible: false
$on:
visible: true
margin-top: 8
HorizontalSeparator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 8
MenuLabel
id: serverLabel
!text: tr('Server')
@ -132,16 +182,24 @@ EnterGameWindow
anchors.top: prev.bottom
margin-top: 2
HorizontalSeparator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 6
EnterGameButton
!text: tr('Ok')
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: prev.bottom
margin-top: 4
@onClick: EnterGame.doLogin()
Label
id: serverInfoLabel
font: verdana-11px-rounded
anchors.bottom: parent.bottom
anchors.top: prev.top
anchors.left: parent.left
margin-top: 5
color: green
text-auto-resize: true
text-auto-resize: true

View File

@ -113,15 +113,18 @@ function installLocale(locale)
if _G.allowedLocales and not _G.allowedLocales[locale.name] then return end
if locale.name ~= defaultLocaleName then
local updatesNeeded = 0
for _i,k in pairs(neededTranslations) do
local updatesNamesMissing = {}
for _,k in pairs(neededTranslations) do
if locale.translation[k] == nil then
updatesNeeded = updatesNeeded + 1
updatesNamesMissing[#updatesNamesMissing + 1] = k
end
end
if updatesNeeded > 0 then
pdebug('Locale \'' .. locale.name .. '\' is missing ' .. updatesNeeded .. ' translations.')
if #updatesNamesMissing > 0 then
pdebug('Locale \'' .. locale.name .. '\' is missing ' .. #updatesNamesMissing .. ' translations.')
for _,name in pairs(updatesNamesMissing) do
pdebug('["' .. name ..'"] = \"\",')
end
end
end
@ -141,7 +144,10 @@ end
function setLocale(name)
local locale = installedLocales[name]
if locale == currentLocale then return end
if locale == currentLocale then
g_settings.set('locale', name)
return
end
if not locale then
pwarning("Locale " .. name .. ' does not exist.')
return false
@ -166,16 +172,20 @@ end
-- global function used to translate texts
function _G.tr(text, ...)
if currentLocale then
if tonumber(text) then
-- todo: use locale information to calculate this. also detect floating numbers
if tonumber(text) and currentLocale.formatNumbers then
local number = tostring(text):split('.')
local out = ''
local number = tostring(text):reverse()
for i=1,#number do
out = out .. number:sub(i, i)
local reverseNumber = number[1]:reverse()
for i=1,#reverseNumber do
out = out .. reverseNumber:sub(i, i)
if i % 3 == 0 and i ~= #number then
out = out .. ','
out = out .. currentLocale.thousandsSeperator
end
end
if number[2] then
out = number[2] .. currentLocale.decimalSeperator .. out
end
return out:reverse()
elseif tostring(text) then
local translation = currentLocale.translation[text]

View File

@ -2,7 +2,7 @@ Module
name: client_locales
description: Translates texts to selected language
author: baxnie, edubart
website: www.otclient.info
website: https://github.com/edubart/otclient
sandboxed: true
scripts: [ locales ]
@onLoad: init()

View File

@ -21,40 +21,47 @@ neededTranslations = {
"4c) False Report to Gamemaster",
"Accept",
"Account name",
"Account Status:",
"Action:",
"Account Status",
"Action",
"Activate ignorelist",
"Activate whitelist",
"Add",
"Add new server",
"Add new VIP",
"Addon 1",
"Addon 2",
"Addon 3",
"Add to VIP list",
"Adjust volume",
"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!",
"All",
"All modules and scripts were reloaded.",
"Allow auto chase override",
"Also known as dash in tibia community, recommended\nfor playing characters with high speed",
"Allowed Players",
"Allow VIPs to message you",
"Ambient light: %s%%",
"Amount:",
"Amount",
"Anonymous",
"Are you sure you want to logout?",
"Any",
"Attack",
"Auction End",
"Audio",
"Authenticator Token",
"Author",
"Autoload",
"Autoload priority",
"Auto login",
"Auto login selected character on next charlist load",
"Axe Fighting",
"Balance:",
"Balance",
"Banishment",
"Banishment + Final Warning",
"Battle",
"Browse",
"Browse Field",
"Bug report sent.",
"Button Assign",
"Buy",
"Buyer Name",
"Buy Now",
"Buy Offers",
"Buy with backpack",
@ -63,6 +70,8 @@ neededTranslations = {
"Cap",
"Capacity",
"Center",
"Change language",
"Channel appended to %s",
"Channels",
"Character List",
"Classic control",
@ -70,15 +79,23 @@ neededTranslations = {
"Clear Messages",
"Clear object",
"Client needs update.",
"Client Version",
"Close",
"Close this channel",
"Club Fighting",
"Combat Controls",
"Comment:",
"Comment",
"Connecting to game server...",
"Connecting to login server...",
"Connection Error",
"Connection failed.",
"Connection failed, the server address does not exist.",
"Connection refused, the server might be offline or restarting.\nPlease try again later.",
"Connection timed out. Either your network is failing or the server is offline.",
"Console",
"Cooldown",
"Cooldowns",
"Copy",
"Copy message",
"Copy name",
"Copy Name",
@ -86,53 +103,72 @@ neededTranslations = {
"Create mark",
"Create New Offer",
"Create Offer",
"Current hotkeys:",
"Critical Hit Chance",
"Critical Hit Damage",
"Current hotkeys",
"Current hotkey to add: %s",
"Current Offers",
"Default",
"Delete mark",
"Description:",
"Description",
"Destructive Behaviour",
"Detail",
"Details",
"Disable chat mode, allow to walk using ASDW",
"Disable chat mode, allow to walk using ASDW",
"Disable Shared Experience",
"Dismount",
"Display connection speed to the server (milliseconds)",
"Display creature health bars",
"Display creature names",
"Display player mana bar",
"Display text messages",
"Distance Fighting",
"%d of experience per hour",
"Don\'t stretch/shrink Game Window",
"Edit hotkey text:",
"Druid",
"Edit hotkey text",
"Edit List",
"Edit %s",
"Edit Text",
"Enable music",
"Edit VIP list entry",
"Enable audio",
"Enable chat mode",
"Enable dash walking",
"Enable lights",
"Enable music sound",
"Enable Shared Experience",
"Enable smart walking",
"Enable vertical synchronization",
"Enable walk booster",
"Enter Game",
"Enter one name per line.",
"Enter with your account again to update your client.",
"Error",
"Error",
"(ERROR %d)",
"Excessive Unjustified Player Killing",
"Exclude from private chat",
"Exit",
"Experience",
"Filter list to match your level",
"Filter list to match your vocation",
"Find:",
"Filters",
"Find",
"Fishing",
"Fist Fighting",
"Follow",
"Force Exit",
"Formula",
"For Your Information",
"Free Account",
"Fullscreen",
"Game",
"Game framerate limit: %s",
"Global ignore settings",
"Global whitelist settings",
"Graphics",
"Graphics card driver not detected",
"Graphics Engine:",
"Group",
"Head",
"Healing",
"Health Info",
@ -146,43 +182,50 @@ neededTranslations = {
"Hide spells for higher exp. levels",
"Hide spells for other vocations",
"Hit Points",
"Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks",
"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",
"Host",
"Hotkey delay: %dms",
"Hotkey delay: %sms",
"Hotkeys",
"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.",
"Ignore",
"Ignore capacity",
"Ignored players:",
"Ignored Players",
"Ignore equipped",
"Ignore List",
"Ignore players",
"Ignore Private Messages",
"Ignore Yelling",
"Interface framerate limit: %s",
"Invalid authentification token.",
"Inventory",
"Invite to Party",
"Invite to private chat",
"IP Address Banishment",
"Item Name",
"Item Offers",
"It is empty.",
"Join %s\'s Party",
"Knight",
"Leave Party",
"Level",
"Life Leech Amount",
"Life Leech Chance",
"Lifetime Premium Account",
"Limits FPS to 60",
"List of items that you're able to buy",
"List of items that you're able to sell",
"Load",
"Logging out...",
"Login",
"Login Error",
"Login Error",
"Logout",
"Look",
"Magic Level",
"Make sure that your client uses\nthe correct game protocol version",
"Make sure that your client uses\nthe correct game client version",
"Mana",
"Manage hotkeys:",
"Market",
"Market Error",
"Market Offers",
"Message of the day",
"Message to ",
@ -193,11 +236,14 @@ neededTranslations = {
"Mount",
"Move Stackable Item",
"Move up",
"Music volume: %d",
"My Offers",
"Name:",
"Name",
"Name Report",
"Name Report + Banishment",
"Name Report + Banishment + Final Warning",
"New Server",
"Next level in %d hours and %d minutes",
"No",
"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.",
"No item selected.",
@ -205,39 +251,47 @@ neededTranslations = {
"No Outfit",
"No statement has been selected.",
"Notation",
"Notify-Login",
"NPC Trade",
"Offer History",
"Offers",
"Offer Type:",
"Offer Type",
"Offline Training",
"Ok",
"on %s.\n",
"Open",
"Open a private message channel:",
"Open a private message channel",
"Open charlist automatically when starting client",
"Open in new window",
"Open new channel",
"Open purse",
"Open PvP",
"Open PvP Situations",
"Options",
"Overview",
"Paladin",
"Pass Leadership to %s",
"Password",
"Piece Price:",
"Please enter a character name:",
"Piece Price",
"Please enter a character name",
"Please, press the key you wish to add onto your hotkeys manager",
"Please Select",
"Please state the rule violation in one clear sentence and wait for a reply from a gamemaster. Please note that your message will disappear if you close the channel.",
"Please use this dialog to only report bugs. Do not report rule violations here!",
"Please wait",
"Please wait patiently for a gamemaster to reply",
"Port",
"Position:",
"Position: %i %i %i",
"Position",
"Premium",
"Premium Account (%s) days left",
"Price:",
"Price",
"Primary",
"Process",
"Protocol",
"Quest Log",
"Randomize",
"Randomize characters outfit",
"Reason:",
"Reason",
"Refresh",
"Refresh Offers",
"Regeneration Time",
@ -245,31 +299,46 @@ neededTranslations = {
"Reload All",
"Remember account and password when starts client",
"Remember password",
"Remove ",
"Remove",
"Remove %s",
"Report Bug",
"Report Rule",
"Report Rule Violation",
"Reserved for more functionality later.",
"Reset All",
"Reset Market",
"Reset selection, filters & search",
"Revoke %s\'s Invitation",
"Rotate",
"Rule Violation",
"Rule Violations",
"Save",
"Save Messages",
"Search:",
"Search",
"Search all items",
"Secondary",
"Select",
"Select all",
"Select object",
"Select Outfit",
"Select your language",
"Sell",
"Sell All",
"Seller Name",
"Sell Now",
"Sell Offers",
"Send",
"Send automatically",
"Send Message",
"Server",
"Server list",
"Server List",
"Server Log",
"Set Outfit",
"%s has finished the request",
"%s has logged in.",
"%s has logged out.",
"Shielding",
"Show all items",
"Show connection ping",
@ -286,8 +355,15 @@ neededTranslations = {
"Show status messages in console",
"Show Text",
"Show timestamps in console",
"Show Top Menu",
"Show your depot items only",
"Skills",
"Skull Time",
"%s of experience left",
"Sorcerer",
"Sort by name",
"Sort by status",
"Sort by type",
"Soul",
"Soul Points",
"Special",
@ -295,9 +371,10 @@ neededTranslations = {
"Spell Cooldowns",
"Spell List",
"Stamina",
"Statement:",
"Statement",
"Statement Report",
"Statistics",
"Stay logged during session",
"Stop Attack",
"Stop Follow",
"Support",
@ -308,17 +385,23 @@ neededTranslations = {
"Sword Fighting",
"Terminal",
"There is no way.",
"Title",
"Total Price:",
"This offer is 25%% above the average market price",
"This offer is 25%% below the average market price",
"Total Price",
"Trade",
"Trade with ...",
"Trying to reconnect in %s seconds.",
"Turn delay: %dms",
"Turn delay: %sms",
"Two-Factor Authentification",
"Type",
"Unable to load dat file, please place a valid dat in '%s'",
"Unable to load spr file, please place a valid spr in '%s'",
"Unable to logout.",
"Unignore",
"Unjustified Points",
"Unload",
"Update needed",
"Update needed",
"Use",
"Use on target",
"Use on yourself",
@ -329,7 +412,8 @@ neededTranslations = {
"Vocation",
"Waiting List",
"Website",
"Weight:",
"Weight",
"Will boost your walk on high speed characters",
"Will detect when to use diagonal step based on the\nkeys you are pressing",
"With crosshair",
"Yes",
@ -358,8 +442,13 @@ neededTranslations = {
"You must enter a comment.",
"You must enter a valid server address and port.",
"You must select a character to login!",
"Your Capacity:",
"You must select an action.",
"You must select a reason.",
"Your Capacity",
"Your client needs updating, try redownloading it.",
"Your connection has been lost.\nEither your network or the server went down.",
"You read the following, written by \n%s\n",
"You read the following, written on \n%s.\n",
"Your Money:",
"Your Money",
"Your request has been closed",
}

View File

@ -2,7 +2,7 @@ Module
name: client_modulemanager
description: Manage other modules
author: edubart
website: www.otclient.info
website: https://github.com/edubart/otclient
sandboxed: true
scripts: [ modulemanager ]
dependencies: [ client_topmenu ]

View File

@ -34,15 +34,59 @@ Panel
id: displayHealth
!text: tr('Display creature health bars')
OptionCheckBox
id: displayMana
!text: tr('Display player mana bar')
OptionCheckBox
id: displayText
!text: tr('Display text messages')
Label
id: turnDelayLabel
!text: tr('Turn delay: %sms', 30)
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 12
@onSetup: |
local value = modules.client_options.getOption('turnDelay')
self:setText(tr('Turn delay: %dms', value))
OptionScrollbar
id: turnDelay
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
minimum: 30
maximum: 250
Label
id: hotkeyDelayLabel
!text: tr('Hotkey delay: %dms', 30)
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 12
@onSetup: |
local value = modules.client_options.getOption('hotkeyDelay')
self:setText(tr('Hotkey delay: %dms', value))
OptionScrollbar
id: hotkeyDelay
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 3
minimum: 30
maximum: 250
Button
id: changeLocale
!text: tr('Change language')
@onClick: modules.client_locales.createWindow()
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 5
margin-top: 12
width: 120

View File

@ -25,8 +25,11 @@ local defaultOptions = {
ambientLight = 25,
displayNames = true,
displayHealth = true,
displayMana = true,
displayText = true,
dontStretchShrink = false
dontStretchShrink = false,
turnDelay = 50,
hotkeyDelay = 50,
}
local optionsWindow
@ -106,8 +109,8 @@ function init()
graphicsPanel = g_ui.loadUI('graphics')
optionsTabBar:addTab(tr('Graphics'), graphicsPanel, '/images/optionstab/graphics')
audioPanel = g_ui.loadUI('audio')
optionsTabBar:addTab(tr('Audio'), audioPanel, '/images/optionstab/audio')
soundPanel = g_ui.loadUI('audio')
optionsTabBar:addTab(tr('Audio'), soundPanel, '/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)
@ -155,15 +158,17 @@ function hide()
end
function toggleDisplays()
if options['displayNames'] and options['displayHealth'] then
if options['displayNames'] and options['displayHealth'] and options['displayMana'] then
setOption('displayNames', false)
elseif options['displayHealth'] then
setOption('displayHealth', false)
setOption('displayMana', false)
else
if not options['displayNames'] and not options['displayHealth'] then
setOption('displayNames', true)
else
setOption('displayHealth', true)
setOption('displayMana', true)
end
end
end
@ -185,17 +190,23 @@ function setOption(key, value, force)
elseif key == 'fullscreen' then
g_window.setFullscreen(value)
elseif key == 'enableAudio' then
g_sounds.setAudioEnabled(value)
if g_sounds then
g_sounds.setAudioEnabled(value)
end
if value then
audioButton:setIcon('/images/topbuttons/audio')
else
audioButton:setIcon('/images/topbuttons/audio_mute')
end
elseif key == 'enableMusicSound' then
g_sounds.getChannel(SoundChannels.Music):setEnabled(value)
if g_sounds then
g_sounds.getChannel(SoundChannels.Music):setEnabled(value)
end
elseif key == 'musicSoundVolume' then
g_sounds.getChannel(SoundChannels.Music):setGain(value/100)
audioPanel:getChildById('musicSoundVolumeLabel'):setText(tr('Music volume: %d', value))
if g_sounds then
g_sounds.getChannel(SoundChannels.Music):setGain(value/100)
end
soundPanel:getChildById('musicSoundVolumeLabel'):setText(tr('Music volume: %d', value))
elseif key == 'showLeftPanel' then
modules.game_interface.getLeftPanel():setOn(value)
elseif key == 'backgroundFrameRate' then
@ -222,12 +233,18 @@ function setOption(key, value, force)
gameMapPanel:setDrawNames(value)
elseif key == 'displayHealth' then
gameMapPanel:setDrawHealthBars(value)
elseif key == 'displayMana' then
gameMapPanel:setDrawManaBar(value)
elseif key == 'displayText' then
gameMapPanel:setDrawTexts(value)
elseif key == 'dontStretchShrink' then
addEvent(function()
modules.game_interface.updateStretchShrink()
end)
elseif key == 'turnDelay' then
generalPanel:getChildById('turnDelayLabel'):setText(tr('Turn delay: %sms', value))
elseif key == 'hotkeyDelay' then
generalPanel:getChildById('hotkeyDelayLabel'):setText(tr('Hotkey delay: %sms', value))
end
-- change value for keybind updates

View File

@ -2,7 +2,7 @@ Module
name: client_options
description: Create the options window
author: edubart, BeniS
website: www.otclient.info
website: https://github.com/edubart/otclient
sandboxed: true
scripts: [ options ]
@onLoad: init()

View File

@ -19,7 +19,7 @@ function AddServer.add()
local added, error = ServerList.add(host, port, protocol)
if not added then
displayErrorBox(tr('Add Error'), tr(error))
displayErrorBox(tr('Error'), tr(error))
else
AddServer.hide()
end

View File

@ -12,7 +12,9 @@ function ServerList.init()
serverTextList = serverListWindow:getChildById('serverList')
servers = g_settings.getNode('ServerList') or {}
ServerList.load()
if servers then
ServerList.load()
end
end
function ServerList.terminate()
@ -24,8 +26,8 @@ function ServerList.terminate()
end
function ServerList.load()
for k,server in pairs(servers) do
ServerList.add(k, server.port, server.protocol, true)
for host, server in pairs(servers) do
ServerList.add(host, server.port, server.protocol, true)
end
end
@ -43,7 +45,9 @@ function ServerList.select()
end
function ServerList.add(host, port, protocol, load)
if not load and servers[host] then
if not host or not port or not protocol then
return false, 'Failed to load settings'
elseif not load and servers[host] then
return false, 'Server already exists'
elseif host == '' or port == '' then
return false, 'Required fields are missing'

View File

@ -2,7 +2,7 @@ Module
name: client_serverlist
description: Manages a server list of previously entered servers
author: BeniS
website: www.otclient.info
website: https://github.com/edubart/otclient
dependencies:
- client_entergame

View File

@ -1,123 +0,0 @@
UUID = nil
HOST = 'otclient.herokuapp.com'
PORT = 80
FIRST_REPORT_DELAY = 15
REPORT_DELAY = 60
sendReportEvent = nil
firstReportEvent = nil
function initUUID()
UUID = g_settings.getString('report-uuid')
if not UUID or #UUID ~= 36 then
UUID = g_crypt.genUUID()
g_settings.set('report-uuid', UUID)
end
end
function init()
connect(g_game, { onGameStart = onGameStart,
onGameEnd = onGameEnd })
initUUID()
end
function terminate()
disconnect(g_game, { onGameStart = onGameStart,
onGameEnd = onGameEnd })
removeEvent(firstReportEvent)
removeEvent(sendReportEvent)
end
function configure(host, port, delay)
if not host then return end
HOST = host
PORT = port or PORT
REPORT_DELAY = delay or REPORT_DELAY
end
function sendReport()
if not HOST then return end
local protocolHttp = ProtocolHttp.create()
protocolHttp.onConnect = onConnect
protocolHttp.onRecv = onRecv
protocolHttp.onError = onError
protocolHttp:connect(HOST, PORT)
end
function onGameStart()
if not HOST then return end
removeEvent(firstReportEvent)
removeEvent(sendReportEvent)
firstReportEvent = addEvent(sendReport, FIRST_REPORT_DELAY*1000)
sendReportEvent = cycleEvent(sendReport, REPORT_DELAY*1000)
end
function onGameEnd()
removeEvent(firstReportEvent)
removeEvent(sendReportEvent)
end
function onConnect(protocol)
if not g_game.isOnline() then
protocol:disconnect()
return
end
local post = ''
post = post .. 'uid=' .. UUID
post = post .. '&report_delay=' .. REPORT_DELAY
post = post .. '&os=' .. g_app.getOs()
post = post .. '&graphics_vendor=' .. g_graphics.getVendor()
post = post .. '&graphics_renderer=' .. g_graphics.getRenderer()
post = post .. '&graphics_version=' .. g_graphics.getVersion()
post = post .. '&painter_engine=' .. g_graphics.getPainterEngine()
post = post .. '&fps=' .. g_app.getBackgroundPaneFps()
post = post .. '&max_fps=' .. g_app.getBackgroundPaneMaxFps()
post = post .. '&fullscreen=' .. tostring(g_window.isFullscreen())
post = post .. '&window_width=' .. g_window.getWidth()
post = post .. '&window_height=' .. g_window.getHeight()
post = post .. '&player_name=' .. g_game.getCharacterName()
post = post .. '&world_name=' .. g_game.getWorldName()
post = post .. '&otserv_host=' .. G.host
post = post .. '&otserv_port=' .. G.port
post = post .. '&otserv_protocol=' .. g_game.getProtocolVersion()
post = post .. '&otserv_client=' .. g_game.getClientVersion()
post = post .. '&build_version=' .. g_app.getVersion()
post = post .. '&build_revision=' .. g_app.getBuildRevision()
post = post .. '&build_commit=' .. g_app.getBuildCommit()
post = post .. '&build_date=' .. g_app.getBuildDate()
post = post .. '&display_width=' .. g_window.getDisplayWidth()
post = post .. '&display_height=' .. g_window.getDisplayHeight()
post = post .. '&cpu=' .. g_platform.getCPUName()
post = post .. '&mem=' .. g_platform.getTotalSystemMemory()
post = post .. '&os_name=' .. g_platform.getOSName()
post = post .. getAdditionalData()
local message = ''
message = message .. "POST /report HTTP/1.1\r\n"
message = message .. "Host: " .. HOST .. "\r\n"
message = message .. "Accept: */*\r\n"
message = message .. "Connection: close\r\n"
message = message .. "Content-Type: application/x-www-form-urlencoded\r\n"
message = message .. "Content-Length: " .. post:len() .. "\r\n\r\n"
message = message .. post
protocol:send(message)
protocol:recv()
end
function getAdditionalData()
return ''
end
function onRecv(protocol, message)
if string.find(message, 'HTTP/1.1 200 OK') then
--pinfo('Stats sent to server successfully!')
end
protocol:disconnect()
end
function onError(protocol, message, code)
pdebug('Could not send statistics: ' .. message)
end

View File

@ -1,9 +0,0 @@
Module
name: client_stats
description: Sends client statistics to a server
author: baxnie
website: www.otclient.info
sandboxed: true
scripts: [ stats ]
@onLoad: init()
@onUnload: terminate()

View File

@ -2,7 +2,7 @@ Module
name: client_styles
description: Load client fonts and styles
author: edubart
website: www.otclient.info
website: https://github.com/edubart/otclient
scripts: [ styles ]
sandboxed: true
@onLoad: init()

View File

@ -30,6 +30,10 @@ local allLines = {}
-- private functions
local function navigateCommand(step)
if commandTextEdit:isMultiline() then
return
end
local numCommands = #commandHistory
if numCommands > 0 then
currentHistoryIndex = math.min(math.max(currentHistoryIndex + step, 0), numCommands)
@ -96,16 +100,29 @@ local function completeCommand()
end
end
local function doCommand()
local currentCommand = commandTextEdit:getText()
local function doCommand(textWidget)
local currentCommand = textWidget:getText()
executeCommand(currentCommand)
if commandTextEdit then
commandTextEdit:clearText()
end
textWidget:clearText()
return true
end
local function addNewline(textWidget)
if not textWidget:isOn() then
textWidget:setOn(true)
end
textWidget:appendText('\n')
end
local function onCommandChange(textWidget, newText, oldText)
local _, newLineCount = string.gsub(newText, '\n', '\n')
textWidget:setHeight((newLineCount + 1) * textWidget.baseHeight)
if newLineCount == 0 and textWidget:isOn() then
textWidget:setOn(false)
end
end
local function onLog(level, message, time)
if disabled then return end
-- avoid logging while reporting logs (would cause a infinite loop)
@ -129,6 +146,8 @@ function init()
commandHistory = g_settings.getList('terminal-history')
commandTextEdit = terminalWindow:getChildById('commandTextEdit')
commandTextEdit:setHeight(commandTextEdit.baseHeight)
connect(commandTextEdit, {onTextChange = onCommandChange})
g_keyboard.bindKeyPress('Up', function() navigateCommand(1) end, commandTextEdit)
g_keyboard.bindKeyPress('Down', function() navigateCommand(-1) end, commandTextEdit)
g_keyboard.bindKeyPress('Ctrl+C',
@ -138,6 +157,7 @@ function init()
return true
end, commandTextEdit)
g_keyboard.bindKeyDown('Tab', completeCommand, commandTextEdit)
g_keyboard.bindKeyPress('Shift+Enter', addNewline, commandTextEdit)
g_keyboard.bindKeyDown('Enter', doCommand, commandTextEdit)
g_keyboard.bindKeyDown('Escape', hide, terminalWindow)
@ -293,7 +313,7 @@ function addLine(text, color)
end
function executeCommand(command)
if command == nil or #command == 0 then return end
if command == nil or #string.gsub(command, '\n', '') == 0 then return end
-- add command line
addLine("> " .. command, "#ffffff")

View File

@ -2,7 +2,7 @@ Module
name: client_terminal
description: Terminal for executing lua functions
author: edubart
website: www.otclient.info
website: https://github.com/edubart/otclient
scripts: [ terminal ]
sandboxed: true
@onLoad: init()

View File

@ -47,7 +47,7 @@ UIWindow
anchors.left: parent.left
anchors.right: terminalScroll.left
anchors.top: terminalScroll.top
anchors.bottom: commandSymbolLabel.top
anchors.bottom: commandTextEdit.top
layout:
type: verticalBox
align-bottom: true
@ -80,14 +80,25 @@ UIWindow
UITextEdit
id: commandTextEdit
height: 12
background: #aaaaaa11
border-color: #aaaaaa88
&baseHeight: 12
anchors.bottom: parent.bottom
anchors.left: commandSymbolLabel.right
anchors.right: parent.right
anchors.right: terminalScroll.left
margin-left: 1
padding-left: 2
font: terminus-10px
selection-color: black
selection-background-color: white
border-width-left: 0
border-width-top: 0
multiline: false
$on:
border-width-left: 1
border-width-top: 1
multiline: true
ResizeBorder
id: bottomResizeBorder

View File

@ -51,6 +51,8 @@ function init()
pingLabel = topMenu:getChildById('pingLabel')
fpsLabel = topMenu:getChildById('fpsLabel')
g_keyboard.bindKeyDown('Ctrl+Shift+T', toggle)
if g_game.isOnline() then
online()
end
@ -164,3 +166,22 @@ end
function getTopMenu()
return topMenu
end
function toggle()
local menu = getTopMenu()
if not menu then
return
end
if menu:isVisible() then
menu:hide()
modules.client_background.getBackground():addAnchor(AnchorTop, 'parent', AnchorTop)
modules.game_interface.getRootPanel():addAnchor(AnchorTop, 'parent', AnchorTop)
modules.game_interface.getShowTopMenuButton():show()
else
menu:show()
modules.client_background.getBackground():addAnchor(AnchorTop, 'topMenu', AnchorBottom)
modules.game_interface.getRootPanel():addAnchor(AnchorTop, 'topMenu', AnchorBottom)
modules.game_interface.getShowTopMenuButton():hide()
end
end

View File

@ -2,7 +2,7 @@ Module
name: client_topmenu
description: Create the top menu
author: edubart
website: www.otclient.info
website: https://github.com/edubart/otclient
scripts: [ topmenu ]
sandboxed: true
@onLoad: init()

View File

@ -2,7 +2,7 @@ Module
name: corelib
description: Contains core lua classes, functions and constants used by other modules
author: OTClient team
website: www.otclient.info
website: https://github.com/edubart/otclient
reloadable: false
@onLoad: |
@ -10,6 +10,7 @@ Module
dofile 'string'
dofile 'table'
dofile 'bitwise'
dofile 'struct'
dofile 'const'
dofile 'util'

View File

@ -26,6 +26,11 @@ local function retranslateKeyComboDesc(keyComboDesc)
if keyComboDesc == nil then
error('Unable to translate key combo \'' .. keyComboDesc .. '\'')
end
if type(keyComboDesc) == 'number' then
keyComboDesc = tostring(keyComboDesc)
end
local keyCombo = {}
for i,currentKeyDesc in ipairs(keyComboDesc:split('+')) do
for keyCode, keyDesc in pairs(KeyCodeDescs) do

173
modules/corelib/struct.lua Normal file
View File

@ -0,0 +1,173 @@
Struct = {}
function Struct.pack(format, ...)
local stream = {}
local vars = {...}
local endianness = true
for i = 1, format:len() do
local opt = format:sub(i, i)
if opt == '>' then
endianness = false
elseif opt:find('[bBhHiIlL]') then
local n = opt:find('[hH]') and 2 or opt:find('[iI]') and 4 or opt:find('[lL]') and 8 or 1
local val = tonumber(table.remove(vars, 1))
if val < 0 then
val = val + 2 ^ (n * 8 - 1)
end
local bytes = {}
for j = 1, n do
table.insert(bytes, string.char(val % (2 ^ 8)))
val = math.floor(val / (2 ^ 8))
end
if not endianness then
table.insert(stream, string.reverse(table.concat(bytes)))
else
table.insert(stream, table.concat(bytes))
end
elseif opt:find('[fd]') then
local val = tonumber(table.remove(vars, 1))
local sign = 0
if val < 0 then
sign = 1
val = -val
end
local mantissa, exponent = math.frexp(val)
if val == 0 then
mantissa = 0
exponent = 0
else
mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, (opt == 'd') and 53 or 24)
exponent = exponent + ((opt == 'd') and 1022 or 126)
end
local bytes = {}
if opt == 'd' then
val = mantissa
for i = 1, 6 do
table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
val = math.floor(val / (2 ^ 8))
end
else
table.insert(bytes, string.char(math.floor(mantissa) % (2 ^ 8)))
val = math.floor(mantissa / (2 ^ 8))
table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
val = math.floor(val / (2 ^ 8))
end
table.insert(bytes, string.char(math.floor(exponent * ((opt == 'd') and 16 or 128) + val) % (2 ^ 8)))
val = math.floor((exponent * ((opt == 'd') and 16 or 128) + val) / (2 ^ 8))
table.insert(bytes, string.char(math.floor(sign * 128 + val) % (2 ^ 8)))
val = math.floor((sign * 128 + val) / (2 ^ 8))
if not endianness then
table.insert(stream, string.reverse(table.concat(bytes)))
else
table.insert(stream, table.concat(bytes))
end
elseif opt == 's' then
table.insert(stream, tostring(table.remove(vars, 1)))
table.insert(stream, string.char(0))
elseif opt == 'c' then
local n = format:sub(i + 1):match('%d+')
local length = tonumber(n)
if length > 0 then
local str = tostring(table.remove(vars, 1))
if length - str:len() > 0 then
str = str .. string.rep(' ', length - str:len())
end
table.insert(stream, str:sub(1, length))
end
i = i + n:len()
end
end
return table.concat(stream)
end
function Struct.unpack(format, stream)
local vars = {}
local iterator = 1
local endianness = true
for i = 1, format:len() do
local opt = format:sub(i, i)
if opt == '>' then
endianness = false
elseif opt:find('[bBhHiIlL]') then
local n = opt:find('[hH]') and 2 or opt:find('[iI]') and 4 or opt:find('[lL]') and 8 or 1
local signed = opt:lower() == opt
local val = 0
for j = 1, n do
local byte = string.byte(stream:sub(iterator, iterator))
if endianness then
val = val + byte * (2 ^ ((j - 1) * 8))
else
val = val + byte * (2 ^ ((n - j) * 8))
end
iterator = iterator + 1
end
if signed then
val = val - 2 ^ (n * 8 - 1)
end
table.insert(vars, val)
elseif opt:find('[fd]') then
local n = (opt == 'd') and 8 or 4
local x = stream:sub(iterator, iterator + n - 1)
iterator = iterator + n
if not endianness then
x = string.reverse(x)
end
local sign = 1
local mantissa = string.byte(x, (opt == 'd') and 7 or 3) % ((opt == 'd') and 16 or 128)
for i = n - 2, 1, -1 do
mantissa = mantissa * (2 ^ 8) + string.byte(x, i)
end
if string.byte(x, n) > 127 then
sign = -1
end
local exponent = (string.byte(x, n) % 128) * ((opt == 'd') and 16 or 2) + math.floor(string.byte(x, n - 1) / ((opt == 'd') and 16 or 128))
if exponent == 0 then
table.insert(vars, 0.0)
else
mantissa = (math.ldexp(mantissa, (opt == 'd') and -52 or -23) + 1) * sign
table.insert(vars, math.ldexp(mantissa, exponent - ((opt == 'd') and 1023 or 127)))
end
elseif opt == 's' then
local bytes = {}
for j = iterator, stream:len() do
if stream:sub(j, j) == string.char(0) then
break
end
table.insert(bytes, stream:sub(j, j))
end
local str = table.concat(bytes)
iterator = iterator + str:len() + 1
table.insert(vars, str)
elseif opt == 'c' then
local n = format:sub(i + 1):match('%d+')
table.insert(vars, stream:sub(iterator, iterator + tonumber(n)))
iterator = iterator + tonumber(n)
i = i + n:len()
end
end
return unpack(vars)
end

View File

@ -10,13 +10,24 @@ local function moveToolTip(first)
if not first and (not toolTipLabel:isVisible() or toolTipLabel:getOpacity() < 0.1) then return end
local pos = g_window.getMousePosition()
local windowSize = g_window.getSize()
local labelSize = toolTipLabel:getSize()
pos.x = pos.x + 1
pos.y = pos.y + 1
local xdif = g_window.getSize().width - (pos.x + toolTipLabel:getWidth())
if xdif < 10 then
pos.x = pos.x - toolTipLabel:getWidth() - 3
if windowSize.width - (pos.x + labelSize.width) < 10 then
pos.x = pos.x - labelSize.width - 3
else
pos.x = pos.x + 10
end
if windowSize.height - (pos.y + labelSize.height) < 10 then
pos.y = pos.y - labelSize.height - 3
else
pos.y = pos.y + 10
end
toolTipLabel:setPosition(pos)
end
@ -51,7 +62,6 @@ function g_tooltip.init()
toolTipLabel:setBackgroundColor('#111111cc')
toolTipLabel:setTextAlign(AlignCenter)
toolTipLabel:hide()
toolTipLabel.onMouseMove = function() moveToolTip() end
end)
end
@ -78,10 +88,18 @@ function g_tooltip.display(text)
toolTipLabel:enable()
g_effects.fadeIn(toolTipLabel, 100)
moveToolTip(true)
connect(rootWidget, {
onMouseMove = moveToolTip,
})
end
function g_tooltip.hide()
g_effects.fadeOut(toolTipLabel, 100)
disconnect(rootWidget, {
onMouseMove = moveToolTip,
})
end

View File

@ -19,13 +19,14 @@ function UIComboBox:clearOptions()
self:clearText()
end
function UIComboBox:getOption(text)
if not self.options then return nil end
function UIComboBox:isOption(text)
if not self.options then return false end
for i,v in ipairs(self.options) do
if v.text == text then
return nil
return true
end
end
return false
end
function UIComboBox:setOption(text, dontSignal)

View File

@ -3,6 +3,7 @@ UIMiniWindow = extends(UIWindow, "UIMiniWindow")
function UIMiniWindow.create()
local miniwindow = UIMiniWindow.internalCreate()
miniwindow.UIMiniWindowContainer = true
return miniwindow
end

View File

@ -69,7 +69,7 @@ function UIMiniWindowContainer:fitAll(noRemoveChild)
end
local child = children[i]
if child ~= noRemoveChild then
if child ~= noRemoveChild and child:isVisible() then
local childHeight = child:getHeight()
sumHeight = sumHeight - childHeight
table.insert(removeChildren, child)
@ -83,7 +83,7 @@ function UIMiniWindowContainer:fitAll(noRemoveChild)
end
function UIMiniWindowContainer:onDrop(widget, mousePos)
if widget:getClassName() == 'UIMiniWindow' then
if widget.UIMiniWindowContainer then
local oldParent = widget:getParent()
if oldParent == self then
return true

View File

@ -6,7 +6,7 @@ local function onTabClick(tab)
tab.tabBar:selectTab(tab)
end
local function updateMargins(tabBar, ignored)
local function updateMargins(tabBar)
if #tabBar.tabs == 0 then return end
local currentMargin = 0
@ -17,19 +17,19 @@ local function updateMargins(tabBar, ignored)
end
local function updateNavigation(tabBar)
if prevNavigation then
if tabBar.prevNavigation then
if #tabBar.preTabs > 0 or table.find(tabBar.tabs, tabBar.currentTab) ~= 1 then
prevNavigation:enable()
tabBar.prevNavigation:enable()
else
prevNavigation:disable()
tabBar.prevNavigation:disable()
end
end
if nextNavigation then
if tabBar.nextNavigation then
if #tabBar.postTabs > 0 or table.find(tabBar.tabs, tabBar.currentTab) ~= #tabBar.tabs then
nextNavigation:enable()
tabBar.nextNavigation:enable()
else
nextNavigation:disable()
tabBar.nextNavigation:disable()
end
end
end
@ -187,7 +187,7 @@ local function onTabDragMove(tab, mousePos, mouseMoved)
end
local function tabBlink(tab, step)
step = step or 0
local step = step or 0
tab:setOn(not tab:isOn())
removeEvent(tab.blinkEvent)
@ -218,6 +218,19 @@ function UIMoveableTabBar.create()
return tabbar
end
function UIMoveableTabBar:onDestroy()
if self.prevNavigation then
self.prevNavigation:disable()
end
if self.nextNavigation then
self.nextNavigation:disable()
end
self.nextNavigation = nil
self.prevNavigation = nil
end
function UIMoveableTabBar:setContentWidget(widget)
self.contentWidget = widget
if #self.tabs > 0 then
@ -296,8 +309,11 @@ function UIMoveableTabBar:moveTab(tab, units)
end
function UIMoveableTabBar:onStyleApply(styleName, styleNode)
if styleNode['moveable'] then
self.tabsMoveable = styleNode['moveable']
if styleNode['movable'] then
self.tabsMoveable = styleNode['movable']
end
if styleNode['tab-spacing'] then
self:setTabSpacing(styleNode['tab-spacing'])
end
end
@ -318,9 +334,12 @@ function UIMoveableTabBar:removeTab(tab)
end
if self.currentTab == tab then
self:selectPrevTab()
if #self.tabs == 1 then
self.currentTab = nil
elseif index == #self.tabs then
self:selectPrevTab()
else
self:selectNextTab()
end
end
table.remove(tabTable, index)
@ -369,6 +388,11 @@ function UIMoveableTabBar:selectTab(tab)
tab:setOn(false)
tab.blinking = false
if tab.blinkEvent then
removeEvent(tab.blinkEvent)
tab.blinkEvent = nil
end
local parent = tab:getParent()
parent:focusChild(tab, MouseFocusReason)
updateNavigation(self)
@ -467,14 +491,14 @@ function UIMoveableTabBar:getCurrentTab()
end
function UIMoveableTabBar:setNavigation(prevButton, nextButton)
prevNavigation = prevButton
nextNavigation = nextButton
self.prevNavigation = prevButton
self.nextNavigation = nextButton
if prevNavigation then
prevNavigation.onClick = function() self:selectPrevTab() end
if self.prevNavigation then
self.prevNavigation.onClick = function() self:selectPrevTab() end
end
if nextNavigation then
nextNavigation.onClick = function() self:selectNextTab() end
if self.nextNavigation then
self.nextNavigation.onClick = function() self:selectNextTab() end
end
updateNavigation(self)
end

View File

@ -8,6 +8,7 @@ function UIPopupMenu.create()
local layout = UIVerticalLayout.create(menu)
layout:setFitChildren(true)
menu:setLayout(layout)
menu.isGameMenu = false
return menu
end
@ -34,6 +35,7 @@ function UIPopupMenu:display(pos)
rootWidget:addChild(self)
self:setPosition(pos)
self:grabMouse()
self:focus()
--self:grabKeyboard()
currentMenu = self
end
@ -76,6 +78,10 @@ function UIPopupMenu:addSeparator()
g_ui.createWidget(self:getStyleName() .. 'Separator', self)
end
function UIPopupMenu:setGameMenu(state)
self.isGameMenu = state
end
function UIPopupMenu:onDestroy()
if currentMenu == self then
currentMenu = nil
@ -105,4 +111,12 @@ local function onRootGeometryUpdate()
currentMenu:destroy()
end
end
connect(rootWidget, { onGeometryChange = onRootGeometryUpdate} )
local function onGameEnd()
if currentMenu and currentMenu.isGameMenu then
currentMenu:destroy()
end
end
connect(rootWidget, { onGeometryChange = onRootGeometryUpdate })
connect(g_game, { onGameEnd = onGameEnd } )

View File

@ -28,7 +28,7 @@ local function calcValues(self)
proportion = math.min(math.max(self.step, 1), range)/range
end
local px = math.max(proportion * pxrange, 10)
local px = math.max(proportion * pxrange, 6)
px = px - px % 2 + 1
local offset = 0
@ -126,8 +126,8 @@ end
function UIScrollBar:onSetup()
self.setupDone = true
local sliderButton = self:getChildById('sliderButton')
g_mouse.bindAutoPress(self:getChildById('decrementButton'), function() self:decrement() end, 300)
g_mouse.bindAutoPress(self:getChildById('incrementButton'), function() self:increment() end, 300)
g_mouse.bindAutoPress(self:getChildById('decrementButton'), function() self:onDecrement() end, 300)
g_mouse.bindAutoPress(self:getChildById('incrementButton'), function() self:onIncrement() end, 300)
g_mouse.bindPressMove(sliderButton, function(mousePos, mouseMoved) parseSliderPos(self, sliderButton, mousePos, mouseMoved) end)
g_mouse.bindPress(sliderButton, function(mousePos, mouseButton) parseSliderPress(self, sliderButton, mousePos, mouseButton) end)
@ -158,6 +158,26 @@ function UIScrollBar:onStyleApply(styleName, styleNode)
end
end
function UIScrollBar:onDecrement()
if g_keyboard.isCtrlPressed() then
self:decrement(self.value)
elseif g_keyboard.isShiftPressed() then
self:decrement(10)
else
self:decrement()
end
end
function UIScrollBar:onIncrement()
if g_keyboard.isCtrlPressed() then
self:increment(self.maximum)
elseif g_keyboard.isShiftPressed() then
self:increment(10)
else
self:increment()
end
end
function UIScrollBar:decrement(count)
count = count or self.step
self:setValue(self.value - count)
@ -264,4 +284,4 @@ function UIScrollBar:getStep() return self.step end
function UIScrollBar:getOrientation() return self.orientation end
function UIScrollBar:getShowValue() return self.showValue end
function UIScrollBar:getSymbol() return self.symbol end
function UIScrollBar:getMouseScroll() return self.mouseScroll end
function UIScrollBar:getMouseScroll() return self.mouseScroll end

View File

@ -12,7 +12,7 @@ function UISpinBox.create()
spinbox.step = 1
spinbox.firstchange = true
spinbox.mouseScroll = true
spinbox:setText("0")
spinbox:setText("1")
spinbox:setValue(1)
return spinbox
end
@ -23,7 +23,7 @@ function UISpinBox:onSetup()
end
function UISpinBox:onMouseWheel(mousePos, direction)
if not self.mouseScroll then
if not self.mouseScroll then
return false
end
if direction == MouseWheelUp then
@ -66,7 +66,15 @@ function UISpinBox:onTextChange(text, oldText)
end
function UISpinBox:onValueChange(value)
-- nothing todo
-- nothing to do
end
function UISpinBox:onFocusChange(focused)
if not focused then
if self:getText():len() == 0 then
self:setText(self.minimum)
end
end
end
function UISpinBox:onStyleApply(styleName, styleNode)
@ -109,14 +117,16 @@ function UISpinBox:down()
self:setValue(self.value - self.step)
end
function UISpinBox:setValue(value)
function UISpinBox:setValue(value, dontSignal)
value = value or 0
value = math.max(math.min(self.maximum, value), self.minimum)
if value == self.value then return end
self.value = value
if self:getText():len() > 0 then
self:setText(value)
end
self.value = value
local upButton = self:getChildById('up')
local downButton = self:getChildById('down')
@ -127,7 +137,9 @@ function UISpinBox:setValue(value)
downButton:setEnabled(self.maximum ~= self.minimum and self.value ~= self.minimum)
end
signalcall(self.onValueChange, self, value)
if not dontSignal then
signalcall(self.onValueChange, self, value)
end
end
function UISpinBox:getValue()

View File

@ -38,6 +38,7 @@ function UITabBar:addTab(text, panel, icon)
end
local tab = g_ui.createWidget(self:getStyleName() .. 'Button', self.buttonsPanel)
panel.isTab = true
tab.tabPanel = panel
tab.tabBar = self
@ -76,7 +77,13 @@ function UITabBar:removeTab(tab)
local index = table.find(self.tabs, tab)
if index == nil then return end
if self.currentTab == tab then
self:selectPrevTab()
if #self.tabs == 1 then
self.currentTab = nil
elseif index == #self.tabs then
self:selectPrevTab()
else
self:selectNextTab()
end
end
table.remove(self.tabs, index)
tab:destroy()

View File

@ -3,33 +3,45 @@
TODO:
* Make table headers more robust.
* Get dynamic row heights working with text wrapping.
* Every second row different background color applied.
]]
TABLE_SORTING_ASC = 0
TABLE_SORTING_DESC = 1
UITable = extends(UIWidget, "UITable")
local HEADER_ID = 'row0'
-- Initialize default values
function UITable.create()
local table = UITable.internalCreate()
table.headerRow = nil
table.headerColumns = {}
table.dataSpace = nil
table.rows = {}
table.rowBaseStyle = nil
table.columns = {}
table.columnWidth = {}
table.columBaseStyle = nil
table.headerRowBaseStyle = nil
table.headerColumnBaseStyle = nil
table.selectedRow = nil
table.defaultColumnWidth = 80
table.sortColumn = -1
table.sortType = TABLE_SORTING_ASC
table.autoSort = false
return table
end
-- Clear table values
function UITable:onDestroy()
for k,row in pairs(self.rows) do
for _,row in pairs(self.rows) do
row.onClick = nil
end
self.rows = {}
self.columns = {}
self.headerRow = {}
self.headerRow = nil
self.headerColumns = {}
self.columnWidth = {}
self.selectedRow = nil
if self.dataSpace then
@ -38,36 +50,58 @@ function UITable:onDestroy()
end
end
-- Detect if a header is already defined
function UITable:onSetup()
local header = self:getChildById('header')
if header then
self:setHeader(header)
end
end
-- Parse table related styles
function UITable:onStyleApply(styleName, styleNode)
for name, value in pairs(styleNode) do
if name == 'table-data' then
addEvent(function()
self:setTableData(self:getParent():getChildById(value))
end)
elseif name == 'column-style' then
addEvent(function()
self:setColumnStyle(value)
end)
elseif name == 'row-style' then
addEvent(function()
self:setRowStyle(value)
end)
elseif name == 'header-column-style' then
addEvent(function()
self:setHeaderColumnStyle(value)
end)
elseif name == 'header-row-style' then
addEvent(function()
self:setHeaderRowStyle(value)
end)
if value ~= false then
if name == 'table-data' then
addEvent(function()
self:setTableData(self:getParent():getChildById(value))
end)
elseif name == 'column-style' then
addEvent(function()
self:setColumnStyle(value)
end)
elseif name == 'row-style' then
addEvent(function()
self:setRowStyle(value)
end)
elseif name == 'header-column-style' then
addEvent(function()
self:setHeaderColumnStyle(value)
end)
elseif name == 'header-row-style' then
addEvent(function()
self:setHeaderRowStyle(value)
end)
end
end
end
end
function UITable:setColumnWidth(width)
if self:hasHeader() then return end
self.columnWidth = width
end
function UITable:setDefaultColumnWidth(width)
self.defaultColumnWidth = width
end
-- Check if the table has a header
function UITable:hasHeader()
return self.headerRow ~= nil
end
-- Clear all rows
function UITable:clearData()
if not self.dataSpace then
return
@ -78,16 +112,42 @@ function UITable:clearData()
self.rows = {}
end
function UITable:addHeaderRow(data)
-- Set existing child as header
function UITable:setHeader(headerWidget)
self:removeHeader()
if self.dataSpace then
local newHeight = self.dataSpace:getHeight()-headerRow:getHeight()-self.dataSpace:getMarginTop()
self.dataSpace:applyStyle({ height = newHeight })
end
self.headerColumns = {}
self.columnWidth = {}
for colId, column in pairs(headerWidget:getChildren()) do
column.colId = colId
column.table = self
table.insert(self.columnWidth, column:getWidth())
table.insert(self.headerColumns, column)
end
self.headerRow = headerWidget
end
-- Create and add header from table data
function UITable:addHeader(data)
if not data or type(data) ~= 'table' then
g_logger.error('UITable:addHeaderRow - table columns must be provided in a table')
return
end
self:removeHeader()
-- build header columns
local columns = {}
for _, column in pairs(data) do
for colId, column in pairs(data) do
local col = g_ui.createWidget(self.headerColumnBaseStyle)
col.colId = colId
col.table = self
for type, value in pairs(column) do
if type == 'width' then
col:setWidth(value)
@ -104,26 +164,37 @@ function UITable:addHeaderRow(data)
-- create a new header
local headerRow = g_ui.createWidget(self.headerRowBaseStyle, self)
local newHeight = (self.dataSpace:getHeight()-headerRow:getHeight())-self.dataSpace:getMarginTop()
local newHeight = self.dataSpace:getHeight()-headerRow:getHeight()-self.dataSpace:getMarginTop()
self.dataSpace:applyStyle({ height = newHeight })
headerRow:setId(HEADER_ID)
headerRow:setId('header')
self.headerColumns = {}
self.columnWidth = {}
for _, column in pairs(columns) do
headerRow:addChild(column)
self.columns[HEADER_ID] = column
table.insert(self.columnWidth, column:getWidth())
table.insert(self.headerColumns, column)
end
headerRow.onClick = function(headerRow) self:selectRow(headerRow) end
self.headerRow = headerRow
return headerRow
end
function UITable:removeHeaderRow()
self.headerRow:destroy()
self.headerRow = nil
-- Remove header
function UITable:removeHeader()
if self:hasHeader() then
if self.dataSpace then
local newHeight = self.dataSpace:getHeight()+self.headerRow:getHeight()+self.dataSpace:getMarginTop()
self.dataSpace:applyStyle({ height = newHeight })
end
self.headerColumns = {}
self.columnWidth = {}
self.headerRow:destroy()
self.headerRow = nil
end
end
function UITable:addRow(data, ref, height)
function UITable:addRow(data, height)
if not self.dataSpace then
g_logger.error('UITable:addRow - table data space has not been set, cannot add rows.')
return
@ -134,41 +205,123 @@ function UITable:addRow(data, ref, height)
end
local row = g_ui.createWidget(self.rowBaseStyle)
if ref then row.ref = ref end
row.table = self
if height then row:setHeight(height) end
local rowId = #self.rows
row:setId('row'..(rowId < 1 and 1 or rowId))
local rowId = #self.rows + 1
row.rowId = rowId
row:setId('row'..rowId)
row:updateBackgroundColor()
for _, column in pairs(data) do
self.columns[rowId] = {}
for colId, column in pairs(data) do
local col = g_ui.createWidget(self.columBaseStyle, row)
for type, value in pairs(column) do
if type == 'width' then
col:setWidth(value)
elseif type == 'height' then
col:setHeight(value)
elseif type == 'text' then
col:setText(value)
end
if column.width then
col:setWidth(column.width)
else
col:setWidth(self.columnWidth[colId] or self.defaultColumnWidth)
end
self.columns[rowId] = col
if column.height then
col:setHeight(column.height)
end
if column.text then
col:setText(column.text)
end
if column.sortvalue then
col.sortvalue = column.sortvalue
else
col.sortvalue = column.text or 0
end
table.insert(self.columns[rowId], col)
end
row.onFocusChange = function(row, focused)
if focused then self:selectRow(row) end
end
self.dataSpace:addChild(row)
table.insert(self.rows, row)
if self.autoSort then
self:sort()
end
return row
end
-- Update row indices and background color
function UITable:updateRows()
for rowId = 1, #self.rows do
local row = self.rows[rowId]
row.rowId = rowId
row:setId('row'..rowId)
row:updateBackgroundColor()
end
end
-- Removes the given row widget from the table
function UITable:removeRow(row)
if self.selectedRow == row then
self:selectRow(nil)
end
row.onClick = nil
table.removevalue(self.rows, row)
row.table = nil
table.remove(self.columns, row.rowId)
table.remove(self.rows, row.rowId)
self.dataSpace:removeChild(row)
self:updateRows()
end
function UITable:toggleSorting(enabled)
self.autoSort = enabled
end
function UITable:setSorting(colId, sortType)
self.headerColumns[colId]:focus()
if sortType then
self.sortType = sortType
elseif self.sortColumn == colId then
if self.sortType == TABLE_SORTING_ASC then
self.sortType = TABLE_SORTING_DESC
else
self.sortType = TABLE_SORTING_ASC
end
else
self.sortType = TABLE_SORTING_ASC
end
self.sortColumn = colId
end
function UITable:sort()
if self.sortColumn <= 0 then
return
end
if self.sortType == TABLE_SORTING_ASC then
table.sort(self.rows, function(rowA, b)
return rowA:getChildByIndex(self.sortColumn).sortvalue < b:getChildByIndex(self.sortColumn).sortvalue
end)
else
table.sort(self.rows, function(rowA, b)
return rowA:getChildByIndex(self.sortColumn).sortvalue > b:getChildByIndex(self.sortColumn).sortvalue
end)
end
if self.dataSpace then
for _, child in pairs(self.dataSpace:getChildren()) do
self.dataSpace:removeChild(child)
end
end
self:updateRows()
self.columns = {}
for _, row in pairs(self.rows) do
if self.dataSpace then
self.dataSpace:addChild(row)
end
self.columns[row.rowId] = {}
for _, column in pairs(row:getChildren()) do
table.insert(self.columns[row.rowId], column)
end
end
end
function UITable:selectRow(selectedRow)
@ -189,21 +342,34 @@ function UITable:selectRow(selectedRow)
end
function UITable:setTableData(tableData)
local headerHeight = 0
if self.headerRow then
headerHeight = self.headerRow:getHeight()
end
self.dataSpace = tableData
self.dataSpace:applyStyle({ height = self:getHeight() })
self.dataSpace:applyStyle({ height = self:getHeight()-headerHeight-self:getMarginTop() })
end
function UITable:setRowStyle(style)
function UITable:setRowStyle(style, dontUpdate)
self.rowBaseStyle = style
for _, row in pairs(self.rows) do
row:setStyle(style)
if not dontUpdate then
for _, row in pairs(self.rows) do
row:setStyle(style)
end
end
end
function UITable:setColumnStyle(style)
function UITable:setColumnStyle(style, dontUpdate)
self.columBaseStyle = style
for _, col in pairs(self.columns) do
col:setStyle(style)
if not dontUpdate then
for _, columns in pairs(self.columns) do
for _, col in pairs(columns) do
col:setStyle(style)
end
end
end
end
@ -216,7 +382,51 @@ end
function UITable:setHeaderColumnStyle(style)
self.headerColumnBaseStyle = style
if table.haskey(HEADER_ID) then
self.columns[HEADER_ID]:setStyle(style)
for _, col in pairs(self.headerColumns) do
col:setStyle(style)
end
end
UITableRow = extends(UIWidget, "UITableRow")
function UITableRow:onFocusChange(focused)
if focused then
if self.table then self.table:selectRow(self) end
end
end
function UITableRow:onStyleApply(styleName, styleNode)
for name,value in pairs(styleNode) do
if name == 'even-background-color' then
self.evenBackgroundColor = value
elseif name == 'odd-background-color' then
self.oddBackgroundColor = value
end
end
end
function UITableRow:updateBackgroundColor()
self.backgroundColor = nil
local isEven = (self.rowId % 2 == 0)
if isEven and self.evenBackgroundColor then
self.backgroundColor = self.evenBackgroundColor
elseif not isEven and self.oddBackgroundColor then
self.backgroundColor = self.oddBackgroundColor
end
if self.backgroundColor then
self:mergeStyle({ ['background-color'] = self.backgroundColor })
end
end
UITableHeaderColumn = extends(UIButton, "UITableHeaderColumn")
function UITableHeaderColumn:onClick()
if self.table then
self.table:setSorting(self.colId)
self.table:sort()
end
end

View File

@ -296,6 +296,16 @@ function numbertoboolean(number)
end
end
function protectedcall(func, ...)
local status, ret = pcall(func, ...)
if status then
return ret
end
perror(ret)
return false
end
function signalcall(param, ...)
if type(param) == 'function' then
local status, ret = pcall(param, ...)
@ -313,7 +323,7 @@ function signalcall(param, ...)
perror(ret)
end
end
elseif func ~= nil then
elseif param ~= nil then
error('attempt to call a non function value')
end
return false

View File

@ -244,28 +244,34 @@ function doCreatureFitFilters(creature)
local localPlayer = g_game.getLocalPlayer()
if pos.z ~= localPlayer:getPosition().z or not creature:canBeSeen() then return false end
local hidePlayers = hidePlayersButton:isChecked()
local hideNPCs = hideNPCsButton:isChecked()
local hideMonsters = hideMonstersButton:isChecked()
local hideSkulls = hideSkullsButton:isChecked()
local hideParty = hidePartyButton:isChecked()
if hidePlayers and creature:isPlayer() then
return false
elseif hideNPCs and creature:isNpc() then
return false
elseif hideMonsters and creature:isMonster() then
return false
elseif hideSkulls and creature:isPlayer() and creature:getSkull() == SkullNone then
return false
elseif hideParty and creature:getShield() > ShieldWhiteBlue then
return false
end
return true
end
function doShowCreatureAtBattle(creature)
if doCreatureFitFilters(creature) then
local hidePlayers = hidePlayersButton:isChecked()
local hideNPCs = hideNPCsButton:isChecked()
local hideMonsters = hideMonstersButton:isChecked()
local hideSkulls = hideSkullsButton:isChecked()
local hideParty = hidePartyButton:isChecked()
if hidePlayers and creature:isPlayer() then
return false
elseif hideNPCs and creature:isNpc() then
return false
elseif hideMonsters and creature:isMonster() then
return false
elseif hideSkulls and creature:isPlayer() and creature:getSkull() == SkullNone then
return false
elseif hideParty and creature:getShield() > ShieldWhiteBlue then
return false
end
return true
end
return false
end
function onCreatureHealthPercentChange(creature, health)
local battleButton = battleButtonsByCreaturesList[creature:getId()]
if battleButton then
@ -452,7 +458,7 @@ function addCreature(creature)
end
local localPlayer = g_game.getLocalPlayer()
battleButton:setVisible(localPlayer:hasSight(creature:getPosition()) and creature:canBeSeen())
battleButton:setVisible(localPlayer:hasSight(creature:getPosition()) and creature:canBeSeen() and doShowCreatureAtBattle(creature))
end
function removeAllCreatures()
@ -484,10 +490,10 @@ function onBattleButtonMouseRelease(self, mousePosition, mouseButton)
if ((g_mouse.isPressed(MouseLeftButton) and mouseButton == MouseRightButton)
or (g_mouse.isPressed(MouseRightButton) and mouseButton == MouseLeftButton)) then
mouseWidget.cancelNextRelease = true
g_game.look(self.creature)
g_game.look(self.creature, true)
return true
elseif mouseButton == MouseLeftButton and g_keyboard.isShiftPressed() then
g_game.look(self.creature)
g_game.look(self.creature, true)
return true
elseif mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
modules.game_interface.createThingMenu(mousePosition, nil, nil, self.creature)

View File

@ -2,7 +2,7 @@ Module
name: game_battle
description: Manage battle window
author: andrefaramir, BeniS
website: www.otclient.info
website: https://github.com/edubart/otclient
sandboxed: true
scripts: [ battle ]
@onLoad: init()

View File

@ -2,7 +2,7 @@ Module
name: game_bugreport
description: Bug report interface (Ctrl+Z)
author: edubart
website: www.otclient.info
website: https://github.com/edubart/otclient
scripts: [ bugreport ]
sandboxed: true
@onLoad: init()

View File

@ -15,7 +15,8 @@ fightModeRadioGroup = nil
pvpModeRadioGroup = nil
function init()
combatControlsButton = modules.client_topmenu.addRightGameToggleButton('combatControlsButton', tr('Combat Controls'), '/images/topbuttons/combatcontrols', toggle)
combatControlsButton = modules.client_topmenu.addRightGameToggleButton('combatControlsButton',
tr('Combat Controls'), '/images/topbuttons/combatcontrols', toggle)
combatControlsButton:setOn(true)
combatControlsWindow = g_ui.loadUI('combatcontrols', modules.game_interface.getRightPanel())
combatControlsWindow:disableResize()

View File

@ -2,7 +2,7 @@ Module
name: game_combatcontrols
description: Combat controls window
author: edubart, BeniS
website: www.otclient.info
website: https://github.com/edubart/otclient
sandboxed: true
scripts: [ combatcontrols ]
@onLoad: init()

View File

@ -25,7 +25,7 @@ MainWindow
Label
id: openPrivateChannelWithLabel
!text: tr('Open a private message channel:')
!text: tr('Open a private message channel') .. ':'
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: next.top

View File

@ -35,7 +35,7 @@ MainWindow
width: 180
Label
!text: tr('Ignored Players:')
!text: tr('Ignored Players') .. ':'
anchors.left: parent.left
anchors.top: prev.bottom
margin-top: 10
@ -108,7 +108,7 @@ MainWindow
width: 180
Label
!text: tr('Allowed Players:')
!text: tr('Allowed Players') .. ':'
anchors.top: prev.bottom
anchors.left: prev.left
margin-top: 10

View File

@ -3,7 +3,7 @@ SpeakTypesSettings = {
say = { speakType = MessageModes.Say, color = '#FFFF00' },
whisper = { speakType = MessageModes.Whisper, color = '#FFFF00' },
yell = { speakType = MessageModes.Yell, color = '#FFFF00' },
broadcast = { speakType = MessageModes.GamemasterPrivateFrom, color = '#F55E5E' },
broadcast = { speakType = MessageModes.GamemasterBroadcast, color = '#F55E5E' },
private = { speakType = MessageModes.PrivateTo, color = '#5FF7F7', private = true },
privateRed = { speakType = MessageModes.GamemasterTo, color = '#F55E5E', private = true },
privatePlayerToPlayer = { speakType = MessageModes.PrivateTo, color = '#9F9DFD', private = true },
@ -38,6 +38,7 @@ SpeakTypes = {
[MessageModes.RVRChannel] = SpeakTypesSettings.channelWhite,
[MessageModes.RVRContinue] = SpeakTypesSettings.rvrContinue,
[MessageModes.RVRAnswer] = SpeakTypesSettings.rvrAnswerFrom,
[MessageModes.NpcFromStartBlock] = SpeakTypesSettings.privateNpcToPlayer,
-- ignored types
[MessageModes.Spell] = SpeakTypesSettings.none,
@ -51,6 +52,13 @@ SayModes = {
[3] = { speakTypeDesc = 'yell', icon = '/images/game/console/yell' }
}
ChannelEventFormats = {
[ChannelEvent.Join] = '%s joined the channel.',
[ChannelEvent.Leave] = '%s left the channel.',
[ChannelEvent.Invite] = '%s has been invited to the channel.',
[ChannelEvent.Exclude] = '%s has been removed from the channel.',
}
MAX_HISTORY = 500
MAX_LINES = 100
HELP_CHANNEL = 9
@ -97,7 +105,8 @@ function init()
onRuleViolationCancel = onRuleViolationCancel,
onRuleViolationLock = onRuleViolationLock,
onGameStart = online,
onGameEnd = offline
onGameEnd = offline,
onChannelEvent = onChannelEvent,
})
consolePanel = g_ui.loadUI('console', modules.game_interface.getBottomPanel())
@ -105,7 +114,6 @@ function init()
consoleContentPanel = consolePanel:getChildById('consoleContentPanel')
consoleTabBar = consolePanel:getChildById('consoleTabBar')
consoleTabBar:setContentWidget(consoleContentPanel)
consoleTabBar:setTabSpacing(-1)
channels = {}
consolePanel.onKeyPress = function(self, keyCode, keyboardModifiers)
@ -114,13 +122,10 @@ function init()
local tab = consoleTabBar:getCurrentTab()
if not tab then return false end
local consoleBuffer = tab.tabPanel:getChildById('consoleBuffer')
if not consoleBuffer then return false end
local selection = tab.tabPanel:getChildById('consoleBuffer').selectionText
if not selection then return false end
local consoleLabel = consoleBuffer:getFocusedChild()
if not consoleLabel or not consoleLabel:hasSelection() then return false end
g_window.setClipboardText(consoleLabel:getSelection())
g_window.setClipboardText(selection)
return true
end
@ -148,6 +153,27 @@ function init()
end
end
function clearSelection(consoleBuffer)
for _,label in pairs(consoleBuffer:getChildren()) do
label:clearSelection()
end
consoleBuffer.selectionText = nil
consoleBuffer.selection = nil
end
function selectAll(consoleBuffer)
clearSelection(consoleBuffer)
if consoleBuffer:getChildCount() > 0 then
local text = {}
for _,label in pairs(consoleBuffer:getChildren()) do
label:selectAll()
table.insert(text, label:getSelection())
end
consoleBuffer.selectionText = table.concat(text, '\n')
consoleBuffer.selection = { first = consoleBuffer:getChildIndex(consoleBuffer:getFirstChild()), last = consoleBuffer:getChildIndex(consoleBuffer:getLastChild()) }
end
end
function toggleChat()
if consoleToggleChat:isChecked() then
disableChat()
@ -164,12 +190,18 @@ function enableChat()
g_keyboard.unbindKeyUp("Space")
g_keyboard.unbindKeyUp("Enter")
g_keyboard.unbindKeyUp("Escape")
gameInterface.unbindWalkKey("W")
gameInterface.unbindWalkKey("D")
gameInterface.unbindWalkKey("S")
gameInterface.unbindWalkKey("A")
gameInterface.unbindWalkKey("E")
gameInterface.unbindWalkKey("Q")
gameInterface.unbindWalkKey("C")
gameInterface.unbindWalkKey("Z")
consoleToggleChat:setTooltip(tr("Disable chat mode, allow to walk using ASDW"))
end
@ -187,12 +219,18 @@ function disableChat()
end
g_keyboard.bindKeyUp("Space", quickFunc)
g_keyboard.bindKeyUp("Enter", quickFunc)
g_keyboard.bindKeyUp("Escape", quickFunc)
gameInterface.bindWalkKey("W", North)
gameInterface.bindWalkKey("D", East)
gameInterface.bindWalkKey("S", South)
gameInterface.bindWalkKey("A", West)
gameInterface.bindWalkKey("E", NorthEast)
gameInterface.bindWalkKey("Q", NorthWest)
gameInterface.bindWalkKey("C", SouthEast)
gameInterface.bindWalkKey("Z", SouthWest)
consoleToggleChat:setTooltip(tr("Enable chat mode"))
end
@ -210,7 +248,8 @@ function terminate()
onRuleViolationCancel = onRuleViolationCancel,
onRuleViolationLock = onRuleViolationLock,
onGameStart = online,
onGameEnd = offline
onGameEnd = offline,
onChannelEvent = onChannelEvent,
})
if g_game.isOnline() then clear() end
@ -233,7 +272,13 @@ function terminate()
violationWindow:destroy()
end
consoleTabBar = nil
consoleContentPanel = nil
consoleToggleChat = nil
consoleTextEdit = nil
consolePanel:destroy()
consolePanel = nil
ownPrivateName = nil
Console = nil
@ -288,11 +333,14 @@ function clear()
channels = {}
consoleTabBar:removeTab(defaultTab)
defaultTab = nil
consoleTabBar:removeTab(serverTab)
serverTab = nil
local npcTab = consoleTabBar:getTab('NPCs')
if npcTab then
consoleTabBar:removeTab(npcTab)
npcTab = nil
end
if violationReportTab then
@ -505,6 +553,8 @@ function addTabText(text, speaktype, tab, creatureName)
label:setColor(speaktype.color)
consoleTabBar:blinkTab(tab)
label.highlightInfo = {}
-- Overlay for consoleBuffer which shows highlighted words only
if speaktype.npcChat and (g_game.getCharacterName() ~= creatureName or g_game.getCharacterName() == 'Account Manager') then
@ -534,6 +584,10 @@ function addTabText(text, speaktype, tab, creatureName)
local dataBlock = { _start = highlightData[(i-1)*3+1], _end = highlightData[(i-1)*3+2], words = highlightData[(i-1)*3+3] }
local lastBlockEnd = (highlightData[(i-2)*3+2] or 1)
for i = dataBlock._start, dataBlock._end do
label.highlightInfo[i] = dataBlock.words
end
for letter = lastBlockEnd, dataBlock._start-1 do
local tmpChar = string.byte(drawText:sub(letter, letter))
local fillChar = (tmpChar == 10 or tmpChar == 32) and string.char(tmpChar) or string.char(127)
@ -557,12 +611,109 @@ function addTabText(text, speaktype, tab, creatureName)
end
label.name = creatureName
label.onMouseRelease = function (self, mousePos, mouseButton)
processMessageMenu(mousePos, mouseButton, creatureName, text, self, tab)
consoleBuffer.onMouseRelease = function(self, mousePos, mouseButton)
processMessageMenu(mousePos, mouseButton, nil, nil, nil, tab)
end
label.onMouseRelease = function(self, mousePos, mouseButton)
if mouseButton == MouseLeftButton then
local position = label:getTextPos(mousePos)
if position and label.highlightInfo[position] then
sendMessage(label.highlightInfo[position], npcTab)
end
elseif mouseButton == MouseRightButton then
processMessageMenu(mousePos, mouseButton, creatureName, text, self, tab)
end
end
label.onMousePress = function(self, mousePos, button)
if button == MouseLeftButton then clearSelection(consoleBuffer) end
end
label.onDragEnter = function(self, mousePos)
clearSelection(consoleBuffer)
return true
end
label.onDragLeave = function(self, droppedWidget, mousePos)
local text = {}
for selectionChild = consoleBuffer.selection.first, consoleBuffer.selection.last do
local label = self:getParent():getChildByIndex(selectionChild)
table.insert(text, label:getSelection())
end
consoleBuffer.selectionText = table.concat(text, '\n')
return true
end
label.onDragMove = function(self, mousePos, mouseMoved)
local parent = self:getParent()
local parentRect = parent:getPaddingRect()
local selfIndex = parent:getChildIndex(self)
local child = parent:getChildByPos(mousePos)
-- find bonding children
if not child then
if mousePos.y < self:getY() then
for index = selfIndex - 1, 1, -1 do
local label = parent:getChildByIndex(index)
if label:getY() + label:getHeight() > parentRect.y then
if (mousePos.y >= label:getY() and mousePos.y <= label:getY() + label:getHeight()) or index == 1 then
child = label
break
end
else
child = parent:getChildByIndex(index + 1)
break
end
end
elseif mousePos.y > self:getY() + self:getHeight() then
for index = selfIndex + 1, parent:getChildCount(), 1 do
local label = parent:getChildByIndex(index)
if label:getY() < parentRect.y + parentRect.height then
if (mousePos.y >= label:getY() and mousePos.y <= label:getY() + label:getHeight()) or index == parent:getChildCount() then
child = label
break
end
else
child = parent:getChildByIndex(index - 1)
break
end
end
else
child = self
end
end
if not child then return false end
local childIndex = parent:getChildIndex(child)
-- remove old selection
clearSelection(consoleBuffer)
-- update self selection
local textBegin = self:getTextPos(self:getLastClickPosition())
local textPos = self:getTextPos(mousePos)
self:setSelection(textBegin, textPos)
consoleBuffer.selection = { first = math.min(selfIndex, childIndex), last = math.max(selfIndex, childIndex) }
-- update siblings selection
if child ~= self then
for selectionChild = consoleBuffer.selection.first + 1, consoleBuffer.selection.last - 1 do
parent:getChildByIndex(selectionChild):selectAll()
end
local textPos = child:getTextPos(mousePos)
if childIndex > selfIndex then
child:setSelection(0, textPos)
else
child:setSelection(string.len(child:getText()), textPos)
end
end
return true
end
if consoleBuffer:getChildCount() > MAX_LINES then
consoleBuffer:getFirstChild():destroy()
local child = consoleBuffer:getFirstChild()
clearSelection(consoleBuffer)
child:destroy()
end
end
@ -578,7 +729,10 @@ end
function processChannelTabMenu(tab, mousePos, mouseButton)
local menu = g_ui.createWidget('PopupMenu')
menu:setGameMenu(true)
local worldName = g_game.getWorldName()
local characterName = g_game.getCharacterName()
channelName = tab:getText()
if tab ~= defaultTab and tab ~= serverTab then
menu:addOption(tr('Close'), function() removeTab(channelName) end)
@ -588,8 +742,28 @@ function processChannelTabMenu(tab, mousePos, mouseButton)
if consoleTabBar:getCurrentTab() == tab then
menu:addOption(tr('Clear Messages'), function() clearChannel(consoleTabBar) end)
menu:addOption(tr('Save Messages'), function()
local panel = consoleTabBar:getTabPanel(tab)
local consoleBuffer = panel:getChildById('consoleBuffer')
local lines = {}
for _,label in pairs(consoleBuffer:getChildren()) do
table.insert(lines, label:getText())
end
local filename = worldName .. ' - ' .. characterName .. ' - ' .. channelName .. '.txt'
local filepath = '/' .. filename
-- extra information at the beginning
table.insert(lines, 1, os.date('\nChannel saved at %a %b %d %H:%M:%S %Y'))
if g_resources.fileExists(filepath) then
table.insert(lines, 1, protectedcall(g_resources.readFileContents, filepath) or '')
end
g_resources.writeFileContents(filepath, table.concat(lines, '\n'))
modules.game_textmessage.displayStatusMessage(tr('Channel appended to %s', filename))
end)
end
--menu:addOption(tr('Save Messages'), function() --[[TODO]] end)
menu:display(mousePos)
end
@ -597,6 +771,7 @@ end
function processMessageMenu(mousePos, mouseButton, creatureName, text, label, tab)
if mouseButton == MouseRightButton then
local menu = g_ui.createWidget('PopupMenu')
menu:setGameMenu(true)
if creatureName and #creatureName > 0 then
if creatureName ~= g_game.getCharacterName() then
menu:addOption(tr('Message to ' .. creatureName), function () g_game.openPrivateChannel(creatureName) end)
@ -622,12 +797,15 @@ function processMessageMenu(mousePos, mouseButton, creatureName, text, label, ta
menu:addOption(tr('Copy name'), function () g_window.setClipboardText(creatureName) end)
end
if label:hasSelection() then
menu:addOption(tr('Copy'), function() g_window.setClipboardText(label:getSelection()) end, '(Ctrl+C)')
local selection = tab.tabPanel:getChildById('consoleBuffer').selectionText
if selection and #selection > 0 then
menu:addOption(tr('Copy'), function() g_window.setClipboardText(selection) end, '(Ctrl+C)')
end
menu:addOption(tr('Copy message'), function() g_window.setClipboardText(text) end)
menu:addOption(tr('Select all'), function() label:selectAll() end)
if tab.violations then
if text then
menu:addOption(tr('Copy message'), function() g_window.setClipboardText(text) end)
end
menu:addOption(tr('Select all'), function() selectAll(tab.tabPanel:getChildById('consoleBuffer')) end)
if tab.violations and creatureName then
menu:addSeparator()
menu:addOption(tr('Process') .. ' ' .. creatureName, function() processViolation(creatureName, text) end)
menu:addOption(tr('Remove') .. ' ' .. creatureName, function() g_game.closeRuleViolation(creatureName) end)
@ -687,7 +865,7 @@ function sendMessage(message, tab)
end
-- player used whisper
local chatCommandMessage = message:match("^%#[w|W] (.*)")
chatCommandMessage = message:match("^%#[w|W] (.*)")
if chatCommandMessage ~= nil then
chatCommandSayMode = 'whisper'
message = chatCommandMessage
@ -695,13 +873,28 @@ function sendMessage(message, tab)
end
-- player say
local chatCommandMessage = message:match("^%#[s|S] (.*)")
chatCommandMessage = message:match("^%#[s|S] (.*)")
if chatCommandMessage ~= nil then
chatCommandSayMode = 'say'
message = chatCommandMessage
channel = 0
end
-- player red talk on channel
chatCommandMessage = message:match("^%#[c|C] (.*)")
if chatCommandMessage ~= nil then
chatCommandSayMode = 'channelRed'
message = chatCommandMessage
end
-- player broadcast
chatCommandMessage = message:match("^%#[b|B] (.*)")
if chatCommandMessage ~= nil then
chatCommandSayMode = 'broadcast'
message = chatCommandMessage
channel = 0
end
local findIni, findEnd, chatCommandInitial, chatCommandPrivate, chatCommandEnd, chatCommandMessage = message:find("([%*%@])(.+)([%*%@])(.*)")
if findIni ~= nil and findIni == 1 then -- player used private chat command
if chatCommandInitial == chatCommandEnd then
@ -807,7 +1000,7 @@ function navigateMessageHistory(step)
end
function applyMessagePrefixies(name, level, message)
if name then
if name and #name > 0 then
if modules.client_options.getOption('showLevelsInConsole') and level > 0 then
message = name .. ' [' .. level .. ']: ' .. message
else
@ -823,7 +1016,9 @@ function onTalk(name, level, mode, message, channelId, creaturePos)
return
end
if ignoreNpcMessages and mode == MessageModes.NpcFrom then return end
local isNpcMode = (mode == MessageModes.NpcFromStartBlock or mode == MessageModes.NpcFrom)
if ignoreNpcMessages and isNpcMode then return end
speaktype = SpeakTypes[mode]
@ -839,7 +1034,7 @@ function onTalk(name, level, mode, message, channelId, creaturePos)
if mode == MessageModes.Yell and isIgnoringYelling() then
return
elseif speaktype.private and isIgnoringPrivate() and mode ~= MessageModes.NpcFrom then
elseif speaktype.private and isIgnoringPrivate() and not isNpcMode then
return
elseif isIgnored(name) then
return
@ -852,21 +1047,21 @@ function onTalk(name, level, mode, message, channelId, creaturePos)
if (mode == MessageModes.Say or mode == MessageModes.Whisper or mode == MessageModes.Yell or
mode == MessageModes.Spell or mode == MessageModes.MonsterSay or mode == MessageModes.MonsterYell or
mode == MessageModes.NpcFrom or mode == MessageModes.BarkLow or mode == MessageModes.BarkLoud) and
creaturePos then
-- Remove curly braces from screen message
local staticMessage = message
if mode == MessageModes.NpcFrom then
local highlightData = getHighlightedText(staticMessage)
if #highlightData > 0 then
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] }
staticMessage = staticMessage:gsub("{"..dataBlock.words.."}", dataBlock.words)
end
mode == MessageModes.NpcFrom or mode == MessageModes.BarkLow or mode == MessageModes.BarkLoud or
mode == MessageModes.NpcFromStartBlock) and creaturePos then
local staticText = StaticText.create()
-- Remove curly braces from screen message
local staticMessage = message
if isNpcMode then
local highlightData = getHighlightedText(staticMessage)
if #highlightData > 0 then
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] }
staticMessage = staticMessage:gsub("{"..dataBlock.words.."}", dataBlock.words)
end
end
local staticText = StaticText.create()
staticText:setColor(speaktype.color)
end
staticText:addMessage(name, mode, staticMessage)
g_map.addThing(staticText, creaturePos, -1)
end
@ -1020,15 +1215,15 @@ function loadCommunicationSettings()
local ignoreNode = g_settings.getNode('IgnorePlayers')
if ignoreNode then
for i = 1, #ignoreNode do
table.insert(communicationSettings.ignoredPlayers, ignoreNode[i])
for _, player in pairs(ignoreNode) do
table.insert(communicationSettings.ignoredPlayers, player)
end
end
local whitelistNode = g_settings.getNode('WhitelistedPlayers')
if whitelistNode then
for i = 1, #whitelistNode do
table.insert(communicationSettings.whitelistedPlayers, whitelistNode[i])
for _, player in pairs(whitelistNode) do
table.insert(communicationSettings.whitelistedPlayers, player)
end
end
@ -1264,3 +1459,19 @@ function offline()
end
clear()
end
function onChannelEvent(channelId, name, type)
local fmt = ChannelEventFormats[type]
if not fmt then
print(('Unknown channel event type (%d).'):format(type))
return
end
local channel = channels[channelId]
if channel then
local tab = getTab(channel)
if tab then
addTabText(fmt:format(name), SpeakTypesSettings.channelOrange, tab)
end
end
end

View File

@ -2,7 +2,7 @@ Module
name: game_console
description: Manage chat window
author: edubart, andrefaramir, baxnie, sn4ake, BeniS
website: www.otclient.info
website: https://github.com/edubart/otclient
sandboxed: true
scripts: [ console ]
@onLoad: init()

View File

@ -10,6 +10,9 @@ ConsoleLabel < UITextEdit
change-cursor-image: false
cursor-visible: false
editable: false
draggable: true
selectable: false
focusable: false
ConsolePhantomLabel < UILabel
font: verdana-11px-antialised
@ -81,7 +84,8 @@ Panel
margin-left: 5
margin-top: 3
margin-right: 5
moveable: true
tab-spacing: 2
movable: true
TabButton
id: nextChannelButton

View File

@ -110,6 +110,7 @@ function onContainerOpen(container, previousContainer)
containerWindow:setText(name)
containerItemWidget:setItem(container:getContainerItem())
containerItemWidget:setPhantom(true)
containerPanel:destroyChildren()
for slot=0,container:getCapacity()-1 do

View File

@ -2,7 +2,7 @@ Module
name: game_containers
description: Manage containers
author: edubart, baxnie
website: www.otclient.info
website: https://github.com/edubart/otclient
sandboxed: true
scripts: [containers]
@onLoad: init()

View File

@ -2,7 +2,7 @@ Module
name: game_cooldown
description: Spellcooldowns
author: OTClient team
website: www.otclient.info
website: https://github.com/edubart/otclient
sandboxed: true
scripts: [ cooldown ]
@onLoad: init()

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