mirror of
https://github.com/edubart/otclient.git
synced 2025-09-14 14:53:34 +02:00
Compare commits
125 Commits
multi-grap
...
v0.6.4
Author | SHA1 | Date | |
---|---|---|---|
![]() |
28786a3570 | ||
![]() |
b07a77f705 | ||
![]() |
0d44942e8e | ||
![]() |
dd829395e3 | ||
![]() |
18fa54181a | ||
![]() |
5b8ff29fa3 | ||
![]() |
59e90e8f1e | ||
![]() |
5db37857bf | ||
![]() |
fc0297d6db | ||
![]() |
1060c6f78c | ||
![]() |
c9597d6682 | ||
![]() |
d3e97d33c7 | ||
![]() |
2b015d49d7 | ||
![]() |
f04b4a0b42 | ||
![]() |
ff5c22d4c0 | ||
![]() |
d6105a98d1 | ||
![]() |
0938e22eb9 | ||
![]() |
1868b235cb | ||
![]() |
9a30050340 | ||
![]() |
9d689f0c43 | ||
![]() |
2b34c0ea0a | ||
![]() |
d32f71c2b9 | ||
![]() |
3cff331723 | ||
![]() |
9894f0c0b9 | ||
![]() |
e60372fdea | ||
![]() |
d2473fd424 | ||
![]() |
7d7bd00a63 | ||
![]() |
c81a623c43 | ||
![]() |
8b165b95fd | ||
![]() |
6f9436dd60 | ||
![]() |
ae95f51346 | ||
![]() |
9b84570372 | ||
![]() |
38dec168ee | ||
![]() |
84b722f8c7 | ||
![]() |
b3717ceb93 | ||
![]() |
3340e06da6 | ||
![]() |
084ee45650 | ||
![]() |
7290ec3334 | ||
![]() |
971d90a596 | ||
![]() |
8230bf2af4 | ||
![]() |
241b54262a | ||
![]() |
63ce68b449 | ||
![]() |
f47ea05abc | ||
![]() |
de3160c90d | ||
![]() |
67bd00556d | ||
![]() |
778559c7b9 | ||
![]() |
3aac0ac0ec | ||
![]() |
4adfafc67e | ||
![]() |
1b27a095a9 | ||
![]() |
e6977b1b43 | ||
![]() |
5843b78e87 | ||
![]() |
7cf645e715 | ||
![]() |
537508021e | ||
![]() |
e741a62ce9 | ||
![]() |
56d6ef6642 | ||
![]() |
3db8f54aa9 | ||
![]() |
9234030c1b | ||
![]() |
520baa28ea | ||
![]() |
bbdeac2e33 | ||
![]() |
1f914351bb | ||
![]() |
eb68504dc1 | ||
![]() |
32647f11bf | ||
![]() |
644d4daeea | ||
![]() |
b27352c321 | ||
![]() |
a6be9ae525 | ||
![]() |
5df3ec8cf2 | ||
![]() |
00729bbc2e | ||
![]() |
3b2d8a2b5e | ||
![]() |
d5298c1011 | ||
![]() |
aaad8ab8a0 | ||
![]() |
efbd9ab693 | ||
![]() |
092209c0bb | ||
![]() |
05f7f6a4cf | ||
![]() |
2c36ca7215 | ||
![]() |
926eb9f01e | ||
![]() |
96bb28e806 | ||
![]() |
e15995e1eb | ||
![]() |
719debfeae | ||
![]() |
e7137c2535 | ||
![]() |
5eabf6f518 | ||
![]() |
5849136526 | ||
![]() |
0451fd6b58 | ||
![]() |
9cf878335a | ||
![]() |
529b646316 | ||
![]() |
1ea2b380ca | ||
![]() |
914fe249ab | ||
![]() |
4d498ed0d8 | ||
![]() |
9aa667da26 | ||
![]() |
e6db43ac3a | ||
![]() |
b5911cf1de | ||
![]() |
5fbb71157d | ||
![]() |
0ff36a1a0a | ||
![]() |
4a04a18835 | ||
![]() |
6fa9631d6a | ||
![]() |
261642190b | ||
![]() |
95abf2a1d2 | ||
![]() |
c4adf2d817 | ||
![]() |
c7c259ef80 | ||
![]() |
987c6d6c91 | ||
![]() |
c8185474de | ||
![]() |
be071c7103 | ||
![]() |
2f9e2c3e33 | ||
![]() |
b81590f297 | ||
![]() |
e062562888 | ||
![]() |
18d23653c4 | ||
![]() |
6c119627bb | ||
![]() |
d847a78a4d | ||
![]() |
0dccc870b5 | ||
![]() |
e4c7ca604b | ||
![]() |
d427560b98 | ||
![]() |
cc12db0d1f | ||
![]() |
1ce6df99ac | ||
![]() |
57bb6ff974 | ||
![]() |
9bae1b9e25 | ||
![]() |
1415de222c | ||
![]() |
34ceb3c95e | ||
![]() |
b43a196eac | ||
![]() |
a3a65d40ce | ||
![]() |
6ef3508362 | ||
![]() |
a71e07f063 | ||
![]() |
4bdd1e79fd | ||
![]() |
e9e4dcd71b | ||
![]() |
0891e2b30a | ||
![]() |
24664714bd | ||
![]() |
da51dd467e |
71
.gitignore
vendored
71
.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
/modules/.project
|
||||
build*
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
@@ -39,3 +38,73 @@ tags
|
||||
Thumbs.db
|
||||
.directory
|
||||
src/framework/graphics/dx/
|
||||
modules/.project/modules.sublime-workspace
|
||||
|
||||
#################
|
||||
## Visual Studio
|
||||
#################
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
build/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.log
|
||||
*.scc
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
|
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
project(otclient)
|
||||
|
||||
set(VERSION "0.6.2")
|
||||
set(VERSION "0.6.4")
|
||||
|
||||
option(FRAMEWORK_SOUND "Use SOUND " ON)
|
||||
option(FRAMEWORK_GRAPHICS "Use GRAPHICS " ON)
|
||||
|
BIN
data/images/game/dangerous.png
Normal file
BIN
data/images/game/dangerous.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 227 B |
BIN
data/images/game/emblems/emblem_member.png
Normal file
BIN
data/images/game/emblems/emblem_member.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 333 B |
BIN
data/images/game/emblems/emblem_other.png
Normal file
BIN
data/images/game/emblems/emblem_other.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 319 B |
BIN
data/images/game/shields/shield_gray.png
Normal file
BIN
data/images/game/shields/shield_gray.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 330 B |
BIN
data/images/game/summon_other.png
Normal file
BIN
data/images/game/summon_other.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 283 B |
BIN
data/images/game/summon_own.png
Normal file
BIN
data/images/game/summon_own.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 283 B |
@@ -1,36 +1,31 @@
|
||||
-- by Don Daniello
|
||||
-- 09 June 2012
|
||||
-- http://DonDaniello.com
|
||||
-- http://otland.net/members/Don+Daniello
|
||||
|
||||
locale = {
|
||||
name = "pl",
|
||||
languageName = "Polski",
|
||||
|
||||
translation = {
|
||||
["1a) Offensive Name"] = false,
|
||||
["1b) Invalid Name Format"] = false,
|
||||
["1c) Unsuitable Name"] = false,
|
||||
["1d) Name Inciting Rule Violation"] = false,
|
||||
["2a) Offensive Statement"] = false,
|
||||
["2b) Spamming"] = false,
|
||||
["2c) Illegal Advertising"] = false,
|
||||
["2d) Off-Topic Public Statement"] = false,
|
||||
["2e) Non-English Public Statement"] = false,
|
||||
["2f) Inciting Rule Violation"] = false,
|
||||
["3a) Bug Abuse"] = false,
|
||||
["3b) Game Weakness Abuse"] = false,
|
||||
["3c) Using Unofficial Software to Play"] = false,
|
||||
["3d) Hacking"] = false,
|
||||
["3e) Multi-Clienting"] = false,
|
||||
["3f) Account Trading or Sharing"] = false,
|
||||
["4a) Threatening Gamemaster"] = false,
|
||||
["4b) Pretending to Have Influence on Rule Enforcement"] = false,
|
||||
["4c) False Report to Gamemaster"] = false,
|
||||
["Accept"] = false,
|
||||
["1a) Offensive Name"] = "1a) Obrazliwe Imie",
|
||||
["1b) Invalid Name Format"] = "1b) Niepoprawny Format Imienia",
|
||||
["1c) Unsuitable Name"] = "1c) Nieodpowiednie Imie",
|
||||
["1d) Name Inciting Rule Violation"] = "1d) Imie Nawolujace Do Lamania Regulaminu",
|
||||
["2a) Offensive Statement"] = "2a) Obrazliwa wypowiedz",
|
||||
["2b) Spamming"] = "2b) Spamowanie",
|
||||
["2c) Illegal Advertising"] = "2c) Nielegalne Reklamy",
|
||||
["2d) Off-Topic Public Statement"] = "2d) Publiczne Wypowiadanie Sie Nie Na Temat",
|
||||
["2e) Non-English Public Statement"] = "2e) Publiczne wypowiadanie Sie W Jezyku Innym Niz Angielski",
|
||||
["2f) Inciting Rule Violation"] = "2f) Nawolywanie Do Lamania Regulaminu ",
|
||||
["3a) Bug Abuse"] = "3a) Wykorzystywanie Bledow",
|
||||
["3b) Game Weakness Abuse"] = "3b) Wykorzystanie Slabosci Gry",
|
||||
["3c) Using Unofficial Software to Play"] = "3c) Gra Przy Uzyciu Nieoficjalnego Oprogramowania",
|
||||
["3d) Hacking"] = "3d) Wlamywanie Sie",
|
||||
["3e) Multi-Clienting"] = "3e) Uzycie Multi-Klienta",
|
||||
["3f) Account Trading or Sharing"] = "3f) Handel Lub Udostepnianie Kont",
|
||||
["4a) Threatening Gamemaster"] = "4a) Grozby Pod Adresem Mistrza Gry",
|
||||
["4b) Pretending to Have Influence on Rule Enforcement"] = "4b) Udawanie Wplywu na Ustanawianie Regul Gry",
|
||||
["4c) False Report to Gamemaster"] = "4c) Wyslanie Falszywego Raportu Mistrzowi Gry",
|
||||
["Accept"] = "Akceptuj",
|
||||
["Account name"] = "Numer konta",
|
||||
["Account Status:"] = false,
|
||||
["Action:"] = false,
|
||||
["Account Status:"] = "Status Konta:",
|
||||
["Action:"] = "Akcja:",
|
||||
["Add"] = "Dodaj",
|
||||
["Add new VIP"] = "Nowy VIP",
|
||||
["Addon 1"] = "Addon 1",
|
||||
@@ -39,15 +34,15 @@ locale = {
|
||||
["Add to VIP list"] = "Dodaj do VIPow",
|
||||
["Adjust volume"] = "Zmien glosnosc",
|
||||
["Alas! Brave adventurer, you have met a sad fate.\nBut do not despair, for the gods will bring you back\ninto this world in exchange for a small sacrifice\n\nSimply click on Ok to resume your journeys!"] = false,
|
||||
["All"] = false,
|
||||
["All"] = "Wszystkie",
|
||||
["All modules and scripts were reloaded."] = "Wszystkie moduly ",
|
||||
["Allow auto chase override"] = false,
|
||||
["Also known as dash in tibia community, recommended\nfor playing characters with high speed"] = false,
|
||||
["Ambient light: %s%%"] = false,
|
||||
["Ambient light: %s%%"] = "Swiatlo tla: %s%%",
|
||||
["Amount:"] = "Ilosc:",
|
||||
["Amount"] = false,
|
||||
["Anonymous"] = false,
|
||||
["Are you sure you want to logout?"] = false,
|
||||
["Amount"] = "Ilosc",
|
||||
["Anonymous"] = "Anonimowy",
|
||||
["Are you sure you want to logout?"] = "Czy jestes pewien, ze sie chcesz wylogowac?",
|
||||
["Attack"] = "Atak",
|
||||
["Author"] = "Autor",
|
||||
["Autoload"] = "Autoladowanie",
|
||||
@@ -59,17 +54,17 @@ locale = {
|
||||
["Banishment"] = false,
|
||||
["Banishment + Final Warning"] = false,
|
||||
["Battle"] = "Bitwa",
|
||||
["Browse"] = false,
|
||||
["Bug report sent."] = false,
|
||||
["Browse"] = "Przegladaj",
|
||||
["Bug report sent."] = "Raport o bledzie zostal wyslany.",
|
||||
["Button Assign"] = "Przypisanie Klawisza",
|
||||
["Buy"] = "Kup",
|
||||
["Buy Now"] = false,
|
||||
["Buy Offers"] = false,
|
||||
["Buy Now"] = "Kup Teraz",
|
||||
["Buy Offers"] = "Oferty Kupna",
|
||||
["Buy with backpack"] = "Kupuj z plecakami",
|
||||
["Cancel"] = "Anuluj",
|
||||
["Cannot login while already in game."] = false,
|
||||
["Cannot login while already in game."] = "Nie mozna zalogowac gdy juz w grze",
|
||||
["Cap"] = false,
|
||||
["Capacity"] = "Capacidad",
|
||||
["Capacity"] = "Ladownosc",
|
||||
["Center"] = false,
|
||||
["Channels"] = "Kanaly",
|
||||
["Character List"] = "Lista postaci",
|
||||
@@ -82,65 +77,64 @@ locale = {
|
||||
["Close this channel"] = "Zamknij kanal",
|
||||
["Club Fighting"] = "Walka obuchem",
|
||||
["Combat Controls"] = "Kontrola walki",
|
||||
["Comment:"] = false,
|
||||
["Comment:"] = "Komentarz:",
|
||||
["Connecting to game server..."] = "Laczenie z serwerem gry...",
|
||||
["Connecting to login server..."] = "Laczenie z serwerem logowania...",
|
||||
["Console"] = false,
|
||||
["Console"] = "Konsola",
|
||||
["Cooldowns"] = false,
|
||||
["Copy message"] = false,
|
||||
["Copy name"] = false,
|
||||
["Copy Name"] = "Kopiuj Nick",
|
||||
["Create Map Mark"] = false,
|
||||
["Create mark"] = false,
|
||||
["Create New Offer"] = false,
|
||||
["Create Offer"] = false,
|
||||
["Copy message"] = "Kopiuj wiadomosc",
|
||||
["Copy name"] = "Kopiuj imie",
|
||||
["Copy Name"] = "Kopiuj Imie",
|
||||
["Create Map Mark"] = "Utworz Znacznik na Mapie",
|
||||
["Create mark"] = "Utworz znacznik",
|
||||
["Create New Offer"] = "Utworz Nowa Oferte",
|
||||
["Create Offer"] = "Utworz Oferte",
|
||||
["Current hotkeys:"] = "Aktualny hotkey:",
|
||||
["Current hotkey to add: %s"] = "Aktualny hotkey do dodania: %s",
|
||||
["Current Offers"] = false,
|
||||
["Current Offers"] = "Obecne Oferty",
|
||||
["Default"] = "Domyslny",
|
||||
["Delete mark"] = false,
|
||||
["Description:"] = false,
|
||||
["Delete mark"] = "Usun znacznik",
|
||||
["Description:"] = "Opis:",
|
||||
["Description"] = "Opis",
|
||||
["Destructive Behaviour"] = false,
|
||||
["Destructive Behaviour"] = "Destrukcyjne Zachowanie",
|
||||
["Detail"] = "Szczegoly",
|
||||
["Details"] = false,
|
||||
["Details"] = "Szczegoly",
|
||||
["Disable Shared Experience"] = "Wylacz Dzielenie Doswiadczenia",
|
||||
["Dismount"] = false,
|
||||
["Display connection speed to the server (milliseconds)"] = false,
|
||||
["Display connection speed to the server (milliseconds)"] = "Wyswietl ping do serwera (ms)",
|
||||
["Distance Fighting"] = "Walka na odleglosc",
|
||||
["Don't stretch/shrink Game Window"] = false,
|
||||
["Don't stretch/shrink Game Window"] = "Nie rozszerzaj/zwezaj Okna Gry",
|
||||
["Edit hotkey text:"] = "Edytuj tresc hotkeya:",
|
||||
["Edit List"] = false,
|
||||
["Edit List"] = "Lista Edycji",
|
||||
["Edit Text"] = "Edytuj tekst",
|
||||
["Enable music"] = false,
|
||||
["Enable music"] = "Odtwarzaj muzyke",
|
||||
["Enable Shared Experience"] = "Wlacz dzielenie doswiadczenia",
|
||||
["Enable smart walking"] = false,
|
||||
["Enable vertical synchronization"] = "Wlacz synchronizacje pionowa",
|
||||
["Enable walk booster"] = false,
|
||||
["Enter Game"] = "Wejdz do gry",
|
||||
["Enter one name per line."] = false,
|
||||
["Enter with your account again to update your client."] = false,
|
||||
["Enter one name per line."] = "Wprowadz jedno imie na linie",
|
||||
["Enter with your account again to update your client."] = "Zaloguj sie ponownie by zaktualizowac klienta",
|
||||
["Error"] = "Blad",
|
||||
["Error"] = "Blad",
|
||||
["Excessive Unjustified Player Killing"] = false,
|
||||
["Excessive Unjustified Player Killing"] = "Nadmierne Nieusprawiedliwione Zabijanie Graczy",
|
||||
["Exclude from private chat"] = "Wyrzuc w prywatnej konwersacji",
|
||||
["Exit"] = false,
|
||||
["Experience"] = "Doswiadczenie",
|
||||
["Filter list to match your level"] = false,
|
||||
["Filter list to match your vocation"] = false,
|
||||
["Find:"] = false,
|
||||
["Filter list to match your level"] = "Wyswietl tylko odpowiednie dla mojego poziomu",
|
||||
["Filter list to match your vocation"] = "Wyswietl tylko odpowiednie dla mojej klasy",
|
||||
["Find:"] = "Szukaj:",
|
||||
["Fishing"] = "Wedkarstwo",
|
||||
["Fist Fighting"] = "Walka wrecz",
|
||||
["Follow"] = "Podazaj",
|
||||
["Force Exit"] = false,
|
||||
["Force Exit"] = "Wymus Zamkniecie",
|
||||
["For Your Information"] = false,
|
||||
["Free Account"] = false,
|
||||
["Free Account"] = "Darmowe Konto",
|
||||
["Fullscreen"] = "Pelen ekran",
|
||||
["Game"] = false,
|
||||
["Game framerate limit: %s"] = false,
|
||||
["Game"] = "Gra",
|
||||
["Game framerate limit: %s"] = "Limit FPS: %s",
|
||||
["Graphics"] = "Grafika",
|
||||
["Graphics card driver not detected"] = false,
|
||||
["Graphics Engine:"] = false,
|
||||
["Graphics card driver not detected"] = "Nie wykryto karty graficznej",
|
||||
["Graphics Engine:"] = "Silnik graficzny:",
|
||||
["Head"] = "Glowa",
|
||||
["Healing"] = false,
|
||||
["Health Info"] = false,
|
||||
@@ -148,43 +142,43 @@ locale = {
|
||||
["Hide monsters"] = "Ukryj potwory",
|
||||
["Hide non-skull players"] = "Ukryj graczy bez skulla",
|
||||
["Hide Npcs"] = "Ukryj NPCe",
|
||||
["Hide Offline"] = false,
|
||||
["Hide party members"] = "Ukryj czlonkow zabawy",
|
||||
["Hide Offline"] = "Ukryj Niedostepnych",
|
||||
["Hide party members"] = "Ukryj czlonkow druzyny",
|
||||
["Hide players"] = "Ukryj graczy",
|
||||
["Hide spells for higher exp. levels"] = false,
|
||||
["Hide spells for other vocations"] = false,
|
||||
["Hide spells for higher exp. levels"] = "Ukryj zaklecia wyzszych poziomow postaci",
|
||||
["Hide spells for other vocations"] = "Ukryj zaklecia innych klas",
|
||||
["Hit Points"] = "Punkty uderzen",
|
||||
["Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks"] = false,
|
||||
["Hotkeys"] = "Hotkeye",
|
||||
["If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character."] = false,
|
||||
["Ignore"] = false,
|
||||
["Ignore"] = "Ignoruj",
|
||||
["Ignore capacity"] = "Ignoruj pojemnosc",
|
||||
["Ignored players:"] = false,
|
||||
["Ignored players:"] = "Ignorowani gracze:",
|
||||
["Ignore equipped"] = "Ignoruj ekwipunek",
|
||||
["Ignore List"] = false,
|
||||
["Ignore players"] = false,
|
||||
["Ignore Private Messages"] = false,
|
||||
["Ignore Yelling"] = false,
|
||||
["Interface framerate limit: %s"] = false,
|
||||
["Inventory"] = "Inwentarz",
|
||||
["Invite to Party"] = "Zapros do zabawy",
|
||||
["Ignore List"] = "Lista Ignorowanych",
|
||||
["Ignore players"] = "Ignoruj graczy",
|
||||
["Ignore Private Messages"] = "Ignoruj Prywatne Wiadomosci",
|
||||
["Ignore Yelling"] = "Ignoruj Krzyki",
|
||||
["Interface framerate limit: %s"] = "Limit FPS interfejsu: %s",
|
||||
["Inventory"] = "Ekwipunek",
|
||||
["Invite to Party"] = "Zapros do druzyny",
|
||||
["Invite to private chat"] = "Zapros do prywatnej konwersacji",
|
||||
["IP Address Banishment"] = false,
|
||||
["Item Offers"] = false,
|
||||
["It is empty."] = false,
|
||||
["Join %s's Party"] = false,
|
||||
["Leave Party"] = "Opusc zabawe",
|
||||
["IP Address Banishment"] = "Blokada adresu IP",
|
||||
["Item Offers"] = "Oferty Przedmiotow",
|
||||
["It is empty."] = "To jest puste.",
|
||||
["Join %s's Party"] = "Dolacz do druzyny gracza %s",
|
||||
["Leave Party"] = "Opusc druzyne",
|
||||
["Level"] = "Poziom",
|
||||
["Lifetime Premium Account"] = false,
|
||||
["Lifetime Premium Account"] = "Konto Premium na Stale",
|
||||
["Limits FPS to 60"] = "Ogranicz FPS do 60",
|
||||
["List of items that you're able to buy"] = "Lista przedmiotow, ktore mozesz kupic",
|
||||
["List of items that you're able to sell"] = "Lista przedmiotow, ktore mozesz sprzedac",
|
||||
["Load"] = "Wczytaj",
|
||||
["Logging out..."] = false,
|
||||
["Logging out..."] = "Wylogowuje...",
|
||||
["Login"] = "Zaloguj",
|
||||
["Login Error"] = "Blad Logowania",
|
||||
["Login Error"] = "Blad Logowania",
|
||||
["Logout"] = false,
|
||||
["Logout"] = "Wyloguj",
|
||||
["Look"] = "Spojrz",
|
||||
["Magic Level"] = "Poziom Magiczny",
|
||||
["Make sure that your client uses\nthe correct game protocol version"] = "Upewnij sie, ze twoj klient\nuzywa wlasciwego protokolu gry.",
|
||||
@@ -193,7 +187,7 @@ locale = {
|
||||
["Market"] = false,
|
||||
["Market Offers"] = false,
|
||||
["Message of the day"] = "Wiadomosc dnia",
|
||||
["Message to "] = false,
|
||||
["Message to "] = "Wiadomosc do ",
|
||||
["Message to %s"] = "Wiadomosc do %s",
|
||||
["Minimap"] = "Minimapa",
|
||||
["Module Manager"] = "Menedzer modulow",
|
||||
@@ -201,32 +195,32 @@ locale = {
|
||||
["Mount"] = false,
|
||||
["Move Stackable Item"] = "Przenies przedmiot",
|
||||
["Move up"] = "Przenies wyzej",
|
||||
["My Offers"] = false,
|
||||
["My Offers"] = "Moje Oferty",
|
||||
["Name:"] = "Nazwa:",
|
||||
["Name Report"] = false,
|
||||
["Name Report + Banishment"] = false,
|
||||
["Name Report + Banishment + Final Warning"] = false,
|
||||
["No"] = false,
|
||||
["No"] = "Nie",
|
||||
["No graphics card detected, everything will be drawn using the CPU,\nthus the performance will be really bad.\nPlease update your graphics driver to have a better performance."] = false,
|
||||
["No item selected."] = false,
|
||||
["No Mount"] = false,
|
||||
["No Outfit"] = false,
|
||||
["No item selected."] = "Nie wybrano przedmiotu.",
|
||||
["No Mount"] = "Brak wierzchowca",
|
||||
["No Outfit"] = "Brak stroju",
|
||||
["No statement has been selected."] = false,
|
||||
["Notation"] = false,
|
||||
["NPC Trade"] = "Handel NPC",
|
||||
["Offer History"] = false,
|
||||
["Offers"] = false,
|
||||
["Offer Type:"] = false,
|
||||
["Offline Training"] = false,
|
||||
["Offer History"] = "Historia Ofert",
|
||||
["Offers"] = "Oferty",
|
||||
["Offer Type:"] = "Typ Oferty:",
|
||||
["Offline Training"] = "Trening Offline",
|
||||
["Ok"] = "Ok",
|
||||
["on %s.\n"] = false,
|
||||
["Open"] = "Otworz",
|
||||
["Open a private message channel:"] = "Otworz prywatny kanal:",
|
||||
["Open charlist automatically when starting client"] = false,
|
||||
["Open charlist automatically when starting client"] = "Automatycznie otworz liste postaci przy starcie gry",
|
||||
["Open in new window"] = "Otworz w nowym oknie",
|
||||
["Open new channel"] = "Otworz nowy kanal",
|
||||
["Options"] = "Opcje",
|
||||
["Overview"] = false,
|
||||
["Overview"] = "Podsumowanie",
|
||||
["Pass Leadership to %s"] = "Przekaz przywodztwo %s",
|
||||
["Password"] = "Haslo",
|
||||
["Piece Price:"] = false,
|
||||
@@ -236,79 +230,79 @@ locale = {
|
||||
["Please use this dialog to only report bugs. Do not report rule violations here!"] = false,
|
||||
["Please wait"] = "Prosze czekac",
|
||||
["Port"] = "Port",
|
||||
["Position:"] = false,
|
||||
["Position: %i %i %i"] = false,
|
||||
["Premium Account (%s) days left"] = false,
|
||||
["Position:"] = "Pozycja:",
|
||||
["Position: %i %i %i"] = "Pozycja: %i %i %i",
|
||||
["Premium Account (%s) days left"] = "Konto Premium (%s) dni",
|
||||
["Price:"] = "Cena:",
|
||||
["Primary"] = "Podstawowy",
|
||||
["Protocol"] = false,
|
||||
["Quest Log"] = false,
|
||||
["Protocol"] = "Protokol",
|
||||
["Quest Log"] = "Dziennik Misji",
|
||||
["Randomize"] = false,
|
||||
["Randomize characters outfit"] = false,
|
||||
["Reason:"] = false,
|
||||
["Reason:"] = "Powod:",
|
||||
["Refresh"] = "Odswiez",
|
||||
["Refresh Offers"] = false,
|
||||
["Regeneration Time"] = false,
|
||||
["Reject"] = false,
|
||||
["Refresh Offers"] = "Odswiez Oferty",
|
||||
["Regeneration Time"] = "Czas Regeneracji",
|
||||
["Reject"] = "Odrzuc",
|
||||
["Reload All"] = "Przeladuj Wszystko",
|
||||
["Remember account and password when starts client"] = false,
|
||||
["Remember account and password when starts client"] = "Zapamietaj identyfikator konta oraz haslo",
|
||||
["Remember password"] = "Zapamietaj haslo",
|
||||
["Remove"] = "Usun",
|
||||
["Remove %s"] = "Usun %s",
|
||||
["Report Bug"] = false,
|
||||
["Reserved for more functionality later."] = false,
|
||||
["Report Bug"] = "Zglos Blad",
|
||||
["Reserved for more functionality later."] = "Zarezerowane dla przyszlych funkcjonalnosci.",
|
||||
["Reset Market"] = false,
|
||||
["Revoke %s's Invitation"] = false,
|
||||
["Revoke %s's Invitation"] = "Odmow na zaproszenie gracza %s",
|
||||
["Rotate"] = "Obroc",
|
||||
["Rule Violation"] = false,
|
||||
["Save"] = false,
|
||||
["Save Messages"] = false,
|
||||
["Rule Violation"] = "Zlamanie Regul",
|
||||
["Save"] = "Zapisz",
|
||||
["Save Messages"] = "Zapisz Wiadomosci",
|
||||
["Search:"] = "Szukaj:",
|
||||
["Search all items"] = false,
|
||||
["Search all items"] = "Znajdz wszystkie przedmioty",
|
||||
["Secondary"] = "Drugorzedny",
|
||||
["Select object"] = "Wybierz obiekt",
|
||||
["Select Outfit"] = "Wybierz outfit",
|
||||
["Select your language"] = false,
|
||||
["Select your language"] = "Wybierz jezyk",
|
||||
["Sell"] = "Sprzedaj",
|
||||
["Sell Now"] = false,
|
||||
["Sell Offers"] = false,
|
||||
["Send"] = false,
|
||||
["Sell Now"] = "Sprzedaj Teraz",
|
||||
["Sell Offers"] = "Oferty Sprzedazy",
|
||||
["Send"] = "Wyslij",
|
||||
["Send automatically"] = "Wyslij automatycznie",
|
||||
["Send Message"] = false,
|
||||
["Send Message"] = "Wyslij Wiadomosc",
|
||||
["Server"] = "Serwer",
|
||||
["Server Log"] = "Log Serwera",
|
||||
["Set Outfit"] = "Ustaw outfit",
|
||||
["Shielding"] = "Obrona tarcza",
|
||||
["Show all items"] = "Pokaz wszystkie przedmioty",
|
||||
["Show connection ping"] = false,
|
||||
["Show connection ping"] = "Wyswietl ping",
|
||||
["Show Depot Only"] = false,
|
||||
["Show event messages in console"] = "Pokaz wydarzenia w konsoli",
|
||||
["Show frame rate"] = "Pokaz ilosc FPS",
|
||||
["Show frame rate"] = "Pokaz FPS",
|
||||
["Show info messages in console"] = "Pokaz informacje w konsoli",
|
||||
["Show left panel"] = false,
|
||||
["Show left panel"] = "Pokaz lewy panel",
|
||||
["Show levels in console"] = "Pokaz poziomy w konsoli",
|
||||
["Show Offline"] = false,
|
||||
["Show Offline"] = "Pokaz Niedostepnych",
|
||||
["Show private messages in console"] = "Pokaz prywatne wiadomosci w konsoli",
|
||||
["Show private messages on screen"] = false,
|
||||
["Show Server Messages"] = false,
|
||||
["Show private messages on screen"] = "Pokaz prywatne wiadomosci na ekranie",
|
||||
["Show Server Messages"] = "Pokaz Wiadomosci Serwera",
|
||||
["Show status messages in console"] = "Pokaz status w konsoli",
|
||||
["Show Text"] = false,
|
||||
["Show Text"] = "Pokaz Tekst",
|
||||
["Show timestamps in console"] = "Pokaz znaczniki czasu w konsoli",
|
||||
["Show your depot items only"] = false,
|
||||
["Skills"] = "Umiejetnosci",
|
||||
["Soul"] = false,
|
||||
["Soul"] = "Dusze",
|
||||
["Soul Points"] = "Punkty Duszy",
|
||||
["Special"] = false,
|
||||
["Speed"] = false,
|
||||
["Speed"] = "Predkosc",
|
||||
["Spell Cooldowns"] = false,
|
||||
["Spell List"] = false,
|
||||
["Spell List"] = "Lista Zaklec",
|
||||
["Stamina"] = "Wytrzymalosc",
|
||||
["Statement:"] = false,
|
||||
["Statement Report"] = false,
|
||||
["Statistics"] = false,
|
||||
["Stop Attack"] = "Zatrzymaj atak",
|
||||
["Stop Follow"] = "Zatrzymaj podazanie",
|
||||
["Support"] = false,
|
||||
["Statistics"] = "Statystki",
|
||||
["Stop Attack"] = "Anuluj atak",
|
||||
["Stop Follow"] = "Przestan podazac",
|
||||
["Support"] = "Wsparcie",
|
||||
["%s: (use object)"] = "%s: (uzyj obiekt)",
|
||||
["%s: (use object on target)"] = "%s: (uzyj obiektu na celu)",
|
||||
["%s: (use object on yourself)"] = "%s: (uzyj obiektu na sobie)",
|
||||
@@ -316,15 +310,15 @@ locale = {
|
||||
["Sword Fighting"] = "Atak mieczem",
|
||||
["Terminal"] = "Terminal",
|
||||
["There is no way."] = "Nie ma drogi.",
|
||||
["Title"] = false,
|
||||
["Total Price:"] = false,
|
||||
["Title"] = "Tytul",
|
||||
["Total Price"] = "Cena sumaryczna",
|
||||
["Trade"] = "Handel",
|
||||
["Trade with ..."] = "Handluj z ...",
|
||||
["Trying to reconnect in %s seconds."] = false,
|
||||
["Unable to load dat file, please place a valid dat in '%s'"] = false,
|
||||
["Unable to load spr file, please place a valid spr in '%s'"] = false,
|
||||
["Trying to reconnect in %s seconds."] = "Ponowna proba laczenia za %s sekund.",
|
||||
["Unable to load dat file, please place a valid dat in '%s'"] = "Nie mozna zaladowac pliku .dat z '%s'",
|
||||
["Unable to load spr file, please place a valid spr in '%s'"] = "Nie mozna zaladowac pliku .spr z '%s'",
|
||||
["Unable to logout."] = "Nie mozna sie wylogowac.",
|
||||
["Unignore"] = false,
|
||||
["Unignore"] = "Anuluj Ignorowanie",
|
||||
["Unload"] = "Wylacz",
|
||||
["Update needed"] = false,
|
||||
["Use"] = "Uzyj",
|
||||
@@ -334,42 +328,87 @@ locale = {
|
||||
["Version"] = "Wersja",
|
||||
["VIP List"] = "Lista VIP",
|
||||
["Voc."] = false,
|
||||
["Vocation"] = false,
|
||||
["Waiting List"] = false,
|
||||
["Vocation"] = "Klasa",
|
||||
["Waiting List"] = "Lista Oczekujacych",
|
||||
["Website"] = "Strona:",
|
||||
["Weight:"] = "Waga:",
|
||||
["Will detect when to use diagonal step based on the\nkeys you are pressing"] = false,
|
||||
["With crosshair"] = "Z celownikiem",
|
||||
["Yes"] = false,
|
||||
["You are bleeding"] = false,
|
||||
["Yes"] = "Tak",
|
||||
["You are bleeding"] = "Krwawisz",
|
||||
["You are burning"] = "Palisz sie",
|
||||
["You are cursed"] = "Jestes przeklety",
|
||||
["You are dazzled"] = "Jestes oslepiony",
|
||||
["You are dead."] = "Zginales marnie.",
|
||||
["You are dead"] = false,
|
||||
["You are dead"] = "Jestes martwy",
|
||||
["You are drowning"] = "Topisz sie",
|
||||
["You are drunk"] = false,
|
||||
["You are drunk"] = "Caly swiat wiruje",
|
||||
["You are electrified"] = "Jestes porazony pradem",
|
||||
["You are freezing"] = "Marzniesz",
|
||||
["You are hasted"] = "Zapieprzasz",
|
||||
["You are hungry"] = false,
|
||||
["You are hungry"] = "Burczy ci w brzuchu",
|
||||
["You are paralysed"] = "Jestes sparalizowany",
|
||||
["You are poisoned"] = "Jestes zatruty",
|
||||
["You are protected by a magic shield"] = "Jestes chroniony magiczna tarcza",
|
||||
["You are strengthened"] = "Jestes wzmocniony",
|
||||
["You are within a protection zone"] = "Jestes w strefie ochronnej",
|
||||
["You can enter new text."] = false,
|
||||
["You can enter new text."] = "Mozesz wprowadzic nowy tekst.",
|
||||
["You have %s percent"] = "Masz %s procent",
|
||||
["You have %s percent to go"] = "Brakuje Ci %s procent",
|
||||
["You may not logout during a fight"] = "Nie mozesz sie wylogowac w trakcie walki",
|
||||
["You may not logout or enter a protection zone"] = "Nie mozesz sie wylogowac ani wejsc do strefy ochronnej",
|
||||
["You must enter a comment."] = false,
|
||||
["You must enter a valid server address and port."] = false,
|
||||
["You must enter a comment."] = "Prosze wprowadzic komentarz",
|
||||
["You must enter a valid server address and port."] = "Prosze wprowadzic poprawny adres i port.",
|
||||
["You must select a character to login!"] = "Musisz wybrac postac aby sie zalogowac!",
|
||||
["Your Capacity:"] = false,
|
||||
["Your Capacity:"] = "Twoja Ladownosc:",
|
||||
["You read the following, written by \n%s\n"] = false,
|
||||
["You read the following, written on \n%s.\n"] = false,
|
||||
["Your Money:"] = false,
|
||||
["Enable dash walking"] = false,
|
||||
["Will boost your walk on high speed characters"] = "Przyspieszy poruszanie sie postaci o wysokiej predkosci",
|
||||
["Display creature names"] = "Wyswietlaj nazwy potworow",
|
||||
["Display creature health bars"] = "Wyswietlaj paski zycia potworow",
|
||||
["Display text messages"] = "Wyswietlaj wiadomosci tekstowe",
|
||||
["Change language"] = "Zmien jezyk",
|
||||
["Enable lights"] = "Odblokuj oswietlenie",
|
||||
["Enable audio"] = "Odblokuj dzwiek",
|
||||
["Enable music sound"] = "Odblokuj muzyke",
|
||||
["Music volume: %d"] = "Glosnosc muzyki: %d",
|
||||
["Audio"] = "Dzwiek",
|
||||
["Server List"] = "Lista serwerow",
|
||||
["Server list"] = "Lista serwerow",
|
||||
["Client Version"] = "Wersja klienta",
|
||||
["Add new server"] = "Dodaj nowy serwer",
|
||||
["Select"] = "Wybierz",
|
||||
["New Server"] = "Nowy serwer",
|
||||
["Host"] = false,
|
||||
["Reset All"] = "Ustaw domyslne",
|
||||
["Disable chat mode, allow to walk using ASDW"] = "Zablokuj tryb rozmow, zezwol na poruszanie sie za pomoca klawiszy ADSW",
|
||||
["Name"] = "Imie",
|
||||
["Price"] = "Cena",
|
||||
["Your Money"] = "Twoje fundusze",
|
||||
["Weight"] = "Waga",
|
||||
["Your Capacity"] = "Twoj udzwig",
|
||||
["Search"] = "Szukaj",
|
||||
["Sell All"] = "Sprzedaj wszystko",
|
||||
["Statement"] = false,
|
||||
["Reason"] = "Powod",
|
||||
["Action"] = "Akcja",
|
||||
["Comment"] = "Komentarz",
|
||||
["Balance"] = false,
|
||||
["Offer Type"] = "Typ oferty",
|
||||
["Piece Price"] = false,
|
||||
["Find"] = "Szukaj",
|
||||
["Formula"] = "Formula",
|
||||
["Group"] = "Groupa",
|
||||
["Type"] = "Typ",
|
||||
["Cooldown"] = false,
|
||||
["Premium"] = false,
|
||||
["Any"] = "Dowolny",
|
||||
["Sorcerer"] = "Czarodziej",
|
||||
["Druid"] = false,
|
||||
["Paladin"] = "Paladyn",
|
||||
["Knight"] = "Rycerz"
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -11,3 +11,9 @@ HorizontalList < UIScrollArea
|
||||
border-width: 1
|
||||
border-color: #1d222b
|
||||
background-color: #222833
|
||||
|
||||
VerticalList < UIScrollArea
|
||||
layout: verticalBox
|
||||
border-width: 1
|
||||
border-color: #1d222b
|
||||
background-color: #222833
|
2
init.lua
2
init.lua
@@ -48,7 +48,7 @@ g_modules.ensureModuleLoaded("game_interface")
|
||||
-- mods 1000-9999
|
||||
g_modules.autoLoadModules(9999)
|
||||
|
||||
local script = '/' .. g_app.getCompactName() .. 'rc.lua'
|
||||
local script = '/' .. g_app.getCompactName() .. 'rc'
|
||||
|
||||
if g_resources.fileExists(script) then
|
||||
dofile(script)
|
||||
|
10
modules/.project/modules.sublime-project
Normal file
10
modules/.project/modules.sublime-project
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"folders":
|
||||
[
|
||||
{
|
||||
"path": "..",
|
||||
"folder_exclude_patterns": [".*", "*.*~"],
|
||||
"file_exclude_patterns": [".*", "*.*~"]
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
local musicFilename = "/sounds/startup"
|
||||
local musicChannel = nil
|
||||
local musicChannel = g_sounds.getChannel(1)
|
||||
|
||||
function setMusic(filename)
|
||||
musicFilename = filename
|
||||
@@ -57,14 +57,11 @@ function init()
|
||||
onExit = exit })
|
||||
|
||||
g_window.setMinimumSize({ width = 600, height = 480 })
|
||||
|
||||
musicChannel = g_sounds.getChannel(1)
|
||||
g_sounds.preload(musicFilename)
|
||||
|
||||
-- initialize in fullscreen mode on mobile devices
|
||||
if g_app.getOs() == "android" then
|
||||
g_window.maximize()
|
||||
--g_window.setFullscreen(true)
|
||||
if g_window.getPlatformType() == "X11-EGL" then
|
||||
g_window.setFullscreen(true)
|
||||
else
|
||||
-- window size
|
||||
local size = { width = 800, height = 600 }
|
||||
@@ -107,11 +104,6 @@ function terminate()
|
||||
g_settings.set('window-size', g_window.getUnmaximizedSize())
|
||||
g_settings.set('window-pos', g_window.getUnmaximizedPos())
|
||||
g_settings.set('window-maximized', g_window.isMaximized())
|
||||
|
||||
local protocolVersion = g_game.getProtocolVersion()
|
||||
if protocolVersion ~= 0 then
|
||||
g_settings.set('protocol-version', protocolVersion)
|
||||
end
|
||||
end
|
||||
|
||||
function exit()
|
||||
|
@@ -19,4 +19,4 @@ Module
|
||||
- client_terminal
|
||||
- client_modulemanager
|
||||
- client_serverlist
|
||||
//- client_stats
|
||||
- client_stats
|
||||
|
@@ -6,7 +6,7 @@ local enterGame
|
||||
local motdWindow
|
||||
local motdButton
|
||||
local enterGameButton
|
||||
local protocolBox
|
||||
local clientBox
|
||||
local protocolLogin
|
||||
local motdEnabled = true
|
||||
|
||||
@@ -73,11 +73,6 @@ local function onCharacterList(protocol, characters, account, otui)
|
||||
end
|
||||
end
|
||||
|
||||
local function onChangeProtocol(combobox, option)
|
||||
local clients = g_game.getSupportedClients(option)
|
||||
protocolBox:setTooltip("Supports Client" .. (#clients > 1 and "s" or "") .. ": " .. table.tostring(clients))
|
||||
end
|
||||
|
||||
local function onUpdateNeeded(protocol, signature)
|
||||
loadBox:destroy()
|
||||
loadBox = nil
|
||||
@@ -109,7 +104,8 @@ function EnterGame.init()
|
||||
local host = g_settings.get('host')
|
||||
local port = g_settings.get('port')
|
||||
local autologin = g_settings.getBoolean('autologin')
|
||||
local protocolVersion = g_settings.getInteger('protocol-version')
|
||||
local clientVersion = g_settings.getInteger('client-version')
|
||||
if clientVersion == 0 then clientVersion = 860 end
|
||||
|
||||
if port == nil or port == 0 then port = 7171 end
|
||||
|
||||
@@ -120,11 +116,11 @@ function EnterGame.init()
|
||||
enterGame:getChildById('serverPortTextEdit'):setText(port)
|
||||
enterGame:getChildById('autoLoginBox'):setChecked(autologin)
|
||||
|
||||
protocolBox = enterGame:getChildById('protocolComboBox')
|
||||
protocolBox.onOptionChange = onChangeProtocol
|
||||
if protocolVersion then
|
||||
protocolBox:setCurrentOption(protocolVersion)
|
||||
clientBox = enterGame:getChildById('clientComboBox')
|
||||
for _, proto in pairs(g_game.getSupportedClients()) do
|
||||
clientBox:addOption(proto)
|
||||
end
|
||||
clientBox:setCurrentOption(clientVersion)
|
||||
|
||||
enterGame:hide()
|
||||
|
||||
@@ -154,7 +150,7 @@ function EnterGame.terminate()
|
||||
enterGame = nil
|
||||
enterGameButton:destroy()
|
||||
enterGameButton = nil
|
||||
protocolBox = nil
|
||||
clientBox = nil
|
||||
if motdWindow then
|
||||
motdWindow:destroy()
|
||||
motdWindow = nil
|
||||
@@ -218,8 +214,7 @@ function EnterGame.doLogin()
|
||||
G.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
|
||||
G.host = enterGame:getChildById('serverHostTextEdit'):getText()
|
||||
G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText())
|
||||
local protocolVersion = tonumber(protocolBox:getText())
|
||||
local clientVersions = g_game.getSupportedClients(protocolVersion)
|
||||
local clientVersion = tonumber(clientBox:getText())
|
||||
EnterGame.hide()
|
||||
|
||||
if g_game.isOnline() then
|
||||
@@ -230,6 +225,7 @@ function EnterGame.doLogin()
|
||||
|
||||
g_settings.set('host', G.host)
|
||||
g_settings.set('port', G.port)
|
||||
g_settings.set('client-version', clientVersion)
|
||||
|
||||
protocolLogin = ProtocolLogin.create()
|
||||
protocolLogin.onLoginError = onError
|
||||
@@ -245,10 +241,8 @@ function EnterGame.doLogin()
|
||||
end })
|
||||
|
||||
g_game.chooseRsa(G.host)
|
||||
g_game.setProtocolVersion(protocolVersion)
|
||||
if #clientVersions > 0 then
|
||||
g_game.setClientVersion(clientVersions[#clientVersions])
|
||||
end
|
||||
g_game.setClientVersion(clientVersion)
|
||||
g_game.setProtocolVersion(g_game.getProtocolVersionForClient(clientVersion))
|
||||
|
||||
if modules.game_things.isLoaded() then
|
||||
protocolLogin:login(G.host, G.port, G.account, G.password)
|
||||
@@ -269,14 +263,14 @@ end
|
||||
function EnterGame.setDefaultServer(host, port, protocol)
|
||||
local hostTextEdit = enterGame:getChildById('serverHostTextEdit')
|
||||
local portTextEdit = enterGame:getChildById('serverPortTextEdit')
|
||||
local protocolLabel = enterGame:getChildById('protocolLabel')
|
||||
local clientLabel = enterGame:getChildById('clientLabel')
|
||||
local accountTextEdit = enterGame:getChildById('accountNameTextEdit')
|
||||
local passwordTextEdit = enterGame:getChildById('accountPasswordTextEdit')
|
||||
|
||||
if hostTextEdit:getText() ~= host then
|
||||
hostTextEdit:setText(host)
|
||||
portTextEdit:setText(port)
|
||||
protocolBox:setCurrentOption(protocol)
|
||||
clientBox:setCurrentOption(protocol)
|
||||
accountTextEdit:setText('')
|
||||
passwordTextEdit:setText('')
|
||||
end
|
||||
@@ -292,9 +286,9 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
|
||||
portTextEdit:setVisible(false)
|
||||
portTextEdit:setHeight(0)
|
||||
|
||||
protocolBox:setCurrentOption(protocol)
|
||||
protocolBox:setVisible(false)
|
||||
protocolBox:setHeight(0)
|
||||
clientBox:setCurrentOption(protocol)
|
||||
clientBox:setVisible(false)
|
||||
clientBox:setHeight(0)
|
||||
|
||||
local serverLabel = enterGame:getChildById('serverLabel')
|
||||
serverLabel:setVisible(false)
|
||||
@@ -302,9 +296,9 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
|
||||
local portLabel = enterGame:getChildById('portLabel')
|
||||
portLabel:setVisible(false)
|
||||
portLabel:setHeight(0)
|
||||
local protocolLabel = enterGame:getChildById('protocolLabel')
|
||||
protocolLabel:setVisible(false)
|
||||
protocolLabel:setHeight(0)
|
||||
local clientLabel = enterGame:getChildById('clientLabel')
|
||||
clientLabel:setVisible(false)
|
||||
clientLabel:setHeight(0)
|
||||
|
||||
local serverListButton = enterGame:getChildById('serverListButton')
|
||||
serverListButton:setVisible(false)
|
||||
|
@@ -68,7 +68,7 @@ EnterGameWindow
|
||||
|
||||
TextEdit
|
||||
id: serverHostTextEdit
|
||||
!tooltip: tr('Make sure that your client uses\nthe correct game protocol version')
|
||||
!tooltip: tr('Make sure that your client uses\nthe correct game client version')
|
||||
anchors.left: parent.left
|
||||
anchors.right: serverListButton.left
|
||||
anchors.top: serverLabel.bottom
|
||||
@@ -76,8 +76,8 @@ EnterGameWindow
|
||||
margin-right: 4
|
||||
|
||||
MenuLabel
|
||||
id: protocolLabel
|
||||
!text: tr('Protocol')
|
||||
id: clientLabel
|
||||
!text: tr('Client Version')
|
||||
anchors.left: parent.left
|
||||
anchors.top: serverHostTextEdit.bottom
|
||||
text-auto-resize: true
|
||||
@@ -85,17 +85,13 @@ EnterGameWindow
|
||||
margin-top: 8
|
||||
|
||||
ComboBox
|
||||
id: protocolComboBox
|
||||
id: clientComboBox
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.horizontalCenter
|
||||
anchors.top: protocolLabel.bottom
|
||||
anchors.top: clientLabel.bottom
|
||||
margin-top: 2
|
||||
margin-right: 3
|
||||
width: 90
|
||||
@onSetup: |
|
||||
for _, proto in pairs(g_game.getSupportedProtocols()) do
|
||||
self:addOption(proto)
|
||||
end
|
||||
|
||||
MenuLabel
|
||||
id: portLabel
|
||||
@@ -110,7 +106,7 @@ EnterGameWindow
|
||||
text: 7171
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.top: protocolComboBox.top
|
||||
anchors.top: clientComboBox.top
|
||||
margin-left: 3
|
||||
|
||||
CheckBox
|
||||
|
@@ -137,7 +137,7 @@ function unloadCurrentModule()
|
||||
local module = g_modules.getModule(focusedChild:getText())
|
||||
if module then
|
||||
module:unload()
|
||||
if ModuleManager == nil then return end
|
||||
if modules.client_modulemanager == nil then return end
|
||||
updateModuleInfo(module:getName())
|
||||
refreshLoadedModules()
|
||||
end
|
||||
|
@@ -40,13 +40,17 @@ Panel
|
||||
!text: tr('Fullscreen')
|
||||
tooltip: Ctrl+Shift+F
|
||||
|
||||
OptionCheckBox
|
||||
id: dontStretchShrink
|
||||
!text: tr('Don\'t stretch/shrink Game Window')
|
||||
|
||||
Label
|
||||
id: backgroundFrameRateLabel
|
||||
!text: tr('Game framerate limit: %s', 'max')
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 6
|
||||
margin-top: 12
|
||||
@onSetup: |
|
||||
local value = modules.client_options.getOption('backgroundFrameRate')
|
||||
local text = value
|
||||
|
@@ -25,7 +25,8 @@ local defaultOptions = {
|
||||
ambientLight = 25,
|
||||
displayNames = true,
|
||||
displayHealth = true,
|
||||
displayText = true
|
||||
displayText = true,
|
||||
dontStretchShrink = false
|
||||
}
|
||||
|
||||
local optionsWindow
|
||||
@@ -223,6 +224,10 @@ function setOption(key, value, force)
|
||||
gameMapPanel:setDrawHealthBars(value)
|
||||
elseif key == 'displayText' then
|
||||
gameMapPanel:setDrawTexts(value)
|
||||
elseif key == 'dontStretchShrink' then
|
||||
addEvent(function()
|
||||
modules.game_interface.updateStretchShrink()
|
||||
end)
|
||||
end
|
||||
|
||||
-- change value for keybind updates
|
||||
|
@@ -49,7 +49,7 @@ MainWindow
|
||||
anchors.left: protocolLabel.left
|
||||
anchors.right: port.right
|
||||
@onSetup: |
|
||||
for _, proto in pairs(g_game.getSupportedProtocols()) do
|
||||
for _, proto in pairs(g_game.getSupportedClients()) do
|
||||
self:addOption(proto)
|
||||
end
|
||||
|
||||
|
@@ -257,11 +257,14 @@ function flushLines()
|
||||
for _,line in pairs(cachedLines) do
|
||||
-- delete old lines if needed
|
||||
if numLines > MaxLogLines then
|
||||
local len = #terminalBuffer:getChildByIndex(1):getText()
|
||||
terminalBuffer:getChildByIndex(1):destroy()
|
||||
local firstChild = terminalBuffer:getChildByIndex(1)
|
||||
if firstChild then
|
||||
local len = #firstChild:getText()
|
||||
firstChild:destroy()
|
||||
table.remove(allLines, 1)
|
||||
fulltext = string.sub(fulltext, len)
|
||||
end
|
||||
end
|
||||
|
||||
local label = g_ui.createWidget('TerminalLabel', terminalBuffer)
|
||||
label:setId('terminalLabel' .. numLines)
|
||||
@@ -285,6 +288,7 @@ function addLine(text, color)
|
||||
flushEvent = scheduleEvent(flushLines, 10)
|
||||
end
|
||||
|
||||
text = string.gsub(text, '\t', ' ')
|
||||
table.insert(cachedLines, {text=text, color=color})
|
||||
end
|
||||
|
||||
|
@@ -157,14 +157,14 @@ function g_keyboard.unbindKeyDown(keyComboDesc, arg1, arg2)
|
||||
disconnect(widget.boundKeyDownCombos, keyComboDesc, callback)
|
||||
end
|
||||
|
||||
function g_keyboard.unbindKeyUp(keyComboDesc, widget)
|
||||
function g_keyboard.unbindKeyUp(keyComboDesc, arg1, arg2)
|
||||
local callback, widget = getUnbindArgs(arg1, arg2)
|
||||
if widget.boundKeyUpCombos == nil then return end
|
||||
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
|
||||
disconnect(widget.boundKeyUpCombos, keyComboDesc, callback)
|
||||
end
|
||||
|
||||
function g_keyboard.unbindKeyPress(keyComboDesc, widget, callback)
|
||||
function g_keyboard.unbindKeyPress(keyComboDesc, arg1, arg2)
|
||||
local callback, widget = getUnbindArgs(arg1, arg2)
|
||||
if widget.boundKeyPressCombos == nil then return end
|
||||
local keyComboDesc = retranslateKeyComboDesc(keyComboDesc)
|
||||
|
@@ -20,8 +20,8 @@ function string:starts(start)
|
||||
return string.sub(self, 1, #start) == start
|
||||
end
|
||||
|
||||
function string.ends(s, test)
|
||||
return test =='' or string.sub(s,-string.len(test)) == test
|
||||
function string:ends(test)
|
||||
return test =='' or string.sub(self,-string.len(test)) == test
|
||||
end
|
||||
|
||||
function string:trim()
|
||||
|
@@ -110,7 +110,9 @@ function UITabBar:selectTab(tab)
|
||||
tab:setOn(false)
|
||||
|
||||
local parent = tab:getParent()
|
||||
if parent then
|
||||
parent:focusChild(tab, MouseFocusReason)
|
||||
end
|
||||
end
|
||||
|
||||
function UITabBar:selectNextTab()
|
||||
|
@@ -1,11 +1,16 @@
|
||||
battleWindow = nil
|
||||
battleButton = nil
|
||||
battlePanel = nil
|
||||
filterPanel = nil
|
||||
toggleFilterButton = nil
|
||||
lastBattleButtonSwitched = nil
|
||||
battleButtonsByCreaturesList = {}
|
||||
creatureAgeList = {}
|
||||
|
||||
mouseWidget = nil
|
||||
|
||||
sortTypeBox = nil
|
||||
sortOrderBox = nil
|
||||
hidePlayersButton = nil
|
||||
hideNPCsButton = nil
|
||||
hideMonstersButton = nil
|
||||
@@ -25,6 +30,15 @@ function init()
|
||||
|
||||
battlePanel = battleWindow:recursiveGetChildById('battlePanel')
|
||||
|
||||
filterPanel = battleWindow:recursiveGetChildById('filterPanel')
|
||||
toggleFilterButton = battleWindow:recursiveGetChildById('toggleFilterButton')
|
||||
|
||||
if isHidingFilters() then
|
||||
hideFilterPanel()
|
||||
end
|
||||
|
||||
sortTypeBox = battleWindow:recursiveGetChildById('sortTypeBox')
|
||||
sortOrderBox = battleWindow:recursiveGetChildById('sortOrderBox')
|
||||
hidePlayersButton = battleWindow:recursiveGetChildById('hidePlayers')
|
||||
hideNPCsButton = battleWindow:recursiveGetChildById('hideNPCs')
|
||||
hideMonstersButton = battleWindow:recursiveGetChildById('hideMonsters')
|
||||
@@ -38,6 +52,18 @@ function init()
|
||||
|
||||
battleWindow:setContentMinimumHeight(80)
|
||||
|
||||
sortTypeBox:addOption('Name', 'name')
|
||||
sortTypeBox:addOption('Distance', 'distance')
|
||||
sortTypeBox:addOption('Age', 'age')
|
||||
sortTypeBox:addOption('Health', 'health')
|
||||
sortTypeBox:setCurrentOptionByData(getSortType())
|
||||
sortTypeBox.onOptionChange = onChangeSortType
|
||||
|
||||
sortOrderBox:addOption('Asc.', 'asc')
|
||||
sortOrderBox:addOption('Desc.', 'desc')
|
||||
sortOrderBox:setCurrentOptionByData(getSortOrder())
|
||||
sortOrderBox.onOptionChange = onChangeSortOrder
|
||||
|
||||
connect(Creature, {
|
||||
onSkullChange = updateCreatureSkull,
|
||||
onEmblemChange = updateCreatureEmblem,
|
||||
@@ -48,6 +74,10 @@ function init()
|
||||
onDisappear = onCreatureDisappear
|
||||
})
|
||||
|
||||
connect(LocalPlayer, {
|
||||
onPositionChange = onCreaturePositionChange
|
||||
})
|
||||
|
||||
connect(g_game, {
|
||||
onAttackingCreatureChange = onAttack,
|
||||
onFollowingCreatureChange = onFollow,
|
||||
@@ -75,6 +105,10 @@ function terminate()
|
||||
onDisappear = onCreatureDisappear
|
||||
})
|
||||
|
||||
disconnect(LocalPlayer, {
|
||||
onPositionChange = onCreaturePositionChange
|
||||
})
|
||||
|
||||
disconnect(g_game, {
|
||||
onAttackingCreatureChange = onAttack,
|
||||
onFollowingCreatureChange = onFollow,
|
||||
@@ -96,6 +130,93 @@ function onMiniWindowClose()
|
||||
battleButton:setOn(false)
|
||||
end
|
||||
|
||||
function getSortType()
|
||||
local settings = g_settings.getNode('BattleList')
|
||||
if not settings then
|
||||
return 'name'
|
||||
end
|
||||
return settings['sortType']
|
||||
end
|
||||
|
||||
function setSortType(state)
|
||||
settings = {}
|
||||
settings['sortType'] = state
|
||||
g_settings.mergeNode('BattleList', settings)
|
||||
|
||||
checkCreatures()
|
||||
end
|
||||
|
||||
function getSortOrder()
|
||||
local settings = g_settings.getNode('BattleList')
|
||||
if not settings then
|
||||
return 'asc'
|
||||
end
|
||||
return settings['sortOrder']
|
||||
end
|
||||
|
||||
function setSortOrder(state)
|
||||
settings = {}
|
||||
settings['sortOrder'] = state
|
||||
g_settings.mergeNode('BattleList', settings)
|
||||
|
||||
checkCreatures()
|
||||
end
|
||||
|
||||
function isSortAsc()
|
||||
return getSortOrder() == 'asc'
|
||||
end
|
||||
|
||||
function isSortDesc()
|
||||
return getSortOrder() == 'desc'
|
||||
end
|
||||
|
||||
function isHidingFilters()
|
||||
local settings = g_settings.getNode('BattleList')
|
||||
if not settings then
|
||||
return false
|
||||
end
|
||||
return settings['hidingFilters']
|
||||
end
|
||||
|
||||
function setHidingFilters(state)
|
||||
settings = {}
|
||||
settings['hidingFilters'] = state
|
||||
g_settings.mergeNode('BattleList', settings)
|
||||
end
|
||||
|
||||
function hideFilterPanel()
|
||||
filterPanel.originalHeight = filterPanel:getHeight()
|
||||
filterPanel:setHeight(0)
|
||||
toggleFilterButton:getParent():setMarginTop(0)
|
||||
toggleFilterButton:setImageClip(torect("0 0 21 12"))
|
||||
setHidingFilters(true)
|
||||
filterPanel:setVisible(false)
|
||||
end
|
||||
|
||||
function showFilterPanel()
|
||||
toggleFilterButton:getParent():setMarginTop(5)
|
||||
filterPanel:setHeight(filterPanel.originalHeight)
|
||||
toggleFilterButton:setImageClip(torect("21 0 21 12"))
|
||||
setHidingFilters(false)
|
||||
filterPanel:setVisible(true)
|
||||
end
|
||||
|
||||
function toggleFilterPanel()
|
||||
if filterPanel:isVisible() then
|
||||
hideFilterPanel()
|
||||
else
|
||||
showFilterPanel()
|
||||
end
|
||||
end
|
||||
|
||||
function onChangeSortType(comboBox, option)
|
||||
setSortType(option:lower())
|
||||
end
|
||||
|
||||
function onChangeSortOrder(comboBox, option)
|
||||
setSortOrder(option:lower():gsub('[.]', '')) -- Replace dot in option name
|
||||
end
|
||||
|
||||
function checkCreatures()
|
||||
removeAllCreatures()
|
||||
|
||||
@@ -151,15 +272,42 @@ end
|
||||
function onCreatureHealthPercentChange(creature, health)
|
||||
local battleButton = battleButtonsByCreaturesList[creature:getId()]
|
||||
if battleButton then
|
||||
if getSortType() == 'health' then
|
||||
removeCreature(creature)
|
||||
addCreature(creature)
|
||||
return
|
||||
end
|
||||
battleButton:setLifeBarPercent(creature:getHealthPercent())
|
||||
end
|
||||
end
|
||||
|
||||
local function getDistanceBetween(p1, p2)
|
||||
return math.max(math.abs(p1.x - p2.x), math.abs(p1.y - p2.y))
|
||||
end
|
||||
|
||||
function onCreaturePositionChange(creature, newPos, oldPos)
|
||||
if creature:isLocalPlayer() then
|
||||
if oldPos and newPos and newPos.z ~= oldPos.z then
|
||||
checkCreatures()
|
||||
else
|
||||
-- Distance will change when moving, recalculate and move to correct index
|
||||
if getSortType() == 'distance' then
|
||||
local distanceList = {}
|
||||
for id, creatureButton in pairs(battleButtonsByCreaturesList) do
|
||||
table.insert(distanceList, {distance = getDistanceBetween(newPos, creatureButton.creature:getPosition()), widget = creatureButton})
|
||||
end
|
||||
|
||||
if isSortAsc() then
|
||||
table.sort(distanceList, function(a, b) return a.distance < b.distance end)
|
||||
else
|
||||
table.sort(distanceList, function(a, b) return a.distance > b.distance end)
|
||||
end
|
||||
|
||||
for i = 1, #distanceList do
|
||||
battlePanel:moveChildToIndex(distanceList[i].widget, i)
|
||||
end
|
||||
end
|
||||
|
||||
for id, creatureButton in pairs(battleButtonsByCreaturesList) do
|
||||
addCreature(creatureButton.creature)
|
||||
end
|
||||
@@ -170,6 +318,9 @@ function onCreaturePositionChange(creature, newPos, oldPos)
|
||||
if has and not fit then
|
||||
removeCreature(creature)
|
||||
elseif fit then
|
||||
if has and getSortType() == 'distance' then
|
||||
removeCreature(creature)
|
||||
end
|
||||
addCreature(creature)
|
||||
end
|
||||
end
|
||||
@@ -201,8 +352,13 @@ function addCreature(creature)
|
||||
local creatureId = creature:getId()
|
||||
local battleButton = battleButtonsByCreaturesList[creatureId]
|
||||
|
||||
-- Register when creature is added to battlelist for the first time
|
||||
if not creatureAgeList[creatureId] then
|
||||
creatureAgeList[creatureId] = os.time()
|
||||
end
|
||||
|
||||
if not battleButton then
|
||||
battleButton = g_ui.createWidget('BattleButton', battlePanel)
|
||||
battleButton = g_ui.createWidget('BattleButton')
|
||||
battleButton:setup(creature)
|
||||
|
||||
battleButton.onHoverChange = onBattleButtonHoverChange
|
||||
@@ -217,6 +373,77 @@ function addCreature(creature)
|
||||
if creature == g_game.getFollowingCreature() then
|
||||
onFollow(creature)
|
||||
end
|
||||
|
||||
local inserted = false
|
||||
local nameLower = creature:getName():lower()
|
||||
local healthPercent = creature:getHealthPercent()
|
||||
local playerPosition = g_game.getLocalPlayer():getPosition()
|
||||
local distance = getDistanceBetween(playerPosition, creature:getPosition())
|
||||
local age = creatureAgeList[creatureId]
|
||||
|
||||
local childCount = battlePanel:getChildCount()
|
||||
for i = 1, childCount do
|
||||
local child = battlePanel:getChildByIndex(i)
|
||||
local childName = child:getCreature():getName():lower()
|
||||
local equal = false
|
||||
if getSortType() == 'age' then
|
||||
local childAge = creatureAgeList[child:getCreature():getId()]
|
||||
if (age < childAge and isSortAsc()) or (age > childAge and isSortDesc()) then
|
||||
battlePanel:insertChild(i, battleButton)
|
||||
inserted = true
|
||||
break
|
||||
elseif age == childAge then
|
||||
equal = true
|
||||
end
|
||||
elseif getSortType() == 'distance' then
|
||||
local childDistance = getDistanceBetween(child:getCreature():getPosition(), playerPosition)
|
||||
if (distance < childDistance and isSortAsc()) or (distance > childDistance and isSortDesc()) then
|
||||
battlePanel:insertChild(i, battleButton)
|
||||
inserted = true
|
||||
break
|
||||
elseif childDistance == distance then
|
||||
equal = true
|
||||
end
|
||||
elseif getSortType() == 'health' then
|
||||
local childHealth = child:getCreature():getHealthPercent()
|
||||
if (healthPercent < childHealth and isSortAsc()) or (healthPercent > childHealth and isSortDesc()) then
|
||||
battlePanel:insertChild(i, battleButton)
|
||||
inserted = true
|
||||
break
|
||||
elseif healthPercent == childHealth then
|
||||
equal = true
|
||||
end
|
||||
end
|
||||
|
||||
-- If any other sort type is selected and values are equal, sort it by name also
|
||||
if getSortType() == 'name' or equal then
|
||||
local length = math.min(childName:len(), nameLower:len())
|
||||
for j=1,length do
|
||||
if (nameLower:byte(j) < childName:byte(j) and isSortAsc()) or (nameLower:byte(j) > childName:byte(j) and isSortDesc()) then
|
||||
battlePanel:insertChild(i, battleButton)
|
||||
inserted = true
|
||||
break
|
||||
elseif (nameLower:byte(j) > childName:byte(j) and isSortAsc()) or (nameLower:byte(j) < childName:byte(j) and isSortDesc()) then
|
||||
break
|
||||
elseif j == nameLower:len() and isSortAsc() then
|
||||
battlePanel:insertChild(i, battleButton)
|
||||
inserted = true
|
||||
elseif j == childName:len() and isSortDesc() then
|
||||
battlePanel:insertChild(i, battleButton)
|
||||
inserted = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if inserted then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Insert at the end if no other place is found
|
||||
if not inserted then
|
||||
battlePanel:insertChild(childCount + 1, battleButton)
|
||||
end
|
||||
else
|
||||
battleButton:setLifeBarPercent(creature:getHealthPercent())
|
||||
end
|
||||
@@ -226,6 +453,7 @@ function addCreature(creature)
|
||||
end
|
||||
|
||||
function removeAllCreatures()
|
||||
creatureAgeList = {}
|
||||
for i, v in pairs(battleButtonsByCreaturesList) do
|
||||
removeCreature(v.creature)
|
||||
end
|
||||
|
@@ -45,11 +45,12 @@ MiniWindow
|
||||
&save: true
|
||||
|
||||
Panel
|
||||
id: filterPanel
|
||||
margin-top: 26
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: miniwindowScrollBar.left
|
||||
height: 20
|
||||
height: 45
|
||||
|
||||
Panel
|
||||
anchors.top: parent.top
|
||||
@@ -85,16 +86,56 @@ MiniWindow
|
||||
!tooltip: tr('Hide party members')
|
||||
@onCheckChange: modules.game_battle.checkCreatures()
|
||||
|
||||
HorizontalSeparator
|
||||
Panel
|
||||
anchors.top: prev.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
height: 20
|
||||
width: 128
|
||||
margin-top: 6
|
||||
|
||||
ComboBox
|
||||
id: sortTypeBox
|
||||
width: 74
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
margin-left: -28
|
||||
|
||||
ComboBox
|
||||
id: sortOrderBox
|
||||
width: 54
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
margin-left: 4
|
||||
|
||||
Panel
|
||||
height: 18
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: miniwindowScrollBar.left
|
||||
margin-top: 5
|
||||
|
||||
UIWidget
|
||||
id: toggleFilterButton
|
||||
anchors.top: prev.top
|
||||
width: 21
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
image-source: /images/ui/arrow_vertical
|
||||
image-rect: 0 0 21 12
|
||||
image-clip: 21 0 21 12
|
||||
@onClick: modules.game_battle.toggleFilterPanel()
|
||||
phantom: false
|
||||
|
||||
HorizontalSeparator
|
||||
anchors.top: prev.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: miniwindowScrollBar.left
|
||||
margin-right: 1
|
||||
margin-top: 4
|
||||
margin-top: 11
|
||||
|
||||
MiniWindowContents
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 0
|
||||
margin-top: 6
|
||||
|
||||
Panel
|
||||
id: battlePanel
|
||||
|
206
modules/game_console/communicationwindow.otui
Normal file
206
modules/game_console/communicationwindow.otui
Normal file
@@ -0,0 +1,206 @@
|
||||
IgnoreListLabel < Label
|
||||
font: verdana-11px-monochrome
|
||||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
phantom: false
|
||||
|
||||
$focus:
|
||||
background-color: #ffffff22
|
||||
color: #ffffff
|
||||
|
||||
WhiteListLabel < Label
|
||||
font: verdana-11px-monochrome
|
||||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
phantom: false
|
||||
|
||||
$focus:
|
||||
background-color: #ffffff22
|
||||
color: #ffffff
|
||||
|
||||
|
||||
MainWindow
|
||||
id: communicationWindow
|
||||
!text: tr('Ignore List')
|
||||
size: 515 410
|
||||
@onEscape: self:destroy()
|
||||
|
||||
CheckBox
|
||||
id: checkboxUseIgnoreList
|
||||
!text: tr('Activate ignorelist')
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
width: 180
|
||||
|
||||
Label
|
||||
!text: tr('Ignored Players:')
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 10
|
||||
|
||||
TextList
|
||||
id: ignoreList
|
||||
vertical-scrollbar: ignoreListScrollBar
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
height: 150
|
||||
width: 230
|
||||
margin-bottom: 10
|
||||
margin-top: 3
|
||||
padding: 1
|
||||
focusable: false
|
||||
|
||||
TextEdit
|
||||
id: ignoreNameEdit
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
width: 110
|
||||
margin-top: 5
|
||||
|
||||
Button
|
||||
id: buttonIgnoreAdd
|
||||
!text: tr('Add')
|
||||
width: 48
|
||||
height: 20
|
||||
margin-left: 5
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
|
||||
Button
|
||||
id: buttonIgnoreRemove
|
||||
!text: tr('Remove')
|
||||
width: 64
|
||||
height: 20
|
||||
margin-left: 5
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
|
||||
Label
|
||||
!text: tr('Global ignore settings')
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 20
|
||||
|
||||
CheckBox
|
||||
id: checkboxIgnorePrivateMessages
|
||||
!text: tr('Ignore Private Messages')
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
width: 180
|
||||
margin-top: 5
|
||||
|
||||
CheckBox
|
||||
id: checkboxIgnoreYelling
|
||||
!text: tr('Ignore Yelling')
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
width: 180
|
||||
margin-top: 5
|
||||
|
||||
CheckBox
|
||||
id: checkboxUseWhiteList
|
||||
!text: tr('Activate whitelist')
|
||||
anchors.top: parent.top
|
||||
anchors.left: ignoreList.right
|
||||
margin-left: 20
|
||||
width: 180
|
||||
|
||||
Label
|
||||
!text: tr('Allowed Players:')
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
margin-top: 10
|
||||
|
||||
TextList
|
||||
id: whiteList
|
||||
vertical-scrollbar: whiteListScrollBar
|
||||
anchors.left: prev.left
|
||||
anchors.top: prev.bottom
|
||||
height: 150
|
||||
width: 230
|
||||
margin-bottom: 10
|
||||
margin-top: 3
|
||||
padding: 1
|
||||
focusable: false
|
||||
|
||||
TextEdit
|
||||
id: whitelistNameEdit
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
width: 110
|
||||
margin-top: 5
|
||||
|
||||
Button
|
||||
id: buttonWhitelistAdd
|
||||
!text: tr('Add')
|
||||
width: 48
|
||||
height: 20
|
||||
margin-left: 5
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
|
||||
Button
|
||||
id: buttonWhitelistRemove
|
||||
!text: tr('Remove')
|
||||
width: 64
|
||||
height: 20
|
||||
margin-left: 5
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
|
||||
Label
|
||||
!text: tr('Global whitelist settings')
|
||||
anchors.left: whiteList.left
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 20
|
||||
|
||||
CheckBox
|
||||
id: checkboxAllowVIPs
|
||||
!text: tr('Allow VIPs to message you')
|
||||
anchors.left: prev.left
|
||||
anchors.top: prev.bottom
|
||||
width: 180
|
||||
margin-top: 5
|
||||
|
||||
Panel
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 30
|
||||
|
||||
Panel
|
||||
size: 160 30
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
Button
|
||||
id: buttonSave
|
||||
!text: tr('Save')
|
||||
width: 75
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
||||
Button
|
||||
id: buttonCancel
|
||||
!text: tr('Cancel')
|
||||
width: 75
|
||||
anchors.top: parent.top
|
||||
anchors.left: prev.right
|
||||
margin-left: 10
|
||||
|
||||
VerticalScrollBar
|
||||
id: ignoreListScrollBar
|
||||
anchors.top: ignoreList.top
|
||||
anchors.bottom: ignoreList.bottom
|
||||
anchors.right: ignoreList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
||||
|
||||
VerticalScrollBar
|
||||
id: whiteListScrollBar
|
||||
anchors.top: whiteList.top
|
||||
anchors.bottom: whiteList.bottom
|
||||
anchors.right: whiteList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
@@ -61,7 +61,7 @@ consoleTabBar = nil
|
||||
consoleTextEdit = nil
|
||||
channels = nil
|
||||
channelsWindow = nil
|
||||
ignoreWindow = nil
|
||||
communicationWindow = nil
|
||||
ownPrivateName = nil
|
||||
messageHistory = {}
|
||||
currentMessageIndex = 0
|
||||
@@ -74,10 +74,14 @@ violationReportTab = nil
|
||||
ignoredChannels = {}
|
||||
filters = {}
|
||||
|
||||
local ignoreSettings = {
|
||||
local communicationSettings = {
|
||||
useIgnoreList = true,
|
||||
useWhiteList = true,
|
||||
privateMessages = false,
|
||||
yelling = false,
|
||||
players = {}
|
||||
allowVIPs = false,
|
||||
ignoredPlayers = {},
|
||||
whitelistedPlayers = {}
|
||||
}
|
||||
|
||||
function init()
|
||||
@@ -140,9 +144,58 @@ function init()
|
||||
g_keyboard.bindKeyDown('Ctrl+E', removeCurrentTab)
|
||||
g_keyboard.bindKeyDown('Ctrl+H', openHelp)
|
||||
|
||||
consoleToggleChat = consolePanel:getChildById('toggleChat')
|
||||
load()
|
||||
end
|
||||
|
||||
function toggleChat()
|
||||
if consoleToggleChat:isChecked() then
|
||||
disableChat()
|
||||
else
|
||||
enableChat()
|
||||
end
|
||||
end
|
||||
|
||||
function enableChat()
|
||||
local gameInterface = modules.game_interface
|
||||
|
||||
consoleTextEdit:setVisible(true)
|
||||
consoleTextEdit:setText("")
|
||||
|
||||
g_keyboard.unbindKeyUp("Space")
|
||||
g_keyboard.unbindKeyUp("Enter")
|
||||
|
||||
gameInterface.unbindWalkKey("W")
|
||||
gameInterface.unbindWalkKey("D")
|
||||
gameInterface.unbindWalkKey("S")
|
||||
gameInterface.unbindWalkKey("A")
|
||||
|
||||
consoleToggleChat:setTooltip(tr("Disable chat mode, allow to walk using ASDW"))
|
||||
end
|
||||
|
||||
function disableChat()
|
||||
local gameInterface = modules.game_interface
|
||||
|
||||
consoleTextEdit:setVisible(false)
|
||||
consoleTextEdit:setText("")
|
||||
|
||||
local quickFunc = function()
|
||||
if consoleToggleChat:isChecked() then
|
||||
consoleToggleChat:setChecked(false)
|
||||
end
|
||||
enableChat()
|
||||
end
|
||||
g_keyboard.bindKeyUp("Space", quickFunc)
|
||||
g_keyboard.bindKeyUp("Enter", quickFunc)
|
||||
|
||||
gameInterface.bindWalkKey("W", North)
|
||||
gameInterface.bindWalkKey("D", East)
|
||||
gameInterface.bindWalkKey("S", South)
|
||||
gameInterface.bindWalkKey("A", West)
|
||||
|
||||
consoleToggleChat:setTooltip(tr("Enable chat mode"))
|
||||
end
|
||||
|
||||
function terminate()
|
||||
save()
|
||||
disconnect(g_game, {
|
||||
@@ -166,14 +219,14 @@ function terminate()
|
||||
g_keyboard.unbindKeyDown('Ctrl+E')
|
||||
g_keyboard.unbindKeyDown('Ctrl+H')
|
||||
|
||||
saveIgnoreSettings()
|
||||
saveCommunicationSettings()
|
||||
|
||||
if channelsWindow then
|
||||
channelsWindow:destroy()
|
||||
end
|
||||
|
||||
if ignoreWindow then
|
||||
ignoreWindow:destroy()
|
||||
if communicationWindow then
|
||||
communicationWindow:destroy()
|
||||
end
|
||||
|
||||
if violationWindow then
|
||||
@@ -197,7 +250,7 @@ function load()
|
||||
if settings then
|
||||
messageHistory = settings.messageHistory or {}
|
||||
end
|
||||
loadIgnoreSettings()
|
||||
loadCommunicationSettings()
|
||||
end
|
||||
|
||||
function onTabChange(tabBar, tab)
|
||||
@@ -466,7 +519,7 @@ function addTabText(text, speaktype, tab, creatureName)
|
||||
-- Remove the curly braces
|
||||
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] }
|
||||
text = text:gsub("{"..dataBlock.words.."}", dataBlock.words)
|
||||
text = text:gsub("%{(.-)%}", dataBlock.words, 1)
|
||||
|
||||
-- Recalculate positions as braces are removed
|
||||
highlightData[(i-1)*3+1] = dataBlock._start - ((i-1) * 2)
|
||||
@@ -779,7 +832,11 @@ function onTalk(name, level, mode, message, channelId, creaturePos)
|
||||
return
|
||||
end
|
||||
|
||||
if name ~= g_game.getCharacterName() then
|
||||
local localPlayer = g_game.getLocalPlayer()
|
||||
if name ~= g_game.getCharacterName()
|
||||
and isUsingIgnoreList()
|
||||
and not(isUsingWhiteList()) or (isUsingWhiteList() and not(isWhitelisted(name)) and not(isAllowingVIPs() and localPlayer:hasVip(name))) then
|
||||
|
||||
if mode == MessageModes.Yell and isIgnoringYelling() then
|
||||
return
|
||||
elseif speaktype.private and isIgnoringPrivate() and mode ~= MessageModes.NpcFrom then
|
||||
@@ -957,107 +1014,221 @@ function onChannelList(channelList)
|
||||
end
|
||||
end
|
||||
|
||||
function loadIgnoreSettings()
|
||||
function loadCommunicationSettings()
|
||||
communicationSettings.whitelistedPlayers = {}
|
||||
communicationSettings.ignoredPlayers = {}
|
||||
|
||||
local ignoreNode = g_settings.getNode('IgnorePlayers')
|
||||
if ignoreNode then
|
||||
for i = 1, #ignoreNode do
|
||||
table.insert(ignoreSettings.players, ignoreNode[i])
|
||||
table.insert(communicationSettings.ignoredPlayers, ignoreNode[i])
|
||||
end
|
||||
end
|
||||
ignoreSettings.privateMessages = g_settings.getBoolean('IgnorePrivateMessages')
|
||||
ignoreSettings.yelling = g_settings.getBoolean('IgnoreYelling')
|
||||
|
||||
local whitelistNode = g_settings.getNode('WhitelistedPlayers')
|
||||
if whitelistNode then
|
||||
for i = 1, #whitelistNode do
|
||||
table.insert(communicationSettings.whitelistedPlayers, whitelistNode[i])
|
||||
end
|
||||
end
|
||||
|
||||
communicationSettings.useIgnoreList = g_settings.getBoolean('UseIgnoreList')
|
||||
communicationSettings.useWhiteList = g_settings.getBoolean('UseWhiteList')
|
||||
communicationSettings.privateMessages = g_settings.getBoolean('IgnorePrivateMessages')
|
||||
communicationSettings.yelling = g_settings.getBoolean('IgnoreYelling')
|
||||
communicationSettings.allowVIPs = g_settings.getBoolean('AllowVIPs')
|
||||
end
|
||||
|
||||
function saveIgnoreSettings()
|
||||
local tmpSettings = {}
|
||||
for i = 1, #ignoreSettings.players do
|
||||
table.insert(tmpSettings, ignoreSettings.players[i])
|
||||
function saveCommunicationSettings()
|
||||
local tmpIgnoreList = {}
|
||||
local ignoredPlayers = getIgnoredPlayers()
|
||||
for i = 1, #ignoredPlayers do
|
||||
table.insert(tmpIgnoreList, ignoredPlayers[i])
|
||||
end
|
||||
g_settings.set('IgnorePrivateMessages', ignoreSettings.privateMessages)
|
||||
g_settings.set('IgnoreYelling', ignoreSettings.yelling)
|
||||
g_settings.setNode('IgnorePlayers', tmpSettings)
|
||||
|
||||
local tmpWhiteList = {}
|
||||
local whitelistedPlayers = getWhitelistedPlayers()
|
||||
for i = 1, #whitelistedPlayers do
|
||||
table.insert(tmpWhiteList, whitelistedPlayers[i])
|
||||
end
|
||||
|
||||
g_settings.set('UseIgnoreList', communicationSettings.useIgnoreList)
|
||||
g_settings.set('UseWhiteList', communicationSettings.useWhiteList)
|
||||
g_settings.set('IgnorePrivateMessages', communicationSettings.privateMessages)
|
||||
g_settings.set('IgnoreYelling', communicationSettings.yelling)
|
||||
g_settings.setNode('IgnorePlayers', tmpIgnoreList)
|
||||
g_settings.setNode('WhitelistedPlayers', tmpWhiteList)
|
||||
end
|
||||
|
||||
function getIgnoredPlayers()
|
||||
return communicationSettings.ignoredPlayers
|
||||
end
|
||||
|
||||
function getWhitelistedPlayers()
|
||||
return communicationSettings.whitelistedPlayers
|
||||
end
|
||||
|
||||
function isUsingIgnoreList()
|
||||
return communicationSettings.useIgnoreList
|
||||
end
|
||||
|
||||
function isUsingWhiteList()
|
||||
return communicationSettings.useWhiteList
|
||||
end
|
||||
function isIgnored(name)
|
||||
return table.find(ignoreSettings.players, name, true)
|
||||
return table.find(communicationSettings.ignoredPlayers, name, true)
|
||||
end
|
||||
|
||||
function addIgnoredPlayer(name)
|
||||
if not isIgnored(name) then
|
||||
table.insert(ignoreSettings.players, name)
|
||||
end
|
||||
if isIgnored(name) then return end
|
||||
table.insert(communicationSettings.ignoredPlayers, name)
|
||||
end
|
||||
|
||||
function removeIgnoredPlayer(name)
|
||||
table.removevalue(ignoreSettings.players, name)
|
||||
table.removevalue(communicationSettings.ignoredPlayers, name)
|
||||
end
|
||||
|
||||
function isWhitelisted(name)
|
||||
return table.find(communicationSettings.whitelistedPlayers, name, true)
|
||||
end
|
||||
|
||||
function addWhitelistedPlayer(name)
|
||||
if isWhitelisted(name) then return end
|
||||
table.insert(communicationSettings.whitelistedPlayers, name)
|
||||
end
|
||||
|
||||
function removeWhitelistedPlayer(name)
|
||||
table.removevalue(communicationSettings.whitelistedPlayers, name)
|
||||
end
|
||||
|
||||
function isIgnoringPrivate()
|
||||
return ignoreSettings.privateMessages
|
||||
return communicationSettings.privateMessages
|
||||
end
|
||||
|
||||
function isIgnoringYelling()
|
||||
return ignoreSettings.yelling
|
||||
return communicationSettings.yelling
|
||||
end
|
||||
|
||||
function isAllowingVIPs()
|
||||
return communicationSettings.allowVIPs
|
||||
end
|
||||
|
||||
function onClickIgnoreButton()
|
||||
if ignoreWindow then return end
|
||||
ignoreWindow = g_ui.displayUI('ignorewindow')
|
||||
local ignoreListPanel = ignoreWindow:getChildById('ignoreList')
|
||||
ignoreWindow.onDestroy = function() ignoreWindow = nil end
|
||||
if communicationWindow then return end
|
||||
communicationWindow = g_ui.displayUI('communicationwindow')
|
||||
local ignoreListPanel = communicationWindow:getChildById('ignoreList')
|
||||
local whiteListPanel = communicationWindow:getChildById('whiteList')
|
||||
communicationWindow.onDestroy = function() communicationWindow = nil end
|
||||
|
||||
local removeButton = ignoreWindow:getChildById('buttonRemove')
|
||||
removeButton:disable()
|
||||
ignoreListPanel.onChildFocusChange = function() removeButton:enable() end
|
||||
removeButton.onClick = function()
|
||||
local useIgnoreListBox = communicationWindow:getChildById('checkboxUseIgnoreList')
|
||||
useIgnoreListBox:setChecked(communicationSettings.useIgnoreList)
|
||||
local useWhiteListBox = communicationWindow:getChildById('checkboxUseWhiteList')
|
||||
useWhiteListBox:setChecked(communicationSettings.useWhiteList)
|
||||
|
||||
local removeIgnoreButton = communicationWindow:getChildById('buttonIgnoreRemove')
|
||||
removeIgnoreButton:disable()
|
||||
ignoreListPanel.onChildFocusChange = function() removeIgnoreButton:enable() end
|
||||
removeIgnoreButton.onClick = function()
|
||||
local selection = ignoreListPanel:getFocusedChild()
|
||||
if selection then
|
||||
ignoreListPanel:removeChild(selection)
|
||||
selection:destroy()
|
||||
end
|
||||
if ignoreListPanel:getChildCount() == 0 then
|
||||
removeButton:disable()
|
||||
removeIgnoreButton:disable()
|
||||
end
|
||||
|
||||
local removeWhitelistButton = communicationWindow:getChildById('buttonWhitelistRemove')
|
||||
removeWhitelistButton:disable()
|
||||
whiteListPanel.onChildFocusChange = function() removeWhitelistButton:enable() end
|
||||
removeWhitelistButton.onClick = function()
|
||||
local selection = whiteListPanel:getFocusedChild()
|
||||
if selection then
|
||||
whiteListPanel:removeChild(selection)
|
||||
selection:destroy()
|
||||
end
|
||||
removeWhitelistButton:disable()
|
||||
end
|
||||
|
||||
local newlyIgnoredPlayers = {}
|
||||
local addName = ignoreWindow:getChildById('ignoreNameEdit')
|
||||
local addButton = ignoreWindow:getChildById('buttonAdd')
|
||||
local addFunction = function()
|
||||
if addName:getText() == '' then return end
|
||||
if table.find(ignoreSettings.players, addName:getText()) then return end
|
||||
if table.find(newlyIgnoredPlayers, addName:getText()) then return end
|
||||
local addIgnoreName = communicationWindow:getChildById('ignoreNameEdit')
|
||||
local addIgnoreButton = communicationWindow:getChildById('buttonIgnoreAdd')
|
||||
local addIgnoreFunction = function()
|
||||
local newEntry = addIgnoreName:getText()
|
||||
if newEntry == '' then return end
|
||||
if table.find(getIgnoredPlayers(), newEntry) then return end
|
||||
if table.find(newlyIgnoredPlayers, newEntry) then return end
|
||||
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
|
||||
label:setText(addName:getText())
|
||||
table.insert(newlyIgnoredPlayers, addName:getText())
|
||||
label:setPhantom(false)
|
||||
addName:setText('')
|
||||
label:setText(newEntry)
|
||||
table.insert(newlyIgnoredPlayers, newEntry)
|
||||
addIgnoreName:setText('')
|
||||
end
|
||||
addButton.onClick = addFunction
|
||||
ignoreWindow.onEnter = addFunction
|
||||
addIgnoreButton.onClick = addIgnoreFunction
|
||||
|
||||
local ignorePrivateMessageBox = ignoreWindow:getChildById('checkboxIgnorePrivateMessages')
|
||||
ignorePrivateMessageBox:setChecked(ignoreSettings.privateMessages)
|
||||
local ignoreYellingBox = ignoreWindow:getChildById('checkboxIgnoreYelling')
|
||||
ignoreYellingBox:setChecked(ignoreSettings.yelling)
|
||||
local newlyWhitelistedPlayers = {}
|
||||
local addWhitelistName = communicationWindow:getChildById('whitelistNameEdit')
|
||||
local addWhitelistButton = communicationWindow:getChildById('buttonWhitelistAdd')
|
||||
local addWhitelistFunction = function()
|
||||
local newEntry = addWhitelistName:getText()
|
||||
if newEntry == '' then return end
|
||||
if table.find(getWhitelistedPlayers(), newEntry) then return end
|
||||
if table.find(newlyWhitelistedPlayers, newEntry) then return end
|
||||
local label = g_ui.createWidget('WhiteListLabel', whiteListPanel)
|
||||
label:setText(newEntry)
|
||||
table.insert(newlyWhitelistedPlayers, newEntry)
|
||||
addWhitelistName:setText('')
|
||||
end
|
||||
addWhitelistButton.onClick = addWhitelistFunction
|
||||
|
||||
local saveButton = ignoreWindow:getChildById('buttonSave')
|
||||
communicationWindow.onEnter = function()
|
||||
if addWhitelistName:isFocused() then
|
||||
addWhitelistFunction()
|
||||
elseif addIgnoreName:isFocused() then
|
||||
addIgnoreFunction()
|
||||
end
|
||||
end
|
||||
|
||||
local ignorePrivateMessageBox = communicationWindow:getChildById('checkboxIgnorePrivateMessages')
|
||||
ignorePrivateMessageBox:setChecked(communicationSettings.privateMessages)
|
||||
local ignoreYellingBox = communicationWindow:getChildById('checkboxIgnoreYelling')
|
||||
ignoreYellingBox:setChecked(communicationSettings.yelling)
|
||||
local allowVIPsBox = communicationWindow:getChildById('checkboxAllowVIPs')
|
||||
allowVIPsBox:setChecked(communicationSettings.allowVIPs)
|
||||
|
||||
local saveButton = communicationWindow:recursiveGetChildById('buttonSave')
|
||||
saveButton.onClick = function()
|
||||
ignoreSettings.players = {}
|
||||
communicationSettings.ignoredPlayers = {}
|
||||
for i = 1, ignoreListPanel:getChildCount() do
|
||||
addIgnoredPlayer(ignoreListPanel:getChildByIndex(i):getText())
|
||||
--table.insert(ignoreSettings.players, ignoreListPanel:getChildByIndex(i):getText())
|
||||
end
|
||||
|
||||
ignoreSettings.yelling = ignoreYellingBox:isChecked()
|
||||
ignoreSettings.privateMessages = ignorePrivateMessageBox:isChecked()
|
||||
ignoreWindow:destroy()
|
||||
communicationSettings.whitelistedPlayers = {}
|
||||
for i = 1, whiteListPanel:getChildCount() do
|
||||
addWhitelistedPlayer(whiteListPanel:getChildByIndex(i):getText())
|
||||
end
|
||||
|
||||
for _, name in pairs(ignoreSettings.players) do
|
||||
communicationSettings.useIgnoreList = useIgnoreListBox:isChecked()
|
||||
communicationSettings.useWhiteList = useWhiteListBox:isChecked()
|
||||
communicationSettings.yelling = ignoreYellingBox:isChecked()
|
||||
communicationSettings.privateMessages = ignorePrivateMessageBox:isChecked()
|
||||
communicationSettings.allowVIPs = allowVIPsBox:isChecked()
|
||||
communicationWindow:destroy()
|
||||
end
|
||||
|
||||
local cancelButton = communicationWindow:recursiveGetChildById('buttonCancel')
|
||||
cancelButton.onClick = function()
|
||||
communicationWindow:destroy()
|
||||
end
|
||||
|
||||
local ignoredPlayers = getIgnoredPlayers()
|
||||
for i = 1, #ignoredPlayers do
|
||||
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
|
||||
label:setText(name)
|
||||
label:setPhantom(false)
|
||||
label:setText(ignoredPlayers[i])
|
||||
end
|
||||
|
||||
local whitelistedPlayers = getWhitelistedPlayers()
|
||||
for i = 1, #whitelistedPlayers do
|
||||
local label = g_ui.createWidget('WhiteListLabel', whiteListPanel)
|
||||
label:setText(whitelistedPlayers[i])
|
||||
end
|
||||
end
|
||||
|
||||
|
@@ -56,12 +56,21 @@ Panel
|
||||
id: consolePanel
|
||||
anchors.fill: parent
|
||||
|
||||
CheckBox
|
||||
id: toggleChat
|
||||
!tooltip: tr('Disable chat mode, allow to walk using ASDW')
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
margin-left: 13
|
||||
margin-top: 8
|
||||
@onCheckChange: toggleChat()
|
||||
|
||||
TabButton
|
||||
id: prevChannelButton
|
||||
icon: /images/game/console/leftarrow
|
||||
anchors.left: parent.left
|
||||
anchors.left: toggleChat.right
|
||||
anchors.top: parent.top
|
||||
margin-left: 6
|
||||
margin-left: 3
|
||||
margin-top: 6
|
||||
|
||||
ConsoleTabBar
|
||||
|
@@ -1,98 +0,0 @@
|
||||
IgnoreListLabel < Label
|
||||
font: verdana-11px-monochrome
|
||||
background-color: alpha
|
||||
text-offset: 2 0
|
||||
focusable: true
|
||||
|
||||
$focus:
|
||||
background-color: #ffffff22
|
||||
color: #ffffff
|
||||
|
||||
MainWindow
|
||||
id: ignoreWindow
|
||||
!text: tr('Ignore List')
|
||||
size: 500 240
|
||||
@onEscape: self:destroy()
|
||||
|
||||
Label
|
||||
!text: tr('Ignored players:')
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
|
||||
TextList
|
||||
id: ignoreList
|
||||
vertical-scrollbar: ignoreListScrollBar
|
||||
anchors.left: parent.left
|
||||
anchors.top: prev.bottom
|
||||
height: 150
|
||||
width: 230
|
||||
margin-bottom: 10
|
||||
margin-top: 3
|
||||
padding: 1
|
||||
focusable: false
|
||||
|
||||
Button
|
||||
id: buttonRemove
|
||||
!text: tr('Remove')
|
||||
width: 64
|
||||
anchors.right: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
TextEdit
|
||||
id: ignoreNameEdit
|
||||
anchors.left: ignoreList.right
|
||||
anchors.top: ignoreList.top
|
||||
width: 180
|
||||
margin-left: 8
|
||||
margin-right: 3
|
||||
|
||||
Button
|
||||
id: buttonAdd
|
||||
!text: tr('Add')
|
||||
width: 48
|
||||
height: 20
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.top
|
||||
|
||||
CheckBox
|
||||
id: checkboxIgnorePrivateMessages
|
||||
!text: tr('Ignore Private Messages')
|
||||
anchors.left: ignoreList.right
|
||||
anchors.top: ignoreList.top
|
||||
width: 180
|
||||
margin-top: 25
|
||||
margin-left: 8
|
||||
|
||||
CheckBox
|
||||
id: checkboxIgnoreYelling
|
||||
!text: tr('Ignore Yelling')
|
||||
anchors.left: ignoreList.right
|
||||
anchors.top: prev.top
|
||||
width: 180
|
||||
margin-top: 25
|
||||
margin-left: 8
|
||||
|
||||
Button
|
||||
id: buttonSave
|
||||
!text: tr('Save')
|
||||
width: 64
|
||||
anchors.right: next.left
|
||||
anchors.bottom: parent.bottom
|
||||
margin-right: 10
|
||||
@onClick: self:getParent():onEnter()
|
||||
|
||||
Button
|
||||
id: buttonCancel
|
||||
!text: tr('Cancel')
|
||||
width: 64
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
@onClick: self:getParent():destroy()
|
||||
|
||||
VerticalScrollBar
|
||||
id: ignoreListScrollBar
|
||||
anchors.top: ignoreList.top
|
||||
anchors.bottom: ignoreList.bottom
|
||||
anchors.right: ignoreList.right
|
||||
step: 14
|
||||
pixels-scroll: true
|
@@ -216,6 +216,7 @@ function save()
|
||||
hotkeys[child.keyCombo] = {
|
||||
autoSend = child.autoSend,
|
||||
itemId = child.itemId,
|
||||
subType = child.subType,
|
||||
useType = child.useType,
|
||||
value = child.value
|
||||
}
|
||||
@@ -266,6 +267,9 @@ function onChooseItemMouseRelease(self, mousePosition, mouseButton)
|
||||
|
||||
if item and currentHotkeyLabel then
|
||||
currentHotkeyLabel.itemId = item:getId()
|
||||
if item:isFluidContainer() then
|
||||
currentHotkeyLabel.subType = item:getSubType()
|
||||
end
|
||||
if item:isMultiUse() then
|
||||
currentHotkeyLabel.useType = HOTKEY_MANAGER_USEWITH
|
||||
else
|
||||
@@ -293,6 +297,7 @@ end
|
||||
|
||||
function clearObject()
|
||||
currentHotkeyLabel.itemId = nil
|
||||
currentHotkeyLabel.subType = nil
|
||||
currentHotkeyLabel.useType = nil
|
||||
currentHotkeyLabel.autoSend = nil
|
||||
currentHotkeyLabel.value = nil
|
||||
@@ -340,12 +345,14 @@ function addKeyCombo(keyCombo, keySettings, focus)
|
||||
hotkeyLabel.keyCombo = keyCombo
|
||||
hotkeyLabel.autoSend = toboolean(keySettings.autoSend)
|
||||
hotkeyLabel.itemId = tonumber(keySettings.itemId)
|
||||
hotkeyLabel.subType = tonumber(keySettings.subType)
|
||||
hotkeyLabel.useType = tonumber(keySettings.useType)
|
||||
if keySettings.value then hotkeyLabel.value = tostring(keySettings.value) end
|
||||
else
|
||||
hotkeyLabel.keyCombo = keyCombo
|
||||
hotkeyLabel.autoSend = false
|
||||
hotkeyLabel.itemId = nil
|
||||
hotkeyLabel.subType = nil
|
||||
hotkeyLabel.useType = nil
|
||||
hotkeyLabel.value = ''
|
||||
end
|
||||
@@ -375,15 +382,42 @@ function doKeyCombo(keyCombo)
|
||||
modules.game_console.setTextEditText(hotKey.value)
|
||||
end
|
||||
elseif hotKey.useType == HOTKEY_MANAGER_USE then
|
||||
if g_game.getProtocolVersion() < 780 or hotKey.subType then
|
||||
local item = g_game.findPlayerItem(hotKey.itemId, hotKey.subType or -1)
|
||||
if item then
|
||||
g_game.use(item)
|
||||
end
|
||||
else
|
||||
g_game.useInventoryItem(hotKey.itemId)
|
||||
end
|
||||
elseif hotKey.useType == HOTKEY_MANAGER_USEONSELF then
|
||||
if g_game.getProtocolVersion() < 780 or hotKey.subType then
|
||||
local item = g_game.findPlayerItem(hotKey.itemId, hotKey.subType or -1)
|
||||
if item then
|
||||
g_game.useWith(item, g_game.getLocalPlayer())
|
||||
end
|
||||
else
|
||||
g_game.useInventoryItemWith(hotKey.itemId, g_game.getLocalPlayer())
|
||||
end
|
||||
elseif hotKey.useType == HOTKEY_MANAGER_USEONTARGET then
|
||||
local attackingCreature = g_game.getAttackingCreature()
|
||||
if not attackingCreature then return end
|
||||
if not attackingCreature:getTile() then return end
|
||||
if g_game.getProtocolVersion() < 780 or hotKey.subType then
|
||||
local item = g_game.findPlayerItem(hotKey.itemId, hotKey.subType or -1)
|
||||
if item then
|
||||
g_game.useWith(item, attackingCreature)
|
||||
end
|
||||
else
|
||||
g_game.useInventoryItemWith(hotKey.itemId, attackingCreature)
|
||||
end
|
||||
elseif hotKey.useType == HOTKEY_MANAGER_USEWITH then
|
||||
local item = Item.create(hotKey.itemId)
|
||||
if g_game.getProtocolVersion() < 780 or hotKey.subType then
|
||||
local tmpItem = g_game.findPlayerItem(hotKey.itemId, hotKey.subType or -1)
|
||||
if not tmpItem then return true end
|
||||
item = tmpItem
|
||||
end
|
||||
modules.game_interface.startUseWith(item)
|
||||
end
|
||||
end
|
||||
@@ -428,6 +462,9 @@ function updateHotkeyForm(reset)
|
||||
selectObjectButton:disable()
|
||||
clearObjectButton:enable()
|
||||
currentItemPreview:setItemId(currentHotkeyLabel.itemId)
|
||||
if currentHotkeyLabel.subType then
|
||||
currentItemPreview:setItemSubType(currentHotkeyLabel.subType)
|
||||
end
|
||||
if currentItemPreview:getItem():isMultiUse() then
|
||||
useOnSelf:enable()
|
||||
useOnTarget:enable()
|
||||
|
@@ -11,7 +11,7 @@ countWindow = nil
|
||||
logoutWindow = nil
|
||||
exitWindow = nil
|
||||
bottomSplitter = nil
|
||||
limitZoom = false
|
||||
limitedZoom = false
|
||||
currentViewMode = 0
|
||||
smartWalkDirs = {}
|
||||
smartWalkDir = nil
|
||||
@@ -42,7 +42,8 @@ function init()
|
||||
gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel')
|
||||
connect(gameLeftPanel, { onVisibilityChange = onLeftPanelVisibilityChange })
|
||||
|
||||
logoutButton = modules.client_topmenu.addLeftButton('logoutButton', tr('Exit'), '/images/topbuttons/logout', tryLogout, true)
|
||||
logoutButton = modules.client_topmenu.addLeftButton('logoutButton', tr('Exit'),
|
||||
'/images/topbuttons/logout', tryLogout, true)
|
||||
|
||||
setupViewMode(0)
|
||||
|
||||
@@ -56,42 +57,19 @@ end
|
||||
|
||||
function bindKeys()
|
||||
gameRootPanel:setAutoRepeatDelay(250)
|
||||
g_keyboard.bindKeyDown('Up', function() changeWalkDir(North) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Right', function() changeWalkDir(East) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Down', function() changeWalkDir(South) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Left', function() changeWalkDir(West) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad8', function() changeWalkDir(North) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad9', function() changeWalkDir(NorthEast) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad6', function() changeWalkDir(East) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad3', function() changeWalkDir(SouthEast) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad2', function() changeWalkDir(South) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad1', function() changeWalkDir(SouthWest) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad4', function() changeWalkDir(West) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyDown('Numpad7', function() changeWalkDir(NorthWest) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Up', function() changeWalkDir(North, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Right', function() changeWalkDir(East, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Down', function() changeWalkDir(South, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Left', function() changeWalkDir(West, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad8', function() changeWalkDir(North, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad9', function() changeWalkDir(NorthEast, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad6', function() changeWalkDir(East, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad3', function() changeWalkDir(SouthEast, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad2', function() changeWalkDir(South, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad1', function() changeWalkDir(SouthWest, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad4', function() changeWalkDir(West, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp('Numpad7', function() changeWalkDir(NorthWest, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyPress('Up', function() smartWalk(North) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Right', function() smartWalk(East) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Down', function() smartWalk(South) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Left', function() smartWalk(West) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad8', function() smartWalk(North) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad9', function() smartWalk(NorthEast) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad6', function() smartWalk(East) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad3', function() smartWalk(SouthEast) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad2', function() smartWalk(South) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad1', function() smartWalk(SouthWest) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad4', function() smartWalk(West) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Numpad7', function() smartWalk(NorthWest) end, gameRootPanel)
|
||||
|
||||
bindWalkKey('Up', North)
|
||||
bindWalkKey('Right', East)
|
||||
bindWalkKey('Down', South)
|
||||
bindWalkKey('Left', West)
|
||||
bindWalkKey('Numpad8', North)
|
||||
bindWalkKey('Numpad9', NorthEast)
|
||||
bindWalkKey('Numpad6', East)
|
||||
bindWalkKey('Numpad3', SouthEast)
|
||||
bindWalkKey('Numpad2', South)
|
||||
bindWalkKey('Numpad1', SouthWest)
|
||||
bindWalkKey('Numpad4', West)
|
||||
bindWalkKey('Numpad7', NorthWest)
|
||||
|
||||
g_keyboard.bindKeyPress('Ctrl+Up', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Ctrl+Right', function() g_game.turn(East) changeWalkDir(East) end, gameRootPanel)
|
||||
@@ -104,12 +82,24 @@ function bindKeys()
|
||||
g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel)
|
||||
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel)
|
||||
g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel)
|
||||
g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel)
|
||||
g_keyboard.bindKeyDown('Ctrl+Q', function() tryLogout(false) end, gameRootPanel)
|
||||
g_keyboard.bindKeyDown('Ctrl+L', function() tryLogout(false) end, gameRootPanel)
|
||||
g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel)
|
||||
g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel)
|
||||
end
|
||||
|
||||
function bindWalkKey(key, dir)
|
||||
g_keyboard.bindKeyDown(key, function() changeWalkDir(dir) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyUp(key, function() changeWalkDir(dir, true) end, gameRootPanel, true)
|
||||
g_keyboard.bindKeyPress(key, function() smartWalk(dir) end, gameRootPanel)
|
||||
end
|
||||
|
||||
function unbindWalkKey(key)
|
||||
g_keyboard.unbindKeyDown(key, gameRootPanel)
|
||||
g_keyboard.unbindKeyUp(key, gameRootPanel)
|
||||
g_keyboard.unbindKeyPress(key, gameRootPanel)
|
||||
end
|
||||
|
||||
function terminate()
|
||||
save()
|
||||
hide()
|
||||
@@ -137,16 +127,6 @@ function onGameStart()
|
||||
else
|
||||
g_game.disableFeature(GameForceFirstAutoWalkStep)
|
||||
end
|
||||
|
||||
addEvent(function()
|
||||
if not limitZoom or g_game.isGM() then
|
||||
gameMapPanel:setMaxZoomOut(513)
|
||||
gameMapPanel:setLimitVisibleRange(false)
|
||||
else
|
||||
gameMapPanel:setMaxZoomOut(11)
|
||||
gameMapPanel:setLimitVisibleRange(true)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function onGameEnd()
|
||||
@@ -163,6 +143,16 @@ function show()
|
||||
setupViewMode(0)
|
||||
updateStretchShrink()
|
||||
logoutButton:setTooltip(tr('Logout'))
|
||||
|
||||
addEvent(function()
|
||||
if not limitedZoom or g_game.isGM() then
|
||||
gameMapPanel:setMaxZoomOut(513)
|
||||
gameMapPanel:setLimitVisibleRange(false)
|
||||
else
|
||||
gameMapPanel:setMaxZoomOut(11)
|
||||
gameMapPanel:setLimitVisibleRange(true)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function hide()
|
||||
@@ -215,8 +205,8 @@ function tryExit()
|
||||
return true
|
||||
end
|
||||
|
||||
local exitFunc = function() logout() forceExit() end
|
||||
local logoutFunc = function() logout() exitWindow:destroy() exitWindow = nil end
|
||||
local exitFunc = function() g_game.safeLogout() forceExit() end
|
||||
local logoutFunc = function() g_game.safeLogout() exitWindow:destroy() exitWindow = nil end
|
||||
local cancelFunc = function() exitWindow:destroy() exitWindow = nil end
|
||||
|
||||
exitWindow = displayGeneralBox(tr('Exit'), tr("If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character."),
|
||||
@@ -228,14 +218,10 @@ function tryExit()
|
||||
return true
|
||||
end
|
||||
|
||||
function logout()
|
||||
if g_game.isOnline() then
|
||||
g_game.safeLogout()
|
||||
return true
|
||||
function tryLogout(prompt)
|
||||
if type(prompt) ~= "boolean" then
|
||||
prompt = true
|
||||
end
|
||||
end
|
||||
|
||||
function tryLogout()
|
||||
if not g_game.isOnline() then
|
||||
exit()
|
||||
return
|
||||
@@ -245,13 +231,42 @@ function tryLogout()
|
||||
return
|
||||
end
|
||||
|
||||
local yesCallback = function() logout() logoutWindow:destroy() logoutWindow=nil end
|
||||
local noCallback = function() logoutWindow:destroy() logoutWindow=nil end
|
||||
local msg, yesCallback
|
||||
if not g_game.isConnectionOk() then
|
||||
msg = 'Your connection is failing, if you logout now your character will be still online, do you want to force logout?'
|
||||
|
||||
logoutWindow = displayGeneralBox(tr('Logout'), tr('Are you sure you want to logout?'), {
|
||||
yesCallback = function()
|
||||
g_game.forceLogout()
|
||||
if logoutWindow then
|
||||
logoutWindow:destroy()
|
||||
logoutWindow=nil
|
||||
end
|
||||
end
|
||||
else
|
||||
msg = 'Are you sure you want to logout?'
|
||||
|
||||
yesCallback = function()
|
||||
g_game.safeLogout()
|
||||
if logoutWindow then
|
||||
logoutWindow:destroy()
|
||||
logoutWindow=nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local noCallback = function()
|
||||
logoutWindow:destroy()
|
||||
logoutWindow=nil
|
||||
end
|
||||
|
||||
if prompt then
|
||||
logoutWindow = displayGeneralBox(tr('Logout'), tr(msg), {
|
||||
{ text=tr('Yes'), callback=yesCallback },
|
||||
{ text=tr('No'), callback=noCallback },
|
||||
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
|
||||
else
|
||||
yesCallback()
|
||||
end
|
||||
end
|
||||
|
||||
function stopSmartWalk()
|
||||
@@ -463,7 +478,9 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||
end
|
||||
|
||||
else
|
||||
local localPosition = localPlayer:getPosition()
|
||||
if not classic then shortcut = '(Alt)' else shortcut = nil end
|
||||
if creatureThing:getPosition().z == localPosition.z then
|
||||
if g_game.getAttackingCreature() ~= creatureThing then
|
||||
menu:addOption(tr('Attack'), function() g_game.attack(creatureThing) end, shortcut)
|
||||
else
|
||||
@@ -475,6 +492,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||
else
|
||||
menu:addOption(tr('Stop Follow'), function() g_game.cancelFollow() end)
|
||||
end
|
||||
end
|
||||
|
||||
if creatureThing:isPlayer() then
|
||||
menu:addSeparator()
|
||||
@@ -519,7 +537,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||
end
|
||||
end
|
||||
|
||||
if modules.game_ruleviolation.hasWindowAccess() then
|
||||
if modules.game_ruleviolation.hasWindowAccess() and creatureThing:isPlayer() then
|
||||
menu:addSeparator()
|
||||
menu:addOption(tr('Rule Violation'), function() modules.game_ruleviolation.show(creatureThing:getName()) end)
|
||||
end
|
||||
@@ -531,7 +549,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||
menu:display(menuPosition)
|
||||
end
|
||||
|
||||
function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing)
|
||||
function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing, attackCreature)
|
||||
local keyboardModifiers = g_keyboard.getModifiers()
|
||||
|
||||
if not modules.client_options.getOption('classicControl') then
|
||||
@@ -557,7 +575,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
|
||||
return true
|
||||
end
|
||||
return true
|
||||
elseif creatureThing and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
elseif attackCreature and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
g_game.attack(attackCreature)
|
||||
return true
|
||||
elseif creatureThing and creatureThing:getPosition().z == autoWalkPos.z and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
g_game.attack(creatureThing)
|
||||
return true
|
||||
end
|
||||
@@ -566,7 +587,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
|
||||
else
|
||||
if useThing and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
|
||||
local player = g_game.getLocalPlayer()
|
||||
if creatureThing and creatureThing ~= player then
|
||||
if attackCreature and attackCreature ~= player then
|
||||
g_game.attack(attackCreature)
|
||||
return true
|
||||
elseif creatureThing and creatureThing ~= player and creatureThing:getPosition().z == autoWalkPos.z then
|
||||
g_game.attack(creatureThing)
|
||||
return true
|
||||
elseif useThing:isContainer() then
|
||||
@@ -594,7 +618,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
|
||||
elseif useThing and keyboardModifiers == KeyboardCtrlModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||
return true
|
||||
elseif creatureThing and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
elseif attackCreature and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
g_game.attack(attackCreature)
|
||||
return true
|
||||
elseif creatureThing and creatureThing:getPosition().z == autoWalkPos.z and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||
g_game.attack(creatureThing)
|
||||
return true
|
||||
end
|
||||
@@ -655,6 +682,8 @@ function moveStackableItem(item, toPos)
|
||||
end
|
||||
g_keyboard.bindKeyPress("Up", function() check() spinbox:up() end, spinbox)
|
||||
g_keyboard.bindKeyPress("Down", function() check() spinbox:down() end, spinbox)
|
||||
g_keyboard.bindKeyPress("Right", function() check() spinbox:up() end, spinbox)
|
||||
g_keyboard.bindKeyPress("Left", function() check() spinbox:down() end, spinbox)
|
||||
g_keyboard.bindKeyPress("PageUp", function() check() spinbox:setValue(spinbox:getValue()+10) end, spinbox)
|
||||
g_keyboard.bindKeyPress("PageDown", function() check() spinbox:setValue(spinbox:getValue()-10) end, spinbox)
|
||||
|
||||
@@ -746,8 +775,7 @@ function setupViewMode(mode)
|
||||
gameMapPanel:setZoom(11)
|
||||
gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
|
||||
elseif mode == 2 then
|
||||
local limit = limitZoom and not g_game.isGM()
|
||||
gameMapPanel:setKeepAspectRatio(false)
|
||||
local limit = limitedZoom and not g_game.isGM()
|
||||
gameMapPanel:setLimitVisibleRange(limit)
|
||||
gameMapPanel:setZoom(11)
|
||||
gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
|
||||
@@ -772,5 +800,5 @@ function setupViewMode(mode)
|
||||
end
|
||||
|
||||
function limitZoom()
|
||||
limitZoom = true
|
||||
limitedZoom = true
|
||||
end
|
||||
|
@@ -6,11 +6,11 @@ CountWindow < MainWindow
|
||||
SpinBox
|
||||
id: spinBox
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.bottom
|
||||
width: 0
|
||||
height: 0
|
||||
anchors.top: parent.top
|
||||
width: 1
|
||||
height: 1
|
||||
phantom: true
|
||||
padding-bottom: -40
|
||||
margin-top: 2
|
||||
focusable: true
|
||||
|
||||
Item
|
||||
|
@@ -78,6 +78,7 @@ function UIGameMap:onMouseRelease(mousePosition, mouseButton)
|
||||
local useThing
|
||||
local creatureThing
|
||||
local multiUseThing
|
||||
local attackCreature
|
||||
|
||||
local tile = self:getTile(mousePosition)
|
||||
if tile then
|
||||
@@ -86,7 +87,12 @@ function UIGameMap:onMouseRelease(mousePosition, mouseButton)
|
||||
creatureThing = tile:getTopCreature()
|
||||
end
|
||||
|
||||
local ret = modules.game_interface.processMouseAction(mousePosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing)
|
||||
local autoWalkTile = g_map.getTile(autoWalkPos)
|
||||
if autoWalkTile then
|
||||
attackCreature = autoWalkTile:getTopCreature()
|
||||
end
|
||||
|
||||
local ret = modules.game_interface.processMouseAction(mousePosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing, attackCreature)
|
||||
if ret then
|
||||
self.allowNextRelease = false
|
||||
end
|
||||
|
@@ -86,7 +86,7 @@ function UIItem:onMouseRelease(mousePosition, mouseButton)
|
||||
g_game.look(item)
|
||||
self.cancelNextRelease = true
|
||||
return true
|
||||
elseif modules.game_interface.processMouseAction(mousePosition, mouseButton, nil, item, item, nil, item) then
|
||||
elseif modules.game_interface.processMouseAction(mousePosition, mouseButton, nil, item, item, nil, nil) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
|
@@ -151,8 +151,7 @@ function onTradeTypeChange(radioTabs, selected, deselected)
|
||||
ignoreCapacity:setVisible(currentTradeType == BUY)
|
||||
ignoreEquipped:setVisible(currentTradeType == SELL)
|
||||
showAllItems:setVisible(currentTradeType == SELL)
|
||||
sellAllButton:setVisible(false)
|
||||
--sellAllButton:setVisible(currentTradeType == SELL)
|
||||
sellAllButton:setVisible(currentTradeType == SELL)
|
||||
|
||||
refreshTradeItems()
|
||||
refreshPlayerGoods()
|
||||
|
@@ -252,7 +252,6 @@ MainWindow
|
||||
margin-right: 10
|
||||
visible: false
|
||||
@onClick: modules.game_npctrade.sellAll()
|
||||
visible: false
|
||||
|
||||
Button
|
||||
id: tradeButton
|
||||
|
@@ -17,6 +17,7 @@ end
|
||||
function reset()
|
||||
if deathWindow then
|
||||
deathWindow:destroy()
|
||||
deathWindow = nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -47,7 +48,7 @@ function openWindow()
|
||||
deathWindow = nil
|
||||
end
|
||||
local cancelFunc = function()
|
||||
modules.game_interface.logout()
|
||||
g_game.safeLogout()
|
||||
cancelButton:getParent():destroy()
|
||||
deathWindow = nil
|
||||
end
|
||||
|
@@ -28,6 +28,8 @@ MessageTypes = {
|
||||
[MessageModes.Blue] = MessageSettings.consoleBlue,
|
||||
[MessageModes.PrivateFrom] = MessageSettings.consoleBlue,
|
||||
|
||||
[MessageModes.GamemasterBroadcast] = MessageSettings.consoleRed,
|
||||
|
||||
[MessageModes.DamageDealed] = MessageSettings.status,
|
||||
[MessageModes.DamageReceived] = MessageSettings.status,
|
||||
[MessageModes.Heal] = MessageSettings.status,
|
||||
|
@@ -18,7 +18,7 @@ function isLoaded()
|
||||
end
|
||||
|
||||
function load()
|
||||
local version = g_game.getProtocolVersion()
|
||||
local version = g_game.getClientVersion()
|
||||
|
||||
local datPath, sprPath
|
||||
if filename then
|
||||
|
@@ -88,6 +88,23 @@ function isHiddingOffline()
|
||||
return settings['hideOffline']
|
||||
end
|
||||
|
||||
function getSortedBy()
|
||||
local settings = g_settings.getNode('VipList')
|
||||
if not settings then
|
||||
return 'status'
|
||||
end
|
||||
return settings['sortedBy']
|
||||
end
|
||||
|
||||
function sortBy(state)
|
||||
settings = {}
|
||||
settings['sortedBy'] = state
|
||||
g_settings.mergeNode('VipList', settings)
|
||||
|
||||
refresh()
|
||||
end
|
||||
|
||||
|
||||
function onAddVip(id, name, state)
|
||||
local vipList = vipWindow:getChildById('contentsPanel')
|
||||
|
||||
@@ -118,13 +135,13 @@ function onAddVip(id, name, state)
|
||||
|
||||
for i=1,childrenCount do
|
||||
local child = vipList:getChildByIndex(i)
|
||||
if state == VipState.Online and child.vipState ~= VipState.Online then
|
||||
if state == VipState.Online and child.vipState ~= VipState.Online and getSortedBy() == 'status' then
|
||||
vipList:insertChild(i, label)
|
||||
return
|
||||
end
|
||||
|
||||
if (state ~= VipState.Online and child.vipState ~= VipState.Online)
|
||||
or (state == VipState.Online and child.vipState == VipState.Online) then
|
||||
if ((state ~= VipState.Online and child.vipState ~= VipState.Online)
|
||||
or (state == VipState.Online and child.vipState == VipState.Online)) or getSortedBy() == 'name' then
|
||||
|
||||
local childText = child:getText():lower()
|
||||
local length = math.min(childText:len(), nameLower:len())
|
||||
@@ -168,6 +185,14 @@ function onVipListMousePress(widget, mousePos, mouseButton)
|
||||
menu:addOption(tr('Show Offline'), function() hideOffline(false) end)
|
||||
end
|
||||
|
||||
if not(getSortedBy() == 'name') then
|
||||
menu:addOption(tr('Sort by name'), function() sortBy('name') end)
|
||||
end
|
||||
|
||||
if not(getSortedBy() == 'status') then
|
||||
menu:addOption(tr('Sort by status'), function() sortBy('status') end)
|
||||
end
|
||||
|
||||
menu:display(mousePos)
|
||||
|
||||
return true
|
||||
@@ -196,6 +221,15 @@ function onVipListLabelMousePress(widget, mousePos, mouseButton)
|
||||
else
|
||||
menu:addOption(tr('Show Offline'), function() hideOffline(false) end)
|
||||
end
|
||||
|
||||
if not(getSortedBy() == 'name') then
|
||||
menu:addOption(tr('Sort by name'), function() sortBy('name') end)
|
||||
end
|
||||
|
||||
if not(getSortedBy() == 'status') then
|
||||
menu:addOption(tr('Sort by status'), function() sortBy('status') end)
|
||||
end
|
||||
|
||||
menu:display(mousePos)
|
||||
|
||||
return true
|
||||
|
@@ -22,11 +22,14 @@ ShieldBlueNoSharedExpBlink = 7
|
||||
ShieldYellowNoSharedExpBlink = 8
|
||||
ShieldBlueNoSharedExp = 9
|
||||
ShieldYellowNoSharedExp = 10
|
||||
ShieldGray = 11
|
||||
|
||||
EmblemNone = 0
|
||||
EmblemGreen = 1
|
||||
EmblemRed = 2
|
||||
EmblemBlue = 3
|
||||
EmblemMember = 4
|
||||
EmblemOther = 5
|
||||
|
||||
North = 0
|
||||
East = 1
|
||||
@@ -81,6 +84,16 @@ GameNewSpeedLaw = 36
|
||||
GameForceFirstAutoWalkStep = 37
|
||||
GameMinimapRemove = 38
|
||||
GameDoubleShopSellAmount = 39
|
||||
GameContainerPagination = 40
|
||||
GameThingMarks = 41
|
||||
GameLooktypeU16 = 42
|
||||
GamePlayerStamina = 43
|
||||
GamePlayerAddons = 44
|
||||
GameMessageStatements = 45
|
||||
GameMesssageLevel = 46
|
||||
GameNewFluids = 47
|
||||
GamePlayerStateU16 = 48
|
||||
GameNewOutfitProtocol = 49
|
||||
|
||||
TextColors = {
|
||||
red = '#f55e5e', --'#c83200'
|
||||
@@ -162,7 +175,7 @@ CIPSOFT_RSA = "1321277432058722840622950990822933849527763264961655079678763618"
|
||||
"88792221429527047321331896351555606801473202394175817"
|
||||
|
||||
-- set to the latest Tibia.pic signature to make otclient compatible with official tibia
|
||||
PIC_SIGNATURE = 0x50a6469d
|
||||
PIC_SIGNATURE = 0x52131b61
|
||||
|
||||
OsTypes = {
|
||||
Linux = 1,
|
||||
|
@@ -52,23 +52,25 @@ function getShieldImagePathAndBlink(shieldId)
|
||||
if shieldId == ShieldWhiteYellow then
|
||||
path, blink = '/images/game/shields/shield_yellow_white', false
|
||||
elseif shieldId == ShieldWhiteBlue then
|
||||
path, blink = '/images/game/shields//shield_blue_white', false
|
||||
path, blink = '/images/game/shields/shield_blue_white', false
|
||||
elseif shieldId == ShieldBlue then
|
||||
path, blink = '/images/game/shields//shield_blue', false
|
||||
path, blink = '/images/game/shields/shield_blue', false
|
||||
elseif shieldId == ShieldYellow then
|
||||
path, blink = '/images/game/shields//shield_yellow', false
|
||||
path, blink = '/images/game/shields/shield_yellow', false
|
||||
elseif shieldId == ShieldBlueSharedExp then
|
||||
path, blink = '/images/game/shields//shield_blue_shared', false
|
||||
path, blink = '/images/game/shields/shield_blue_shared', false
|
||||
elseif shieldId == ShieldYellowSharedExp then
|
||||
path, blink = '/images/game/shields//shield_yellow_shared', false
|
||||
path, blink = '/images/game/shields/shield_yellow_shared', false
|
||||
elseif shieldId == ShieldBlueNoSharedExpBlink then
|
||||
path, blink = '/images/game/shields//shield_blue_not_shared', true
|
||||
path, blink = '/images/game/shields/shield_blue_not_shared', true
|
||||
elseif shieldId == ShieldYellowNoSharedExpBlink then
|
||||
path, blink = '/images/game/shields//shield_yellow_not_shared', true
|
||||
path, blink = '/images/game/shields/shield_yellow_not_shared', true
|
||||
elseif shieldId == ShieldBlueNoSharedExp then
|
||||
path, blink = '/images/game/shields//shield_blue_not_shared', false
|
||||
path, blink = '/images/game/shields/shield_blue_not_shared', false
|
||||
elseif shieldId == ShieldYellowNoSharedExp then
|
||||
path, blink = '/images/game/shields//shield_yellow_not_shared', false
|
||||
path, blink = '/images/game/shields/shield_yellow_not_shared', false
|
||||
elseif shieldId == ShieldGray then
|
||||
path, blink = '/images/game/shields/shield_gray', false
|
||||
end
|
||||
return path, blink
|
||||
end
|
||||
@@ -81,6 +83,10 @@ function getEmblemImagePath(emblemId)
|
||||
path = '/images/game/emblems/emblem_red'
|
||||
elseif emblemId == EmblemBlue then
|
||||
path = '/images/game/emblems/emblem_blue'
|
||||
elseif emblemId == EmblemMember then
|
||||
path = '/images/game/emblems/emblem_member'
|
||||
elseif emblemId == EmblemOther then
|
||||
path = '/images/game/emblems/emblem_other'
|
||||
end
|
||||
return path
|
||||
end
|
||||
|
@@ -4,9 +4,23 @@ function g_game.getRsa()
|
||||
return currentRsa
|
||||
end
|
||||
|
||||
function g_game.findPlayerItem(itemId, subType)
|
||||
local localPlayer = g_game.getLocalPlayer()
|
||||
if localPlayer then
|
||||
for slot = InventorySlotFirst, InventorySlotLast do
|
||||
local item = localPlayer:getInventoryItem(slot)
|
||||
if item and item:getId() == itemId and (subType == -1 or item:getSubType() == subType) then
|
||||
return item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return g_game.findItemInContainers(itemId, subType)
|
||||
end
|
||||
|
||||
function g_game.chooseRsa(host)
|
||||
if currentRsa ~= CIPSOFT_RSA and currentRsa ~= OTSERV_RSA then return end
|
||||
if string.ends(host, '.tibia.com') or string.ends(host, '.cipsoft.com') then
|
||||
if host:ends('.tibia.com') or host:ends('.cipsoft.com') then
|
||||
g_game.setRsa(CIPSOFT_RSA)
|
||||
|
||||
if g_app.getOs() == 'windows' then
|
||||
@@ -32,22 +46,29 @@ function g_game.isOfficialTibia()
|
||||
return currentRsa == CIPSOFT_RSA
|
||||
end
|
||||
|
||||
function g_game.getSupportedProtocols()
|
||||
function g_game.getSupportedClients()
|
||||
return {
|
||||
810, 811, 840, 842, 850, 853, 854,
|
||||
860, 861, 862, 870, 910, 940, 944,
|
||||
953, 954, 960, 961, 963, 970, 971,
|
||||
973, 974
|
||||
760, 810, 811, 840, 842, 850, 853,
|
||||
854, 860, 861, 862, 870, 910, 940,
|
||||
944, 953, 954, 960, 961, 963, 970,
|
||||
980, 981, 982, 983, 984, 985, 986,
|
||||
1001, 1002, 1010, 1020, 1021, 1022,
|
||||
}
|
||||
end
|
||||
|
||||
function g_game.getSupportedClients(protocol)
|
||||
function g_game.getProtocolVersionForClient(client)
|
||||
clients = {
|
||||
[971] = {980},
|
||||
[973] = {981},
|
||||
[974] = {982}
|
||||
[980] = 971,
|
||||
[981] = 973,
|
||||
[982] = 974,
|
||||
[983] = 975,
|
||||
[984] = 976,
|
||||
[985] = 977,
|
||||
[986] = 978,
|
||||
[1001] = 979,
|
||||
[1002] = 980,
|
||||
}
|
||||
return clients[protocol] or {protocol}
|
||||
return clients[client] or client
|
||||
end
|
||||
|
||||
g_game.setRsa(OTSERV_RSA)
|
||||
|
@@ -188,5 +188,9 @@ ClientOpcodes = {
|
||||
ClientMarketCreate = 246, -- 944
|
||||
ClientMarketCancel = 247, -- 944
|
||||
ClientMarketAccept = 248, -- 944
|
||||
ClientAnswerModalDialog = 249 -- 960
|
||||
ClientAnswerModalDialog = 249, -- 960
|
||||
|
||||
-- 760
|
||||
ClientEnterAccount760 = 513,
|
||||
ClientEnterGame760 = 522
|
||||
}
|
||||
|
@@ -27,9 +27,13 @@ end
|
||||
|
||||
function ProtocolLogin:sendLoginPacket()
|
||||
local msg = OutputMessage.create()
|
||||
|
||||
if g_game.getProtocolVersion() == 760 then
|
||||
msg:addU16(ClientOpcodes.ClientEnterAccount760)
|
||||
else
|
||||
msg:addU8(ClientOpcodes.ClientEnterAccount)
|
||||
msg:addU16(g_game.getOs())
|
||||
end
|
||||
|
||||
msg:addU16(g_game.getProtocolVersion())
|
||||
|
||||
if g_game.getProtocolVersion() >= 971 then
|
||||
@@ -49,6 +53,7 @@ function ProtocolLogin:sendLoginPacket()
|
||||
-- first RSA byte must be 0
|
||||
msg:addU8(0)
|
||||
|
||||
if g_game.getProtocolVersion() >= 800 then
|
||||
-- xtea key
|
||||
self:generateXteaKey()
|
||||
local xteaKey = self:getXteaKey()
|
||||
@@ -56,6 +61,7 @@ function ProtocolLogin:sendLoginPacket()
|
||||
msg:addU32(xteaKey[2])
|
||||
msg:addU32(xteaKey[3])
|
||||
msg:addU32(xteaKey[4])
|
||||
end
|
||||
|
||||
if g_game.getFeature(GameAccountNames) then
|
||||
msg:addString(self.accountName)
|
||||
@@ -73,14 +79,18 @@ function ProtocolLogin:sendLoginPacket()
|
||||
local paddingBytes = g_crypt.rsaGetSize() - (msg:getMessageSize() - offset)
|
||||
assert(paddingBytes >= 0)
|
||||
msg:addPaddingBytes(paddingBytes, 0)
|
||||
if g_game.getProtocolVersion() >= 800 then
|
||||
msg:encryptRsa()
|
||||
end
|
||||
|
||||
if g_game.getFeature(GameProtocolChecksum) then
|
||||
self:enableChecksum()
|
||||
end
|
||||
|
||||
self:send(msg)
|
||||
if g_game.getProtocolVersion() >= 800 then
|
||||
self:enableXteaEncryption()
|
||||
end
|
||||
self:recv()
|
||||
end
|
||||
|
||||
@@ -125,6 +135,33 @@ end
|
||||
|
||||
function ProtocolLogin:parseCharacterList(msg)
|
||||
local characters = {}
|
||||
|
||||
if g_game.getProtocolVersion() > 1010 then
|
||||
local worlds = {}
|
||||
|
||||
local worldsCount = msg:getU8()
|
||||
for i=1, worldsCount do
|
||||
local world = {}
|
||||
local worldId = msg:getU8()
|
||||
world.worldName = msg:getString()
|
||||
world.worldIp = msg:getString()
|
||||
world.worldPort = msg:getU16()
|
||||
msg:getU8() -- unknow byte?
|
||||
worlds[worldId] = world
|
||||
end
|
||||
|
||||
local charactersCount = msg:getU8()
|
||||
for i=1, charactersCount do
|
||||
local character = {}
|
||||
local worldId = msg:getU8()
|
||||
character.name = msg:getString()
|
||||
character.worldName = worlds[worldId].worldName
|
||||
character.worldIp = worlds[worldId].worldIp
|
||||
character.worldPort = worlds[worldId].worldPort
|
||||
characters[i] = character
|
||||
end
|
||||
|
||||
else
|
||||
local charactersCount = msg:getU8()
|
||||
for i=1,charactersCount do
|
||||
local character = {}
|
||||
@@ -139,6 +176,7 @@ function ProtocolLogin:parseCharacterList(msg)
|
||||
|
||||
characters[i] = character
|
||||
end
|
||||
end
|
||||
|
||||
local account = {}
|
||||
account.premDays = msg:getU16()
|
||||
|
@@ -2,3 +2,4 @@
|
||||
-- you can place any custom user code here
|
||||
|
||||
print 'Startup done :]'
|
||||
|
||||
|
@@ -100,6 +100,8 @@ set(client_SOURCES ${client_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/uimapanchorlayout.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/uimapanchorlayout.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/uisprite.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/uisprite.h
|
||||
|
||||
# util
|
||||
${CMAKE_CURRENT_LIST_DIR}/position.h
|
||||
|
@@ -227,14 +227,17 @@ namespace Otc
|
||||
ShieldBlueNoSharedExpBlink, // 7 party member sexp inactive guilty
|
||||
ShieldYellowNoSharedExpBlink, // 8 // party leader sexp inactive guilty
|
||||
ShieldBlueNoSharedExp, // 9 party member sexp inactive innocent
|
||||
ShieldYellowNoSharedExp // 10 party leader sexp inactive innocent
|
||||
ShieldYellowNoSharedExp, // 10 party leader sexp inactive innocent
|
||||
ShieldGray // 11 member of another party
|
||||
};
|
||||
|
||||
enum PlayerEmblems {
|
||||
EmblemNone = 0,
|
||||
EmblemGreen,
|
||||
EmblemRed,
|
||||
EmblemBlue
|
||||
EmblemBlue,
|
||||
EmblemMember,
|
||||
EmblemOther
|
||||
};
|
||||
|
||||
enum PlayerStates {
|
||||
@@ -353,6 +356,18 @@ namespace Otc
|
||||
GameForceFirstAutoWalkStep = 37,
|
||||
GameMinimapRemove = 38,
|
||||
GameDoubleShopSellAmount = 39,
|
||||
GameContainerPagination = 40,
|
||||
GameThingMarks = 41,
|
||||
GameLooktypeU16 = 42,
|
||||
GamePlayerStamina = 43,
|
||||
GamePlayerAddons = 44,
|
||||
GameMessageStatements = 45,
|
||||
GameMessageLevel = 46,
|
||||
GameNewFluids = 47,
|
||||
GamePlayerStateU16 = 48,
|
||||
GameNewOutfitProtocol = 49,
|
||||
GamePVPMode = 50,
|
||||
|
||||
// 51-100 reserved to be defined in lua
|
||||
LastGameFeature = 101
|
||||
};
|
||||
|
@@ -23,7 +23,7 @@
|
||||
#include "container.h"
|
||||
#include "item.h"
|
||||
|
||||
Container::Container(int id, int capacity, const std::string& name, const ItemPtr& containerItem, bool hasParent)
|
||||
Container::Container(int id, int capacity, const std::string& name, const ItemPtr& containerItem, bool hasParent, bool isUnlocked, bool hasPages, int containerSize, int firstIndex)
|
||||
{
|
||||
m_id = id;
|
||||
m_capacity = capacity;
|
||||
@@ -31,6 +31,10 @@ Container::Container(int id, int capacity, const std::string& name, const ItemPt
|
||||
m_containerItem = containerItem;
|
||||
m_hasParent = hasParent;
|
||||
m_closed = false;
|
||||
m_unlocked = isUnlocked;
|
||||
m_hasPages = hasPages;
|
||||
m_size = containerSize;
|
||||
m_firstIndex = firstIndex;
|
||||
}
|
||||
|
||||
ItemPtr Container::getItem(int slot)
|
||||
@@ -51,12 +55,20 @@ void Container::onClose()
|
||||
callLuaField("onClose");
|
||||
}
|
||||
|
||||
void Container::onAddItem(const ItemPtr& item)
|
||||
void Container::onAddItem(const ItemPtr& item, int slot)
|
||||
{
|
||||
m_items.push_front(item);
|
||||
updateItemsPositions();
|
||||
|
||||
callLuaField("onAddItem", 0, item);
|
||||
callLuaField("onAddItem", slot, item);
|
||||
}
|
||||
|
||||
ItemPtr Container::findItemById(uint itemId, int subType)
|
||||
{
|
||||
for(const ItemPtr item : m_items)
|
||||
if(item->getId() == itemId && (subType == -1 || item->getSubType() == subType))
|
||||
return item;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Container::onAddItems(const std::vector<ItemPtr>& items)
|
||||
|
@@ -32,7 +32,7 @@
|
||||
class Container : public LuaObject
|
||||
{
|
||||
protected:
|
||||
Container(int id, int capacity, const std::string& name, const ItemPtr& containerItem, bool hasParent);
|
||||
Container(int id, int capacity, const std::string& name, const ItemPtr& containerItem, bool hasParent, bool isUnlocked, bool hasPages, int containerSize, int firstIndex);
|
||||
|
||||
public:
|
||||
ItemPtr getItem(int slot);
|
||||
@@ -45,11 +45,16 @@ public:
|
||||
std::string getName() { return m_name; }
|
||||
bool hasParent() { return m_hasParent; }
|
||||
bool isClosed() { return m_closed; }
|
||||
bool isUnlocked() { return m_unlocked; }
|
||||
bool hasPages() { return m_hasPages; }
|
||||
int getSize() { return m_size; }
|
||||
int getFirstIndex() { return m_firstIndex; }
|
||||
ItemPtr findItemById(uint itemId, int subType);
|
||||
|
||||
protected:
|
||||
void onOpen(const ContainerPtr& previousContainer);
|
||||
void onClose();
|
||||
void onAddItem(const ItemPtr& item);
|
||||
void onAddItem(const ItemPtr& item, int slot);
|
||||
void onAddItems(const std::vector<ItemPtr>& items);
|
||||
void onUpdateItem(int slot, const ItemPtr& item);
|
||||
void onRemoveItem(int slot);
|
||||
@@ -65,6 +70,10 @@ private:
|
||||
std::string m_name;
|
||||
bool m_hasParent;
|
||||
bool m_closed;
|
||||
bool m_unlocked;
|
||||
bool m_hasPages;
|
||||
int m_size;
|
||||
int m_firstIndex;
|
||||
std::deque<ItemPtr> m_items;
|
||||
};
|
||||
|
||||
|
@@ -128,7 +128,7 @@ void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWal
|
||||
dest -= datType->getDisplacement() * scaleFactor;
|
||||
datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase, lightView);
|
||||
dest += getDisplacement() * scaleFactor;
|
||||
zPattern = 1;
|
||||
zPattern = std::min(1, getNumPatternZ() - 1);
|
||||
}
|
||||
|
||||
PointF jumpOffset = m_jumpOffset * scaleFactor;
|
||||
@@ -458,6 +458,11 @@ void Creature::updateWalkAnimation(int totalPixelsWalked)
|
||||
|
||||
int footAnimPhases = getAnimationPhases() - 1;
|
||||
int footDelay = getStepDuration(true) / 3;
|
||||
// Since mount is a different outfit we need to get the mount animation phases
|
||||
if(m_outfit.getMount() != 0) {
|
||||
ThingType *type = g_things.rawGetThingType(m_outfit.getMount(), m_outfit.getCategory());
|
||||
footAnimPhases = type->getAnimationPhases() - 1;
|
||||
}
|
||||
if(footAnimPhases == 0)
|
||||
m_walkAnimationPhase = 0;
|
||||
else if(m_footStepDrawn && m_footTimer.ticksElapsed() >= footDelay && totalPixelsWalked < 32) {
|
||||
|
@@ -50,9 +50,9 @@ void CreatureManager::terminate()
|
||||
void Spawn::load(TiXmlElement* node)
|
||||
{
|
||||
Position centerPos;
|
||||
centerPos.x = node->readType<uint16>("centerx");
|
||||
centerPos.y = node->readType<uint16>("centery");
|
||||
centerPos.z = node->readType<uint8>("centerz");
|
||||
centerPos.x = node->readType<int>("centerx");
|
||||
centerPos.y = node->readType<int>("centery");
|
||||
centerPos.z = node->readType<int>("centerz");
|
||||
|
||||
setCenterPos(centerPos);
|
||||
setRadius(node->readType<int32>("radius"));
|
||||
@@ -65,6 +65,7 @@ void Spawn::load(TiXmlElement* node)
|
||||
std::string cName = cNode->Attribute("name");
|
||||
stdext::tolower(cName);
|
||||
stdext::trim(cName);
|
||||
stdext::ucwords(cName);
|
||||
|
||||
if (!(cType = g_creatures.getCreatureByName(cName)))
|
||||
continue;
|
||||
@@ -76,17 +77,18 @@ void Spawn::load(TiXmlElement* node)
|
||||
dir = (Otc::Direction)dir_;
|
||||
cType->setDirection(dir);
|
||||
|
||||
centerPos.x += cNode->readType<int>("x");
|
||||
centerPos.y += cNode->readType<int>("y");
|
||||
centerPos.z = cNode->readType<int>("z");
|
||||
addCreature(centerPos, cType);
|
||||
Position placePos;
|
||||
placePos.x = centerPos.x + cNode->readType<int>("x");
|
||||
placePos.y = centerPos.y + cNode->readType<int>("y");
|
||||
placePos.z = cNode->readType<int>("z");
|
||||
|
||||
cType->setRace(cNode->ValueStr() == "npc" ? CreatureRaceNpc : CreatureRaceMonster);
|
||||
addCreature(placePos, cType);
|
||||
}
|
||||
}
|
||||
|
||||
void Spawn::save(TiXmlElement*& node)
|
||||
void Spawn::save(TiXmlElement* node)
|
||||
{
|
||||
node = new TiXmlElement("spawn");
|
||||
|
||||
const Position& c = getCenterPos();
|
||||
node->SetAttribute("centerx", c.x);
|
||||
node->SetAttribute("centery", c.y);
|
||||
@@ -97,10 +99,10 @@ void Spawn::save(TiXmlElement*& node)
|
||||
TiXmlElement* creatureNode = nullptr;
|
||||
|
||||
for(const auto& pair : m_creatures) {
|
||||
if(!(creatureNode = new TiXmlElement("monster")))
|
||||
const CreatureTypePtr& creature = pair.second;
|
||||
if(!(creatureNode = new TiXmlElement(creature->getRace() == CreatureRaceNpc ? "npc" : "monster")))
|
||||
stdext::throw_exception("oom?");
|
||||
|
||||
const CreatureTypePtr& creature = pair.second;
|
||||
|
||||
creatureNode->SetAttribute("name", creature->getName());
|
||||
creatureNode->SetAttribute("spawntime", creature->getSpawnTime());
|
||||
@@ -109,8 +111,8 @@ void Spawn::save(TiXmlElement*& node)
|
||||
const Position& placePos = pair.first;
|
||||
assert(placePos.isValid());
|
||||
|
||||
creatureNode->SetAttribute("x", placePos.x);
|
||||
creatureNode->SetAttribute("y", placePos.y);
|
||||
creatureNode->SetAttribute("x", c.x - placePos.x);
|
||||
creatureNode->SetAttribute("y", c.y - placePos.y);
|
||||
creatureNode->SetAttribute("z", placePos.z);
|
||||
|
||||
node->LinkEndChild(creatureNode);
|
||||
@@ -121,11 +123,14 @@ void Spawn::addCreature(const Position& placePos, const CreatureTypePtr& cType)
|
||||
{
|
||||
const Position& centerPos = getCenterPos();
|
||||
int m_radius = getRadius();
|
||||
if(!isInZone(placePos, centerPos, m_radius))
|
||||
stdext::throw_exception(stdext::format("cannot place creature at %s %s %d (increment radius)",
|
||||
if(!isInZone(placePos, centerPos, m_radius)) {
|
||||
g_logger.warning(stdext::format("cannot place creature at %s (spawn's center position: %s, spawn radius: %d) (increment radius)",
|
||||
stdext::to_string(placePos), stdext::to_string(centerPos),
|
||||
m_radius
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
g_map.addThing(cType->cast(), placePos, 4);
|
||||
m_creatures.insert(std::make_pair(placePos, cType));
|
||||
}
|
||||
@@ -145,6 +150,8 @@ CreaturePtr CreatureType::cast()
|
||||
CreaturePtr ret(new Creature);
|
||||
|
||||
std::string cName = getName();
|
||||
stdext::tolower(cName);
|
||||
stdext::trim(cName);
|
||||
stdext::ucwords(cName);
|
||||
ret->setName(cName);
|
||||
|
||||
@@ -199,20 +206,12 @@ void CreatureManager::loadNpcs(const std::string& folder)
|
||||
if(!stdext::ends_with(tmp, "/"))
|
||||
tmp += "/";
|
||||
|
||||
// FIXME: filesystem is not supported anymore, rework the following code with g_resources
|
||||
/*
|
||||
boost::filesystem::path npcPath(boost::filesystem::current_path().generic_string() + tmp);
|
||||
if(!boost::filesystem::exists(npcPath))
|
||||
if(!g_resources.directoryExists(tmp))
|
||||
stdext::throw_exception(stdext::format("NPCs folder '%s' was not found.", folder));
|
||||
|
||||
for(boost::filesystem::directory_iterator it(npcPath), end; it != end; ++it) {
|
||||
std::string f = it->path().filename().string();
|
||||
if(boost::filesystem::is_directory(it->status()))
|
||||
continue;
|
||||
|
||||
loadCreatureBuffer(g_resources.readFileContents(tmp + f));
|
||||
}
|
||||
*/
|
||||
const auto& fileList = g_resources.listDirectoryFiles(tmp);
|
||||
for(const std::string& file : fileList)
|
||||
loadCreatureBuffer(g_resources.readFileContents(tmp + file));
|
||||
}
|
||||
|
||||
void CreatureManager::loadSpawns(const std::string& fileName)
|
||||
@@ -227,6 +226,7 @@ void CreatureManager::loadSpawns(const std::string& fileName)
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
TiXmlDocument doc;
|
||||
doc.Parse(g_resources.readFileContents(fileName).c_str());
|
||||
if(doc.Error())
|
||||
@@ -246,10 +246,14 @@ void CreatureManager::loadSpawns(const std::string& fileName)
|
||||
}
|
||||
doc.Clear();
|
||||
m_spawnLoaded = true;
|
||||
} catch(std::exception& e) {
|
||||
g_logger.error(stdext::format("Failed to load '%s': %s", fileName, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void CreatureManager::saveSpawns(const std::string& fileName)
|
||||
{
|
||||
try {
|
||||
TiXmlDocument doc;
|
||||
doc.SetTabSize(2);
|
||||
|
||||
@@ -260,13 +264,16 @@ void CreatureManager::saveSpawns(const std::string& fileName)
|
||||
doc.LinkEndChild(root);
|
||||
|
||||
for(auto pair : m_spawns) {
|
||||
TiXmlElement* elem;
|
||||
TiXmlElement* elem = new TiXmlElement("spawn");
|
||||
pair.second->save(elem);
|
||||
root->LinkEndChild(elem);
|
||||
}
|
||||
|
||||
if(!doc.SaveFile(fileName))
|
||||
if(!doc.SaveFile("data"+fileName))
|
||||
stdext::throw_exception(stdext::format("failed to save spawns XML %s: %s", fileName, doc.ErrorDesc()));
|
||||
} catch(std::exception& e) {
|
||||
g_logger.error(stdext::format("Failed to save '%s': %s", fileName, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void CreatureManager::loadCreatureBuffer(const std::string& buffer)
|
||||
@@ -283,6 +290,7 @@ void CreatureManager::loadCreatureBuffer(const std::string& buffer)
|
||||
std::string cName = root->Attribute("name");
|
||||
stdext::tolower(cName);
|
||||
stdext::trim(cName);
|
||||
stdext::ucwords(cName);
|
||||
|
||||
CreatureTypePtr newType(new CreatureType(cName));
|
||||
for(TiXmlElement* attrib = root->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) {
|
||||
@@ -329,6 +337,7 @@ const CreatureTypePtr& CreatureManager::getCreatureByName(std::string name)
|
||||
{
|
||||
stdext::tolower(name);
|
||||
stdext::trim(name);
|
||||
stdext::ucwords(name);
|
||||
auto it = std::find_if(m_creatures.begin(), m_creatures.end(),
|
||||
[=] (const CreatureTypePtr& m) -> bool { return m->getName() == name; });
|
||||
if(it != m_creatures.end())
|
||||
@@ -363,8 +372,11 @@ SpawnPtr CreatureManager::getSpawn(const Position& centerPos)
|
||||
SpawnPtr CreatureManager::addSpawn(const Position& centerPos, int radius)
|
||||
{
|
||||
auto iter = m_spawns.find(centerPos);
|
||||
if(iter != m_spawns.end())
|
||||
if(iter != m_spawns.end()) {
|
||||
if(iter->second->getRadius() != radius)
|
||||
iter->second->setRadius(radius);
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
SpawnPtr ret(new Spawn);
|
||||
|
||||
@@ -375,3 +387,5 @@ SpawnPtr CreatureManager::addSpawn(const Position& centerPos, int radius)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et: */
|
||||
|
||||
|
@@ -33,14 +33,20 @@ enum CreatureAttr : uint8
|
||||
CreatureAttrName = 1,
|
||||
CreatureAttrOutfit = 2,
|
||||
CreatureAttrSpawnTime = 3,
|
||||
CreatureAttrDir = 4
|
||||
CreatureAttrDir = 4,
|
||||
CreatureAttrRace = 5
|
||||
};
|
||||
|
||||
enum CreatureRace : uint8
|
||||
{
|
||||
CreatureRaceNpc = 0,
|
||||
CreatureRaceMonster = 1
|
||||
};
|
||||
|
||||
enum SpawnAttr : uint8
|
||||
{
|
||||
SpawnAttrRadius = 0,
|
||||
SpawnAttrCenter = 1,
|
||||
SpawnAttrPos = 2
|
||||
};
|
||||
|
||||
class Spawn : public LuaObject
|
||||
@@ -53,7 +59,7 @@ public:
|
||||
int32 getRadius() { return m_attribs.get<int32>(SpawnAttrRadius); }
|
||||
|
||||
void setCenterPos(const Position& pos) { m_attribs.set(SpawnAttrCenter, pos); }
|
||||
Position getCenterPos() { return m_attribs.get<Position>(SpawnAttrPos); }
|
||||
Position getCenterPos() { return m_attribs.get<Position>(SpawnAttrCenter); }
|
||||
|
||||
void addCreature(const Position& placePos, const CreatureTypePtr& cType);
|
||||
void removeCreature(const Position& pos);
|
||||
@@ -61,7 +67,7 @@ public:
|
||||
|
||||
protected:
|
||||
void load(TiXmlElement* node);
|
||||
void save(TiXmlElement*& node);
|
||||
void save(TiXmlElement* node);
|
||||
|
||||
private:
|
||||
stdext::dynamic_storage<uint8> m_attribs;
|
||||
@@ -87,6 +93,9 @@ public:
|
||||
void setDirection(Otc::Direction dir) { m_attribs.set(CreatureAttrDir, dir); }
|
||||
Otc::Direction getDirection() { return m_attribs.get<Otc::Direction>(CreatureAttrDir); }
|
||||
|
||||
void setRace(CreatureRace race) { m_attribs.set(CreatureAttrRace, race); }
|
||||
CreatureRace getRace() { return m_attribs.get<CreatureRace>(CreatureAttrRace); }
|
||||
|
||||
CreaturePtr cast();
|
||||
|
||||
private:
|
||||
|
@@ -77,8 +77,10 @@ typedef stdext::shared_object_ptr<Spawn> SpawnPtr;
|
||||
typedef std::vector<ThingPtr> ThingList;
|
||||
typedef std::vector<ThingTypePtr> ThingTypeList;
|
||||
typedef std::vector<ItemTypePtr> ItemTypeList;
|
||||
typedef std::vector<HousePtr> HouseList;
|
||||
typedef std::vector<TownPtr> TownList;
|
||||
typedef std::list<HousePtr> HouseList;
|
||||
typedef std::list<TownPtr> TownList;
|
||||
typedef std::list<ItemPtr> ItemList;
|
||||
typedef std::vector<ItemPtr> ItemVector;
|
||||
typedef std::unordered_map<Position, TilePtr, PositionHasher> TileMap;
|
||||
|
||||
// net
|
||||
@@ -96,9 +98,11 @@ class UIMinimap;
|
||||
class UIProgressRect;
|
||||
class UIMapAnchorLayout;
|
||||
class UIPositionAnchor;
|
||||
class UISprite;
|
||||
|
||||
typedef stdext::shared_object_ptr<UIItem> UIItemPtr;
|
||||
typedef stdext::shared_object_ptr<UICreature> UICreaturePtr;
|
||||
typedef stdext::shared_object_ptr<UISprite> UISpritePtr;
|
||||
typedef stdext::shared_object_ptr<UIMap> UIMapPtr;
|
||||
typedef stdext::shared_object_ptr<UIMinimap> UIMinimapPtr;
|
||||
typedef stdext::shared_object_ptr<UIProgressRect> UIProgressRectPtr;
|
||||
|
@@ -99,6 +99,11 @@ void Game::resetGameStates()
|
||||
m_walkEvent = nullptr;
|
||||
}
|
||||
|
||||
if(m_checkConnectionEvent) {
|
||||
m_checkConnectionEvent->cancel();
|
||||
m_checkConnectionEvent = nullptr;
|
||||
}
|
||||
|
||||
m_containers.clear();
|
||||
m_vips.clear();
|
||||
m_gmActions.clear();
|
||||
@@ -183,6 +188,16 @@ void Game::processGameStart()
|
||||
g_game.ping();
|
||||
}, m_pingDelay);
|
||||
}
|
||||
|
||||
m_checkConnectionEvent = g_dispatcher.cycleEvent([this] {
|
||||
if(!g_game.isConnectionOk() && !m_connectionFailWarned) {
|
||||
g_lua.callGlobalField("g_game", "onConnectionFailing", true);
|
||||
m_connectionFailWarned = true;
|
||||
} else if(g_game.isConnectionOk() && m_connectionFailWarned) {
|
||||
g_lua.callGlobalField("g_game", "onConnectionFailing", false);
|
||||
m_connectionFailWarned = false;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
void Game::processGameEnd()
|
||||
@@ -190,6 +205,11 @@ void Game::processGameEnd()
|
||||
m_online = false;
|
||||
g_lua.callGlobalField("g_game", "onGameEnd");
|
||||
|
||||
if(m_connectionFailWarned) {
|
||||
g_lua.callGlobalField("g_game", "onConnectionFailing", false);
|
||||
m_connectionFailWarned = false;
|
||||
}
|
||||
|
||||
// reset game state
|
||||
resetGameStates();
|
||||
|
||||
@@ -214,6 +234,22 @@ void Game::processGMActions(const std::vector<uint8>& actions)
|
||||
g_lua.callGlobalField("g_game", "onGMActions", actions);
|
||||
}
|
||||
|
||||
void Game::processPlayerHelpers(int helpers)
|
||||
{
|
||||
g_lua.callGlobalField("g_game", "onPlayerHelpersUpdate", helpers);
|
||||
}
|
||||
|
||||
void Game::processPlayerModes(Otc::FightModes fightMode, Otc::ChaseModes chaseMode, bool safeMode)
|
||||
{
|
||||
m_fightMode = fightMode;
|
||||
m_chaseMode = chaseMode;
|
||||
m_safeFight = safeMode;
|
||||
|
||||
g_lua.callGlobalField("g_game", "onFightModeChange", fightMode);
|
||||
g_lua.callGlobalField("g_game", "onChaseModeChange", chaseMode);
|
||||
g_lua.callGlobalField("g_game", "onSafeFightChange", safeMode);
|
||||
}
|
||||
|
||||
void Game::processPing()
|
||||
{
|
||||
g_lua.callGlobalField("g_game", "onPing");
|
||||
@@ -248,10 +284,10 @@ void Game::processTalk(const std::string& name, int level, Otc::MessageMode mode
|
||||
g_lua.callGlobalField("g_game", "onTalk", name, level, mode, text, channelId, pos);
|
||||
}
|
||||
|
||||
void Game::processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items)
|
||||
void Game::processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items, bool isUnlocked, bool hasPages, int containerSize, int firstIndex)
|
||||
{
|
||||
ContainerPtr previousContainer = getContainer(containerId);
|
||||
ContainerPtr container = ContainerPtr(new Container(containerId, capacity, name, containerItem, hasParent));
|
||||
ContainerPtr container = ContainerPtr(new Container(containerId, capacity, name, containerItem, hasParent, isUnlocked, hasPages, containerSize, firstIndex));
|
||||
m_containers[containerId] = container;
|
||||
container->onAddItems(items);
|
||||
|
||||
@@ -276,7 +312,7 @@ void Game::processCloseContainer(int containerId)
|
||||
container->onClose();
|
||||
}
|
||||
|
||||
void Game::processContainerAddItem(int containerId, const ItemPtr& item)
|
||||
void Game::processContainerAddItem(int containerId, const ItemPtr& item, int slot)
|
||||
{
|
||||
ContainerPtr container = getContainer(containerId);
|
||||
if(!container) {
|
||||
@@ -284,7 +320,7 @@ void Game::processContainerAddItem(int containerId, const ItemPtr& item)
|
||||
return;
|
||||
}
|
||||
|
||||
container->onAddItem(item);
|
||||
container->onAddItem(item, slot);
|
||||
}
|
||||
|
||||
void Game::processContainerUpdateItem(int containerId, int slot, const ItemPtr& item)
|
||||
@@ -554,7 +590,7 @@ bool Game::walk(Otc::Direction direction)
|
||||
if(m_lastWalkDir != direction) {
|
||||
// must add a new walk event
|
||||
float ticks = m_localPlayer->getStepTicksLeft();
|
||||
if(ticks < 0) { ticks = 0; }
|
||||
if(ticks <= 0) { ticks = 1; }
|
||||
|
||||
if(m_walkEvent) {
|
||||
m_walkEvent->cancel();
|
||||
@@ -697,7 +733,9 @@ void Game::autoWalk(std::vector<Otc::Direction> dirs)
|
||||
|
||||
auto it = dirs.begin();
|
||||
Otc::Direction direction = *it;
|
||||
if(m_localPlayer->canWalk(direction)) {
|
||||
if(!m_localPlayer->canWalk(direction))
|
||||
return;
|
||||
|
||||
TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
|
||||
if(toTile && toTile->isWalkable() && !m_localPlayer->isServerWalking()) {
|
||||
m_localPlayer->preWalk(direction);
|
||||
@@ -707,7 +745,6 @@ void Game::autoWalk(std::vector<Otc::Direction> dirs)
|
||||
dirs.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_lua.callGlobalField("g_game", "onAutoWalk", dirs);
|
||||
|
||||
@@ -863,7 +900,7 @@ void Game::useWith(const ItemPtr& item, const ThingPtr& toThing)
|
||||
if(!pos.isValid()) // virtual item
|
||||
pos = Position(0xFFFF, 0, 0); // means that is a item in inventory
|
||||
|
||||
if(toThing->isCreature())
|
||||
if(toThing->isCreature() && g_game.getProtocolVersion() >= 780)
|
||||
m_protocolGame->sendUseOnCreature(pos, item->getId(), item->getStackPos(), toThing->getId());
|
||||
else
|
||||
m_protocolGame->sendUseItemWith(pos, item->getId(), item->getStackPos(), toThing->getPosition(), toThing->getId(), toThing->getStackPos());
|
||||
@@ -882,6 +919,20 @@ void Game::useInventoryItemWith(int itemId, const ThingPtr& toThing)
|
||||
m_protocolGame->sendUseItemWith(pos, itemId, 0, toThing->getPosition(), toThing->getId(), toThing->getStackPos());
|
||||
}
|
||||
|
||||
ItemPtr Game::findItemInContainers(uint itemId, int subType)
|
||||
{
|
||||
for(auto& it : m_containers) {
|
||||
const ContainerPtr& container = it.second;
|
||||
|
||||
if(container) {
|
||||
ItemPtr item = container->findItemById(itemId, subType);
|
||||
if(item != nullptr)
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Game::open(const ItemPtr& item, const ContainerPtr& previousContainer)
|
||||
{
|
||||
if(!canPerformGameAction() || !item)
|
||||
@@ -1379,24 +1430,40 @@ void Game::setProtocolVersion(int version)
|
||||
if(isOnline())
|
||||
stdext::throw_exception("Unable to change protocol version while online");
|
||||
|
||||
if(version != 0 && (version < 810 || version > 974))
|
||||
if(version != 0 && version != 760 && (version < 810 || version > 1022))
|
||||
stdext::throw_exception(stdext::format("Protocol version %d not supported", version));
|
||||
|
||||
m_features.reset();
|
||||
enableFeature(Otc::GameFormatCreatureName);
|
||||
|
||||
|
||||
if(version >= 780)
|
||||
{
|
||||
enableFeature(Otc::GamePlayerAddons);
|
||||
enableFeature(Otc::GamePlayerStamina);
|
||||
enableFeature(Otc::GameNewFluids);
|
||||
enableFeature(Otc::GameMessageLevel);
|
||||
enableFeature(Otc::GameMessageStatements);
|
||||
enableFeature(Otc::GamePlayerStateU16);
|
||||
enableFeature(Otc::GameLooktypeU16);
|
||||
enableFeature(Otc::GameNewOutfitProtocol);
|
||||
}
|
||||
|
||||
if(version >= 840) {
|
||||
enableFeature(Otc::GameProtocolChecksum);
|
||||
enableFeature(Otc::GameChallengeOnLogin);
|
||||
enableFeature(Otc::GameAccountNames);
|
||||
}
|
||||
|
||||
if(version <= 854) {
|
||||
if(version >= 780 && version <= 854) { // 780 might not be accurate
|
||||
enableFeature(Otc::GameChargeableItems);
|
||||
}
|
||||
|
||||
if(version >= 854) {
|
||||
if(version >= 850) {
|
||||
enableFeature(Otc::GameDoubleFreeCapacity);
|
||||
}
|
||||
|
||||
if(version >= 854) {
|
||||
enableFeature(Otc::GameCreatureEmblems);
|
||||
}
|
||||
|
||||
@@ -1443,6 +1510,18 @@ void Game::setProtocolVersion(int version)
|
||||
enableFeature(Otc::GameNewSpeedLaw);
|
||||
}
|
||||
|
||||
if(version >= 976) {
|
||||
enableFeature(Otc::GameContainerPagination);
|
||||
}
|
||||
|
||||
if(version >= 979) {
|
||||
enableFeature(Otc::GameThingMarks);
|
||||
}
|
||||
|
||||
if(version >= 1000) {
|
||||
enableFeature(Otc::GamePVPMode);
|
||||
}
|
||||
|
||||
m_protocolVersion = version;
|
||||
|
||||
Proto::buildMessageModesMap(version);
|
||||
@@ -1458,7 +1537,7 @@ void Game::setClientVersion(int version)
|
||||
if(isOnline())
|
||||
stdext::throw_exception("Unable to change client version while online");
|
||||
|
||||
if(version != 0 && (version < 810 || version > 982))
|
||||
if(version != 0 && version != 760 && (version < 810 || version > 1022))
|
||||
stdext::throw_exception(stdext::format("Client version %d not supported", version));
|
||||
|
||||
m_clientVersion = version;
|
||||
|
@@ -73,14 +73,17 @@ protected:
|
||||
void processAttackCancel(uint seq);
|
||||
void processWalkCancel(Otc::Direction direction);
|
||||
|
||||
void processPlayerHelpers(int helpers);
|
||||
void processPlayerModes(Otc::FightModes fightMode, Otc::ChaseModes chaseMode, bool safeMode);
|
||||
|
||||
// message related
|
||||
void processTextMessage(Otc::MessageMode mode, const std::string& text);
|
||||
void processTalk(const std::string& name, int level, Otc::MessageMode mode, const std::string& text, int channelId, const Position& pos);
|
||||
|
||||
// container related
|
||||
void processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items);
|
||||
void processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items, bool isUnlocked, bool hasPages, int containerSize, int firstIndex);
|
||||
void processCloseContainer(int containerId);
|
||||
void processContainerAddItem(int containerId, const ItemPtr& item);
|
||||
void processContainerAddItem(int containerId, const ItemPtr& item, int slot);
|
||||
void processContainerUpdateItem(int containerId, int slot, const ItemPtr& item);
|
||||
void processContainerRemoveItem(int containerId, int slot);
|
||||
|
||||
@@ -158,6 +161,7 @@ public:
|
||||
void useWith(const ItemPtr& fromThing, const ThingPtr& toThing);
|
||||
void useInventoryItem(int itemId);
|
||||
void useInventoryItemWith(int itemId, const ThingPtr& toThing);
|
||||
ItemPtr findItemInContainers(uint itemId, int subType);
|
||||
|
||||
// container related
|
||||
int open(const ItemPtr& item, const ContainerPtr& previousContainer);
|
||||
@@ -281,6 +285,7 @@ public:
|
||||
bool isDead() { return m_dead; }
|
||||
bool isAttacking() { return !!m_attackingCreature; }
|
||||
bool isFollowing() { return !!m_followingCreature; }
|
||||
bool isConnectionOk() { return m_protocolGame && m_protocolGame->getElapsedTicksSinceLastRead() < 5000; }
|
||||
|
||||
int getPing() { return m_ping >= 0 ? std::max(m_ping, m_pingTimer.elapsed_millis()) : -1; }
|
||||
ContainerPtr getContainer(int index) { return m_containers[index]; }
|
||||
@@ -340,6 +345,8 @@ private:
|
||||
std::bitset<Otc::LastGameFeature> m_features;
|
||||
ScheduledEventPtr m_pingEvent;
|
||||
ScheduledEventPtr m_walkEvent;
|
||||
ScheduledEventPtr m_checkConnectionEvent;
|
||||
bool m_connectionFailWarned;
|
||||
int m_protocolVersion;
|
||||
int m_clientVersion;
|
||||
std::string m_clientSignature;
|
||||
|
@@ -28,12 +28,10 @@ HouseManager g_houses;
|
||||
|
||||
House::House()
|
||||
{
|
||||
m_nullTile = TilePtr(new Tile(Position()));
|
||||
}
|
||||
|
||||
House::House(uint32 hId, const std::string &name, const Position &pos)
|
||||
{
|
||||
m_nullTile = TilePtr(new Tile(Position()));
|
||||
setId(hId);
|
||||
setName(name);
|
||||
if(pos.isValid())
|
||||
@@ -42,16 +40,32 @@ House::House(uint32 hId, const std::string &name, const Position &pos)
|
||||
|
||||
void House::setTile(const TilePtr& tile)
|
||||
{
|
||||
tile->setFlags(TILESTATE_HOUSE);
|
||||
tile->setFlag(TILESTATE_HOUSE);
|
||||
tile->setHouseId(getId());
|
||||
m_tiles.insert(std::make_pair(tile->getPosition(), tile));
|
||||
}
|
||||
|
||||
const TilePtr& House::getTile(const Position& position)
|
||||
TilePtr House::getTile(const Position& position)
|
||||
{
|
||||
TileMap::const_iterator iter = m_tiles.find(position);
|
||||
if(iter != m_tiles.end())
|
||||
return iter->second;
|
||||
return m_nullTile;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void House::addDoor(const ItemPtr& door)
|
||||
{
|
||||
if (!door) return;
|
||||
door->setDoorId(m_lastDoorId);
|
||||
m_doors[m_lastDoorId++] = door;
|
||||
}
|
||||
|
||||
void House::removeDoorById(uint32 doorId)
|
||||
{
|
||||
if(doorId >= m_lastDoorId)
|
||||
stdext::throw_exception(stdext::format("Failed to remove door of id %d (would overflow), max id: %d",
|
||||
doorId, m_lastDoorId));
|
||||
m_doors[doorId] = nullptr;
|
||||
}
|
||||
|
||||
void House::load(const TiXmlElement *elem)
|
||||
@@ -67,16 +81,14 @@ void House::load(const TiXmlElement *elem)
|
||||
m_isGuildHall = elem->readType<bool>("guildhall");
|
||||
|
||||
Position entryPos;
|
||||
entryPos.x = elem->readType<uint16>("entryx");
|
||||
entryPos.y = elem->readType<uint16>("entryy");
|
||||
entryPos.z = elem->readType<uint8>("entryz");
|
||||
entryPos.x = elem->readType<int>("entryx");
|
||||
entryPos.y = elem->readType<int>("entryy");
|
||||
entryPos.z = elem->readType<int>("entryz");
|
||||
setEntry(entryPos);
|
||||
}
|
||||
|
||||
void House::save(TiXmlElement*& elem)
|
||||
void House::save(TiXmlElement* elem)
|
||||
{
|
||||
elem = new TiXmlElement("house");
|
||||
|
||||
elem->SetAttribute("name", getName());
|
||||
elem->SetAttribute("houseid", getId());
|
||||
|
||||
@@ -93,7 +105,6 @@ void House::save(TiXmlElement*& elem)
|
||||
|
||||
HouseManager::HouseManager()
|
||||
{
|
||||
m_nullHouse = HousePtr(new House);
|
||||
}
|
||||
|
||||
void HouseManager::addHouse(const HousePtr& house)
|
||||
@@ -109,15 +120,22 @@ void HouseManager::removeHouse(uint32 houseId)
|
||||
m_houses.erase(it);
|
||||
}
|
||||
|
||||
const HousePtr& HouseManager::getHouse(uint32 houseId)
|
||||
HousePtr HouseManager::getHouse(uint32 houseId)
|
||||
{
|
||||
auto it = findHouse(houseId);
|
||||
return it != m_houses.end() ? *it : nullptr;
|
||||
}
|
||||
|
||||
HousePtr HouseManager::getHouseByName(std::string name)
|
||||
{
|
||||
auto it = std::find_if(m_houses.begin(), m_houses.end(),
|
||||
[=] (const HousePtr& house) -> bool { return house->getId() == houseId; });
|
||||
return it != m_houses.end() ? *it : m_nullHouse;
|
||||
[=] (const HousePtr& house) -> bool { return house->getName() == name; });
|
||||
return it != m_houses.end() ? *it : nullptr;
|
||||
}
|
||||
|
||||
void HouseManager::load(const std::string& fileName)
|
||||
{
|
||||
try {
|
||||
TiXmlDocument doc;
|
||||
doc.Parse(g_resources.readFileContents(fileName).c_str());
|
||||
if(doc.Error())
|
||||
@@ -138,10 +156,14 @@ void HouseManager::load(const std::string& fileName)
|
||||
|
||||
house->load(elem);
|
||||
}
|
||||
} catch(std::exception& e) {
|
||||
g_logger.error(stdext::format("Failed to load '%s': %s", fileName, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void HouseManager::save(const std::string& fileName)
|
||||
{
|
||||
try {
|
||||
TiXmlDocument doc;
|
||||
doc.SetTabSize(2);
|
||||
|
||||
@@ -152,13 +174,25 @@ void HouseManager::save(const std::string& fileName)
|
||||
doc.LinkEndChild(root);
|
||||
|
||||
for(auto house : m_houses) {
|
||||
TiXmlElement *elem;
|
||||
TiXmlElement *elem = new TiXmlElement("house");
|
||||
house->save(elem);
|
||||
root->LinkEndChild(elem);
|
||||
}
|
||||
|
||||
if(!doc.SaveFile(fileName))
|
||||
if(!doc.SaveFile("data"+fileName))
|
||||
stdext::throw_exception(stdext::format("failed to save houses XML %s: %s", fileName, doc.ErrorDesc()));
|
||||
} catch(std::exception& e) {
|
||||
g_logger.error(stdext::format("Failed to save '%s': %s", fileName, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
HouseList HouseManager::filterHouses(uint32 townId)
|
||||
{
|
||||
HouseList ret;
|
||||
for(const HousePtr& house : m_houses)
|
||||
if(house->getTownId() == townId)
|
||||
ret.push_back(house);
|
||||
return ret;
|
||||
}
|
||||
|
||||
HouseList::iterator HouseManager::findHouse(uint32 houseId)
|
||||
@@ -166,3 +200,5 @@ HouseList::iterator HouseManager::findHouse(uint32 houseId)
|
||||
return std::find_if(m_houses.begin(), m_houses.end(),
|
||||
[=] (const HousePtr& house) -> bool { return house->getId() == houseId; });
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et: */
|
||||
|
@@ -43,10 +43,10 @@ class House : public LuaObject
|
||||
public:
|
||||
House();
|
||||
House(uint32 hId, const std::string& name = "", const Position& pos=Position());
|
||||
~House() { m_tiles.clear(); m_nullTile = nullptr; }
|
||||
~House() { m_tiles.clear(); }
|
||||
|
||||
void setTile(const TilePtr& tile);
|
||||
const TilePtr& getTile(const Position& pos);
|
||||
TilePtr getTile(const Position& pos);
|
||||
|
||||
void setName(const std::string& name) { m_attribs.set(HouseAttrName, name); }
|
||||
std::string getName() { return m_attribs.get<std::string>(HouseAttrName); }
|
||||
@@ -66,14 +66,19 @@ public:
|
||||
void setEntry(const Position& p) { m_attribs.set(HouseAttrEntry, p); }
|
||||
Position getEntry() { return m_attribs.get<Position>(HouseAttrEntry); }
|
||||
|
||||
void addDoor(const ItemPtr& door);
|
||||
void removeDoor(const ItemPtr& door) { removeDoorById(door->getDoorId()); }
|
||||
void removeDoorById(uint32 doorId);
|
||||
|
||||
protected:
|
||||
void load(const TiXmlElement* elem);
|
||||
void save(TiXmlElement*& elem);
|
||||
void save(TiXmlElement* elem);
|
||||
|
||||
private:
|
||||
stdext::packed_storage<uint8> m_attribs;
|
||||
TileMap m_tiles;
|
||||
TilePtr m_nullTile;
|
||||
ItemVector m_doors;
|
||||
uint32 m_lastDoorId;
|
||||
stdext::boolean<false> m_isGuildHall;
|
||||
|
||||
friend class HouseManager;
|
||||
@@ -85,16 +90,18 @@ public:
|
||||
|
||||
void addHouse(const HousePtr& house);
|
||||
void removeHouse(uint32 houseId);
|
||||
HouseList getHouseList() { return m_houses; }
|
||||
const HousePtr& getHouse(uint32 houseId);
|
||||
void clear() { m_houses.clear(); m_nullHouse = nullptr; }
|
||||
HousePtr getHouse(uint32 houseId);
|
||||
HousePtr getHouseByName(std::string name);
|
||||
|
||||
void load(const std::string& fileName);
|
||||
void save(const std::string& fileName);
|
||||
|
||||
void clear() { m_houses.clear(); }
|
||||
HouseList getHouseList() { return m_houses; }
|
||||
HouseList filterHouses(uint32 townId);
|
||||
|
||||
private:
|
||||
HouseList m_houses;
|
||||
HousePtr m_nullHouse;
|
||||
|
||||
protected:
|
||||
HouseList::iterator findHouse(uint32 houseId);
|
||||
|
@@ -40,7 +40,11 @@
|
||||
Item::Item() :
|
||||
m_clientId(0),
|
||||
m_serverId(0),
|
||||
m_countOrSubType(1)
|
||||
m_countOrSubType(1),
|
||||
m_color(Color::alpha),
|
||||
m_async(true),
|
||||
m_phase(0),
|
||||
m_lastPhase(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -58,6 +62,11 @@ ItemPtr Item::createFromOtb(int id)
|
||||
return item;
|
||||
}
|
||||
|
||||
std::string Item::getName()
|
||||
{
|
||||
return g_things.findItemTypeByClientId(m_clientId)->getName();
|
||||
}
|
||||
|
||||
void Item::draw(const Point& dest, float scaleFactor, bool animate, LightView *lightView)
|
||||
{
|
||||
if(m_clientId == 0)
|
||||
@@ -70,7 +79,15 @@ void Item::draw(const Point& dest, float scaleFactor, bool animate, LightView *l
|
||||
int xPattern = 0, yPattern = 0, zPattern = 0;
|
||||
calculatePatterns(xPattern, yPattern, zPattern);
|
||||
|
||||
if(m_color != Color::alpha)
|
||||
g_painter->setColor(m_color);
|
||||
rawGetThingType()->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase, lightView);
|
||||
|
||||
/// Sanity check
|
||||
/// This is just to ensure that we don't overwrite some color and
|
||||
/// screw up the whole rendering.
|
||||
if(m_color != Color::alpha)
|
||||
g_painter->resetColor();
|
||||
}
|
||||
|
||||
void Item::setId(uint32 id)
|
||||
@@ -187,6 +204,11 @@ void Item::serializeItem(const OutputBinaryTreePtr& out)
|
||||
out->addU16(getDepotId());
|
||||
}
|
||||
|
||||
if(isHouseDoor()) {
|
||||
out->addU8(ATTR_HOUSEDOORID);
|
||||
out->addU8(getDoorId());
|
||||
}
|
||||
|
||||
uint16 aid = m_attribs.get<uint16>(ATTR_ACTION_ID);
|
||||
uint16 uid = m_attribs.get<uint16>(ATTR_UNIQUE_ID);
|
||||
if(aid) {
|
||||
@@ -200,10 +222,8 @@ void Item::serializeItem(const OutputBinaryTreePtr& out)
|
||||
}
|
||||
|
||||
out->endNode();
|
||||
if(!m_containerItems.empty()) {
|
||||
for(auto c : m_containerItems)
|
||||
c->serializeItem(out);
|
||||
}
|
||||
for(auto i : m_containerItems)
|
||||
i->serializeItem(out);
|
||||
}
|
||||
|
||||
int Item::getSubType()
|
||||
@@ -271,6 +291,7 @@ void Item::calculatePatterns(int& xPattern, int& yPattern, int& zPattern)
|
||||
}
|
||||
} else if(isSplash() || isFluidContainer()) {
|
||||
int color = Otc::FluidTransparent;
|
||||
if(g_game.getFeature(Otc::GameNewFluids)) {
|
||||
switch(m_countOrSubType) {
|
||||
case Otc::FluidNone:
|
||||
color = Otc::FluidTransparent;
|
||||
@@ -330,6 +351,8 @@ void Item::calculatePatterns(int& xPattern, int& yPattern, int& zPattern)
|
||||
color = Otc::FluidTransparent;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
color = m_countOrSubType;
|
||||
|
||||
xPattern = (color % 4) % getNumPatternX();
|
||||
yPattern = (color / 4) % getNumPatternY();
|
||||
@@ -343,9 +366,17 @@ void Item::calculatePatterns(int& xPattern, int& yPattern, int& zPattern)
|
||||
int Item::calculateAnimationPhase(bool animate)
|
||||
{
|
||||
if(getAnimationPhases() > 1) {
|
||||
if(animate)
|
||||
if(animate) {
|
||||
if(m_async)
|
||||
return (g_clock.millis() % (Otc::ITEM_TICKS_PER_FRAME * getAnimationPhases())) / Otc::ITEM_TICKS_PER_FRAME;
|
||||
else
|
||||
else {
|
||||
if(g_clock.millis() - m_lastPhase >= Otc::ITEM_TICKS_PER_FRAME) {
|
||||
m_phase = (m_phase + 1) % getAnimationPhases();
|
||||
m_lastPhase = g_clock.millis();
|
||||
}
|
||||
return m_phase;
|
||||
}
|
||||
} else
|
||||
return getAnimationPhases()-1;
|
||||
}
|
||||
return 0;
|
||||
@@ -367,3 +398,4 @@ ThingType* Item::rawGetThingType()
|
||||
{
|
||||
return g_things.rawGetThingType(m_clientId, ThingCategoryItem);
|
||||
}
|
||||
/* vim: set ts=4 sw=4 et :*/
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#define ITEM_H
|
||||
|
||||
#include <framework/global.h>
|
||||
|
||||
#include "thing.h"
|
||||
#include "effect.h"
|
||||
#include "itemtype.h"
|
||||
@@ -88,6 +89,7 @@ public:
|
||||
void setCountOrSubType(int value) { m_countOrSubType = value; }
|
||||
void setCount(int count) { m_countOrSubType = count; }
|
||||
void setSubType(int subType) { m_countOrSubType = subType; }
|
||||
void setColor(const Color& c) { m_color = c; }
|
||||
|
||||
int getCountOrSubType() { return m_countOrSubType; }
|
||||
int getSubType();
|
||||
@@ -95,10 +97,9 @@ public:
|
||||
uint32 getId() { return m_clientId; }
|
||||
uint16 getClientId() { return m_clientId; }
|
||||
uint16 getServerId() { return m_serverId; }
|
||||
std::string getName();
|
||||
bool isValid();
|
||||
|
||||
ItemPtr clone();
|
||||
|
||||
void unserializeItem(const BinaryTreePtr& in);
|
||||
void serializeItem(const OutputBinaryTreePtr& out);
|
||||
|
||||
@@ -111,6 +112,9 @@ public:
|
||||
void setActionId(uint16 actionId) { m_attribs.set(ATTR_ACTION_ID, actionId); }
|
||||
void setUniqueId(uint16 uniqueId) { m_attribs.set(ATTR_UNIQUE_ID, uniqueId); }
|
||||
|
||||
void setAsync(bool enable) { m_async = enable; }
|
||||
|
||||
bool isHouseDoor() { return m_attribs.has(ATTR_HOUSEDOORID); }
|
||||
bool isDepot() { return m_attribs.has(ATTR_DEPOT_ID); }
|
||||
bool isContainer() { return m_attribs.has(ATTR_CONTAINER_ITEMS); }
|
||||
bool isDoor() { return m_attribs.has(ATTR_HOUSEDOORID); }
|
||||
@@ -118,6 +122,7 @@ public:
|
||||
bool isMoveable();
|
||||
bool isGround();
|
||||
|
||||
ItemPtr clone();
|
||||
ItemPtr asItem() { return static_self_cast<Item>(); }
|
||||
bool isItem() { return true; }
|
||||
|
||||
@@ -136,7 +141,12 @@ private:
|
||||
uint16 m_serverId;
|
||||
uint8 m_countOrSubType;
|
||||
stdext::packed_storage<uint8> m_attribs;
|
||||
std::vector<ItemPtr> m_containerItems;
|
||||
ItemList m_containerItems;
|
||||
Color m_color;
|
||||
bool m_async;
|
||||
|
||||
uint8 m_phase;
|
||||
ticks_t m_lastPhase;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "thingtypemanager.h"
|
||||
#include "thingtype.h"
|
||||
#include "game.h"
|
||||
|
||||
#include <framework/core/filestream.h>
|
||||
#include <framework/core/binarytree.h>
|
||||
@@ -50,28 +51,37 @@ void ItemType::unserialize(const BinaryTreePtr& node)
|
||||
switch(attr) {
|
||||
case ItemTypeAttrServerId: {
|
||||
uint16 serverId = node->getU16();
|
||||
if(g_game.getProtocolVersion() < 960) {
|
||||
if(serverId > 20000 && serverId < 20100) {
|
||||
serverId -= 20000;
|
||||
} else if(lastId > 99 && lastId != serverId - 1) {
|
||||
|
||||
while(lastId != serverId - 1) {
|
||||
ItemTypePtr tmp(new ItemType);
|
||||
tmp->setServerId(lastId++);
|
||||
g_things.addItemType(tmp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(serverId > 30000 && serverId < 30100) {
|
||||
serverId -= 30000;
|
||||
} else if(lastId > 99 && lastId != serverId - 1) {
|
||||
while(lastId != serverId - 1) {
|
||||
ItemTypePtr tmp(new ItemType);
|
||||
tmp->setServerId(lastId++);
|
||||
g_things.addItemType(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
setServerId(serverId);
|
||||
lastId = serverId;
|
||||
break;
|
||||
}
|
||||
case ItemTypeAttrClientId: {
|
||||
case ItemTypeAttrClientId:
|
||||
setClientId(node->getU16());
|
||||
break;
|
||||
}
|
||||
case ItemTypeAttrName: {
|
||||
case ItemTypeAttrName:
|
||||
setName(node->getString(len));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
node->skip(len); // skip attribute
|
||||
break;
|
||||
|
@@ -26,7 +26,6 @@
|
||||
#include <framework/graphics/framebuffermanager.h>
|
||||
#include <framework/graphics/painter.h>
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/ogl/textureogl.h>
|
||||
|
||||
enum {
|
||||
MAX_LIGHT_INTENSITY = 8,
|
||||
@@ -62,7 +61,7 @@ TexturePtr LightView::generateLightBubble(float centerFactor)
|
||||
}
|
||||
}
|
||||
|
||||
TexturePtr tex = TexturePtr(new TextureOGL(lightImage, true));
|
||||
TexturePtr tex = TexturePtr(new Texture(lightImage, true));
|
||||
tex->setSmooth(true);
|
||||
return tex;
|
||||
}
|
||||
|
@@ -72,7 +72,7 @@ bool LocalPlayer::canWalk(Otc::Direction direction)
|
||||
return false;
|
||||
|
||||
// last walk is not done yet
|
||||
if(m_walkTimer.ticksElapsed() < getStepDuration())
|
||||
if((m_walkTimer.ticksElapsed() < getStepDuration()) && !isAutoWalking())
|
||||
return false;
|
||||
|
||||
// prewalk has a timeout, because for some reason that I don't know yet the server sometimes doesn't answer the prewalk
|
||||
@@ -83,7 +83,7 @@ bool LocalPlayer::canWalk(Otc::Direction direction)
|
||||
return false;
|
||||
|
||||
// cannot walk while already walking
|
||||
if(m_walking && !prewalkTimeouted)
|
||||
if((m_walking && !isAutoWalking()) && (!prewalkTimeouted || m_secondPreWalk))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -95,6 +95,7 @@ void LocalPlayer::walk(const Position& oldPos, const Position& newPos)
|
||||
if(m_preWalking) {
|
||||
// switch to normal walking
|
||||
m_preWalking = false;
|
||||
m_secondPreWalk = false;
|
||||
m_lastPrewalkDone = true;
|
||||
// if is to the last prewalk destination, updates the walk preserving the animation
|
||||
if(newPos == m_lastPrewalkDestination) {
|
||||
@@ -118,7 +119,8 @@ void LocalPlayer::preWalk(Otc::Direction direction)
|
||||
Position newPos = m_position.translatedToDirection(direction);
|
||||
|
||||
// avoid reanimating prewalks
|
||||
if(m_preWalking && m_lastPrewalkDestination == newPos) {
|
||||
if(m_preWalking) {
|
||||
m_secondPreWalk = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -277,6 +279,7 @@ void LocalPlayer::terminateWalk()
|
||||
{
|
||||
Creature::terminateWalk();
|
||||
m_preWalking = false;
|
||||
m_secondPreWalk = false;
|
||||
m_idleTimer.restart();
|
||||
|
||||
auto self = asLocalPlayer();
|
||||
|
@@ -126,6 +126,7 @@ private:
|
||||
ticks_t m_walkLockExpiration;
|
||||
stdext::boolean<false> m_preWalking;
|
||||
stdext::boolean<true> m_lastPrewalkDone;
|
||||
stdext::boolean<false> m_secondPreWalk;
|
||||
stdext::boolean<false> m_serverWalking;
|
||||
stdext::boolean<false> m_knownCompletePath;
|
||||
|
||||
|
@@ -47,6 +47,7 @@
|
||||
#include "uiminimap.h"
|
||||
#include "uimapanchorlayout.h"
|
||||
#include "uiprogressrect.h"
|
||||
#include "uisprite.h"
|
||||
#include "outfit.h"
|
||||
|
||||
#include <framework/luaengine/luainterface.h>
|
||||
@@ -66,20 +67,26 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindSingletonFunction("g_things", "getItemType", &ThingTypeManager::getItemType, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "getThingTypes", &ThingTypeManager::getThingTypes, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "findItemTypeByClientId", &ThingTypeManager::findItemTypeByClientId, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "findThingTypeByAttr", &ThingTypeManager::findThingTypeByAttr, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "findItemTypeByName", &ThingTypeManager::findItemTypeByName, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "findItemTypesByName", &ThingTypeManager::findItemTypesByName, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "findItemTypesByString", &ThingTypeManager::findItemTypesByString, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "findItemTypeByCategory", &ThingTypeManager::findItemTypeByCategory, &g_things);
|
||||
g_lua.bindSingletonFunction("g_things", "findThingTypeByAttr", &ThingTypeManager::findThingTypeByAttr, &g_things);
|
||||
|
||||
g_lua.registerSingletonClass("g_houses");
|
||||
g_lua.bindSingletonFunction("g_houses", "clear", &HouseManager::clear, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "load", &HouseManager::load, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "save", &HouseManager::save, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "getHouse", &HouseManager::getHouse, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "getHouseByName", &HouseManager::getHouseByName, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "addHouse", &HouseManager::addHouse, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "removeHouse", &HouseManager::removeHouse, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "getHouseList", &HouseManager::getHouseList, &g_houses);
|
||||
g_lua.bindSingletonFunction("g_houses", "filterHouses", &HouseManager::filterHouses, &g_houses);
|
||||
|
||||
g_lua.registerSingletonClass("g_towns");
|
||||
g_lua.bindSingletonFunction("g_towns", "getTown", &TownManager::getTown, &g_towns);
|
||||
g_lua.bindSingletonFunction("g_towns", "getTownByName",&TownManager::getTownByName,&g_towns);
|
||||
g_lua.bindSingletonFunction("g_towns", "addTown", &TownManager::addTown, &g_towns);
|
||||
g_lua.bindSingletonFunction("g_towns", "removeTown", &TownManager::removeTown, &g_towns);
|
||||
g_lua.bindSingletonFunction("g_towns", "getTowns", &TownManager::getTowns, &g_towns);
|
||||
@@ -99,6 +106,8 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindSingletonFunction("g_map", "getThing", &Map::getThing, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "removeThingByPos", &Map::removeThingByPos, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "removeThing", &Map::removeThing, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "colorizeThing", &Map::colorizeThing, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "removeThingColor", &Map::removeThingColor, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "clean", &Map::clean, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "cleanTile", &Map::cleanTile, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "cleanTexts", &Map::cleanTexts, &g_map);
|
||||
@@ -119,6 +128,20 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindSingletonFunction("g_map", "setSpawnFile", &Map::setSpawnFile, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "createTile", &Map::createTile, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "getSize", &Map::getSize, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "setDescription", &Map::setDescription, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "getDescriptions", &Map::getDescriptions, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "clearDescriptions", &Map::clearDescriptions, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "setShowZone", &Map::setShowZone, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "setShowZones", &Map::setShowZones, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "setZoneColor", &Map::setZoneColor, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "setZoneOpacity", &Map::setZoneOpacity, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "getZoneOpacity", &Map::getZoneOpacity, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "getZoneColor", &Map::getZoneColor, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "showZones", &Map::showZones, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "showZone", &Map::showZone, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "beginGhostMode", &Map::beginGhostMode, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "endGhostMode", &Map::endGhostMode, &g_map);
|
||||
g_lua.bindSingletonFunction("g_map", "findItemsById", &Map::findItemsById, &g_map);
|
||||
|
||||
g_lua.registerSingletonClass("g_minimap");
|
||||
g_lua.bindSingletonFunction("g_minimap", "clean", &Minimap::clean, &g_minimap);
|
||||
@@ -162,6 +185,7 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindSingletonFunction("g_game", "useWith", &Game::useWith, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "useInventoryItem", &Game::useInventoryItem, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "useInventoryItemWith", &Game::useInventoryItemWith, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "findItemInContainers", &Game::findItemInContainers, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "open", &Game::open, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "openParent", &Game::openParent, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "close", &Game::close, &g_game);
|
||||
@@ -230,6 +254,7 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindSingletonFunction("g_game", "isDead", &Game::isDead, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "isAttacking", &Game::isAttacking, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "isFollowing", &Game::isFollowing, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "isConnectionOk", &Game::isConnectionOk, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getPing", &Game::getPing, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game);
|
||||
g_lua.bindSingletonFunction("g_game", "getContainers", &Game::getContainers, &g_game);
|
||||
@@ -293,6 +318,10 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<Container>("getContainerItem", &Container::getContainerItem);
|
||||
g_lua.bindClassMemberFunction<Container>("hasParent", &Container::hasParent);
|
||||
g_lua.bindClassMemberFunction<Container>("isClosed", &Container::isClosed);
|
||||
g_lua.bindClassMemberFunction<Container>("isUnlocked", &Container::isUnlocked);
|
||||
g_lua.bindClassMemberFunction<Container>("hasPages", &Container::hasPages);
|
||||
g_lua.bindClassMemberFunction<Container>("getSize", &Container::getSize);
|
||||
g_lua.bindClassMemberFunction<Container>("getFirstIndex", &Container::getFirstIndex);
|
||||
|
||||
g_lua.registerClass<Thing>();
|
||||
g_lua.bindClassMemberFunction<Thing>("setId", &Thing::setId);
|
||||
@@ -335,6 +364,7 @@ void Client::registerLuaFunctions()
|
||||
g_lua.registerClass<House>();
|
||||
g_lua.bindClassStaticFunction<House>("create", []{ return HousePtr(new House); });
|
||||
g_lua.bindClassMemberFunction<House>("setId", &House::setId);
|
||||
g_lua.bindClassMemberFunction<House>("getId", &House::getId);
|
||||
g_lua.bindClassMemberFunction<House>("setName", &House::setName);
|
||||
g_lua.bindClassMemberFunction<House>("getName", &House::getName);
|
||||
g_lua.bindClassMemberFunction<House>("setTownId", &House::setTownId);
|
||||
@@ -343,6 +373,9 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<House>("getTile", &House::getTile);
|
||||
g_lua.bindClassMemberFunction<House>("setEntry", &House::setEntry);
|
||||
g_lua.bindClassMemberFunction<House>("getEntry", &House::getEntry);
|
||||
g_lua.bindClassMemberFunction<House>("addDoor", &House::addDoor);
|
||||
g_lua.bindClassMemberFunction<House>("removeDoor", &House::removeDoor);
|
||||
g_lua.bindClassMemberFunction<House>("removeDoorById", &House::removeDoorById);
|
||||
g_lua.bindClassMemberFunction<House>("setSize", &House::setSize);
|
||||
g_lua.bindClassMemberFunction<House>("getSize", &House::getSize);
|
||||
g_lua.bindClassMemberFunction<House>("setRent", &House::setRent);
|
||||
@@ -422,9 +455,12 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<Item>("clone", &Item::clone);
|
||||
g_lua.bindClassMemberFunction<Item>("setCount", &Item::setCount);
|
||||
g_lua.bindClassMemberFunction<Item>("getCount", &Item::getCount);
|
||||
g_lua.bindClassMemberFunction<Item>("getSubType", &Item::getSubType);
|
||||
g_lua.bindClassMemberFunction<Item>("getId", &Item::getId);
|
||||
g_lua.bindClassMemberFunction<Item>("getName", &Item::getName);
|
||||
g_lua.bindClassMemberFunction<Item>("isStackable", &Item::isStackable);
|
||||
g_lua.bindClassMemberFunction<Item>("isMarketable", &Item::isMarketable);
|
||||
g_lua.bindClassMemberFunction<Item>("isFluidContainer", &Item::isFluidContainer);
|
||||
g_lua.bindClassMemberFunction<Item>("getMarketData", &Item::getMarketData);
|
||||
g_lua.bindClassMemberFunction<Item>("getClothSlot", &Item::getClothSlot);
|
||||
|
||||
@@ -521,6 +557,10 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<Tile>("isClickable", &Tile::isClickable);
|
||||
g_lua.bindClassMemberFunction<Tile>("isPathable", &Tile::isPathable);
|
||||
g_lua.bindClassMemberFunction<Tile>("overwriteMinimapColor", &Tile::overwriteMinimapColor);
|
||||
g_lua.bindClassMemberFunction<Tile>("setFlag", &Tile::setFlag);
|
||||
g_lua.bindClassMemberFunction<Tile>("setFlags", &Tile::setFlags);
|
||||
g_lua.bindClassMemberFunction<Tile>("getFlags", &Tile::getFlags);
|
||||
g_lua.bindClassMemberFunction<Tile>("hasFlag", &Tile::hasFlag);
|
||||
|
||||
g_lua.registerClass<UIItem, UIWidget>();
|
||||
g_lua.bindClassStaticFunction<UIItem>("create", []{ return UIItemPtr(new UIItem); });
|
||||
@@ -538,6 +578,13 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<UIItem>("isVirtual", &UIItem::isVirtual);
|
||||
g_lua.bindClassMemberFunction<UIItem>("isItemVisible", &UIItem::isItemVisible);
|
||||
|
||||
g_lua.registerClass<UISprite, UIWidget>();
|
||||
g_lua.bindClassStaticFunction<UISprite>("create", []{ return UISpritePtr(new UISprite); });
|
||||
g_lua.bindClassMemberFunction<UISprite>("setSpriteId", &UISprite::setSpriteId);
|
||||
g_lua.bindClassMemberFunction<UISprite>("clearSprite", &UISprite::clearSprite);
|
||||
g_lua.bindClassMemberFunction<UISprite>("getSpriteId", &UISprite::getSpriteId);
|
||||
g_lua.bindClassMemberFunction<UISprite>("setSpriteColor", &UISprite::setSpriteColor);
|
||||
|
||||
g_lua.registerClass<UICreature, UIWidget>();
|
||||
g_lua.bindClassStaticFunction<UICreature>("create", []{ return UICreaturePtr(new UICreature); } );
|
||||
g_lua.bindClassMemberFunction<UICreature>("setCreature", &UICreature::setCreature);
|
||||
@@ -549,6 +596,7 @@ void Client::registerLuaFunctions()
|
||||
g_lua.registerClass<UIMap, UIWidget>();
|
||||
g_lua.bindClassStaticFunction<UIMap>("create", []{ return UIMapPtr(new UIMap); });
|
||||
g_lua.bindClassMemberFunction<UIMap>("drawSelf", &UIMap::drawSelf);
|
||||
g_lua.bindClassMemberFunction<UIMap>("movePixels", &UIMap::movePixels);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setZoom", &UIMap::setZoom);
|
||||
g_lua.bindClassMemberFunction<UIMap>("zoomIn", &UIMap::zoomIn);
|
||||
g_lua.bindClassMemberFunction<UIMap>("zoomOut", &UIMap::zoomOut);
|
||||
|
@@ -216,6 +216,42 @@ bool Map::removeThingByPos(const Position& pos, int stackPos)
|
||||
return false;
|
||||
}
|
||||
|
||||
void Map::colorizeThing(const ThingPtr& thing, const Color& color)
|
||||
{
|
||||
if(!thing)
|
||||
return;
|
||||
|
||||
if(thing->isItem())
|
||||
thing->static_self_cast<Item>()->setColor(color);
|
||||
else if(thing->isCreature()) {
|
||||
const TilePtr& tile = thing->getTile();
|
||||
assert(tile);
|
||||
|
||||
const ThingPtr& topThing = tile->getTopThing();
|
||||
assert(topThing);
|
||||
|
||||
topThing->static_self_cast<Item>()->setColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
void Map::removeThingColor(const ThingPtr& thing)
|
||||
{
|
||||
if(!thing)
|
||||
return;
|
||||
|
||||
if(thing->isItem())
|
||||
thing->static_self_cast<Item>()->setColor(Color::alpha);
|
||||
else if(thing->isCreature()) {
|
||||
const TilePtr& tile = thing->getTile();
|
||||
assert(tile);
|
||||
|
||||
const ThingPtr& topThing = tile->getTopThing();
|
||||
assert(topThing);
|
||||
|
||||
topThing->static_self_cast<Item>()->setColor(Color::alpha);
|
||||
}
|
||||
}
|
||||
|
||||
StaticTextPtr Map::getStaticText(const Position& pos)
|
||||
{
|
||||
for(auto staticText : m_staticTexts) {
|
||||
@@ -305,6 +341,62 @@ void Map::cleanTile(const Position& pos)
|
||||
}
|
||||
}
|
||||
|
||||
void Map::setShowZone(tileflags_t zone, bool show)
|
||||
{
|
||||
if(show)
|
||||
m_zoneFlags |= (uint32)zone;
|
||||
else
|
||||
m_zoneFlags &= ~(uint32)zone;
|
||||
}
|
||||
|
||||
void Map::setShowZones(bool show)
|
||||
{
|
||||
if(!show)
|
||||
m_zoneFlags = 0;
|
||||
else if(m_zoneFlags == 0)
|
||||
m_zoneFlags = TILESTATE_HOUSE | TILESTATE_PROTECTIONZONE;
|
||||
}
|
||||
|
||||
void Map::setZoneColor(tileflags_t zone, const Color& color)
|
||||
{
|
||||
if((m_zoneFlags & zone) == zone)
|
||||
m_zoneColors[zone] = color;
|
||||
}
|
||||
|
||||
void Map::beginGhostMode(float opacity)
|
||||
{
|
||||
g_painter->setOpacity(opacity);
|
||||
}
|
||||
|
||||
void Map::endGhostMode()
|
||||
{
|
||||
g_painter->resetOpacity();
|
||||
}
|
||||
|
||||
std::map<Position, ItemPtr> Map::findItemsById(uint16 clientId, uint32 max)
|
||||
{
|
||||
std::map<Position, ItemPtr> ret;
|
||||
uint32 count = 0;
|
||||
for(uint8_t z = 0; z <= Otc::MAX_Z; ++z) {
|
||||
for(const auto& pair : m_tileBlocks[z]) {
|
||||
const TileBlock& block = pair.second;
|
||||
for(const TilePtr& tile : block.getTiles()) {
|
||||
if(unlikely(!tile || tile->isEmpty()))
|
||||
continue;
|
||||
for(const ItemPtr& item : tile->getItems()) {
|
||||
if(item->getId() == clientId) {
|
||||
ret.insert(std::make_pair(tile->getPosition(), item));
|
||||
if(++count >= max)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Map::addCreature(const CreaturePtr& creature)
|
||||
{
|
||||
m_knownCreatures[creature->getId()] = creature;
|
||||
@@ -330,7 +422,7 @@ void Map::removeCreatureById(uint32 id)
|
||||
|
||||
void Map::removeUnawareThings()
|
||||
{
|
||||
// remove creatures from tiles that we are not aware anymore
|
||||
// remove creatures from tiles that we are not aware of anymore
|
||||
for(const auto& pair : m_knownCreatures) {
|
||||
const CreaturePtr& creature = pair.second;
|
||||
if(!isAwareOfPosition(creature->getPosition()))
|
||||
@@ -708,3 +800,5 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et: */
|
||||
|
@@ -144,13 +144,14 @@ public:
|
||||
bool loadOtcm(const std::string& fileName);
|
||||
void saveOtcm(const std::string& fileName);
|
||||
|
||||
void loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar = 0);
|
||||
void saveOtbm(const std::string& fileName, const UIWidgetPtr& pbar = 0);
|
||||
void loadOtbm(const std::string& fileName);
|
||||
void saveOtbm(const std::string& fileName);
|
||||
|
||||
// otbm attributes (description, size, etc.)
|
||||
void setHouseFile(const std::string& file) { m_attribs.set(OTBM_ATTR_HOUSE_FILE, file); }
|
||||
void setSpawnFile(const std::string& file) { m_attribs.set(OTBM_ATTR_SPAWN_FILE, file); }
|
||||
void setDescription(const std::string& desc) { m_attribs.set(OTBM_ATTR_DESCRIPTION, desc); }
|
||||
void clearDescriptions() { m_attribs.remove(OTBM_ATTR_DESCRIPTION); }
|
||||
void setWidth(uint16 w) { m_attribs.set(OTBM_ATTR_WIDTH, w); }
|
||||
void setHeight(uint16 h) { m_attribs.set(OTBM_ATTR_HEIGHT, h); }
|
||||
|
||||
@@ -168,6 +169,8 @@ public:
|
||||
ThingPtr getThing(const Position& pos, int stackPos);
|
||||
bool removeThing(const ThingPtr& thing);
|
||||
bool removeThingByPos(const Position& pos, int stackPos);
|
||||
void colorizeThing(const ThingPtr& thing, const Color& color);
|
||||
void removeThingColor(const ThingPtr& thing);
|
||||
|
||||
StaticTextPtr getStaticText(const Position& pos);
|
||||
|
||||
@@ -179,6 +182,23 @@ public:
|
||||
const TilePtr& getTile(const Position& pos);
|
||||
void cleanTile(const Position& pos);
|
||||
|
||||
// tile zone related
|
||||
void setShowZone(tileflags_t zone, bool show);
|
||||
void setShowZones(bool show);
|
||||
void setZoneColor(tileflags_t flag, const Color& color);
|
||||
void setZoneOpacity(float opacity) { m_zoneOpacity = opacity; }
|
||||
|
||||
float getZoneOpacity() { return m_zoneOpacity; }
|
||||
Color getZoneColor(tileflags_t flag) { return m_zoneColors[flag]; }
|
||||
tileflags_t getZoneFlags() { return (tileflags_t)m_zoneFlags; }
|
||||
bool showZones() { return m_zoneFlags != 0; }
|
||||
bool showZone(tileflags_t zone) { return (m_zoneFlags & zone) == zone; }
|
||||
|
||||
void beginGhostMode(float opacity);
|
||||
void endGhostMode();
|
||||
|
||||
std::map<Position, ItemPtr> findItemsById(uint16 clientId, uint32 max);
|
||||
|
||||
// known creature related
|
||||
void addCreature(const CreaturePtr& creature);
|
||||
CreaturePtr getCreatureById(uint32 id);
|
||||
@@ -223,6 +243,10 @@ private:
|
||||
std::vector<MapViewPtr> m_mapViews;
|
||||
std::unordered_map<Position, std::string, PositionHasher> m_waypoints;
|
||||
|
||||
uint32 m_zoneFlags;
|
||||
std::array<Color, TILESTATE_LAST> m_zoneColors;
|
||||
float m_zoneOpacity;
|
||||
|
||||
Light m_light;
|
||||
Position m_centralPosition;
|
||||
Rect m_tilesRect;
|
||||
@@ -235,3 +259,5 @@ private:
|
||||
extern Map g_map;
|
||||
|
||||
#endif
|
||||
|
||||
/* vim: set ts=4 sw=4 et: */
|
||||
|
@@ -32,8 +32,9 @@
|
||||
#include <framework/xml/tinyxml.h>
|
||||
#include <framework/ui/uiwidget.h>
|
||||
|
||||
void Map::loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar)
|
||||
void Map::loadOtbm(const std::string& fileName)
|
||||
{
|
||||
try {
|
||||
FileStreamPtr fin = g_resources.openFile(fileName);
|
||||
if(!fin)
|
||||
stdext::throw_exception(stdext::format("Unable to load map '%s'", fileName));
|
||||
@@ -73,7 +74,7 @@ void Map::loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar)
|
||||
if(node->getU8() != OTBM_MAP_DATA)
|
||||
stdext::throw_exception("Could not read root data node");
|
||||
|
||||
while (node->canRead()) {
|
||||
while(node->canRead()) {
|
||||
uint8 attribute = node->getU8();
|
||||
std::string tmp = node->getString();
|
||||
switch (attribute) {
|
||||
@@ -94,7 +95,6 @@ void Map::loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar)
|
||||
for(const BinaryTreePtr& nodeMapData : node->getChildren()) {
|
||||
uint8 mapDataType = nodeMapData->getU8();
|
||||
if(mapDataType == OTBM_TILE_AREA) {
|
||||
|
||||
Position basePos;
|
||||
basePos.x = nodeMapData->getU16();
|
||||
basePos.y = nodeMapData->getU16();
|
||||
@@ -102,7 +102,7 @@ void Map::loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar)
|
||||
|
||||
for(const BinaryTreePtr &nodeTile : nodeMapData->getChildren()) {
|
||||
uint8 type = nodeTile->getU8();
|
||||
if(type != OTBM_TILE && type != OTBM_HOUSETILE)
|
||||
if(unlikely(type != OTBM_TILE && type != OTBM_HOUSETILE))
|
||||
stdext::throw_exception(stdext::format("invalid node tile type %d", (int)type));
|
||||
|
||||
HousePtr house = nullptr;
|
||||
@@ -121,7 +121,7 @@ void Map::loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar)
|
||||
|
||||
while(nodeTile->canRead()) {
|
||||
uint8 tileAttr = nodeTile->getU8();
|
||||
switch (tileAttr) {
|
||||
switch(tileAttr) {
|
||||
case OTBM_ATTR_TILE_FLAGS: {
|
||||
uint32 _flags = nodeTile->getU32();
|
||||
if((_flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE)
|
||||
@@ -137,6 +137,8 @@ void Map::loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar)
|
||||
if((_flags & TILESTATE_REFRESH) == TILESTATE_REFRESH)
|
||||
flags |= TILESTATE_REFRESH;
|
||||
|
||||
if((_flags & TILESTATE_HOUSE) == TILESTATE_HOUSE)
|
||||
flags |= TILESTATE_HOUSE;
|
||||
break;
|
||||
}
|
||||
case OTBM_ATTR_ITEM: {
|
||||
@@ -151,7 +153,7 @@ void Map::loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar)
|
||||
}
|
||||
|
||||
for(const BinaryTreePtr& nodeItem : nodeTile->getChildren()) {
|
||||
if(nodeItem->getU8() != OTBM_ITEM)
|
||||
if(unlikely(nodeItem->getU8() != OTBM_ITEM))
|
||||
stdext::throw_exception("invalid item node");
|
||||
|
||||
ItemPtr item = Item::createFromOtb(nodeItem->getU16());
|
||||
@@ -177,10 +179,9 @@ void Map::loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar)
|
||||
}
|
||||
|
||||
if(const TilePtr& tile = getTile(pos)) {
|
||||
if(house)
|
||||
tile->setHouseId(house->getId());
|
||||
if(tile->hasFlag(TILESTATE_HOUSE))
|
||||
tile->setFlags(tile->getFlags() & ~TILESTATE_HOUSE);
|
||||
tile->setFlags((tileflags_t)flags);
|
||||
//if(!(++pbarvalue % 8192) && pbar);
|
||||
}
|
||||
}
|
||||
} else if(mapDataType == OTBM_TOWNS) {
|
||||
@@ -197,10 +198,8 @@ void Map::loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar)
|
||||
townCoords.y = nodeTown->getU16();
|
||||
townCoords.z = nodeTown->getU8();
|
||||
|
||||
if(!(town = g_towns.getTown(townId))) {
|
||||
town = TownPtr(new Town(townId, townName, townCoords));
|
||||
g_towns.addTown(town);
|
||||
}
|
||||
if(!(town = g_towns.getTown(townId)))
|
||||
g_towns.addTown(TownPtr(new Town(townId, townName, townCoords)));
|
||||
}
|
||||
} else if(mapDataType == OTBM_WAYPOINTS && headerVersion > 1) {
|
||||
for(const BinaryTreePtr &nodeWaypoint : nodeMapData->getChildren()) {
|
||||
@@ -222,10 +221,14 @@ void Map::loadOtbm(const std::string& fileName, const UIWidgetPtr& pbar)
|
||||
}
|
||||
|
||||
fin->close();
|
||||
} catch(std::exception& e) {
|
||||
g_logger.error(stdext::format("Failed to load '%s': %s", fileName, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void Map::saveOtbm(const std::string& fileName, const UIWidgetPtr&/* pbar*/)
|
||||
void Map::saveOtbm(const std::string& fileName)
|
||||
{
|
||||
try {
|
||||
FileStreamPtr fin = g_resources.createFile(fileName);
|
||||
if(!fin)
|
||||
stdext::throw_exception(stdext::format("failed to open file '%s' for write", fileName));
|
||||
@@ -295,10 +298,8 @@ void Map::saveOtbm(const std::string& fileName, const UIWidgetPtr&/* pbar*/)
|
||||
root->addString(spawnFile);
|
||||
|
||||
// house file.
|
||||
if(version > 1) {
|
||||
root->addU8(OTBM_ATTR_HOUSE_FILE);
|
||||
root->addString(houseFile);
|
||||
}
|
||||
|
||||
int px = -1, py = -1, pz =-1;
|
||||
bool firstNode = true;
|
||||
@@ -307,11 +308,11 @@ void Map::saveOtbm(const std::string& fileName, const UIWidgetPtr&/* pbar*/)
|
||||
for(const auto& it : m_tileBlocks[z]) {
|
||||
const TileBlock& block = it.second;
|
||||
for(const TilePtr& tile : block.getTiles()) {
|
||||
if(!tile || tile->isEmpty())
|
||||
if(unlikely(!tile || tile->isEmpty()))
|
||||
continue;
|
||||
|
||||
const Position& pos = tile->getPosition();
|
||||
if(!pos.isValid())
|
||||
if(unlikely(!pos.isValid()))
|
||||
continue;
|
||||
|
||||
if(pos.x < px || pos.x >= px + 256
|
||||
@@ -365,21 +366,26 @@ void Map::saveOtbm(const std::string& fileName, const UIWidgetPtr&/* pbar*/)
|
||||
|
||||
root->startNode(OTBM_TOWNS);
|
||||
for(const TownPtr& town : g_towns.getTowns()) {
|
||||
root->startNode(OTBM_TOWN);
|
||||
|
||||
root->addU32(town->getId());
|
||||
root->addString(town->getName());
|
||||
|
||||
Position townPos = town->getPos();
|
||||
root->addPos(townPos.x, townPos.y, townPos.z);
|
||||
root->endNode();
|
||||
}
|
||||
root->endNode();
|
||||
|
||||
if(version > 1) {
|
||||
root->startNode(OTBM_WAYPOINTS);
|
||||
for(const auto& it : m_waypoints) {
|
||||
root->startNode(OTBM_WAYPOINT);
|
||||
root->addString(it.second);
|
||||
|
||||
Position pos = it.first;
|
||||
root->addPos(pos.x, pos.y, pos.z);
|
||||
root->endNode();
|
||||
}
|
||||
root->endNode();
|
||||
}
|
||||
@@ -390,6 +396,9 @@ void Map::saveOtbm(const std::string& fileName, const UIWidgetPtr&/* pbar*/)
|
||||
|
||||
fin->flush();
|
||||
fin->close();
|
||||
} catch(std::exception& e) {
|
||||
g_logger.error(stdext::format("Failed to save '%s': %s", fileName, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
bool Map::loadOtcm(const std::string& fileName)
|
||||
@@ -537,3 +546,5 @@ void Map::saveOtcm(const std::string& fileName)
|
||||
g_logger.error(stdext::format("failed to save OTCM map: %s", e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et: */
|
||||
|
@@ -564,12 +564,20 @@ Position MapView::getPosition(const Point& point, const Size& mapSize)
|
||||
return position;
|
||||
}
|
||||
|
||||
void MapView::move(int x, int y)
|
||||
{
|
||||
m_moveOffset.x = x;
|
||||
m_moveOffset.y = y;
|
||||
}
|
||||
|
||||
Rect MapView::calcFramebufferSource(const Size& destSize)
|
||||
{
|
||||
float scaleFactor = m_tileSize/(float)Otc::TILE_PIXELS;
|
||||
Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * m_tileSize;
|
||||
if(isFollowingCreature())
|
||||
drawOffset += m_followingCreature->getWalkOffset() * scaleFactor;
|
||||
else if(!m_moveOffset.isNull())
|
||||
drawOffset += m_moveOffset * scaleFactor;
|
||||
|
||||
Size srcSize = destSize;
|
||||
Size srcVisible = m_visibleDimension * m_tileSize;
|
||||
@@ -608,21 +616,21 @@ int MapView::calcFirstVisibleFloor()
|
||||
Position pos = cameraPosition.translated(ix, iy);
|
||||
|
||||
// process tiles that we can look through, e.g. windows, doors
|
||||
if((ix == 0 && iy == 0) || (/*(std::abs(ix) != std::abs(iy)) && */g_map.isLookPossible(pos))) {
|
||||
if((ix == 0 && iy == 0) || ((std::abs(ix) != std::abs(iy)) && g_map.isLookPossible(pos))) {
|
||||
Position upperPos = pos;
|
||||
Position coveredPos = pos;
|
||||
|
||||
while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
|
||||
// check tiles physically above
|
||||
TilePtr tile = g_map.getTile(upperPos);
|
||||
if(tile && tile->limitsFloorsView()) {
|
||||
if(tile && tile->limitsFloorsView(!g_map.isLookPossible(pos))) {
|
||||
firstFloor = upperPos.z + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// check tiles geometrically above
|
||||
tile = g_map.getTile(coveredPos);
|
||||
if(tile && tile->limitsFloorsView()) {
|
||||
if(tile && tile->limitsFloorsView(g_map.isLookPossible(pos))) {
|
||||
firstFloor = coveredPos.z + 1;
|
||||
break;
|
||||
}
|
||||
@@ -703,3 +711,5 @@ void MapView::setDrawLights(bool enable)
|
||||
m_lightView = nullptr;
|
||||
m_drawLights = enable;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et: */
|
||||
|
@@ -108,6 +108,8 @@ public:
|
||||
void setDrawLights(bool enable);
|
||||
bool isDrawingLights() { return m_drawLights; }
|
||||
|
||||
void move(int x, int y);
|
||||
|
||||
void setAnimated(bool animated) { m_animated = animated; requestVisibleTilesCacheUpdate(); }
|
||||
bool isAnimating() { return m_animated; }
|
||||
|
||||
@@ -139,6 +141,7 @@ private:
|
||||
Size m_optimizedSize;
|
||||
Point m_virtualCenterOffset;
|
||||
Point m_visibleCenterOffset;
|
||||
Point m_moveOffset;
|
||||
Position m_customCameraPosition;
|
||||
stdext::boolean<true> m_mustUpdateVisibleTilesCache;
|
||||
stdext::boolean<true> m_mustDrawVisibleTilesCache;
|
||||
|
@@ -29,7 +29,6 @@
|
||||
#include <framework/graphics/painter.h>
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/framebuffermanager.h>
|
||||
#include <framework/graphics/ogl/textureogl.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
#include <zlib.h>
|
||||
@@ -66,7 +65,7 @@ void MinimapBlock::update()
|
||||
|
||||
if(shouldDraw) {
|
||||
if(!m_texture) {
|
||||
m_texture = TexturePtr(new TextureOGL(image, true));
|
||||
m_texture = TexturePtr(new Texture(image, true));
|
||||
} else {
|
||||
m_texture->uploadPixels(image, true);
|
||||
}
|
||||
|
@@ -189,6 +189,8 @@ public:
|
||||
bool isInRange(const Position& pos, int minXRange, int maxXRange, int minYRange, int maxYRange) const {
|
||||
return (pos.x >= x-minXRange && pos.x <= x+maxXRange && pos.y >= y-minYRange && pos.y <= y+maxYRange && pos.z == z);
|
||||
}
|
||||
// operator less than for std::map
|
||||
bool operator<(const Position& other) const { return x < other.x || y < other.y || z < other.z; }
|
||||
|
||||
bool up(int n = 1) {
|
||||
int nz = z-n;
|
||||
|
@@ -57,7 +57,7 @@ void buildMessageModesMap(int version) {
|
||||
messageModesMap[Otc::MessageFailure] = 20;
|
||||
messageModesMap[Otc::MessageBlue] = 21;
|
||||
messageModesMap[Otc::MessageRed] = 22;
|
||||
} else if(version >= 854) {
|
||||
} else if(version >= 850) {
|
||||
messageModesMap[Otc::MessageNone] = 0;
|
||||
messageModesMap[Otc::MessageSay] = 1;
|
||||
messageModesMap[Otc::MessageWhisper] = 2;
|
||||
@@ -87,7 +87,7 @@ void buildMessageModesMap(int version) {
|
||||
messageModesMap[Otc::MessageLook] = 25;
|
||||
messageModesMap[Otc::MessageFailure] = 26;
|
||||
messageModesMap[Otc::MessageBlue] = 27;
|
||||
} else if(version >= 810) {
|
||||
} else if(version >= 760) {
|
||||
messageModesMap[Otc::MessageNone] = 0;
|
||||
messageModesMap[Otc::MessageSay] = 1;
|
||||
messageModesMap[Otc::MessageWhisper] = 2;
|
||||
|
@@ -102,6 +102,8 @@ namespace Proto {
|
||||
GameServerCreatureSkull = 144,
|
||||
GameServerCreatureParty = 145,
|
||||
GameServerCreatureUnpass = 146,
|
||||
GameServerCreatureMarks = 147,
|
||||
GameServerPlayerHelpers = 148,
|
||||
GameServerEditText = 150,
|
||||
GameServerEditList = 151,
|
||||
GameServerPlayerDataBasic = 159, // 950
|
||||
@@ -109,6 +111,7 @@ namespace Proto {
|
||||
GameServerPlayerSkills = 161,
|
||||
GameServerPlayerState = 162,
|
||||
GameServerClearTarget = 163,
|
||||
GameServerPlayerModes = 167,
|
||||
GameServerSpellDelay = 164, // 870
|
||||
GameServerSpellGroupDelay = 165, // 870
|
||||
GameServerMultiUseDelay = 166, // 870
|
||||
@@ -247,7 +250,9 @@ namespace Proto {
|
||||
enum CreatureType {
|
||||
CreatureTypePlayer = 0,
|
||||
CreatureTypeMonster,
|
||||
CreatureTypeNpc
|
||||
CreatureTypeNpc,
|
||||
CreatureTypeSummonOwn,
|
||||
CreatureTypeSummonOther
|
||||
};
|
||||
|
||||
enum CreaturesIdRange {
|
||||
|
@@ -125,6 +125,7 @@ public:
|
||||
void addPosition(const OutputMessagePtr& msg, const Position& position);
|
||||
|
||||
private:
|
||||
void parsePlayerHelpers(const InputMessagePtr& msg);
|
||||
void parseMessage(const InputMessagePtr& msg);
|
||||
void parsePendingGame(const InputMessagePtr& msg);
|
||||
void parseEnterGame(const InputMessagePtr& msg);
|
||||
@@ -178,6 +179,7 @@ private:
|
||||
void parsePlayerSkills(const InputMessagePtr& msg);
|
||||
void parsePlayerState(const InputMessagePtr& msg);
|
||||
void parsePlayerCancelAttack(const InputMessagePtr& msg);
|
||||
void parsePlayerModes(const InputMessagePtr& msg);
|
||||
void parseSpellCooldown(const InputMessagePtr& msg);
|
||||
void parseSpellGroupCooldown(const InputMessagePtr& msg);
|
||||
void parseMultiUseCooldown(const InputMessagePtr& msg);
|
||||
@@ -213,6 +215,7 @@ private:
|
||||
void parseShowModalDialog(const InputMessagePtr& msg);
|
||||
void parseExtendedOpcode(const InputMessagePtr& msg);
|
||||
void parseChangeMapAwareRange(const InputMessagePtr& msg);
|
||||
void parseCreaturesMark(const InputMessagePtr& msg);
|
||||
|
||||
public:
|
||||
void setMapDescription(const InputMessagePtr& msg, int x, int y, int z, int width, int height);
|
||||
|
@@ -219,6 +219,9 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
||||
case Proto::GameServerClearTarget:
|
||||
parsePlayerCancelAttack(msg);
|
||||
break;
|
||||
case Proto::GameServerPlayerModes:
|
||||
parsePlayerModes(msg);
|
||||
break;
|
||||
case Proto::GameServerTalk:
|
||||
parseTalk(msg);
|
||||
break;
|
||||
@@ -323,6 +326,13 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
||||
case Proto::GameServerEnterGame:
|
||||
parseEnterGame(msg);
|
||||
break;
|
||||
case Proto::GameServerPlayerHelpers:
|
||||
parsePlayerHelpers(msg);
|
||||
break;
|
||||
// PROTOCOL>=1000
|
||||
case Proto::GameServerCreatureMarks:
|
||||
parseCreaturesMark(msg);
|
||||
break;
|
||||
// otclient ONLY
|
||||
case Proto::GameServerExtendedOpcode:
|
||||
parseExtendedOpcode(msg);
|
||||
@@ -379,13 +389,25 @@ void ProtocolGame::parseEnterGame(const InputMessagePtr& msg)
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolGame::parsePlayerHelpers(const InputMessagePtr& msg)
|
||||
{
|
||||
uint id = msg->getU32();
|
||||
int helpers = msg->getU16();
|
||||
|
||||
CreaturePtr creature = g_map.getCreatureById(id);
|
||||
if(creature)
|
||||
g_game.processPlayerHelpers(helpers);
|
||||
else
|
||||
g_logger.traceError("could not get creature");
|
||||
}
|
||||
|
||||
void ProtocolGame::parseGMActions(const InputMessagePtr& msg)
|
||||
{
|
||||
std::vector<uint8> actions;
|
||||
|
||||
int numViolationReasons;
|
||||
|
||||
if(g_game.getProtocolVersion() >= 854)
|
||||
if(g_game.getProtocolVersion() >= 850)
|
||||
numViolationReasons = 20;
|
||||
else
|
||||
numViolationReasons = 32;
|
||||
@@ -535,7 +557,7 @@ void ProtocolGame::parseTileAddThing(const InputMessagePtr& msg)
|
||||
Position pos = getPosition(msg);
|
||||
int stackPos = -1;
|
||||
|
||||
if(g_game.getProtocolVersion() >= 854)
|
||||
if(g_game.getProtocolVersion() >= 850)
|
||||
stackPos = msg->getU8();
|
||||
|
||||
ThingPtr thing = getThing(msg);
|
||||
@@ -603,13 +625,26 @@ void ProtocolGame::parseOpenContainer(const InputMessagePtr& msg)
|
||||
std::string name = msg->getString();
|
||||
int capacity = msg->getU8();
|
||||
bool hasParent = (msg->getU8() != 0);
|
||||
|
||||
bool isUnlocked = false;
|
||||
bool hasPages = false;
|
||||
int containerSize = 0;
|
||||
int firstIndex = 0;
|
||||
|
||||
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||
isUnlocked = (msg->getU8() != 0); // drag and drop
|
||||
hasPages = (msg->getU8() != 0); // pagination
|
||||
containerSize = msg->getU16(); // container size
|
||||
firstIndex = msg->getU16(); // first index
|
||||
}
|
||||
|
||||
int itemCount = msg->getU8();
|
||||
|
||||
std::vector<ItemPtr> items(itemCount);
|
||||
for(int i = 0; i < itemCount; i++)
|
||||
items[i] = getItem(msg);
|
||||
|
||||
g_game.processOpenContainer(containerId, containerItem, name, capacity, hasParent, items);
|
||||
g_game.processOpenContainer(containerId, containerItem, name, capacity, hasParent, items, isUnlocked, hasPages, containerSize, firstIndex);
|
||||
}
|
||||
|
||||
void ProtocolGame::parseCloseContainer(const InputMessagePtr& msg)
|
||||
@@ -621,14 +656,23 @@ void ProtocolGame::parseCloseContainer(const InputMessagePtr& msg)
|
||||
void ProtocolGame::parseContainerAddItem(const InputMessagePtr& msg)
|
||||
{
|
||||
int containerId = msg->getU8();
|
||||
int slot = 0;
|
||||
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||
slot = msg->getU16(); // slot
|
||||
}
|
||||
ItemPtr item = getItem(msg);
|
||||
g_game.processContainerAddItem(containerId, item);
|
||||
g_game.processContainerAddItem(containerId, item, slot);
|
||||
}
|
||||
|
||||
void ProtocolGame::parseContainerUpdateItem(const InputMessagePtr& msg)
|
||||
{
|
||||
int containerId = msg->getU8();
|
||||
int slot = msg->getU8();
|
||||
int slot;
|
||||
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||
slot = msg->getU16();
|
||||
} else {
|
||||
slot = msg->getU8();
|
||||
}
|
||||
ItemPtr item = getItem(msg);
|
||||
g_game.processContainerUpdateItem(containerId, slot, item);
|
||||
}
|
||||
@@ -636,7 +680,16 @@ void ProtocolGame::parseContainerUpdateItem(const InputMessagePtr& msg)
|
||||
void ProtocolGame::parseContainerRemoveItem(const InputMessagePtr& msg)
|
||||
{
|
||||
int containerId = msg->getU8();
|
||||
int slot = msg->getU8();
|
||||
int slot;
|
||||
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||
slot = msg->getU16();
|
||||
|
||||
int itemId = msg->getU16();
|
||||
if(itemId != 0)
|
||||
getItem(msg, itemId);
|
||||
} else {
|
||||
slot = msg->getU8();
|
||||
}
|
||||
g_game.processContainerRemoveItem(containerId, slot);
|
||||
}
|
||||
|
||||
@@ -931,7 +984,15 @@ void ProtocolGame::parseCreatureUnpass(const InputMessagePtr& msg)
|
||||
void ProtocolGame::parseEditText(const InputMessagePtr& msg)
|
||||
{
|
||||
uint id = msg->getU32();
|
||||
int itemId = msg->getU16();
|
||||
|
||||
int itemId;
|
||||
if(g_game.getProtocolVersion() >= 1010) {
|
||||
// TODO: processEditText with ItemPtr as parameter
|
||||
ItemPtr item = getItem(msg);
|
||||
itemId = item->getId();
|
||||
} else
|
||||
itemId = msg->getU16();
|
||||
|
||||
int maxLength = msg->getU16();
|
||||
std::string text = msg->getString();
|
||||
std::string writter = msg->getString();
|
||||
@@ -1016,7 +1077,9 @@ void ProtocolGame::parsePlayerStats(const InputMessagePtr& msg)
|
||||
|
||||
double magicLevelPercent = msg->getU8();
|
||||
double soul = msg->getU8();
|
||||
double stamina = msg->getU16();
|
||||
double stamina = 0;
|
||||
if(g_game.getFeature(Otc::GamePlayerStamina))
|
||||
stamina = msg->getU16();
|
||||
|
||||
double baseSpeed = 0;
|
||||
if(g_game.getFeature(Otc::GameSkillsBase))
|
||||
@@ -1070,7 +1133,12 @@ void ProtocolGame::parsePlayerSkills(const InputMessagePtr& msg)
|
||||
|
||||
void ProtocolGame::parsePlayerState(const InputMessagePtr& msg)
|
||||
{
|
||||
int states = msg->getU16();
|
||||
int states;
|
||||
if(g_game.getFeature(Otc::GamePlayerStateU16))
|
||||
states = msg->getU16();
|
||||
else
|
||||
states = msg->getU8();
|
||||
|
||||
m_localPlayer->setStates(states);
|
||||
}
|
||||
|
||||
@@ -1083,6 +1151,20 @@ void ProtocolGame::parsePlayerCancelAttack(const InputMessagePtr& msg)
|
||||
g_game.processAttackCancel(seq);
|
||||
}
|
||||
|
||||
|
||||
void ProtocolGame::parsePlayerModes(const InputMessagePtr& msg)
|
||||
{
|
||||
int fightMode = msg->getU8();
|
||||
int chaseMode = msg->getU8();
|
||||
bool safeMode = msg->getU8();
|
||||
|
||||
//TODO: implement pvp modes
|
||||
if(g_game.getFeature(Otc::GamePVPMode))
|
||||
msg->getU8(); // pvp mode
|
||||
|
||||
g_game.processPlayerModes((Otc::FightModes)fightMode, (Otc::ChaseModes)chaseMode, safeMode);
|
||||
}
|
||||
|
||||
void ProtocolGame::parseSpellCooldown(const InputMessagePtr& msg)
|
||||
{
|
||||
int spellId = msg->getU8();
|
||||
@@ -1108,10 +1190,15 @@ void ProtocolGame::parseMultiUseCooldown(const InputMessagePtr& msg)
|
||||
|
||||
void ProtocolGame::parseTalk(const InputMessagePtr& msg)
|
||||
{
|
||||
if(g_game.getFeature(Otc::GameMessageStatements))
|
||||
msg->getU32(); // channel statement guid
|
||||
|
||||
std::string name = g_game.formatCreatureName(msg->getString());
|
||||
int level = msg->getU16();
|
||||
|
||||
int level = 0;
|
||||
if(g_game.getFeature(Otc::GameMessageLevel))
|
||||
level = msg->getU16();
|
||||
|
||||
Otc::MessageMode mode = Proto::translateMessageModeFromServer(msg->getU8());
|
||||
int channelId = 0;
|
||||
Position pos;
|
||||
@@ -1358,8 +1445,9 @@ void ProtocolGame::parseFloorChangeDown(const InputMessagePtr& msg)
|
||||
void ProtocolGame::parseOpenOutfitWindow(const InputMessagePtr& msg)
|
||||
{
|
||||
Outfit currentOutfit = getOutfit(msg);
|
||||
|
||||
std::vector<std::tuple<int, std::string, int> > outfitList;
|
||||
|
||||
if(g_game.getFeature(Otc::GameNewOutfitProtocol)) {
|
||||
int outfitCount = msg->getU8();
|
||||
for(int i = 0; i < outfitCount; i++) {
|
||||
int outfitId = msg->getU16();
|
||||
@@ -1368,6 +1456,12 @@ void ProtocolGame::parseOpenOutfitWindow(const InputMessagePtr& msg)
|
||||
|
||||
outfitList.push_back(std::make_tuple(outfitId, outfitName, outfitAddons));
|
||||
}
|
||||
} else {
|
||||
int outfitStart = msg->getU8();
|
||||
int outfitEnd = msg->getU8();
|
||||
for(int i = outfitStart; i <= outfitEnd; i++)
|
||||
outfitList.push_back(std::make_tuple(i, "", 0));
|
||||
}
|
||||
|
||||
std::vector<std::tuple<int, std::string> > mountList;
|
||||
if(g_game.getFeature(Otc::GamePlayerMounts)) {
|
||||
@@ -1579,6 +1673,28 @@ void ProtocolGame::parseChangeMapAwareRange(const InputMessagePtr& msg)
|
||||
g_lua.callGlobalField("g_game", "onMapChangeAwareRange", xrange, yrange);
|
||||
}
|
||||
|
||||
void ProtocolGame::parseCreaturesMark(const InputMessagePtr& msg)
|
||||
{
|
||||
int len = msg->getU8();
|
||||
for(int i=0; i<len; ++i) {
|
||||
uint32 id = msg->getU32();
|
||||
bool isPermanent = msg->getU8() != 1;
|
||||
uint8 markType = msg->getU8();
|
||||
|
||||
CreaturePtr creature = g_map.getCreatureById(id);
|
||||
if(creature) {
|
||||
if(isPermanent) {
|
||||
if(markType == 0xff)
|
||||
creature->hideStaticSquare();
|
||||
else
|
||||
creature->showStaticSquare(Color::from8bit(markType));
|
||||
} else
|
||||
creature->addTimedSquare(markType);
|
||||
} else
|
||||
g_logger.traceError("could not get creature");
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolGame::setMapDescription(const InputMessagePtr& msg, int x, int y, int z, int width, int height)
|
||||
{
|
||||
int startz, endz, zstep;
|
||||
@@ -1643,14 +1759,21 @@ Outfit ProtocolGame::getOutfit(const InputMessagePtr& msg)
|
||||
{
|
||||
Outfit outfit;
|
||||
|
||||
int lookType = msg->getU16();
|
||||
int lookType;
|
||||
if(g_game.getFeature(Otc::GameLooktypeU16))
|
||||
lookType = msg->getU16();
|
||||
else
|
||||
lookType = msg->getU8();
|
||||
|
||||
if(lookType != 0) {
|
||||
outfit.setCategory(ThingCategoryCreature);
|
||||
int head = msg->getU8();
|
||||
int body = msg->getU8();
|
||||
int legs = msg->getU8();
|
||||
int feet = msg->getU8();
|
||||
int addons = msg->getU8();
|
||||
int addons = 0;
|
||||
if(g_game.getFeature(Otc::GamePlayerAddons))
|
||||
addons = msg->getU8();
|
||||
|
||||
if(!g_things.isValidDatId(lookType, ThingCategoryCreature)) {
|
||||
g_logger.traceError(stdext::format("invalid outfit looktype %d", lookType));
|
||||
@@ -1804,10 +1927,24 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
||||
// emblem is sent only when the creature is not known
|
||||
int emblem = -1;
|
||||
bool unpass = true;
|
||||
uint8 mark;
|
||||
|
||||
if(g_game.getFeature(Otc::GameCreatureEmblems) && !known)
|
||||
emblem = msg->getU8();
|
||||
|
||||
if(g_game.getFeature(Otc::GameThingMarks)) {
|
||||
msg->getU8(); // creature type for summons
|
||||
mark = msg->getU8(); // mark
|
||||
msg->getU16(); // helpers
|
||||
|
||||
if(creature) {
|
||||
if(mark == 0xff)
|
||||
creature->hideStaticSquare();
|
||||
else
|
||||
creature->showStaticSquare(Color::from8bit(mark));
|
||||
}
|
||||
}
|
||||
|
||||
if(g_game.getProtocolVersion() >= 854)
|
||||
unpass = msg->getU8();
|
||||
|
||||
@@ -1860,6 +1997,10 @@ ItemPtr ProtocolGame::getItem(const InputMessagePtr& msg, int id)
|
||||
if(item->getId() == 0)
|
||||
stdext::throw_exception(stdext::format("unable to create item with invalid id %d", id));
|
||||
|
||||
if(g_game.getFeature(Otc::GameThingMarks)) {
|
||||
msg->getU8(); // mark
|
||||
}
|
||||
|
||||
if(item->isStackable() || item->isFluidContainer() || item->isSplash() || item->isChargeable())
|
||||
item->setCountOrSubType(msg->getU8());
|
||||
|
||||
@@ -1867,7 +2008,7 @@ ItemPtr ProtocolGame::getItem(const InputMessagePtr& msg, int id)
|
||||
if(item->getAnimationPhases() > 1) {
|
||||
// 0xfe => random phase
|
||||
// 0xff => async?
|
||||
msg->getU8(); // phase
|
||||
item->setAsync(msg->getU8() == 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -52,8 +52,16 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
|
||||
{
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
|
||||
if(g_game.getProtocolVersion() == 760)
|
||||
{
|
||||
msg->addU16(0x20A);
|
||||
msg->addU8(g_game.getOs());
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->addU8(Proto::ClientPendingGame);
|
||||
msg->addU16(g_game.getOs());
|
||||
}
|
||||
msg->addU16(g_game.getProtocolVersion());
|
||||
|
||||
if(g_game.getProtocolVersion() >= 971) {
|
||||
@@ -65,6 +73,8 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
|
||||
|
||||
msg->addU8(0); // first RSA byte must be 0
|
||||
|
||||
if(g_game.getProtocolVersion() >= 800)
|
||||
{
|
||||
// xtea key
|
||||
generateXteaKey();
|
||||
msg->addU32(m_xteaKey[0]);
|
||||
@@ -72,6 +82,7 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
|
||||
msg->addU32(m_xteaKey[2]);
|
||||
msg->addU32(m_xteaKey[3]);
|
||||
msg->addU8(0); // is gm set?
|
||||
}
|
||||
|
||||
if(g_game.getFeature(Otc::GameAccountNames))
|
||||
msg->addString(m_accountName);
|
||||
@@ -96,6 +107,7 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
|
||||
msg->addPaddingBytes(paddingBytes);
|
||||
|
||||
// encrypt with RSA
|
||||
if(g_game.getProtocolVersion() >= 800)
|
||||
msg->encryptRsa();
|
||||
|
||||
if(g_game.getFeature(Otc::GameProtocolChecksum))
|
||||
@@ -103,6 +115,7 @@ void ProtocolGame::sendLoginPacket(uint challengeTimestamp, uint8 challengeRando
|
||||
|
||||
send(msg);
|
||||
|
||||
if(g_game.getProtocolVersion() >= 800)
|
||||
enableXteaEncryption();
|
||||
}
|
||||
|
||||
@@ -567,6 +580,11 @@ void ProtocolGame::sendChangeFightModes(Otc::FightModes fightMode, Otc::ChaseMod
|
||||
msg->addU8(fightMode);
|
||||
msg->addU8(chaseMode);
|
||||
msg->addU8(safeFight ? 0x01: 0x00);
|
||||
|
||||
//TODO: implement pvp modes
|
||||
if(g_game.getFeature(Otc::GamePVPMode))
|
||||
msg->addU8(0); // pvp mode
|
||||
|
||||
send(msg);
|
||||
}
|
||||
|
||||
|
@@ -48,11 +48,9 @@ bool SpriteManager::loadSpr(std::string file)
|
||||
file = g_resources.guessFilePath(file, "spr");
|
||||
|
||||
m_spritesFile = g_resources.openFile(file);
|
||||
|
||||
// cache file buffer to avoid lags from hard drive
|
||||
#ifndef MOBILE
|
||||
m_spritesFile->cache();
|
||||
#endif
|
||||
|
||||
m_signature = m_spritesFile->getU32();
|
||||
m_spritesCount = g_game.getFeature(Otc::GameSpritesU32) ? m_spritesFile->getU32() : m_spritesFile->getU16();
|
||||
m_spritesOffset = m_spritesFile->tell();
|
||||
|
@@ -28,7 +28,6 @@
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/texture.h>
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/ogl/textureogl.h>
|
||||
#include <framework/graphics/texturemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
#include <framework/otml/otml.h>
|
||||
@@ -68,6 +67,17 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
|
||||
attr -= 1;
|
||||
}
|
||||
|
||||
if(g_game.getProtocolVersion() >= 1010) {
|
||||
/* In 10.10 all attributes from 16 and up were
|
||||
* incremented by 1 to make space for 16 as
|
||||
* "No Movement Animation" flag.
|
||||
*/
|
||||
if(attr == 16)
|
||||
attr = ThingAttrNoMoveAnimation;
|
||||
else if(attr > 16)
|
||||
attr -= 1;
|
||||
}
|
||||
|
||||
switch(attr) {
|
||||
case ThingAttrDisplacement: {
|
||||
m_displacement.x = fin->getU16();
|
||||
@@ -93,6 +103,7 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
|
||||
m_attribs.set(attr, market);
|
||||
break;
|
||||
}
|
||||
case ThingAttrUsable:
|
||||
case ThingAttrElevation: {
|
||||
m_elevation = fin->getU16();
|
||||
m_attribs.set(attr, m_elevation);
|
||||
@@ -127,8 +138,8 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
|
||||
|
||||
int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;
|
||||
|
||||
if(totalSprites == 0)
|
||||
stdext::throw_exception("a thing type has no sprites");
|
||||
// if(totalSprites == 0)
|
||||
// stdext::throw_exception("a thing type has no sprites");
|
||||
if(totalSprites > 4096)
|
||||
stdext::throw_exception("a thing type has more than 4096 sprites");
|
||||
|
||||
@@ -284,7 +295,7 @@ const TexturePtr& ThingType::getTexture(int animationPhase)
|
||||
}
|
||||
}
|
||||
}
|
||||
animationPhaseTexture = TexturePtr(new TextureOGL(fullImage));
|
||||
animationPhaseTexture = TexturePtr(new Texture(fullImage, true));
|
||||
animationPhaseTexture->setSmooth(true);
|
||||
}
|
||||
return animationPhaseTexture;
|
||||
|
@@ -76,11 +76,13 @@ enum ThingAttr : uint8 {
|
||||
ThingAttrLook = 31,
|
||||
ThingAttrCloth = 32,
|
||||
ThingAttrMarket = 33,
|
||||
ThingAttrUsable = 34,
|
||||
|
||||
// additional
|
||||
ThingAttrOpacity = 100,
|
||||
ThingAttrNotPreWalkable = 101,
|
||||
|
||||
ThingAttrNoMoveAnimation = 253, // real value is 16, but we need to do this for backwards compatibility
|
||||
ThingAttrChargeable = 254, // deprecated
|
||||
ThingLastAttr = 255
|
||||
};
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "itemtype.h"
|
||||
#include "creature.h"
|
||||
#include "creatures.h"
|
||||
#include "game.h"
|
||||
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
@@ -134,6 +135,7 @@ bool ThingTypeManager::loadOtml(std::string file)
|
||||
|
||||
void ThingTypeManager::loadOtb(const std::string& file)
|
||||
{
|
||||
try {
|
||||
FileStreamPtr fin = g_resources.openFile(file);
|
||||
|
||||
uint signature = fin->getU32();
|
||||
@@ -155,6 +157,7 @@ void ThingTypeManager::loadOtb(const std::string& file)
|
||||
|
||||
m_reverseItemTypes.clear();
|
||||
m_itemTypes.resize(root->getChildren().size() + 1, m_nullItemType);
|
||||
m_reverseItemTypes.resize(root->getChildren().size() + 1, m_nullItemType);
|
||||
|
||||
for(const BinaryTreePtr& node : root->getChildren()) {
|
||||
ItemTypePtr itemType(new ItemType);
|
||||
@@ -162,16 +165,20 @@ void ThingTypeManager::loadOtb(const std::string& file)
|
||||
addItemType(itemType);
|
||||
|
||||
uint16 clientId = itemType->getClientId();
|
||||
if(clientId >= m_reverseItemTypes.size())
|
||||
m_reverseItemTypes.resize(clientId+1);
|
||||
if(unlikely(clientId >= m_reverseItemTypes.size()))
|
||||
m_reverseItemTypes.resize(clientId + 1);
|
||||
m_reverseItemTypes[clientId] = itemType;
|
||||
}
|
||||
|
||||
m_otbLoaded = true;
|
||||
} catch(std::exception& e) {
|
||||
g_logger.error(stdext::format("Failed to load '%s' (OTB file): %s", file, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void ThingTypeManager::loadXml(const std::string& file)
|
||||
{
|
||||
try {
|
||||
if(!isOtbLoaded())
|
||||
stdext::throw_exception("OTB must be loaded before XML");
|
||||
|
||||
@@ -184,8 +191,8 @@ void ThingTypeManager::loadXml(const std::string& file)
|
||||
if(!root || root->ValueTStr() != "items")
|
||||
stdext::throw_exception("invalid root tag name");
|
||||
|
||||
for (TiXmlElement *element = root->FirstChildElement(); element; element = element->NextSiblingElement()) {
|
||||
if(element->ValueTStr() != "item")
|
||||
for(TiXmlElement *element = root->FirstChildElement(); element; element = element->NextSiblingElement()) {
|
||||
if(unlikely(element->ValueTStr() != "item"))
|
||||
continue;
|
||||
|
||||
uint16 id = element->readType<uint16>("id");
|
||||
@@ -205,23 +212,26 @@ void ThingTypeManager::loadXml(const std::string& file)
|
||||
std::vector<int32> end = stdext::split<int32>(element->Attribute("toid"), ";");
|
||||
if(begin[0] && begin.size() == end.size()) {
|
||||
size_t size = begin.size();
|
||||
for(size_t i = 0; i < size; ++i) {
|
||||
for(size_t i = 0; i < size; ++i)
|
||||
while(begin[i] <= end[i])
|
||||
parseItemType(begin[i]++, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc.Clear();
|
||||
m_xmlLoaded = true;
|
||||
g_logger.debug("items.xml read successfully.");
|
||||
} catch(std::exception& e) {
|
||||
g_logger.error(stdext::format("Failed to load '%s' (XML file): %s", file, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void ThingTypeManager::parseItemType(uint16 id, TiXmlElement* elem)
|
||||
{
|
||||
uint16 serverId = id;
|
||||
ItemTypePtr itemType = nullptr;
|
||||
if(g_game.getProtocolVersion() < 960) {
|
||||
if(serverId > 20000 && serverId < 20100) {
|
||||
serverId -= 20000;
|
||||
|
||||
@@ -230,6 +240,16 @@ void ThingTypeManager::parseItemType(uint16 id, TiXmlElement* elem)
|
||||
addItemType(itemType);
|
||||
} else
|
||||
itemType = getItemType(serverId);
|
||||
} else {
|
||||
if(serverId > 30000 && serverId < 30100) {
|
||||
serverId -= 30000;
|
||||
|
||||
itemType = ItemTypePtr(new ItemType);
|
||||
itemType->setServerId(serverId);
|
||||
addItemType(itemType);
|
||||
} else
|
||||
itemType = getItemType(serverId);
|
||||
}
|
||||
|
||||
itemType->setName(elem->Attribute("name"));
|
||||
for(TiXmlElement* attrib = elem->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) {
|
||||
@@ -267,7 +287,7 @@ void ThingTypeManager::parseItemType(uint16 id, TiXmlElement* elem)
|
||||
void ThingTypeManager::addItemType(const ItemTypePtr& itemType)
|
||||
{
|
||||
uint16 id = itemType->getServerId();
|
||||
if(id >= m_itemTypes.size())
|
||||
if(unlikely(id >= m_itemTypes.size()))
|
||||
m_itemTypes.resize(id + 1, m_nullItemType);
|
||||
m_itemTypes[id] = itemType;
|
||||
}
|
||||
@@ -283,6 +303,32 @@ const ItemTypePtr& ThingTypeManager::findItemTypeByClientId(uint16 id)
|
||||
return m_nullItemType;
|
||||
}
|
||||
|
||||
const ItemTypePtr& ThingTypeManager::findItemTypeByName(std::string name)
|
||||
{
|
||||
for(const ItemTypePtr& it : m_itemTypes)
|
||||
if(it->getName() == name)
|
||||
return it;
|
||||
return m_nullItemType;
|
||||
}
|
||||
|
||||
ItemTypeList ThingTypeManager::findItemTypesByName(std::string name)
|
||||
{
|
||||
ItemTypeList ret;
|
||||
for(const ItemTypePtr& it : m_itemTypes)
|
||||
if(it->getName() == name)
|
||||
ret.push_back(it);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ItemTypeList ThingTypeManager::findItemTypesByString(std::string name)
|
||||
{
|
||||
ItemTypeList ret;
|
||||
for(const ItemTypePtr& it : m_itemTypes)
|
||||
if(it->getName().find(name) != std::string::npos)
|
||||
ret.push_back(it);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const ThingTypePtr& ThingTypeManager::getThingType(uint16 id, ThingCategory category)
|
||||
{
|
||||
if(category >= ThingLastCategory || id >= m_thingTypes[category].size()) {
|
||||
@@ -295,7 +341,7 @@ const ThingTypePtr& ThingTypeManager::getThingType(uint16 id, ThingCategory cate
|
||||
const ItemTypePtr& ThingTypeManager::getItemType(uint16 id)
|
||||
{
|
||||
if(id >= m_itemTypes.size() || m_itemTypes[id] == m_nullItemType) {
|
||||
g_logger.error(stdext::format("invalid thing type server id %d", id));
|
||||
g_logger.error(stdext::format("invalid thing type, server id: %d", id));
|
||||
return m_nullItemType;
|
||||
}
|
||||
return m_itemTypes[id];
|
||||
@@ -326,3 +372,5 @@ const ThingTypeList& ThingTypeManager::getThingTypes(ThingCategory category)
|
||||
stdext::throw_exception(stdext::format("invalid thing type category %d", category));
|
||||
return m_thingTypes[category];
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et: */
|
||||
|
@@ -43,6 +43,9 @@ public:
|
||||
|
||||
void addItemType(const ItemTypePtr& itemType);
|
||||
const ItemTypePtr& findItemTypeByClientId(uint16 id);
|
||||
const ItemTypePtr& findItemTypeByName(std::string name);
|
||||
ItemTypeList findItemTypesByName(std::string name);
|
||||
ItemTypeList findItemTypesByString(std::string str);
|
||||
|
||||
const ThingTypePtr& getNullThingType() { return m_nullThingType; }
|
||||
const ItemTypePtr& getNullItemType() { return m_nullItemType; }
|
||||
|
@@ -43,6 +43,15 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags, LightView *
|
||||
{
|
||||
bool animate = drawFlags & Otc::DrawAnimations;
|
||||
|
||||
/* Flags to be checked for. */
|
||||
static const tileflags_t flags[] = {
|
||||
TILESTATE_HOUSE,
|
||||
TILESTATE_PROTECTIONZONE,
|
||||
TILESTATE_OPTIONALZONE,
|
||||
TILESTATE_HARDCOREZONE,
|
||||
TILESTATE_NOLOGOUT
|
||||
};
|
||||
|
||||
// first bottom items
|
||||
if(drawFlags & (Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawOnBottom)) {
|
||||
m_drawElevation = 0;
|
||||
@@ -50,10 +59,28 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags, LightView *
|
||||
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom())
|
||||
break;
|
||||
|
||||
bool restore = false;
|
||||
if(g_map.showZones() && thing->isGround()) {
|
||||
for(unsigned int i = 0; i < sizeof(flags) / sizeof(tileflags_t); ++i) {
|
||||
tileflags_t flag = flags[i];
|
||||
if(hasFlag(flag) && g_map.showZone(flag)) {
|
||||
g_painter->setOpacity(g_map.getZoneOpacity());
|
||||
g_painter->setColor(g_map.getZoneColor(flag));
|
||||
restore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((thing->isGround() && drawFlags & Otc::DrawGround) ||
|
||||
(thing->isGroundBorder() && drawFlags & Otc::DrawGroundBorders) ||
|
||||
(thing->isOnBottom() && drawFlags & Otc::DrawOnBottom)) {
|
||||
thing->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView);
|
||||
|
||||
if(restore) {
|
||||
g_painter->resetOpacity();
|
||||
g_painter->resetColor();
|
||||
}
|
||||
}
|
||||
|
||||
m_drawElevation += thing->getElevation();
|
||||
@@ -116,25 +143,19 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags, LightView *
|
||||
CreaturePtr creature = thing->static_self_cast<Creature>();
|
||||
if(creature && (!creature->isWalking() || !animate))
|
||||
creature->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// effects
|
||||
if(drawFlags & Otc::DrawEffects) {
|
||||
for(const EffectPtr& effect : m_effects){
|
||||
if(drawFlags & Otc::DrawEffects)
|
||||
for(const EffectPtr& effect : m_effects)
|
||||
effect->draw(dest - m_drawElevation*scaleFactor, scaleFactor, animate, lightView);
|
||||
}
|
||||
}
|
||||
|
||||
// top items
|
||||
if(drawFlags & Otc::DrawOnTop) {
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isOnTop()){
|
||||
if(drawFlags & Otc::DrawOnTop)
|
||||
for(const ThingPtr& thing : m_things)
|
||||
if(thing->isOnTop())
|
||||
thing->draw(dest, scaleFactor, animate, lightView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draw translucent light (for tiles beneath holes)
|
||||
if(hasTranslucentLight() && lightView) {
|
||||
@@ -289,10 +310,9 @@ ThingPtr Tile::getTopThing()
|
||||
{
|
||||
if(isEmpty())
|
||||
return nullptr;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
for(const ThingPtr& thing : m_things)
|
||||
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop() && !thing->isCreature())
|
||||
return thing;
|
||||
}
|
||||
return m_things[m_things.size() - 1];
|
||||
}
|
||||
|
||||
@@ -339,9 +359,8 @@ int Tile::getGroundSpeed()
|
||||
uint8 Tile::getMinimapColorByte()
|
||||
{
|
||||
uint8 color = 255; // alpha
|
||||
if(m_minimapColor != 0) {
|
||||
if(m_minimapColor != 0)
|
||||
return m_minimapColor;
|
||||
}
|
||||
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop())
|
||||
@@ -498,11 +517,9 @@ bool Tile::isWalkable(bool ignoreCreatures)
|
||||
|
||||
bool Tile::isPathable()
|
||||
{
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
for(const ThingPtr& thing : m_things)
|
||||
if(thing->isNotPathable())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -524,19 +541,17 @@ bool Tile::isSingleDimension()
|
||||
{
|
||||
if(!m_walkingCreatures.empty())
|
||||
return false;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
for(const ThingPtr& thing : m_things)
|
||||
if(thing->getHeight() != 1 || thing->getWidth() != 1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tile::isLookPossible()
|
||||
{
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
for(const ThingPtr& thing : m_things)
|
||||
if(thing->blockProjectile())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -590,15 +605,20 @@ bool Tile::hasCreature()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Tile::limitsFloorsView()
|
||||
bool Tile::limitsFloorsView(bool isFreeView)
|
||||
{
|
||||
// ground and walls limits the view
|
||||
ThingPtr firstThing = getThing(0);
|
||||
|
||||
if(isFreeView) {
|
||||
if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || firstThing->isOnBottom()))
|
||||
return true;
|
||||
} else if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || (firstThing->isOnBottom() && firstThing->blockProjectile())))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Tile::canErase()
|
||||
{
|
||||
return m_walkingCreatures.empty() && m_effects.empty() && m_things.empty() && m_flags == 0 && m_minimapColor == 0;
|
||||
@@ -635,7 +655,9 @@ void Tile::checkTranslucentLight()
|
||||
}
|
||||
|
||||
if(translucent)
|
||||
tile->m_flags = tile->m_flags | TILESTATE_TRANSLUECENT_LIGHT;
|
||||
tile->m_flags |= TILESTATE_TRANSLUECENT_LIGHT;
|
||||
else
|
||||
tile->m_flags = tile->m_flags & ~TILESTATE_TRANSLUECENT_LIGHT;
|
||||
tile->m_flags &= ~TILESTATE_TRANSLUECENT_LIGHT;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et :*/
|
||||
|
@@ -48,7 +48,9 @@ enum tileflags_t
|
||||
TILESTATE_TRASHHOLDER = 1 << 20,
|
||||
TILESTATE_BED = 1 << 21,
|
||||
TILESTATE_DEPOT = 1 << 22,
|
||||
TILESTATE_TRANSLUECENT_LIGHT = 1 << 23
|
||||
TILESTATE_TRANSLUECENT_LIGHT = 1 << 23,
|
||||
|
||||
TILESTATE_LAST = 1 << 24
|
||||
};
|
||||
|
||||
class Tile : public LuaObject
|
||||
@@ -105,17 +107,19 @@ public:
|
||||
bool mustHookSouth();
|
||||
bool mustHookEast();
|
||||
bool hasCreature();
|
||||
bool limitsFloorsView();
|
||||
bool limitsFloorsView(bool isFreeView = false);
|
||||
bool canErase();
|
||||
bool hasElevation(int elevation = 1);
|
||||
void overwriteMinimapColor(uint8 color) { m_minimapColor = color; }
|
||||
|
||||
void setFlags(tileflags_t flags) { m_flags |= (uint32)flags; }
|
||||
void setFlag(uint32 flag) { m_flags |= flag; }
|
||||
void setFlags(uint32 flags) { m_flags = flags; }
|
||||
bool hasFlag(uint32 flag) { return (m_flags & flag) == flag; }
|
||||
uint32 getFlags() { return m_flags; }
|
||||
|
||||
void setHouseId(uint32 hid) { m_houseId = hid; }
|
||||
uint32 getHouseId() { return m_houseId; }
|
||||
bool isHouseTile() const { return (m_flags & TILESTATE_HOUSE) == TILESTATE_HOUSE; }
|
||||
bool isHouseTile() const { return m_houseId != 0 && (m_flags & TILESTATE_HOUSE) == TILESTATE_HOUSE; }
|
||||
|
||||
TilePtr asTile() { return static_self_cast<Tile>(); }
|
||||
|
||||
|
@@ -58,6 +58,15 @@ const TownPtr& TownManager::getTown(uint32 townId)
|
||||
return m_nullTown;
|
||||
}
|
||||
|
||||
const TownPtr& TownManager::getTownByName(std::string name)
|
||||
{
|
||||
auto it = std::find_if(m_towns.begin(), m_towns.end(),
|
||||
[=] (const TownPtr& town) -> bool { return town->getName() == name; } );
|
||||
if(it != m_towns.end())
|
||||
return *it;
|
||||
return m_nullTown;
|
||||
}
|
||||
|
||||
TownList::iterator TownManager::findTown(uint32 townId)
|
||||
{
|
||||
return std::find_if(m_towns.begin(), m_towns.end(),
|
||||
|
@@ -54,6 +54,7 @@ public:
|
||||
void addTown(const TownPtr& town);
|
||||
void removeTown(uint32 townId);
|
||||
const TownPtr& getTown(uint32 townId);
|
||||
const TownPtr& getTownByName(std::string name);
|
||||
|
||||
TownList getTowns() { return m_towns; }
|
||||
void clear() { m_towns.clear(); m_nullTown = nullptr; }
|
||||
|
@@ -63,8 +63,8 @@ void UIItem::drawSelf(Fw::DrawPane drawPane)
|
||||
g_painter->setColor(Color(231, 231, 231));
|
||||
m_font->drawText(count, Rect(m_rect.topLeft(), m_rect.bottomRight() - Point(3, 0)), Fw::AlignBottomRight);
|
||||
}
|
||||
// debug, show item id
|
||||
//m_font->drawText(stdext::to_string(m_item->getId()), m_rect, Fw::AlignBottomRight);
|
||||
if(m_showId)
|
||||
m_font->drawText(stdext::to_string(m_item->getServerId()), m_rect, Fw::AlignBottomRight);
|
||||
}
|
||||
|
||||
drawBorder(m_rect);
|
||||
@@ -98,5 +98,7 @@ void UIItem::onStyleApply(const std::string& styleName, const OTMLNodePtr& style
|
||||
setItemVisible(node->value<bool>());
|
||||
else if(node->tag() == "virtual")
|
||||
setVirtual(node->value<bool>());
|
||||
else if(node->tag() == "show-id")
|
||||
m_showId = node->value<bool>();
|
||||
}
|
||||
}
|
||||
|
@@ -54,6 +54,7 @@ protected:
|
||||
ItemPtr m_item;
|
||||
stdext::boolean<false> m_virtual;
|
||||
stdext::boolean<true> m_itemVisible;
|
||||
stdext::boolean<false> m_showId;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -70,6 +70,11 @@ void UIMap::drawSelf(Fw::DrawPane drawPane)
|
||||
}
|
||||
}
|
||||
|
||||
void UIMap::movePixels(int x, int y)
|
||||
{
|
||||
m_mapView->move(x, y);
|
||||
}
|
||||
|
||||
bool UIMap::setZoom(int zoom)
|
||||
{
|
||||
m_zoom = std::min(std::max(zoom, m_maxZoomIn), m_maxZoomOut);
|
||||
@@ -215,3 +220,5 @@ void UIMap::updateMapSize()
|
||||
if(!m_keepAspectRatio)
|
||||
updateVisibleDimension();
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et: */
|
||||
|
@@ -37,6 +37,7 @@ public:
|
||||
|
||||
void drawSelf(Fw::DrawPane drawPane);
|
||||
|
||||
void movePixels(int x, int y);
|
||||
bool setZoom(int zoom);
|
||||
bool zoomIn();
|
||||
bool zoomOut();
|
||||
|
87
src/client/uisprite.cpp
Normal file
87
src/client/uisprite.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 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
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uisprite.h"
|
||||
#include <framework/otml/otml.h>
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/texturemanager.h>
|
||||
#include <client/spritemanager.h>
|
||||
|
||||
UISprite::UISprite() :
|
||||
m_spriteId(0),
|
||||
m_spriteColor(Color::white)
|
||||
{ }
|
||||
|
||||
void UISprite::drawSelf(Fw::DrawPane drawPane)
|
||||
{
|
||||
if((drawPane & Fw::ForegroundPane) == 0)
|
||||
return;
|
||||
|
||||
// draw style components in order
|
||||
if(m_backgroundColor.aF() > Fw::MIN_ALPHA) {
|
||||
Rect backgroundDestRect = m_rect;
|
||||
backgroundDestRect.expand(-m_borderWidth.top, -m_borderWidth.right, -m_borderWidth.bottom, -m_borderWidth.left);
|
||||
drawBackground(m_rect);
|
||||
}
|
||||
|
||||
drawImage(m_rect);
|
||||
|
||||
if(m_spriteVisible && m_sprite) {
|
||||
g_painter->setColor(m_spriteColor);
|
||||
g_painter->drawTexturedRect(getPaddingRect(), m_sprite);
|
||||
}
|
||||
|
||||
drawBorder(m_rect);
|
||||
drawIcon(m_rect);
|
||||
drawText(m_rect);
|
||||
}
|
||||
|
||||
void UISprite::setSpriteId(int id)
|
||||
{
|
||||
if(!g_sprites.isLoaded())
|
||||
return;
|
||||
|
||||
m_spriteId = id;
|
||||
if(id == 0)
|
||||
m_sprite = nullptr;
|
||||
else {
|
||||
ImagePtr image = g_sprites.getSpriteImage(id);
|
||||
if(image)
|
||||
m_sprite = new Texture(image);
|
||||
else
|
||||
m_sprite = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UISprite::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
|
||||
{
|
||||
UIWidget::onStyleApply(styleName, styleNode);
|
||||
|
||||
for(const OTMLNodePtr& node : styleNode->children()) {
|
||||
if(node->tag() == "sprite-id")
|
||||
setSpriteId(node->value<int>());
|
||||
else if(node->tag() == "sprite-visible")
|
||||
setSpriteVisible(node->value<bool>());
|
||||
else if(node->tag() == "sprite-color")
|
||||
setSpriteColor(node->value<Color>());
|
||||
}
|
||||
}
|
@@ -20,30 +20,35 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICSCONTEXT_H
|
||||
#define GRAPHICSCONTEXT_H
|
||||
#ifndef UISPRITE_H
|
||||
#define UISPRITE_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <framework/ui/uiwidget.h>
|
||||
|
||||
class GraphicsContext : public stdext::shared_object
|
||||
class UISprite : public UIWidget
|
||||
{
|
||||
public:
|
||||
GraphicsContext(const std::string& name);
|
||||
virtual ~GraphicsContext() {}
|
||||
UISprite();
|
||||
void drawSelf(Fw::DrawPane drawPane);
|
||||
|
||||
std::string getName() { return m_name; }
|
||||
void setSpriteId(int id);
|
||||
int getSpriteId() { return m_spriteId; }
|
||||
void clearSprite() { setSpriteId(0); }
|
||||
|
||||
virtual void create() {}
|
||||
virtual void destroy() {}
|
||||
virtual void restore() {}
|
||||
void setSpriteColor(Color color) { m_spriteColor = color; }
|
||||
|
||||
virtual void swapBuffers() {}
|
||||
|
||||
virtual void setVerticalSync(bool enable) {}
|
||||
bool isSpriteVisible() { return m_spriteVisible; }
|
||||
void setSpriteVisible(bool visible) { m_spriteVisible = visible; }
|
||||
|
||||
protected:
|
||||
std::string m_name;
|
||||
void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
|
||||
|
||||
TexturePtr m_sprite;
|
||||
uint16 m_spriteId;
|
||||
Color m_spriteColor;
|
||||
|
||||
stdext::boolean<true> m_spriteVisible;
|
||||
};
|
||||
|
||||
#endif
|
@@ -123,20 +123,15 @@ set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/otml/otmlparser.h
|
||||
|
||||
# crash handler
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/crashhandler.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/unixcrashhandler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32crashhandler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32platform.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/unixplatform.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/platform.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/platform.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32platform.cpp
|
||||
)
|
||||
else()
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/unixplatform.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set_source_files_properties(${CMAKE_CURRENT_LIST_DIR}/luafunctions.cpp
|
||||
PROPERTIES LANGUAGE CXX COMPILE_FLAGS "-g0 -Os")
|
||||
|
||||
@@ -263,15 +258,6 @@ if(CRASH_HANDLER)
|
||||
message(STATUS "Crash handler: ON")
|
||||
if(WIN32)
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} imagehlp)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/crashhandler.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32crashhandler.cpp
|
||||
)
|
||||
else()
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/crashhandler.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/unixcrashhandler.cpp
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Crash handler: OFF")
|
||||
@@ -284,7 +270,7 @@ endif()
|
||||
if(WIN32)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthreads")
|
||||
set(framework_DEFINITIONS ${framework_DEFINITIONS} -D_WIN32_WINNT=0x0501)
|
||||
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -Wl,--large-address-aware") # strip all debug information
|
||||
#set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -Wl,--large-address-aware") # strip all debug information
|
||||
set(SYSTEM_LIBRARIES "")
|
||||
else()
|
||||
if(APPLE)
|
||||
@@ -304,24 +290,18 @@ endif()
|
||||
|
||||
if(FRAMEWORK_GRAPHICS)
|
||||
set(OPENGLES "OFF" CACHE "Use OpenGL ES 1.0 or 2.0 (for mobiles devices)" STRING)
|
||||
if(OPENGLES)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/graphicscontextegl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/graphicscontextegl.h
|
||||
)
|
||||
if(OPENGLES STREQUAL "2.0")
|
||||
find_package(OpenGLES2 REQUIRED)
|
||||
find_package(EGL REQUIRED)
|
||||
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DOPENGL_ES=2)
|
||||
set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES2_INCLUDE_DIR})
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES2_LIBRARY})
|
||||
elseif(OPENGLES STREQUAL "1.0")
|
||||
ELSEif(OPENGLES STREQUAL "1.0")
|
||||
find_package(OpenGLES1 REQUIRED)
|
||||
find_package(EGL REQUIRED)
|
||||
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DOPENGL_ES=1)
|
||||
set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES1_INCLUDE_DIR})
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES1_LIBRARY})
|
||||
endif()
|
||||
else()
|
||||
## TODO: CMake Documentation says that this is not the right
|
||||
# Thing for Mac OS X, but it works for now.
|
||||
@@ -356,8 +336,6 @@ if(FRAMEWORK_GRAPHICS)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/dx/painterdx9.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/dx/painterdx9.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/dx/graphicscontextdx9.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/dx/graphicscontextdx9.h
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -365,44 +343,6 @@ if(FRAMEWORK_GRAPHICS)
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} X11)
|
||||
endif()
|
||||
|
||||
option(SDL "Use SDL 2.0 support" OFF)
|
||||
if(SDL)
|
||||
find_package(SDL2 REQUIRED)
|
||||
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DSDL)
|
||||
set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${SDL2_INCLUDE_DIR})
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} ${SDL2_LIBRARY})
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/sdl/paintersdl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/sdl/paintersdl.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/sdlwindow.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/sdlwindow.h
|
||||
)
|
||||
else()
|
||||
if(WIN32)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32window.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32window.h
|
||||
)
|
||||
if(NOT OPENGLES)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/graphicscontextwgl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/graphicscontextwgl.h
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/x11window.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/x11window.h
|
||||
)
|
||||
if(NOT OPENGLES)
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/graphicscontextglx.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/graphicscontextglx.h
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(framework_SOURCES ${framework_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.h
|
||||
@@ -422,8 +362,6 @@ if(FRAMEWORK_GRAPHICS)
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/glutil.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/graphicscontext.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/graphicscontext.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/hardwarebuffer.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/hardwarebuffer.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/image.cpp
|
||||
@@ -459,8 +397,6 @@ if(FRAMEWORK_GRAPHICS)
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/shaderprogram.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/texture.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/texture.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/textureogl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/ogl/textureogl.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/texturemanager.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/texturemanager.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/vertexarray.h
|
||||
@@ -499,6 +435,10 @@ if(FRAMEWORK_GRAPHICS)
|
||||
# platform window
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/platformwindow.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/platformwindow.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32window.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/win32window.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/x11window.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform/x11window.h
|
||||
|
||||
# window input
|
||||
${CMAKE_CURRENT_LIST_DIR}/input/mouse.cpp
|
||||
@@ -606,6 +546,10 @@ if(FRAMEWORK_SQL)
|
||||
set(framework_DEFINITIONS ${framework_DEFINITIONS} -DFW_SQL)
|
||||
endif()
|
||||
|
||||
if(EXTRA_LIBS)
|
||||
set(framework_LIBRARIES ${framework_LIBRARIES} ${EXTRA_LIBS})
|
||||
endif()
|
||||
|
||||
include_directories(${framework_INCLUDE_DIRS})
|
||||
add_definitions(${framework_DEFINITIONS})
|
||||
|
||||
|
@@ -4,7 +4,13 @@
|
||||
# EGL_LIBRARY - the EGL library
|
||||
|
||||
FIND_PATH(EGL_INCLUDE_DIR NAMES EGL/egl.h)
|
||||
FIND_LIBRARY(EGL_LIBRARY NAMES EGL.dll EGL)
|
||||
SET(_EGL_STATIC_LIBS libEGL.a)
|
||||
SET(_EGL_SHARED_LIBS libEGL.dll.a EGL)
|
||||
#IF(USE_STATIC_LIBS)
|
||||
# FIND_LIBRARY(EGL_LIBRARY NAMES ${_EGL_STATIC_LIBS} ${_EGL_SHARED_LIBS})
|
||||
#ELSE()
|
||||
FIND_LIBRARY(EGL_LIBRARY NAMES ${_EGL_SHARED_LIBS} ${_EGL_STATIC_LIBS})
|
||||
#ENDIF()
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(EGL DEFAULT_MSG EGL_LIBRARY EGL_INCLUDE_DIR)
|
||||
MARK_AS_ADVANCED(EGL_LIBRARY EGL_INCLUDE_DIR)
|
@@ -4,7 +4,13 @@
|
||||
# OPENGLES1_LIBRARY - the OpenGL ES 1.0 library
|
||||
|
||||
FIND_PATH(OPENGLES1_INCLUDE_DIR NAMES GLES/gl.h)
|
||||
FIND_LIBRARY(OPENGLES1_LIBRARY NAMES GLESv1_CM.dll GLES_CM.dll GLESv1_CM GLES_CM)
|
||||
SET(_OPENGLES1_STATIC_LIBS libGLESv1_CM.a libGLES_CM.a)
|
||||
SET(_OPENGLES1_SHARED_LIBS libGLESv1_CM.dll.a libGLES_CM.dll.a GLESv1_CM GLES_CM)
|
||||
#IF(USE_STATIC_LIBS)
|
||||
# FIND_LIBRARY(OPENGLES1_LIBRARY NAMES ${_OPENGLES1_STATIC_LIBS} ${_OPENGLES1_SHARED_LIBS})
|
||||
#ELSE()
|
||||
FIND_LIBRARY(OPENGLES1_LIBRARY NAMES ${_OPENGLES1_SHARED_LIBS} ${_OPENGLES1_STATIC_LIBS})
|
||||
#ENDIF()
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenGLES2 DEFAULT_MSG OPENGLES1_LIBRARY OPENGLES1_INCLUDE_DIR)
|
||||
MARK_AS_ADVANCED(OPENGLES1_LIBRARY OPENGLES1_INCLUDE_DIR)
|
@@ -4,7 +4,13 @@
|
||||
# OPENGLES2_LIBRARY - the OpenGL ES 2.0 library
|
||||
|
||||
FIND_PATH(OPENGLES2_INCLUDE_DIR NAMES GLES2/gl2.h)
|
||||
FIND_LIBRARY(OPENGLES2_LIBRARY NAMES GLESv2.dll GLESv2)
|
||||
SET(_OPENGLES2_STATIC_LIBS libGLESv2.a)
|
||||
SET(_OPENGLES2_SHARED_LIBS libGLESv2.dll.a GLESv2)
|
||||
#IF(USE_STATIC_LIBS)
|
||||
# FIND_LIBRARY(OPENGLES2_LIBRARY NAMES ${_OPENGLES2_STATIC_LIBS} ${_OPENGLES2_SHARED_LIBS})
|
||||
#ELSE()
|
||||
FIND_LIBRARY(OPENGLES2_LIBRARY NAMES ${_OPENGLES2_SHARED_LIBS} ${_OPENGLES2_STATIC_LIBS})
|
||||
#ENDIF()
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenGLES2 DEFAULT_MSG OPENGLES2_LIBRARY OPENGLES2_INCLUDE_DIR)
|
||||
MARK_AS_ADVANCED(OPENGLES2_LIBRARY OPENGLES2_INCLUDE_DIR)
|
@@ -1,16 +0,0 @@
|
||||
# Try to find the SDL2 library
|
||||
# SDL2_FOUND - system has SDL2
|
||||
# SDL2_INCLUDE_DIR - the SDL2 include directory
|
||||
# SDL2_LIBRARY - the SDL2 library
|
||||
|
||||
FIND_PATH(SDL2_INCLUDE_DIR PATH_SUFFIXES SDL2 SDL NAMES SDL.h)
|
||||
SET(_SDL2_STATIC_LIBS libSDL2.a libSDL.a)
|
||||
SET(_SDL2_SHARED_LIBS libSDL2.dll.a SDL2 SDL libSDL.dll.a SDL)
|
||||
IF(USE_STATIC_LIBS)
|
||||
FIND_LIBRARY(SDL2_LIBRARY NAMES ${_SDL2_STATIC_LIBS} ${_SDL2_SHARED_LIBS})
|
||||
ELSE()
|
||||
FIND_LIBRARY(SDL2_LIBRARY NAMES ${_SDL2_SHARED_LIBS} ${_SDL2_STATIC_LIBS})
|
||||
ENDIF()
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 DEFAULT_MSG SDL2_LIBRARY SDL2_INCLUDE_DIR)
|
||||
MARK_AS_ADVANCED(SDL2_LIBRARY SDL2_INCLUDE_DIR)
|
@@ -23,11 +23,11 @@
|
||||
#ifndef FRAMEWORK_CONST_H
|
||||
#define FRAMEWORK_CONST_H
|
||||
|
||||
#include "stdext/compiler.h"
|
||||
|
||||
#define DEG_TO_RAD (acos(-1)/180.0)
|
||||
#define RAD_TO_DEC (180.0/acos(-1))
|
||||
|
||||
#define BUILD_COMPILER "gcc " __VERSION__
|
||||
|
||||
#ifndef BUILD_COMMIT
|
||||
#define BUILD_COMMIT "devel"
|
||||
#endif
|
||||
@@ -52,9 +52,8 @@
|
||||
|
||||
namespace Fw
|
||||
{
|
||||
constexpr float pi = 3.14159265;
|
||||
constexpr float MIN_ALPHA = 0.003f;
|
||||
|
||||
static const float pi = 3.14159265;
|
||||
static const float MIN_ALPHA = 0.003f;
|
||||
enum Key : unsigned char {
|
||||
KeyUnknown = 0,
|
||||
KeyEscape = 1,
|
||||
|
@@ -33,7 +33,6 @@
|
||||
#include <framework/platform/platform.h>
|
||||
|
||||
#include <locale>
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
#ifdef FW_NET
|
||||
#include <framework/net/connection.h>
|
||||
@@ -148,6 +147,11 @@ void Application::poll()
|
||||
#endif
|
||||
|
||||
g_dispatcher.poll();
|
||||
|
||||
// poll connection again to flush pending write
|
||||
#ifdef FW_NET
|
||||
Connection::poll();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Application::exit()
|
||||
@@ -164,14 +168,10 @@ void Application::close()
|
||||
|
||||
std::string Application::getOs()
|
||||
{
|
||||
#if defined(ANDROID)
|
||||
return "android";
|
||||
#elif defined(IOS)
|
||||
return "ios";
|
||||
#elif defined(WIN32)
|
||||
#if defined(WIN32)
|
||||
return "windows";
|
||||
#elif defined(__APPLE__)
|
||||
return "macos";
|
||||
return "mac";
|
||||
#elif __linux
|
||||
return "linux";
|
||||
#else
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user