mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
Compare commits
299 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
160c15a5f2 | ||
|
|
0ff0e5b59e | ||
|
|
3fd25ca889 | ||
|
|
b0a5f477c1 | ||
|
|
f25498d4d0 | ||
|
|
fbcf00e0fc | ||
|
|
3303722bc7 | ||
|
|
5abb3f78cf | ||
|
|
457e5f1eb5 | ||
|
|
ada57d4384 | ||
|
|
f2fce0f602 | ||
|
|
55dfe0ccc9 | ||
|
|
69abd8c434 | ||
|
|
011de295fd | ||
|
|
dbb4ad0b2a | ||
|
|
bd56a5dad9 | ||
|
|
79d9225c02 | ||
|
|
d83f370fb4 | ||
|
|
889f14a64f | ||
|
|
858e5a0492 | ||
|
|
c61fb787ae | ||
|
|
57d4dc2459 | ||
|
|
a17c45a698 | ||
|
|
94321ea178 | ||
|
|
bf6bf20ae4 | ||
|
|
7b7ec2d0aa | ||
|
|
1bb7fdf89a | ||
|
|
05ce1f4242 | ||
|
|
9c6a789d2b | ||
|
|
33a1a45a63 | ||
|
|
39e917927f | ||
|
|
79861569a2 | ||
|
|
e762340953 | ||
|
|
4a8fe6de7d | ||
|
|
7c456b970c | ||
|
|
dd63a6a2ab | ||
|
|
00342b0b61 | ||
|
|
d34f7c304e | ||
|
|
6168937901 | ||
|
|
189ac56fc0 | ||
|
|
f7f5cafec2 | ||
|
|
8248dad50a | ||
|
|
12b9e3fa89 | ||
|
|
269487f32c | ||
|
|
d19a920c09 | ||
|
|
29c8c3d0af | ||
|
|
a59fd45076 | ||
|
|
4316d3ad40 | ||
|
|
6377a9e659 | ||
|
|
959d0ace0b | ||
|
|
178a67e180 | ||
|
|
a695a4188c | ||
|
|
f503967c45 | ||
|
|
c1af1fd884 | ||
|
|
e5013e79fd | ||
|
|
6fddbe40a4 | ||
|
|
5a45c6a5e6 | ||
|
|
b5c7faff65 | ||
|
|
6df3a27279 | ||
|
|
dde09a8a02 | ||
|
|
fa9d518980 | ||
|
|
d63ac946f6 | ||
|
|
33b1e4a978 | ||
|
|
bb00355ca3 | ||
|
|
24e1c46a8c | ||
|
|
0360f6f600 | ||
|
|
b74b03151b | ||
|
|
cc328baf19 | ||
|
|
ec05120118 | ||
|
|
acad94770b | ||
|
|
92394e415a | ||
|
|
f3d694ac79 | ||
|
|
cd9f90cea9 | ||
|
|
ee568da6ec | ||
|
|
4651165e4d | ||
|
|
e5de7a8a45 | ||
|
|
9ee7b44ddb | ||
|
|
e400155a64 | ||
|
|
0fc006d2d4 | ||
|
|
5082a6155d | ||
|
|
fd96f8f758 | ||
|
|
d91090e806 | ||
|
|
1a04ee3354 | ||
|
|
f0e1e02f03 | ||
|
|
8c56610418 | ||
|
|
b6b734ff36 | ||
|
|
a937fb7ac6 | ||
|
|
efe7b468c9 | ||
|
|
f9416c549d | ||
|
|
9516affde5 | ||
|
|
c85ba1a208 | ||
|
|
00de81c60d | ||
|
|
62a95effb8 | ||
|
|
85e1accebc | ||
|
|
90a31ac99f | ||
|
|
8b9b653028 | ||
|
|
4f1854b138 | ||
|
|
33554e8942 | ||
|
|
f0231c8d9f | ||
|
|
5360b09d0f | ||
|
|
939a3f1e31 | ||
|
|
bf0f218b28 | ||
|
|
9fabd2c728 | ||
|
|
a163279fab | ||
|
|
5598b80ef4 | ||
|
|
d6b722a967 | ||
|
|
2ec5fda3e7 | ||
|
|
13d0dfeb07 | ||
|
|
ddce998cad | ||
|
|
103251a537 | ||
|
|
e1fd2db64d | ||
|
|
0c492531b8 | ||
|
|
8b9854804b | ||
|
|
849872d181 | ||
|
|
a48f30e8a4 | ||
|
|
fce8b01493 | ||
|
|
05d24dbde8 | ||
|
|
20a1829317 | ||
|
|
8fcd8ea429 | ||
|
|
d73557ee5e | ||
|
|
3b1bcfe1a5 | ||
|
|
da59440106 | ||
|
|
83cc16107e | ||
|
|
99760d7c72 | ||
|
|
ab8d7caced | ||
|
|
090410cbf8 | ||
|
|
739e7bc81a | ||
|
|
f1483f4595 | ||
|
|
62a4bcf2d2 | ||
|
|
8de6296878 | ||
|
|
e5a5ad425a | ||
|
|
b3369d0b3f | ||
|
|
294ba109df | ||
|
|
3eeecf11cb | ||
|
|
d00252ad72 | ||
|
|
dcff6f6525 | ||
|
|
ffddd3c6b8 | ||
|
|
d0ec950dc1 | ||
|
|
7b9d7bec1b | ||
|
|
88e21d8597 | ||
|
|
b81e1745f6 | ||
|
|
201f31b3ac | ||
|
|
a31e018959 | ||
|
|
efa93e218a | ||
|
|
ca0e57b99c | ||
|
|
d0f64fe66c | ||
|
|
8fd52835a6 | ||
|
|
8a01124eed | ||
|
|
a50ddb98dd | ||
|
|
e896daa148 | ||
|
|
1a46e58477 | ||
|
|
e2ab00b4ba | ||
|
|
568677ff32 | ||
|
|
321c9ba7f4 | ||
|
|
674a2a7814 | ||
|
|
2bc40e9421 | ||
|
|
770f11321f | ||
|
|
bb87762467 | ||
|
|
317e12eddf | ||
|
|
1cbe1aea76 | ||
|
|
8f77774569 | ||
|
|
a521935934 | ||
|
|
b84854d4ba | ||
|
|
c75777e5c3 | ||
|
|
44c90b71fa | ||
|
|
a8d686104e | ||
|
|
e80015a7cd | ||
|
|
71e44e572a | ||
|
|
741ebf38f9 | ||
|
|
08717c36d0 | ||
|
|
fe7f05c89c | ||
|
|
447f7f02a7 | ||
|
|
c1b92df9bf | ||
|
|
7c1e61d843 | ||
|
|
63cd83c102 | ||
|
|
0220587637 | ||
|
|
f076a30180 | ||
|
|
5abdbe2080 | ||
|
|
2bc85dd109 | ||
|
|
bd2a5acf21 | ||
|
|
278176a48e | ||
|
|
eddb034a5c | ||
|
|
c3fe4b0224 | ||
|
|
432223264e | ||
|
|
99eb8f426b | ||
|
|
ff3babacb7 | ||
|
|
4daf474ff4 | ||
|
|
f01c624f82 | ||
|
|
5661f09454 | ||
|
|
2f53abdb3e | ||
|
|
3eace0680d | ||
|
|
3b32ce6b1f | ||
|
|
74f68c8a69 | ||
|
|
e197072409 | ||
|
|
4c4cde1165 | ||
|
|
d55989510a | ||
|
|
99fdad29dd | ||
|
|
141bc10901 | ||
|
|
b5d73f0ac4 | ||
|
|
e69811c4de | ||
|
|
b6e1bcaeac | ||
|
|
7eda6dd778 | ||
|
|
dabf307c13 | ||
|
|
ef5d7cce3b | ||
|
|
d7c6092d5f | ||
|
|
6dc6124673 | ||
|
|
f33a15db4d | ||
|
|
6603cbf099 | ||
|
|
b1ef81c7e9 | ||
|
|
00bd33abfb | ||
|
|
973d2d90aa | ||
|
|
58babe24fe | ||
|
|
645894fdbf | ||
|
|
cb1916c484 | ||
|
|
af7015097b | ||
|
|
c9aa0b3f6d | ||
|
|
ce915cbada | ||
|
|
b0194a6e81 | ||
|
|
482a8dbd7d | ||
|
|
59e254be54 | ||
|
|
17fdd13d3d | ||
|
|
e825ed84e8 | ||
|
|
a7eabb4b9d | ||
|
|
960e48b7aa | ||
|
|
8394a3863f | ||
|
|
23260c2366 | ||
|
|
a2d4b014fc | ||
|
|
11584a68d6 | ||
|
|
bd2e0ccada | ||
|
|
3c69284e15 | ||
|
|
220fb81833 | ||
|
|
00f53fbb09 | ||
|
|
63756b23d9 | ||
|
|
44e6e2ed38 | ||
|
|
81e6098960 | ||
|
|
38ac7b1dcb | ||
|
|
bfa1f261e0 | ||
|
|
a0887f189f | ||
|
|
7ce72bf623 | ||
|
|
320ad252d1 | ||
|
|
ef686c9c57 | ||
|
|
e28c00ccda | ||
|
|
e2beb82f29 | ||
|
|
b1a6911ede | ||
|
|
f35be8fa36 | ||
|
|
1d5436bbd2 | ||
|
|
a5f13325c0 | ||
|
|
7ac0601f88 | ||
|
|
7f08708555 | ||
|
|
f6e15c35fc | ||
|
|
7b30c49785 | ||
|
|
d771103428 | ||
|
|
2afcceaefb | ||
|
|
3d08de51e1 | ||
|
|
8fa83eab64 | ||
|
|
4ab558858f | ||
|
|
6f59afe8e6 | ||
|
|
5239cbd293 | ||
|
|
7276fed9e7 | ||
|
|
022ceba20d | ||
|
|
5b8a862df9 | ||
|
|
11ab3e0f19 | ||
|
|
998763be7b | ||
|
|
58a235e2e3 | ||
|
|
3e7a34a2ea | ||
|
|
111e53aaef | ||
|
|
c1f5d2ea9b | ||
|
|
20732e38d8 | ||
|
|
cea81d1810 | ||
|
|
8b317d4b21 | ||
|
|
dd0bb30481 | ||
|
|
051334da22 | ||
|
|
e9399c169a | ||
|
|
ce82a8f09f | ||
|
|
54695a9490 | ||
|
|
08270ae09e | ||
|
|
f6d80cf473 | ||
|
|
0cb5d6b896 | ||
|
|
4a47900860 | ||
|
|
f2ec843f7e | ||
|
|
ed67493bb8 | ||
|
|
09e0886cdd | ||
|
|
5ecb46633a | ||
|
|
5db946590e | ||
|
|
444e372a66 | ||
|
|
af39933cc8 | ||
|
|
2619c88db4 | ||
|
|
b76fc3b2a7 | ||
|
|
cc886b4db9 | ||
|
|
a3c9b52073 | ||
|
|
7673e256c8 | ||
|
|
2f767ba835 | ||
|
|
7ec07c0dca | ||
|
|
c779e9139a | ||
|
|
97b3e860a0 | ||
|
|
4a80934346 | ||
|
|
9897a6cf23 | ||
|
|
7c0a2192f7 | ||
|
|
92b180ca05 |
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
*.php text eol=lf
|
||||
*.js text eol=lf
|
||||
*.css text eol=lf
|
||||
*.sql text eol=lf
|
||||
17
.gitignore
vendored
17
.gitignore
vendored
@@ -1,6 +1,13 @@
|
||||
# Git
|
||||
*.orig
|
||||
|
||||
# cache
|
||||
/cache/template/*
|
||||
/setup/generated/alphaMaps/*.png
|
||||
/cache/firstrun
|
||||
|
||||
# extract from MPQ
|
||||
/setup/mpqdata/*
|
||||
|
||||
# generated files
|
||||
/static/js/profile_all.js
|
||||
@@ -11,20 +18,26 @@
|
||||
/static/widgets/searchbox/searchbox.html
|
||||
/static/download/searchplugins/aowow.xml
|
||||
/config/config.php
|
||||
/datasets/*
|
||||
!/datasets/zones
|
||||
# /datasets/item-scaling
|
||||
|
||||
# extracted sounds
|
||||
/static/wowsounds/*
|
||||
|
||||
# extracted images
|
||||
/static/images/wow/icons/large/*
|
||||
/static/images/wow/icons/medium/*
|
||||
/static/images/wow/icons/small/*
|
||||
/static/images/wow/icons/tiny/*
|
||||
!/static/images/wow/icons/tiny/quest_*
|
||||
/static/images/wow/hunterpettalents/icons*
|
||||
/static/images/wow/interface/*
|
||||
/static/images/wow/hunterpettalents/*
|
||||
/static/images/wow/Interface/*
|
||||
/static/images/wow/loadingscreens/*
|
||||
/static/images/wow/maps/*
|
||||
!/static/images/wow/maps/overlay*
|
||||
/static/images/wow/talents/icons/*
|
||||
/static/images/wow/talents/backgrounds/*
|
||||
|
||||
# modelviewer (~7GB data)
|
||||
/static/modelviewer/models/*
|
||||
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,6 +0,0 @@
|
||||
[submodule "includes/tools/MPQExtractor"]
|
||||
path = includes/tools/MPQExtractor
|
||||
url = https://github.com/iamcal/MPQExtractor.git
|
||||
[submodule "includes/tools/BLPConverter"]
|
||||
path = includes/tools/BLPConverter
|
||||
url = https://github.com/Kanma/BLPConverter.git
|
||||
24
.htaccess
24
.htaccess
@@ -1,11 +1,19 @@
|
||||
Order Deny,Allow
|
||||
<FilesMatch "\.(conf|php|in)|aowow$">
|
||||
Deny from all
|
||||
<FilesMatch "\.(conf|php|in)$">
|
||||
Deny from all
|
||||
</FilesMatch>
|
||||
<FilesMatch "^(index)\.php$">
|
||||
Allow from all
|
||||
Allow from all
|
||||
</FilesMatch>
|
||||
|
||||
<Files "aowow">
|
||||
ForceType application/x-httpd-php
|
||||
</Files>
|
||||
|
||||
<Files "prQueue">
|
||||
ForceType application/x-httpd-php
|
||||
</Files>
|
||||
|
||||
# Block view of some folders
|
||||
Options -Indexes
|
||||
DirectoryIndex index.php
|
||||
@@ -13,13 +21,13 @@ DirectoryIndex index.php
|
||||
# Support for UTF8
|
||||
AddDefaultCharset utf8
|
||||
<IfModule mod_charset.c>
|
||||
CharsetDisable on
|
||||
CharsetRecodeMultipartForms Off
|
||||
CharsetDisable on
|
||||
CharsetRecodeMultipartForms Off
|
||||
</IfModule>
|
||||
|
||||
# 5MB should be enough for the largest screenshots in the land
|
||||
php_value default_charset UTF-8
|
||||
php_value upload_max_filesize 5M
|
||||
# UHD screenshots can get pretty large (cannot be set in config)
|
||||
php_value upload_max_filesize 20M
|
||||
php_value post_max_size 25M
|
||||
|
||||
RewriteEngine on
|
||||
# RewriteBase /~user/localPath/ # enable if the rules do not work, when they should
|
||||
|
||||
131
README.md
Normal file
131
README.md
Normal file
@@ -0,0 +1,131 @@
|
||||

|
||||
|
||||
|
||||
## Build Status
|
||||

|
||||
|
||||
|
||||
## Introduction
|
||||
|
||||
AoWoW is a Database tool for World of Warcraft v3.3.5 (build 12340)
|
||||
It is based upon the other famous Database tool for WoW, featuring the red smiling rocket.
|
||||
While the first releases can be found as early as 2008, today it is impossible to say who created this project.
|
||||
This is a complete rewrite of the serverside php code and update to the clientside javascripts from 2008 to something 2013ish.
|
||||
|
||||
I myself take no credit for the clientside scripting, design and layout that these php-scripts cater to.
|
||||
Also, this project is not meant to be used for commercial puposes of any kind!
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
+ Webserver running PHP ≥ 5.5.0 including extensions:
|
||||
+ SimpleXML
|
||||
+ GD
|
||||
+ Mysqli
|
||||
+ mbString
|
||||
+ MySQL ≥ 5.5.30
|
||||
+ [TDB 335.63](https://github.com/TrinityCore/TrinityCore/releases/tag/TDB335.63) - including world updates up to 04.05.2017
|
||||
+ Tools require cmake: Please refer to the individual repositories for detailed information
|
||||
+ [MPQExtractor](https://github.com/Sarjuuk/MPQExtractor) / [FFmpeg](https://ffmpeg.org/download.html) / [BLPConverter](https://github.com/Sarjuuk/BLPConverter) (optional)
|
||||
+ WIN users may find it easier to use these alternatives
|
||||
+ [MPQEditor](http://www.zezula.net/en/mpq/download.html) / [FFmpeg](http://ffmpeg.zeranoe.com/builds/) / [BLPConverter](https://github.com/PatrickCyr/BLPConverter) (optional)
|
||||
|
||||
audio processing may require [lame](https://sourceforge.net/projects/lame/files/lame/3.99/) or [vorbis-tools](https://www.xiph.org/downloads/) (which may require libvorbis (which may require libogg))
|
||||
|
||||
|
||||
#### Highly Recommended
|
||||
+ setting the following configuration values on your TrintyCore server will greatly increase the accuracy of spawn points
|
||||
> Calculate.Creature.Zone.Area.Data = 1
|
||||
> Calculate.Gameoject.Zone.Area.Data = 1
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
#### 1. Acquire the required repositories
|
||||
`git clone git@github.com:Sarjuuk/aowow.git aowow`
|
||||
`git clone git@github.com:Sarjuuk/MPQExtractor.git MPQExtractor`
|
||||
|
||||
#### 2. Prepare the database
|
||||
Ensure that the account you are going to use has **full** access on the database AoWoW is going to occupy and ideally only **read** access on the world database you are going to reference.
|
||||
Import `setup/db_structure.sql` into the AoWoW database `mysql -p {your-db-here} < setup/db_structure.sql`
|
||||
|
||||
#### 3. Server created files
|
||||
See to it, that the web server is able to write the following directories and their children. If they are missing, the setup will create them with appropriate permissions
|
||||
* `cache/`
|
||||
* `config/`
|
||||
* `static/download/`
|
||||
* `static/widgets/`
|
||||
* `static/js/`
|
||||
* `static/uploads/`
|
||||
* `static/images/wow/`
|
||||
* `datasets/`
|
||||
|
||||
#### 4. Extract the client archives (MPQs)
|
||||
Extract the following directories from the client archives into `setup/mpqdata/`, while maintaining patch order (base mpq -> patch-mpq: 1 -> 9 -> A -> Z). The required paths are scattered across the archives. Overwrite older files if asked to.
|
||||
.. for every locale you are going to use:
|
||||
> \<localeCode>/DBFilesClient/
|
||||
> \<localeCode>/Interface/WorldMap/
|
||||
> \<localeCode>/Interface/FrameXML/GlobalStrings.lua
|
||||
|
||||
.. once is enough (still apply the localeCode though):
|
||||
> \<localeCode>/Interface/TalentFrame/
|
||||
> \<localeCode>/Interface/Glues/Credits/
|
||||
> \<localeCode>/Interface/Icons/
|
||||
> \<localeCode>/Interface/Spellbook/
|
||||
> \<localeCode>/Interface/PaperDoll/
|
||||
> \<localeCode>/Interface/GLUES/CHARACTERCREATE/
|
||||
> \<localeCode>/Interface/Pictures
|
||||
> \<localeCode>/Interface/PvPRankBadges
|
||||
> \<localeCode>/Interface/FlavorImages
|
||||
> \<localeCode>/Interface/Calendar/Holidays/
|
||||
> \<localeCode>/Sound/
|
||||
|
||||
.. optionaly (not used in AoWoW):
|
||||
> \<localeCode>/Interface/GLUES/LOADINGSCREENS/
|
||||
|
||||
#### 5. Reencode the audio files
|
||||
WAV-files need to be reencoded as `ogg/vorbis` and some MP3s may identify themselves as `application/octet-stream` instead of `audio/mpeg`.
|
||||
* [example for WIN](https://gist.github.com/Sarjuuk/d77b203f7b71d191509afddabad5fc9f)
|
||||
* [example for \*nix](https://gist.github.com/Sarjuuk/1f05ef2affe49a7e7ca0fad7b01c081d)
|
||||
|
||||
#### 6. Run the initial setup from the CLI
|
||||
`php aowow --firstrun`.
|
||||
This should guide you through with minimal input required from your end, but will take some time though, especially compiling the zone-images. Use it to familiarize yourself with the other functions this setup has. Yes, I'm dead serious: *Go read the code!* It will help you understand how to configure AoWoW and keep it in sync with your world database.
|
||||
When you've created your admin account you are done.
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Q: The Page appears white, without any styles.
|
||||
A: The static content is not being displayed. You are either using SSL and AoWoW is unable to detect it or STATIC_HOST is not defined poperly. Either way this can be fixed via config `php aowow --siteconfig`
|
||||
|
||||
Q: Fatal error: Can't inherit abstract function \<functionName> (previously declared abstract in \<className>) in \<path>
|
||||
A: You are using cache optimization modules for php, that are in confict with each other. (Zend OPcache, XCache, ..) Disable all but one.
|
||||
|
||||
Q: Some generated images appear distorted or have alpha-channel issues.
|
||||
A: Image compression is beyond my understanding, so i am unable to fix these issues within the blpReader.
|
||||
BUT you can convert the affected blp file into a png file in the same directory, using the provided BLPConverter.
|
||||
AoWoW will priorize png files over blp files.
|
||||
|
||||
Q: How can i get the modelviewer to work?
|
||||
A: You can't anymore. Wowhead switched from Flash to WebGL (as they should) and moved or deleted the old files in the process.
|
||||
|
||||
Q: I'm getting random javascript errors!
|
||||
A: Some server configurations or external services (like Cloudflare) come with modules, that automaticly minify js and css files. Sometimes they break in the process. Disable the module in this case.
|
||||
|
||||
Q: Some search results within the profiler act rather strange. How does it work?
|
||||
A: Whenever you try to view a new character, AoWoW needs to fetch it first. Since the data is structured for the needs of TrinityCore and not for easy viewing, AoWoW needs to save and restructure it locally. To this end, every char request is placed in a queue. While the queue is not empty, a single instance of `prQueue` is run in the background as not to overwhelm the characters database with requests. This also means, some more exotic search queries can't be run agains the characters database and have to use the incomplete/outdated cached profiles of AoWoW.
|
||||
|
||||
|
||||
## Thanks
|
||||
|
||||
@mix: for providing the php-script to parse .blp and .dbc into usable images and tables
|
||||
@LordJZ: the wrapper-class for DBSimple; the basic idea for the user-class
|
||||
@kliver: basic implementation of screenshot uploads
|
||||
|
||||
|
||||
## Special Thanks
|
||||
Said website with the red smiling rocket, for providing this beautifull website!
|
||||
Please do not reagard this project as blatant rip-off, rather as "We do really liked your presentation, but since time and content progresses, you are sadly no longer supplying the data we need".
|
||||
|
||||

|
||||
24
aowow
Normal file → Executable file
24
aowow
Normal file → Executable file
@@ -1,12 +1,12 @@
|
||||
<?php
|
||||
|
||||
require 'includes/shared.php';
|
||||
|
||||
if (!CLI)
|
||||
die("this script must be run from CLI\n");
|
||||
if (CLI && getcwd().DIRECTORY_SEPARATOR.'aowow' != __FILE__)
|
||||
die("this script must be run from root directory\n");
|
||||
else
|
||||
require 'setup/setup.php';
|
||||
|
||||
?>
|
||||
<?php
|
||||
|
||||
require 'includes/shared.php';
|
||||
|
||||
if (!CLI)
|
||||
die("this script must be run from CLI\n");
|
||||
if (CLI && getcwd().DIRECTORY_SEPARATOR.'aowow' != __FILE__)
|
||||
die("this script must be run from root directory\n");
|
||||
else
|
||||
require 'setup/setup.php';
|
||||
|
||||
?>
|
||||
|
||||
@@ -4,7 +4,7 @@ if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
function extAuth($user, $pass, &$userId = 0)
|
||||
function extAuth($user, $pass, &$userId = 0, &$userGroup = -1)
|
||||
{
|
||||
/*
|
||||
insert some auth mechanism here
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
var wt_presets = {
|
||||
1: {
|
||||
pve: {
|
||||
arms: {__icon:'ability_rogue_eviscerate'},
|
||||
fury: {__icon:'ability_warrior_innerrage',exprtng:100,str:82,critstrkrtng:66,agi:53,armorpenrtng:52,hitrtng:48,hastertng:36,atkpwr:31,armor:5},
|
||||
prot: {__icon:'ability_warrior_defensivestance',sta:100,dodgertng:90,defrtng:86,block:81,agi:67,parryrtng:67,blockrtng:48,str:48,exprtng:19,hitrtng:10,armorpenrtng:10,critstrkrtng:7,armor:6,hastertng:1,atkpwr:1}
|
||||
}
|
||||
},
|
||||
2: {
|
||||
pve: {
|
||||
holy: {__icon:'spell_holy_holybolt',int:100,manargn:88,splpwr:58,critstrkrtng:46,hastertng:35},
|
||||
prot: {__icon:'ability_paladin_shieldofthetemplar',sta:100,dodgertng:94,block:86,defrtng:86,exprtng:79,agi:76,parryrtng:76,hitrtng:58,blockrtng:52,str:50,armor:6,atkpwr:6,splpwr:4,critstrkrtng:3},
|
||||
retrib: {__icon:'spell_holy_auraoflight',mledps:470,hitrtng:100,str:80,exprtng:66,critstrkrtng:40,atkpwr:34,agi:32,hastertng:30,armorpenrtng:22,splpwr:9}
|
||||
}
|
||||
},
|
||||
3: {
|
||||
pve: {
|
||||
beast: {__icon:'ability_hunter_beasttaming',rgddps:213,hitrtng:100,agi:58,critstrkrtng:40,int:37,atkpwr:30,armorpenrtng:28,hastertng:21},
|
||||
marks: {__icon:'ability_marksmanship',rgddps:379,hitrtng:100,agi:74,critstrkrtng:57,armorpenrtng:40,int:39,atkpwr:32,hastertng:24},
|
||||
surv: {__icon:'ability_hunter_swiftstrike',rgddps:181,hitrtng:100,agi:76,critstrkrtng:42,int:35,hastertng:31,atkpwr:29,armorpenrtng:26}
|
||||
}
|
||||
},
|
||||
4: {
|
||||
pve: {
|
||||
assas: {__icon:'ability_rogue_eviscerate',mledps:170,agi:100,exprtng:87,hitrtng:83,critstrkrtng:81,atkpwr:65,armorpenrtng:65,hastertng:64,str:55},
|
||||
combat: {__icon:'ability_backstab',mledps:220,armorpenrtng:100,agi:100,exprtng:82,hitrtng:80,critstrkrtng:75,hastertng:73,str:55,atkpwr:50},
|
||||
subtle: {__icon:'ability_stealth',mledps:228,exprtng:100,agi:100,hitrtng:80,armorpenrtng:75,critstrkrtng:75,hastertng:75,str:55,atkpwr:50}
|
||||
}
|
||||
},
|
||||
5: {
|
||||
pve: {
|
||||
disc: {__icon:'spell_holy_wordfortitude',splpwr:100,manargn:67,int:65,hastertng:59,critstrkrtng:48,spi:22},
|
||||
holy: {__icon:'spell_holy_guardianspirit',manargn:100,int:69,splpwr:60,spi:52,critstrkrtng:38,hastertng:31},
|
||||
shadow: {__icon:'spell_shadow_shadowwordpain',hitrtng:100,shasplpwr:76,splpwr:76,critstrkrtng:54,hastertng:50,spi:16,int:16}
|
||||
}
|
||||
},
|
||||
6: {
|
||||
pve: {
|
||||
blooddps: {__icon:'spell_deathknight_bloodpresence',mledps:360,armorpenrtng:100,str:99,hitrtng:91,exprtng:90,critstrkrtng:57,hastertng:55,atkpwr:36,armor:1},
|
||||
frostdps: {__icon:'spell_deathknight_frostpresence',mledps:337,hitrtng:100,str:97,exprtng:81,armorpenrtng:61,critstrkrtng:45,atkpwr:35,hastertng:28,armor:1},
|
||||
frosttank: {__icon:'spell_deathknight_frostpresence',mledps:419,parryrtng:100,hitrtng:97,str:96,defrtng:85,exprtng:69,dodgertng:61,agi:61,sta:61,critstrkrtng:49,atkpwr:41,armorpenrtng:31,armor:5},
|
||||
unholydps: {__icon:'spell_deathknight_unholypresence',mledps:209,str:100,hitrtng:66,exprtng:51,hastertng:48,critstrkrtng:45,atkpwr:34,armorpenrtng:32,armor:1}
|
||||
}
|
||||
},
|
||||
7: {
|
||||
pve: {
|
||||
elem: {__icon:'spell_nature_lightning',hitrtng:100,splpwr:60,hastertng:56,critstrkrtng:40,int:11},
|
||||
enhance: {__icon:'spell_nature_lightningshield',mledps:135,hitrtng:100,exprtng:84,agi:55,int:55,critstrkrtng:55,hastertng:42,str:35,atkpwr:32,splpwr:29,armorpenrtng:26},
|
||||
resto: {__icon:'spell_nature_magicimmunity',manargn:100,int:85,splpwr:77,critstrkrtng:62,hastertng:35}
|
||||
}
|
||||
},
|
||||
8: {
|
||||
pve: {
|
||||
arcane: {__icon:'spell_holy_magicalsentry',hitrtng:100,hastertng:54,arcsplpwr:49,splpwr:49,critstrkrtng:37,int:34,frosplpwr:24,firsplpwr:24,spi:14},
|
||||
fire: {__icon:'spell_fire_firebolt02',hitrtng:100,hastertng:53,firsplpwr:46,splpwr:46,critstrkrtng:43,frosplpwr:23,arcsplpwr:23,int:13},
|
||||
frost: {__icon:'spell_frost_frostbolt02',hitrtng:100,hastertng:42,frosplpwr:39,splpwr:39,arcsplpwr:19,firsplpwr:19,critstrkrtng:19,int:6}
|
||||
}
|
||||
},
|
||||
9: {
|
||||
pve: {
|
||||
afflic: {__icon:'spell_shadow_deathcoil',hitrtng:100,shasplpwr:72,splpwr:72,hastertng:61,critstrkrtng:38,firsplpwr:36,spi:34,int:15},
|
||||
demo: {__icon:'spell_shadow_metamorphosis',hitrtng:100,hastertng:50,firsplpwr:45,shasplpwr:45,splpwr:45,critstrkrtng:31,spi:29,int:13},
|
||||
destro: {__icon:'spell_shadow_rainoffire',hitrtng:100,firsplpwr:47,splpwr:47,hastertng:46,spi:26,shasplpwr:23,critstrkrtng:16,int:13}
|
||||
}
|
||||
},
|
||||
11: {
|
||||
pve: {
|
||||
balance: {__icon:'spell_nature_starfall',hitrtng:100,splpwr:66,hastertng:54,critstrkrtng:43,spi:22,int:22},
|
||||
feraltank: {__icon:'ability_racial_bearform',agi:100,sta:75,dodgertng:65,defrtng:60,exprtng:16,str:10,armor:10,hitrtng:8,hastertng:5,atkpwr:4,feratkpwr:4,critstrkrtng:3},
|
||||
resto: {__icon:'spell_nature_healingtouch',splpwr:100,manargn:73,hastertng:57,int:51,spi:32,critstrkrtng:11},
|
||||
feraldps: {__icon:'ability_druid_catform',agi:100,armorpenrtng:90,str:80,critstrkrtng:55,exprtng:50,hitrtng:50,feratkpwr:40,atkpwr:40,hastertng:35}
|
||||
}
|
||||
}
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
138
includes/ajaxHandler/account.class.php
Normal file
138
includes/ajaxHandler/account.class.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
class AjaxAccount extends AjaxHandler
|
||||
{
|
||||
protected $validParams = ['exclude', 'weightscales'];
|
||||
protected $_post = array(
|
||||
'groups' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'save' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'delete' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdList']],
|
||||
'name' => [FILTER_CALLBACK, ['options' => 'AjaxAccount::checkName']],
|
||||
'scale' => [FILTER_CALLBACK, ['options' => 'AjaxAccount::checkScale']],
|
||||
'reset' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'mode' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'type' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
);
|
||||
protected $_get = array(
|
||||
'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale']]
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
if (is_numeric($this->_get['locale']))
|
||||
User::useLocale($this->_get['locale']);
|
||||
|
||||
if (!$this->params || !User::$id)
|
||||
return;
|
||||
|
||||
// select handler
|
||||
if ($this->params[0] == 'exclude')
|
||||
$this->handler = 'handleExclude';
|
||||
else if ($this->params[0] == 'weightscales')
|
||||
$this->handler = 'handleWeightscales';
|
||||
}
|
||||
|
||||
protected function handleExclude()
|
||||
{
|
||||
if (!User::$id)
|
||||
return;
|
||||
|
||||
if ($this->_post['mode'] == 1) // directly set exludes
|
||||
{
|
||||
$type = $this->_post['type'];
|
||||
$ids = $this->_post['id'];
|
||||
|
||||
if (!isset(Util::$typeStrings[$type]) || empty($ids))
|
||||
return;
|
||||
|
||||
// ready for some bullshit? here it comes!
|
||||
// we don't get signaled whether an id should be added to or removed from either includes or excludes
|
||||
// so we throw everything into one table and toggle the mode if its already in here
|
||||
|
||||
$includes = DB::Aowow()->selectCol('SELECT typeId FROM ?_profiler_excludes WHERE type = ?d AND typeId IN (?a)', $type, $ids);
|
||||
|
||||
foreach ($ids as $typeId)
|
||||
DB::Aowow()->query('INSERT INTO ?_account_excludes (`userId`, `type`, `typeId`, `mode`) VALUES (?a) ON DUPLICATE KEY UPDATE mode = (mode ^ 0x3)', array(
|
||||
User::$id, $type, $typeId, in_array($includes, $typeId) ? 2 : 1
|
||||
));
|
||||
|
||||
return;
|
||||
}
|
||||
else if ($this->_post['reset'] == 1) // defaults to unavailable
|
||||
{
|
||||
$mask = PR_EXCLUDE_GROUP_UNAVAILABLE;
|
||||
DB::Aowow()->query('DELETE FROM ?_account_excludes WHERE userId = ?d', User::$id);
|
||||
}
|
||||
else // clamp to real groups
|
||||
$mask = $this->_post['groups'] & PR_EXCLUDE_GROUP_ANY;
|
||||
|
||||
DB::Aowow()->query('UPDATE ?_account SET excludeGroups = ?d WHERE id = ?d', $mask, User::$id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
protected function handleWeightscales()
|
||||
{
|
||||
if ($this->_post['save'])
|
||||
{
|
||||
if (!$this->_post['scale'])
|
||||
return 0;
|
||||
|
||||
$id = 0;
|
||||
|
||||
if ($this->_post['id'] && ($id = $this->_post['id'][0]))
|
||||
{
|
||||
if (!DB::Aowow()->selectCell('SELECT 1 FROM ?_account_weightscales WHERE userId = ?d AND id = ?d', User::$id, $id))
|
||||
return 0;
|
||||
|
||||
DB::Aowow()->query('UPDATE ?_account_weightscales SET `name` = ? WHERE id = ?d', $this->_post['name'], $id);
|
||||
}
|
||||
else
|
||||
{
|
||||
$nScales = DB::Aowow()->selectCell('SELECT COUNT(id) FROM ?_account_weightscales WHERE userId = ?d', User::$id);
|
||||
if ($nScales >= 5) // more or less hard-defined in LANG.message_weightscalesaveerror
|
||||
return 0;
|
||||
|
||||
$id = DB::Aowow()->query('INSERT INTO ?_account_weightscales (`userId`, `name`) VALUES (?d, ?)', User::$id, $this->_post['name']);
|
||||
}
|
||||
|
||||
DB::Aowow()->query('DELETE FROM ?_account_weightscale_data WHERE id = ?d', $id);
|
||||
|
||||
foreach (explode(',', $this->_post['scale']) as $s)
|
||||
{
|
||||
list($k, $v) = explode(':', $s);
|
||||
if (!in_array($k, Util::$weightScales) || $v < 1)
|
||||
continue;
|
||||
|
||||
DB::Aowow()->query('INSERT INTO ?_account_weightscale_data VALUES (?d, ?, ?d)', $id, $k, $v);
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
else if ($this->_post['delete'] && $this->_post['id'] && $this->_post['id'][0])
|
||||
DB::Aowow()->query('DELETE FROM ?_account_weightscales WHERE id = ?d AND userId = ?d', $this->_post['id'][0], User::$id);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function checkScale($val)
|
||||
{
|
||||
if (preg_match('/^((\w+:\d+)(,\w+:\d+)*)$/', $val))
|
||||
return $val;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function checkName($val)
|
||||
{
|
||||
$var = trim(urldecode($val));
|
||||
|
||||
return filter_var($var, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
|
||||
}
|
||||
}
|
||||
497
includes/ajaxHandler/admin.class.php
Normal file
497
includes/ajaxHandler/admin.class.php
Normal file
@@ -0,0 +1,497 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
class AjaxAdmin extends AjaxHandler
|
||||
{
|
||||
protected $validParams = ['screenshots', 'siteconfig', 'weight-presets'];
|
||||
protected $_get = array(
|
||||
'action' => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
|
||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkId']],
|
||||
'key' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkKey']],
|
||||
'all' => [FILTER_UNSAFE_RAW, null],
|
||||
'type' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
|
||||
'typeid' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
|
||||
'user' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkUser']],
|
||||
'val' => [FILTER_UNSAFE_RAW, null]
|
||||
);
|
||||
protected $_post = array(
|
||||
'alt' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
|
||||
'id' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'scale' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkScale']],
|
||||
'__icon' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkKey']],
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
// requires 'action' parameter in any case
|
||||
if (!$this->_get['action'] || !$this->params)
|
||||
return;
|
||||
|
||||
if ($this->params[0] == 'screenshots')
|
||||
{
|
||||
if (!User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SCREENSHOT))
|
||||
return;
|
||||
|
||||
if ($this->_get['action'] == 'list')
|
||||
$this->handler = 'ssList';
|
||||
else if ($this->_get['action'] == 'manage')
|
||||
$this->handler = 'ssManage';
|
||||
else if ($this->_get['action'] == 'editalt')
|
||||
$this->handler = 'ssEditAlt';
|
||||
else if ($this->_get['action'] == 'approve')
|
||||
$this->handler = 'ssApprove';
|
||||
else if ($this->_get['action'] == 'sticky')
|
||||
$this->handler = 'ssSticky';
|
||||
else if ($this->_get['action'] == 'delete')
|
||||
$this->handler = 'ssDelete';
|
||||
else if ($this->_get['action'] == 'relocate')
|
||||
$this->handler = 'ssRelocate';
|
||||
}
|
||||
else if ($this->params[0] == 'siteconfig')
|
||||
{
|
||||
if (!User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN))
|
||||
return;
|
||||
|
||||
if ($this->_get['action'] == 'add')
|
||||
$this->handler = 'confAdd';
|
||||
else if ($this->_get['action'] == 'remove')
|
||||
$this->handler = 'confRemove';
|
||||
else if ($this->_get['action'] == 'update')
|
||||
$this->handler = 'confUpdate';
|
||||
}
|
||||
else if ($this->params[0] == 'weight-presets')
|
||||
{
|
||||
if (!User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN | U_GROUP_BUREAU))
|
||||
return;
|
||||
|
||||
if ($this->_get['action'] == 'save')
|
||||
$this->handler = 'wtSave';
|
||||
}
|
||||
}
|
||||
|
||||
// get all => null (optional)
|
||||
// evaled response .. UNK
|
||||
protected function ssList()
|
||||
{
|
||||
// ssm_screenshotPages
|
||||
// ssm_numPagesFound
|
||||
|
||||
$pages = CommunityContent::getScreenshotPagesForManager($this->_get['all'], $nPages);
|
||||
$buff = 'ssm_screenshotPages = '.Util::toJSON($pages).";\n";
|
||||
$buff .= 'ssm_numPagesFound = '.$nPages.';';
|
||||
|
||||
return $buff;
|
||||
}
|
||||
|
||||
// get: [type => type, typeId => typeId] || [user => username]
|
||||
// evaled response .. UNK
|
||||
protected function ssManage()
|
||||
{
|
||||
$res = [];
|
||||
|
||||
if ($this->_get['type'] && $this->_get['type'] && $this->_get['typeid'] && $this->_get['typeid'])
|
||||
$res = CommunityContent::getScreenshotsForManager($this->_get['type'], $this->_get['typeid']);
|
||||
else if ($this->_get['user'])
|
||||
if ($uId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE displayName = ?', $this->_get['user']))
|
||||
$res = CommunityContent::getScreenshotsForManager(0, 0, $uId);
|
||||
|
||||
return 'ssm_screenshotData = '.Util::toJSON($res);
|
||||
}
|
||||
|
||||
// get: id => SSid
|
||||
// resp: ''
|
||||
protected function ssEditAlt()
|
||||
{
|
||||
// doesn't need to be htmlEscaped, ths javascript does that
|
||||
if ($this->_get['id'] && $this->_post['alt'] !== null)
|
||||
DB::Aowow()->query('UPDATE ?_screenshots SET caption = ? WHERE id = ?d', trim($this->_post['alt']), $this->_get['id'][0]);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
// get: id => comma-separated SSids
|
||||
// resp: ''
|
||||
protected function ssApprove()
|
||||
{
|
||||
if (!$this->_get['id'])
|
||||
return '';
|
||||
|
||||
// create resized and thumb version of screenshot
|
||||
$resized = [772, 618];
|
||||
$thumb = [150, 150];
|
||||
$path = 'static/uploads/screenshots/%s/%d.jpg';
|
||||
|
||||
foreach ($this->_get['id'] as $id)
|
||||
{
|
||||
// must not be already approved
|
||||
if ($_ = DB::Aowow()->selectRow('SELECT userIdOwner, date, type, typeId FROM ?_screenshots WHERE (status & ?d) = 0 AND id = ?d', CC_FLAG_APPROVED, $id))
|
||||
{
|
||||
// should also error-log
|
||||
if (!file_exists(sprintf($path, 'pending', $id)))
|
||||
continue;
|
||||
|
||||
$srcImg = imagecreatefromjpeg(sprintf($path, 'pending', $id));
|
||||
$srcW = imagesx($srcImg);
|
||||
$srcH = imagesy($srcImg);
|
||||
|
||||
// write thumb
|
||||
$scale = min(1.0, min($thumb[0] / $srcW, $thumb[1] / $srcH));
|
||||
$destW = $srcW * $scale;
|
||||
$destH = $srcH * $scale;
|
||||
$destImg = imagecreatetruecolor($destW, $destH);
|
||||
|
||||
imagefill($destImg, 0, 0, imagecolorallocate($destImg, 255, 255, 255));
|
||||
imagecopyresampled($destImg, $srcImg, 0, 0, 0, 0, $destW, $destH, $srcW, $srcH);
|
||||
|
||||
imagejpeg($destImg, sprintf($path, 'thumb', $id), 100);
|
||||
|
||||
// write resized (only if required)
|
||||
if ($srcW > $resized[0] || $srcH > $resized[1])
|
||||
{
|
||||
$scale = min(1.0, min($resized[0] / $srcW, $resized[1] / $srcH));
|
||||
$destW = $srcW * $scale;
|
||||
$destH = $srcH * $scale;
|
||||
$destImg = imagecreatetruecolor($destW, $destH);
|
||||
|
||||
imagefill($destImg, 0, 0, imagecolorallocate($destImg, 255, 255, 255));
|
||||
imagecopyresampled($destImg, $srcImg, 0, 0, 0, 0, $destW, $destH, $srcW, $srcH);
|
||||
|
||||
imagejpeg($destImg, sprintf($path, 'resized', $id), 100);
|
||||
}
|
||||
|
||||
imagedestroy($srcImg);
|
||||
|
||||
// move screenshot from pending to normal
|
||||
rename(sprintf($path, 'pending', $id), sprintf($path, 'normal', $id));
|
||||
|
||||
// set as approved in DB and gain rep (once!)
|
||||
DB::Aowow()->query('UPDATE ?_screenshots SET status = ?d, userIdApprove = ?d WHERE id = ?d', CC_FLAG_APPROVED, User::$id, $id);
|
||||
Util::gainSiteReputation($_['userIdOwner'], SITEREP_ACTION_UPLOAD, ['id' => $id, 'what' => 1, 'date' => $_['date']]);
|
||||
// flag DB entry as having screenshots
|
||||
if (Util::$typeClasses[$_['type']] && ($tbl = get_class_vars(Util::$typeClasses[$_['type']])['dataTable']))
|
||||
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $_['typeId']);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
// get: id => comma-separated SSids
|
||||
// resp: ''
|
||||
protected function ssSticky()
|
||||
{
|
||||
if (!$this->_get['id'])
|
||||
return '';
|
||||
|
||||
// approve soon to be sticky screenshots
|
||||
$this->ssApprove();
|
||||
|
||||
// this one is a bit strange: as far as i've seen, the only thing a 'sticky' screenshot does is show up in the infobox
|
||||
// this also means, that only one screenshot per page should be sticky
|
||||
// so, handle it one by one and the last one affecting one particular type/typId-key gets the cake
|
||||
foreach ($this->_get['id'] as $id)
|
||||
{
|
||||
// reset all others
|
||||
DB::Aowow()->query('UPDATE ?_screenshots a, ?_screenshots b SET a.status = a.status & ~?d WHERE a.type = b.type AND a.typeId = b.typeId AND a.id <> b.id AND b.id = ?d', CC_FLAG_STICKY, $id);
|
||||
|
||||
// toggle sticky status
|
||||
DB::Aowow()->query('UPDATE ?_screenshots SET `status` = IF(`status` & ?d, `status` & ~?d, `status` | ?d) WHERE id = ?d AND `status` & ?d', CC_FLAG_STICKY, CC_FLAG_STICKY, CC_FLAG_STICKY, $id, CC_FLAG_APPROVED);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
// get: id => comma-separated SSids
|
||||
// resp: ''
|
||||
// 2 steps: 1) remove from sight, 2) remove from disk
|
||||
protected function ssDelete()
|
||||
{
|
||||
if (!$this->_get['id'])
|
||||
return '';
|
||||
|
||||
$path = 'static/uploads/screenshots/%s/%d.jpg';
|
||||
|
||||
foreach ($this->_get['id'] as $id)
|
||||
{
|
||||
// irrevocably remove already deleted files
|
||||
if (User::isInGroup(U_GROUP_ADMIN) && DB::Aowow()->selectCell('SELECT 1 FROM ?_screenshots WHERE status & ?d AND id = ?d', CC_FLAG_DELETED, $id))
|
||||
{
|
||||
DB::Aowow()->query('DELETE FROM ?_screenshots WHERE id = ?d', $id);
|
||||
if (file_exists(sprintf($path, 'pending', $id)))
|
||||
unlink(sprintf($path, 'pending', $id));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// move pending or normal to pending
|
||||
if (file_exists(sprintf($path, 'normal', $id)))
|
||||
rename(sprintf($path, 'normal', $id), sprintf($path, 'pending', $id));
|
||||
|
||||
// remove resized and thumb
|
||||
if (file_exists(sprintf($path, 'thumb', $id)))
|
||||
unlink(sprintf($path, 'thumb', $id));
|
||||
|
||||
if (file_exists(sprintf($path, 'resized', $id)))
|
||||
unlink(sprintf($path, 'resized', $id));
|
||||
}
|
||||
|
||||
// flag as deleted if not aready
|
||||
$oldEntries = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, GROUP_CONCAT(typeId) FROM ?_screenshots WHERE id IN (?a) GROUP BY `type`', $this->_get['id']);
|
||||
DB::Aowow()->query('UPDATE ?_screenshots SET status = ?d, userIdDelete = ?d WHERE id IN (?a)', CC_FLAG_DELETED, User::$id, $this->_get['id']);
|
||||
// deflag db entry as having screenshots
|
||||
foreach ($oldEntries as $type => $typeIds)
|
||||
{
|
||||
$typeIds = explode(',', $typeIds);
|
||||
$toUnflag = DB::Aowow()->selectCol('SELECT typeId AS ARRAY_KEY, IF(BIT_OR(`status`) & ?d, 1, 0) AS hasMore FROM ?_screenshots WHERE `type` = ?d AND typeId IN (?a) GROUP BY typeId HAVING hasMore = 0', CC_FLAG_APPROVED, $type, $typeIds);
|
||||
if ($toUnflag && Util::$typeClasses[$type] && ($tbl = get_class_vars(Util::$typeClasses[$type])['dataTable']))
|
||||
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags & ~?d WHERE id IN (?a)', CUSTOM_HAS_SCREENSHOT, array_keys($toUnflag));
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
// get: id => ssId, typeid => typeId (but not type..?)
|
||||
// resp: ''
|
||||
protected function ssRelocate()
|
||||
{
|
||||
if (!$this->_get['id'] || !$this->_get['typeid'])
|
||||
return '';
|
||||
|
||||
$id = $this->_get['id'][0];
|
||||
list($type, $oldTypeId) = array_values(DB::Aowow()->selectRow('SELECT type, typeId FROM ?_screenshots WHERE id = ?d', $id));
|
||||
$typeId = (int)$this->_get['typeid'];
|
||||
|
||||
$tc = new Util::$typeClasses[$type]([['id', $typeId]]);
|
||||
if (!$tc->error)
|
||||
{
|
||||
// move screenshot
|
||||
DB::Aowow()->query('UPDATE ?_screenshots SET typeId = ?d WHERE id = ?d', $typeId, $id);
|
||||
|
||||
// flag target as having screenshot
|
||||
DB::Aowow()->query('UPDATE '.$tc::$dataTable.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $typeId);
|
||||
|
||||
// deflag source for having had screenshots (maybe)
|
||||
$ssInfo = DB::Aowow()->selectRow('SELECT IF(BIT_OR(~status) & ?d, 1, 0) AS hasMore FROM ?_screenshots WHERE `status`& ?d AND `type` = ?d AND typeId = ?d', CC_FLAG_DELETED, CC_FLAG_APPROVED, $type, $oldTypeId);
|
||||
if($ssInfo || !$ssInfo['hasMore'])
|
||||
DB::Aowow()->query('UPDATE '.$tc::$dataTable.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $oldTypeId);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function confAdd()
|
||||
{
|
||||
$key = trim($this->_get['key']);
|
||||
$val = trim(urldecode($this->_get['val']));
|
||||
|
||||
if ($key === null)
|
||||
return 'empty option name given';
|
||||
|
||||
if (!strlen($key))
|
||||
return 'invalid chars in option name: [a-z 0-9 _ . -] are allowed';
|
||||
|
||||
if (ini_get($key) === false || ini_set($key, $val) === false)
|
||||
return 'this configuration option cannot be set';
|
||||
|
||||
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_config WHERE `flags` & ?d AND `key` = ?', CON_FLAG_PHP, $key))
|
||||
return 'this configuration option is already in use';
|
||||
|
||||
DB::Aowow()->query('INSERT IGNORE INTO ?_config (`key`, `value`, `cat`, `flags`) VALUES (?, ?, 0, ?d)', $key, $val, CON_FLAG_TYPE_STRING | CON_FLAG_PHP);
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function confRemove()
|
||||
{
|
||||
if (!$this->_get['key'])
|
||||
return 'invalid configuration option given';
|
||||
|
||||
if (DB::Aowow()->query('DELETE FROM ?_config WHERE `key` = ? AND (`flags` & ?d) = 0', $this->_get['key'], CON_FLAG_PERSISTENT))
|
||||
return '';
|
||||
else
|
||||
return 'option name is either protected or was not found';
|
||||
}
|
||||
|
||||
protected function confUpdate()
|
||||
{
|
||||
$key = trim($this->_get['key']);
|
||||
$val = trim(urldecode($this->_get['val']));
|
||||
$msg = '';
|
||||
|
||||
if (!strlen($key))
|
||||
return 'empty option name given';
|
||||
|
||||
$cfg = DB::Aowow()->selectRow('SELECT `flags`, `value` FROM ?_config WHERE `key` = ?', $key);
|
||||
if (!$cfg)
|
||||
return 'configuration option not found';
|
||||
|
||||
if (!($cfg['flags'] & CON_FLAG_TYPE_STRING) && !strlen($val))
|
||||
return 'empty value given';
|
||||
else if ($cfg['flags'] & CON_FLAG_TYPE_INT && !preg_match('/^-?\d+$/i', $val))
|
||||
return "value must be integer";
|
||||
else if ($cfg['flags'] & CON_FLAG_TYPE_FLOAT && !preg_match('/^-?\d*(,|.)?\d+$/i', $val))
|
||||
return "value must be float";
|
||||
else if ($cfg['flags'] & CON_FLAG_TYPE_BOOL)
|
||||
$val = (int)!!$val; // *snort* bwahahaa
|
||||
|
||||
DB::Aowow()->query('UPDATE ?_config SET `value` = ? WHERE `key` = ?', $val, $key);
|
||||
if (!$this->confOnChange($key, $val, $msg))
|
||||
DB::Aowow()->query('UPDATE ?_config SET `value` = ? WHERE `key` = ?', $cfg['value'], $key);
|
||||
|
||||
return $msg;
|
||||
}
|
||||
|
||||
protected function wtSave()
|
||||
{
|
||||
if (!$this->_post['id'] || !$this->_post['__icon'])
|
||||
return 3;
|
||||
|
||||
$writeFile = function($file, $content)
|
||||
{
|
||||
$success = false;
|
||||
if ($handle = @fOpen($file, "w"))
|
||||
{
|
||||
if (fWrite($handle, $content))
|
||||
$success = true;
|
||||
|
||||
fClose($handle);
|
||||
}
|
||||
else
|
||||
die('me no file');
|
||||
|
||||
if ($success)
|
||||
@chmod($file, Util::FILE_ACCESS);
|
||||
|
||||
return $success;
|
||||
};
|
||||
|
||||
|
||||
// save to db
|
||||
|
||||
DB::Aowow()->query('DELETE FROM ?_account_weightscale_data WHERE id = ?d', $this->_post['id']);
|
||||
DB::Aowow()->query('UPDATE ?_account_weightscales SET `icon`= ? WHERE `id` = ?d', $this->_post['__icon'], $this->_post['id']);
|
||||
|
||||
foreach (explode(',', $this->_post['scale']) as $s)
|
||||
{
|
||||
list($k, $v) = explode(':', $s);
|
||||
|
||||
if (!in_array($k, Util::$weightScales) || $v < 1)
|
||||
continue;
|
||||
|
||||
if (DB::Aowow()->query('INSERT INTO ?_account_weightscale_data VALUES (?d, ?, ?d)', $this->_post['id'], $k, $v) === null)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// write dataset
|
||||
|
||||
$wtPresets = [];
|
||||
$scales = DB::Aowow()->select('SELECT id, name, icon, class FROM ?_account_weightscales WHERE userId = 0 ORDER BY class, id ASC');
|
||||
|
||||
foreach ($scales as $s)
|
||||
{
|
||||
$weights = DB::Aowow()->selectCol('SELECT field AS ARRAY_KEY, val FROM ?_account_weightscale_data WHERE id = ?d', $s['id']);
|
||||
if (!$weights)
|
||||
continue;
|
||||
|
||||
$wtPresets[$s['class']]['pve'][$s['name']] = array_merge(['__icon' => $s['icon']], $weights);
|
||||
}
|
||||
|
||||
$toFile = "var wt_presets = ".Util::toJSON($wtPresets).";";
|
||||
$file = 'datasets/weight-presets';
|
||||
|
||||
if (!$writeFile($file, $toFile))
|
||||
return 2;
|
||||
|
||||
|
||||
// all done
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function checkId($val)
|
||||
{
|
||||
// expecting id-list
|
||||
if (preg_match('/\d+(,\d+)*/', $val))
|
||||
return array_map('intVal', explode(',', $val));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function checkKey($val)
|
||||
{
|
||||
// expecting string
|
||||
if (preg_match('/[^a-z0-9_\.\-]/i', $val))
|
||||
return '';
|
||||
|
||||
return strtolower($val);
|
||||
}
|
||||
|
||||
protected function checkUser($val)
|
||||
{
|
||||
$n = Util::lower(trim(urldecode($val)));
|
||||
|
||||
if (User::isValidName($n))
|
||||
return $n;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function checkScale($val)
|
||||
{
|
||||
if (preg_match('/^((\w+:\d+)(,\w+:\d+)*)$/', $val))
|
||||
return $val;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function confOnChange($key, $val, &$msg)
|
||||
{
|
||||
$fn = $buildList = null;
|
||||
|
||||
switch ($key)
|
||||
{
|
||||
case 'battlegroup':
|
||||
$buildList = 'realms,realmMenu';
|
||||
break;
|
||||
case 'name_short':
|
||||
$buildList = 'searchboxBody,demo,searchplugin';
|
||||
break;
|
||||
case 'site_host':
|
||||
$buildList = 'searchplugin,demo,power,searchboxBody';
|
||||
break;
|
||||
case 'static_host':
|
||||
$buildList = 'searchplugin,power,searchboxBody,searchboxScript';
|
||||
break;
|
||||
case 'locales':
|
||||
$buildList = 'locales';
|
||||
$msg .= ' * remember to rebuild all static files for the language you just added.<br />';
|
||||
$msg .= ' * you can speed this up by supplying the regionCode to the setup: <pre class="q1">--locales=<regionCodes,> -f</pre>';
|
||||
break;
|
||||
case 'profiler_queue':
|
||||
$fn = function($x) use (&$msg) {
|
||||
if (!$x)
|
||||
return true;
|
||||
|
||||
return Profiler::queueStart($msg);
|
||||
};
|
||||
break;
|
||||
default: // nothing to do, everything is fine
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($buildList)
|
||||
{
|
||||
// we need to use exec as build() can only be run from CLI
|
||||
exec('php aowow --build='.$buildList, $out);
|
||||
foreach ($out as $o)
|
||||
if (strstr($o, 'ERR'))
|
||||
$msg .= explode('0m]', $o)[1]."<br />\n";
|
||||
}
|
||||
|
||||
return $fn ? $fn($val) : true;
|
||||
}
|
||||
}
|
||||
82
includes/ajaxHandler/arenateam.class.php
Normal file
82
includes/ajaxHandler/arenateam.class.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('invalid access');
|
||||
|
||||
class AjaxArenaTeam extends AjaxHandler
|
||||
{
|
||||
protected $validParams = ['resync', 'status'];
|
||||
protected $_get = array(
|
||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdList']],
|
||||
'profile' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkEmptySet']],
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
if (!$this->params)
|
||||
return;
|
||||
|
||||
switch ($this->params[0])
|
||||
{
|
||||
case 'resync':
|
||||
$this->handler = 'handleResync';
|
||||
break;
|
||||
case 'status':
|
||||
$this->handler = 'handleStatus';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* params
|
||||
id: <prId1,prId2,..,prIdN>
|
||||
user: <string> [optional, not used]
|
||||
profile: <empty> [optional, also get related chars]
|
||||
return: 1
|
||||
*/
|
||||
protected function handleResync()
|
||||
{
|
||||
if ($teams = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_arena_team WHERE id IN (?a)', $this->_get['id']))
|
||||
foreach ($teams as $t)
|
||||
Profiler::scheduleResync(TYPE_ARENA_TEAM, $t['realm'], $t['realmGUID']);
|
||||
|
||||
if ($this->_get['profile'])
|
||||
if ($chars = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_profiles p JOIN ?_profiler_arena_team_member atm ON atm.profileId = p.id WHERE atm.arenaTeamId IN (?a)', $this->_get['id']))
|
||||
foreach ($chars as $c)
|
||||
Profiler::scheduleResync(TYPE_PROFILE, $c['realm'], $c['realmGUID']);
|
||||
|
||||
return '1';
|
||||
}
|
||||
|
||||
/* params
|
||||
id: <prId1,prId2,..,prIdN>
|
||||
return
|
||||
<status object>
|
||||
[
|
||||
nQueueProcesses,
|
||||
[statusCode, timeToRefresh, curQueuePos, errorCode, nResyncTries],
|
||||
[<anotherStatus>]
|
||||
...
|
||||
]
|
||||
|
||||
not all fields are required, if zero they are omitted
|
||||
statusCode:
|
||||
0: end the request
|
||||
1: waiting
|
||||
2: working...
|
||||
3: ready; click to view
|
||||
4: error / retry
|
||||
errorCode:
|
||||
0: unk error
|
||||
1: char does not exist
|
||||
2: armory gone
|
||||
*/
|
||||
protected function handleStatus()
|
||||
{
|
||||
$response = Profiler::resyncStatus(TYPE_ARENA_TEAM, $this->_get['id']);
|
||||
return Util::toJSON($response);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
410
includes/ajaxHandler/comment.class.php
Normal file
410
includes/ajaxHandler/comment.class.php
Normal file
@@ -0,0 +1,410 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
class AjaxComment extends AjaxHandler
|
||||
{
|
||||
const COMMENT_LENGTH_MIN = 10;
|
||||
const COMMENT_LENGTH_MAX = 7500;
|
||||
const REPLY_LENGTH_MIN = 15;
|
||||
const REPLY_LENGTH_MAX = 600;
|
||||
|
||||
protected $_post = array(
|
||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxComment::checkId']],
|
||||
'body' => [FILTER_UNSAFE_RAW, null],// escaped by json_encode
|
||||
'commentbody' => [FILTER_UNSAFE_RAW, null],// escaped by json_encode
|
||||
'response' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
|
||||
'reason' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
|
||||
'remove' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'commentId' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'replyId' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'sticky' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
// 'username' => [FILTER_SANITIZE_STRING, 0xC] // FILTER_FLAG_STRIP_LOW | *_HIGH
|
||||
);
|
||||
|
||||
protected $_get = array(
|
||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
|
||||
'type' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
|
||||
'typeid' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
|
||||
'rating' => [FILTER_SANITIZE_NUMBER_INT, null]
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
if (!$this->params || count($this->params) != 1)
|
||||
return;
|
||||
|
||||
// note: return values must be formated as STRICT json!
|
||||
|
||||
// select handler
|
||||
if ($this->params[0] == 'add')
|
||||
$this->handler = 'handleCommentAdd';
|
||||
else if ($this->params[0] == 'edit')
|
||||
$this->handler = 'handleCommentEdit';
|
||||
else if ($this->params[0] == 'delete')
|
||||
$this->handler = 'handleCommentDelete';
|
||||
else if ($this->params[0] == 'undelete')
|
||||
$this->handler = 'handleCommentUndelete';
|
||||
else if ($this->params[0] == 'rating') // up/down - distribution
|
||||
$this->handler = 'handleCommentRating';
|
||||
else if ($this->params[0] == 'vote') // up, down and remove
|
||||
$this->handler = 'handleCommentVote';
|
||||
else if ($this->params[0] == 'sticky') // toggle flag
|
||||
$this->handler = 'handleCommentSticky';
|
||||
else if ($this->params[0] == 'out-of-date') // toggle flag
|
||||
$this->handler = 'handleCommentOutOfDate';
|
||||
else if ($this->params[0] == 'show-replies')
|
||||
$this->handler = 'handleCommentShowReplies';
|
||||
else if ($this->params[0] == 'add-reply') // also returns all replies on success
|
||||
$this->handler = 'handleReplyAdd';
|
||||
else if ($this->params[0] == 'edit-reply') // also returns all replies on success
|
||||
$this->handler = 'handleReplyEdit';
|
||||
else if ($this->params[0] == 'detach-reply')
|
||||
$this->handler = 'handleReplyDetach';
|
||||
else if ($this->params[0] == 'delete-reply')
|
||||
$this->handler = 'handleReplyDelete';
|
||||
else if ($this->params[0] == 'flag-reply')
|
||||
$this->handler = 'handleReplyFlag';
|
||||
else if ($this->params[0] == 'upvote-reply')
|
||||
$this->handler = 'handleReplyUpvote';
|
||||
else if ($this->params[0] == 'downvote-reply')
|
||||
$this->handler = 'handleReplyDownvote';
|
||||
}
|
||||
|
||||
// i .. have problems believing, that everything uses nifty ajax while adding comments requires a brutal header(Loacation: <wherever>), yet, thats how it is
|
||||
protected function handleCommentAdd()
|
||||
{
|
||||
if (!$this->_get['typeid'] || !$this->_get['type'] || !isset(Util::$typeClasses[$this->_get['type']]))
|
||||
return; // whatever, we cant even send him back
|
||||
|
||||
// this type cannot be commented on
|
||||
if (!(get_class_vars(Util::$typeClasses[$this->_get['type']])['contribute'] & CONTRIBUTE_CO))
|
||||
return;
|
||||
|
||||
// trim to max length
|
||||
if (!User::isInGroup(U_GROUP_MODERATOR) && mb_strlen($this->_post['commentbody']) > (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)))
|
||||
$this->post['commentbody'] = mb_substr($this->_post['commentbody'], 0, (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)));
|
||||
|
||||
if (User::canComment() && !empty($this->_post['commentbody']) && mb_strlen($this->_post['commentbody']) >= self::COMMENT_LENGTH_MIN)
|
||||
{
|
||||
if ($postIdx = DB::Aowow()->query('INSERT INTO ?_comments (type, typeId, userId, roles, body, date) VALUES (?d, ?d, ?d, ?d, ?, UNIX_TIMESTAMP())', $this->_get['type'], $this->_get['typeid'], User::$id, User::$groups, $this->_post['commentbody']))
|
||||
{
|
||||
Util::gainSiteReputation(User::$id, SITEREP_ACTION_COMMENT, ['id' => $postIdx]);
|
||||
|
||||
// every comment starts with a rating of +1 and i guess the simplest thing to do is create a db-entry with the system as owner
|
||||
DB::Aowow()->query('INSERT INTO ?_comments_rates (commentId, userId, value) VALUES (?d, 0, 1)', $postIdx);
|
||||
|
||||
// flag target with hasComment
|
||||
if ($tbl = get_class_vars(Util::$typeClasses[$this->_get['type']])['dataTable'])
|
||||
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $this->_get['typeid']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->doRedirect = true;
|
||||
return '?'.Util::$typeStrings[$this->_get['type']].'='.$this->_get['typeid'].'#comments';
|
||||
}
|
||||
|
||||
protected function handleCommentEdit()
|
||||
{
|
||||
if ((!User::canComment() && !User::isInGroup(U_GROUP_MODERATOR)) || !$this->_get['id'] || !$this->_post['body'])
|
||||
return;
|
||||
|
||||
if (mb_strlen($this->_post['body']) < self::COMMENT_LENGTH_MIN)
|
||||
return;
|
||||
|
||||
// trim to max length
|
||||
if (!User::isInGroup(U_GROUP_MODERATOR) && mb_strlen($this->_post['body']) > (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)))
|
||||
$this->post['body'] = mb_substr($this->_post['body'], 0, (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)));
|
||||
|
||||
$update = array(
|
||||
'body' => $this->_post['body'],
|
||||
'editUserId' => User::$id,
|
||||
'editDate' => time()
|
||||
);
|
||||
|
||||
if (User::isInGroup(U_GROUP_MODERATOR))
|
||||
{
|
||||
$update['responseBody'] = !$this->_post['response'] ? '' : $this->_post['response'];
|
||||
$update['responseUserId'] = !$this->_post['response'] ? 0 : User::$id;
|
||||
$update['responseRoles'] = !$this->_post['response'] ? 0 : User::$groups;
|
||||
}
|
||||
|
||||
DB::Aowow()->query('UPDATE ?_comments SET editCount = editCount + 1, ?a WHERE id = ?d', $update, $this->_get['id']);
|
||||
}
|
||||
|
||||
protected function handleCommentDelete()
|
||||
{
|
||||
if (!$this->_post['id'] || !User::$id)
|
||||
return;
|
||||
|
||||
// in theory, there is a username passed alongside... lets just use the current user (see user.js)
|
||||
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d, deleteUserId = ?d, deleteDate = UNIX_TIMESTAMP() WHERE id IN (?a){ AND userId = ?d}',
|
||||
CC_FLAG_DELETED,
|
||||
User::$id,
|
||||
$this->_post['id'],
|
||||
User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id
|
||||
);
|
||||
|
||||
// deflag hasComment
|
||||
if ($ok)
|
||||
{
|
||||
$coInfo = DB::Aowow()->selectRow('SELECT IF(BIT_OR(~b.flags) & ?d, 1, 0) as hasMore, b.type, b.typeId FROM ?_comments a JOIN ?_comments b ON a.type = b.type AND a.typeId = b.typeId WHERE a.id = ?d',
|
||||
CC_FLAG_DELETED,
|
||||
$this->_post['id']
|
||||
);
|
||||
|
||||
if (!$coInfo['hasMore'] && Util::$typeClasses[$coInfo['type']] && ($tbl = get_class_vars(Util::$typeClasses[$coInfo['type']])['dataTable']))
|
||||
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']);
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleCommentUndelete()
|
||||
{
|
||||
if (!$this->_post['id'] || !User::$id)
|
||||
return;
|
||||
|
||||
// in theory, there is a username passed alongside... lets just use the current user (see user.js)
|
||||
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id IN (?a){ AND userId = deleteUserId AND deleteUserId = ?d}',
|
||||
CC_FLAG_DELETED,
|
||||
$this->_post['id'],
|
||||
User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id
|
||||
);
|
||||
|
||||
// reflag hasComment
|
||||
if ($ok)
|
||||
{
|
||||
$coInfo = DB::Aowow()->selectRow('SELECT type, typeId FROM ?_comments WHERE id = ?d', $this->_post['id']);
|
||||
if (Util::$typeClasses[$coInfo['type']] && ($tbl = get_class_vars(Util::$typeClasses[$coInfo['type']])['dataTable']))
|
||||
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']);
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleCommentRating()
|
||||
{
|
||||
if (!$this->_get['id'])
|
||||
return Util::toJSON(['success' => 0]);
|
||||
|
||||
if ($votes = DB::Aowow()->selectRow('SELECT 1 AS success, SUM(IF(value > 0, value, 0)) AS up, SUM(IF(value < 0, -value, 0)) AS down FROM ?_comments_rates WHERE commentId = ?d and userId <> 0 GROUP BY commentId', $this->_get['id']))
|
||||
return Util::toJSON($votes);
|
||||
else
|
||||
return Util::toJSON(['success' => 1, 'up' => 0, 'down' => 0]);
|
||||
}
|
||||
|
||||
protected function handleCommentVote()
|
||||
{
|
||||
if (!User::$id || !$this->_get['id'] || !$this->_get['rating'])
|
||||
return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
|
||||
|
||||
$target = DB::Aowow()->selectRow('SELECT c.userId AS owner, cr.value FROM ?_comments c LEFT JOIN ?_comments_rates cr ON cr.commentId = c.id AND cr.userId = ?d WHERE c.id = ?d', User::$id, $this->_get['id']);
|
||||
$val = User::canSupervote() ? 2 : 1;
|
||||
if ($this->_get['rating'] < 0)
|
||||
$val *= -1;
|
||||
|
||||
if (User::getCurDailyVotes() <= 0)
|
||||
return Util::toJSON(['error' => 1, 'message' => Lang::main('tooManyVotes')]);
|
||||
else if (!$target || $val != $this->_get['rating'])
|
||||
return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
|
||||
else if (($val > 0 && !User::canUpvote()) || ($val < 0 && !User::canDownvote()))
|
||||
return Util::toJSON(['error' => 1, 'message' => Lang::main('bannedRating')]);
|
||||
|
||||
$ok = false;
|
||||
// old and new have same sign; undo vote (user may have gained/lost access to superVote in the meantime)
|
||||
if ($target['value'] && ($target['value'] < 0) == ($val < 0))
|
||||
$ok = DB::Aowow()->query('DELETE FROM ?_comments_rates WHERE commentId = ?d AND userId = ?d', $this->_get['id'], User::$id);
|
||||
else // replace, because we may be overwriting an old, opposing vote
|
||||
if ($ok = DB::Aowow()->query('REPLACE INTO ?_comments_rates (commentId, userId, value) VALUES (?d, ?d, ?d)', (int)$this->_get['id'], User::$id, $val))
|
||||
User::decrementDailyVotes(); // do not refund retracted votes!
|
||||
|
||||
if (!$ok)
|
||||
return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
|
||||
|
||||
if ($val > 0) // gain rep
|
||||
Util::gainSiteReputation($target['owner'], SITEREP_ACTION_UPVOTED, ['id' => $this->_get['id'], 'voterId' => User::$id]);
|
||||
else if ($val < 0)
|
||||
Util::gainSiteReputation($target['owner'], SITEREP_ACTION_DOWNVOTED, ['id' => $this->_get['id'], 'voterId' => User::$id]);
|
||||
|
||||
return Util::toJSON(['error' => 0]);
|
||||
}
|
||||
|
||||
protected function handleCommentSticky()
|
||||
{
|
||||
if (!$this->_post['id'] || !User::isInGroup(U_GROUP_MODERATOR))
|
||||
return;
|
||||
|
||||
if ($this->_post['sticky'])
|
||||
DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d WHERE id = ?d', CC_FLAG_STICKY, $this->_post['id'][0]);
|
||||
else
|
||||
DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id = ?d', CC_FLAG_STICKY, $this->_post['id'][0]);
|
||||
}
|
||||
|
||||
protected function handleCommentOutOfDate()
|
||||
{
|
||||
$this->contentType = 'text/plain';
|
||||
|
||||
if (!$this->_post['id'])
|
||||
return 'The comment does not exist.';
|
||||
|
||||
$ok = false;
|
||||
if (User::isInGroup(U_GROUP_MODERATOR)) // directly mark as outdated
|
||||
{
|
||||
if (!$this->_post['remove'])
|
||||
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | 0x4 WHERE id = ?d', $this->_post['id'][0]);
|
||||
else
|
||||
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~0x4 WHERE id = ?d', $this->_post['id'][0]);
|
||||
}
|
||||
else if (User::$id && !$this->_post['reason'] || mb_strlen($this->_post['reason']) < self::REPLY_LENGTH_MIN)
|
||||
return 'Your message is too short.';
|
||||
else if (User::$id) // only report as outdated
|
||||
{
|
||||
$ok = DB::Aowow()->query(
|
||||
'INSERT INTO ?_reports (userId, mode, reason, subject, ip, description, userAgent, appName) VALUES (?d, 1, 17, ?d, ?, "<automated comment report>", ?, ?)',
|
||||
User::$id,
|
||||
$this->_post['id'][0],
|
||||
User::$ip,
|
||||
$_SERVER['HTTP_USER_AGENT'],
|
||||
get_browser(null, true)['browser']
|
||||
);
|
||||
}
|
||||
|
||||
if ($ok) // this one is very special; as in: completely retarded
|
||||
return 'ok'; // the script expects the actual characters 'ok' not some string like "ok"
|
||||
|
||||
return Lang::main('genericError');
|
||||
}
|
||||
|
||||
protected function handleCommentShowReplies()
|
||||
{
|
||||
return Util::toJSON(!$this->_get['id'] ? [] : CommunityContent::getCommentReplies($this->_get['id']));
|
||||
}
|
||||
|
||||
protected function handleReplyAdd()
|
||||
{
|
||||
$this->contentType = 'text/plain';
|
||||
|
||||
if (!User::canComment())
|
||||
return 'You are not allowed to reply.';
|
||||
|
||||
else if (!$this->_post['commentId'] || !DB::Aowow()->selectCell('SELECT 1 FROM ?_comments WHERE id = ?d', $this->_post['commentId']))
|
||||
return Lang::main('genericError');
|
||||
|
||||
else if (!$this->_post['body'] || mb_strlen($this->_post['body']) < self::REPLY_LENGTH_MIN || mb_strlen($this->_post['body']) > self::REPLY_LENGTH_MAX)
|
||||
return 'Your reply has '.mb_strlen($this->_post['body']).' characters and must have at least '.self::REPLY_LENGTH_MIN.' and at most '.self::REPLY_LENGTH_MAX.'.';
|
||||
|
||||
else if (DB::Aowow()->query('INSERT INTO ?_comments (`userId`, `roles`, `body`, `date`, `replyTo`) VALUES (?d, ?d, ?, UNIX_TIMESTAMP(), ?d)', User::$id, User::$groups, $this->_post['body'], $this->_post['commentId']))
|
||||
return Util::toJSON(CommunityContent::getCommentReplies($this->_post['commentId']));
|
||||
|
||||
else
|
||||
return Lang::main('genericError');
|
||||
}
|
||||
|
||||
protected function handleReplyEdit()
|
||||
{
|
||||
$this->contentType = 'text/plain';
|
||||
|
||||
if (!User::canComment())
|
||||
return 'You are not allowed to reply.';
|
||||
|
||||
else if (!$this->_post['replyId'] || !$this->_post['commentId'])
|
||||
return Lang::main('genericError');
|
||||
|
||||
else if (!$this->_post['body'] || mb_strlen($this->_post['body']) < self::REPLY_LENGTH_MIN || mb_strlen($this->_post['body']) > self::REPLY_LENGTH_MAX)
|
||||
return 'Your reply has '.mb_strlen($this->_post['body']).' characters and must have at least '.self::REPLY_LENGTH_MIN.' and at most '.self::REPLY_LENGTH_MAX.'.';
|
||||
|
||||
if (DB::Aowow()->query('UPDATE ?_comments SET body = ?, editUserId = ?d, editDate = UNIX_TIMESTAMP(), editCount = editCount + 1 WHERE id = ?d AND replyTo = ?d{ AND userId = ?d}',
|
||||
$this->_post['body'], User::$id, $this->_post['replyId'], $this->_post['commentId'], User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id))
|
||||
return Util::toJSON(CommunityContent::getCommentReplies($this->_post['commentId']));
|
||||
else
|
||||
return Lang::main('genericError');
|
||||
}
|
||||
|
||||
protected function handleReplyDetach()
|
||||
{
|
||||
if (!User::isInGroup(U_GROUP_MODERATOR) || !$this->_post['id'])
|
||||
return;
|
||||
|
||||
DB::Aowow()->query('UPDATE ?_comments c1, ?_comments c2 SET c1.replyTo = 0, c1.type = c2.type, c1.typeId = c2.typeId WHERE c1.replyTo = c2.id AND c1.id = ?d', $this->_post['id'][0]);
|
||||
}
|
||||
|
||||
protected function handleReplyDelete()
|
||||
{
|
||||
if (!User::$id || !$this->_post['id'])
|
||||
return;
|
||||
|
||||
if (DB::Aowow()->query('DELETE FROM ?_comments WHERE id = ?d{ AND userId = ?d}', $this->_post['id'][0], User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id))
|
||||
DB::Aowow()->query('DELETE FROM ?_comments_rates WHERE commentId = ?d', $this->_post['id'][0]);
|
||||
}
|
||||
|
||||
protected function handleReplyFlag()
|
||||
{
|
||||
if (!User::$id || !$this->_post['id'])
|
||||
return;
|
||||
|
||||
DB::Aowow()->query(
|
||||
'INSERT INTO ?_reports (userId, mode, reason, subject, ip, description, userAgent, appName) VALUES (?d, 1, 19, ?d, ?, "<automated commentreply report>", ?, ?)',
|
||||
User::$id,
|
||||
$this->_post['id'][0],
|
||||
User::$ip,
|
||||
$_SERVER['HTTP_USER_AGENT'],
|
||||
get_browser(null, true)['browser']
|
||||
);
|
||||
}
|
||||
|
||||
protected function handleReplyUpvote()
|
||||
{
|
||||
if (!$this->_post['id'] || !User::canUpvote())
|
||||
return;
|
||||
|
||||
$owner = DB::Aowow()->selectCell('SELECT userId FROM ?_comments WHERE id = ?d', $this->_post['id'][0]);
|
||||
if (!$owner)
|
||||
return;
|
||||
|
||||
$ok = DB::Aowow()->query(
|
||||
'INSERT INTO ?_comments_rates (commentId, userId, value) VALUES (?d, ?d, ?d)',
|
||||
$this->_post['id'][0],
|
||||
User::$id,
|
||||
User::canSupervote() ? 2 : 1
|
||||
);
|
||||
|
||||
if ($ok)
|
||||
{
|
||||
Util::gainSiteReputation($owner, SITEREP_ACTION_UPVOTED, ['id' => $this->_post['id'][0], 'voterId' => User::$id]);
|
||||
User::decrementDailyVotes();
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleReplyDownvote()
|
||||
{
|
||||
if (!$this->_post['id'] || !User::canDownvote())
|
||||
return;
|
||||
|
||||
$owner = DB::Aowow()->selectCell('SELECT userId FROM ?_comments WHERE id = ?d', $this->_post['id'][0]);
|
||||
if (!$owner)
|
||||
return;
|
||||
|
||||
$ok = DB::Aowow()->query(
|
||||
'INSERT INTO ?_comments_rates (commentId, userId, value) VALUES (?d, ?d, ?d)',
|
||||
$this->_post['id'][0],
|
||||
User::$id,
|
||||
User::canSupervote() ? -2 : -1
|
||||
);
|
||||
|
||||
if ($ok)
|
||||
{
|
||||
Util::gainSiteReputation($owner, SITEREP_ACTION_DOWNVOTED, ['id' => $this->_post['id'][0], 'voterId' => User::$id]);
|
||||
User::decrementDailyVotes();
|
||||
}
|
||||
}
|
||||
|
||||
protected function checkId($val)
|
||||
{
|
||||
// expecting id-list
|
||||
if (preg_match('/\d+(,\d+)*/', $val))
|
||||
return array_map('intVal', explode(',', $val));
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
?>
|
||||
100
includes/ajaxHandler/contactus.class.php
Normal file
100
includes/ajaxHandler/contactus.class.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
class AjaxContactus extends AjaxHandler
|
||||
{
|
||||
protected $_post = array(
|
||||
'mode' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'reason' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'ua' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
|
||||
'appname' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
|
||||
'page' => [FILTER_SANITIZE_URL, null],
|
||||
'desc' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
|
||||
'id' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'relatedurl' => [FILTER_SANITIZE_URL, null],
|
||||
'email' => [FILTER_SANITIZE_EMAIL, null]
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
// always this one
|
||||
$this->handler = 'handleContactUs';
|
||||
}
|
||||
|
||||
/* responses
|
||||
0: success
|
||||
1: captcha invalid
|
||||
2: description too long
|
||||
3: reason missing
|
||||
7: already reported
|
||||
$: prints response
|
||||
*/
|
||||
protected function handleContactUs()
|
||||
{
|
||||
$mode = $this->_post['mode'];
|
||||
$rsn = $this->_post['reason'];
|
||||
$ua = $this->_post['ua'];
|
||||
$app = $this->_post['appname'];
|
||||
$url = $this->_post['page'];
|
||||
$desc = $this->_post['desc'];
|
||||
|
||||
$contexts = array(
|
||||
[1, 2, 3, 4, 5, 6, 7, 8],
|
||||
[15, 16, 17, 18, 19, 20],
|
||||
[30, 31, 32, 33, 34, 35, 36, 37],
|
||||
[45, 46, 47, 48],
|
||||
[60, 61],
|
||||
[45, 46, 47, 48],
|
||||
[45, 46, 48]
|
||||
);
|
||||
|
||||
if ($mode === null || $rsn === null || $ua === null || $app === null || $url === null)
|
||||
return 'required field missing';
|
||||
|
||||
if (!isset($contexts[$mode]) || !in_array($rsn, $contexts[$mode]))
|
||||
return 'mode invalid';
|
||||
|
||||
if (!$desc)
|
||||
return 3;
|
||||
|
||||
if (mb_strlen($desc) > 500)
|
||||
return 2;
|
||||
|
||||
if (!User::$id && !User::$ip)
|
||||
return 'your ip could not be determined';
|
||||
|
||||
// check already reported
|
||||
$field = User::$id ? 'userId' : 'ip';
|
||||
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_reports WHERE `mode` = ?d AND `reason`= ?d AND `subject` = ?d AND ?# = ?', $mode, $rsn, $this->_post['id'], $field, User::$id ?: User::$ip))
|
||||
return 7;
|
||||
|
||||
$update = array(
|
||||
'userId' => User::$id,
|
||||
'mode' => $mode,
|
||||
'reason' => $rsn,
|
||||
'ip' => User::$ip,
|
||||
'description' => $desc,
|
||||
'userAgent' => $ua,
|
||||
'appName' => $app,
|
||||
'url' => $url
|
||||
);
|
||||
|
||||
if ($_ = $this->_post['id'])
|
||||
$update['subject'] = $_;
|
||||
|
||||
if ($_ = $this->_post['relatedurl'])
|
||||
$update['relatedurl'] = $_;
|
||||
|
||||
if ($_ = $this->_post['email'])
|
||||
$update['email'] = $_;
|
||||
|
||||
if (DB::Aowow()->query('INSERT INTO ?_reports (?#) VALUES (?a)', array_keys($update), array_values($update)))
|
||||
return 0;
|
||||
|
||||
return 'save to db unsuccessful';
|
||||
}
|
||||
}
|
||||
37
includes/ajaxHandler/cookie.class.php
Normal file
37
includes/ajaxHandler/cookie.class.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
class AjaxCookie extends AjaxHandler
|
||||
{
|
||||
public function __construct(array $params)
|
||||
{
|
||||
// note that parent::__construct has to come after this
|
||||
if (!$params || !User::$id)
|
||||
return;
|
||||
|
||||
$this->_get = array(
|
||||
$this->params[0] => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
|
||||
);
|
||||
|
||||
// NOW we know, what to expect and sanitize
|
||||
parent::__construct($params);
|
||||
|
||||
// always this one
|
||||
$this->handler = 'handleCookie';
|
||||
}
|
||||
|
||||
/* responses
|
||||
0: success
|
||||
$: silent error
|
||||
*/
|
||||
protected function handleCookie()
|
||||
{
|
||||
if (User::$id && $this->params && $this->_get[$this->params[0]])
|
||||
if (DB::Aowow()->query('REPLACE INTO ?_account_cookies VALUES (?d, ?, ?)', User::$id, $this->params[0], $this->_get[$this->params[0]]))
|
||||
return 0;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
139
includes/ajaxHandler/data.class.php
Normal file
139
includes/ajaxHandler/data.class.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
class AjaxData extends AjaxHandler
|
||||
{
|
||||
protected $_get = array(
|
||||
'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale']],
|
||||
't' => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
|
||||
'catg' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'skill' => [FILTER_CALLBACK, ['options' => 'AjaxData::checkSkill']],
|
||||
'class' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'callback' => [FILTER_CALLBACK, ['options' => 'AjaxData::checkCallback']]
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
if (is_numeric($this->_get['locale']))
|
||||
User::useLocale($this->_get['locale']);
|
||||
|
||||
// always this one
|
||||
$this->handler = 'handleData';
|
||||
}
|
||||
|
||||
/* responses
|
||||
<string>
|
||||
*/
|
||||
protected function handleData()
|
||||
{
|
||||
$result = '';
|
||||
|
||||
// different data can be strung together
|
||||
foreach ($this->params as $set)
|
||||
{
|
||||
// requires valid token to hinder automated access
|
||||
if ($set != 'item-scaling')
|
||||
if (!$this->_get['t'] || empty($_SESSION['dataKey']) || $this->_get['t'] != $_SESSION['dataKey'])
|
||||
continue;
|
||||
|
||||
switch ($set)
|
||||
{
|
||||
/* issue on no initial data:
|
||||
when we loadOnDemand, the jScript tries to generate the catg-tree before it is initialized
|
||||
it cant be initialized, without loading the data as empty catg are omitted
|
||||
loading the data triggers the generation of the catg-tree
|
||||
*/
|
||||
case 'factions':
|
||||
$result .= $this->loadProfilerData($set);
|
||||
break;
|
||||
case 'companions':
|
||||
$result .= $this->loadProfilerData($set, '778');
|
||||
break;
|
||||
case 'mounts':
|
||||
$result .= $this->loadProfilerData($set, '777');
|
||||
break;
|
||||
case 'quests':
|
||||
// &partial: im not doing this right
|
||||
// it expects a full quest dump on first lookup but will query subCats again if clicked..?
|
||||
// for now omiting the detail clicks with empty results and just set catg update
|
||||
$catg = isset($this->_get['catg']) ? $this->_get['catg'] : 'null';
|
||||
if ($catg == 'null')
|
||||
$result .= $this->loadProfilerData($set);
|
||||
else if ($this->_get['callback'])
|
||||
$result .= "\n\$WowheadProfiler.loadOnDemand('quests', ".$catg.");\n";
|
||||
|
||||
break;
|
||||
case 'recipes':
|
||||
if (!$this->_get['callback'] || !$this->_get['skill'])
|
||||
break;
|
||||
|
||||
foreach ($this->_get['skill'] as $s)
|
||||
Util::loadStaticFile('p-recipes-'.$s, $result, true);
|
||||
|
||||
Util::loadStaticFile('p-recipes-sec', $result, true);
|
||||
$result .= "\n\$WowheadProfiler.loadOnDemand('recipes', null);\n";
|
||||
|
||||
break;
|
||||
// locale independant
|
||||
case 'quick-excludes':
|
||||
case 'zones':
|
||||
case 'weight-presets':
|
||||
case 'item-scaling':
|
||||
case 'realms':
|
||||
case 'statistics':
|
||||
if (!Util::loadStaticFile($set, $result) && CFG_DEBUG)
|
||||
$result .= "alert('could not fetch static data: ".$set."');";
|
||||
|
||||
$result .= "\n\n";
|
||||
break;
|
||||
// localized
|
||||
case 'talents':
|
||||
if ($_ = $this->_get['class'])
|
||||
$set .= "-".$_;
|
||||
case 'achievements':
|
||||
case 'pet-talents':
|
||||
case 'glyphs':
|
||||
case 'gems':
|
||||
case 'enchants':
|
||||
case 'itemsets':
|
||||
case 'pets':
|
||||
if (!Util::loadStaticFile($set, $result, true) && CFG_DEBUG)
|
||||
$result .= "alert('could not fetch static data: ".$set." for locale: ".User::$localeString."');";
|
||||
|
||||
$result .= "\n\n";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function checkSkill($val)
|
||||
{
|
||||
return array_intersect([171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356], explode(',', $val));
|
||||
}
|
||||
|
||||
protected function checkCallback($val)
|
||||
{
|
||||
return substr($val, 0, 29) == '$WowheadProfiler.loadOnDemand';
|
||||
}
|
||||
|
||||
private function loadProfilerData($file, $catg = 'null')
|
||||
{
|
||||
$result = '';
|
||||
if ($this->_get['callback'])
|
||||
if (Util::loadStaticFile('p-'.$file, $result, true))
|
||||
$result .= "\n\$WowheadProfiler.loadOnDemand('".$file."', ".$catg.");\n";
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
107
includes/ajaxHandler/filter.class.php
Normal file
107
includes/ajaxHandler/filter.class.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class AjaxFilter extends AjaxHandler
|
||||
{
|
||||
public $doRedirect = true;
|
||||
|
||||
private $cat = [];
|
||||
private $page = '';
|
||||
private $filter = null;
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
if (!$params)
|
||||
return;
|
||||
|
||||
$p = explode('=', $params[0]);
|
||||
|
||||
$this->page = $p[0];
|
||||
|
||||
if (isset($p[1]))
|
||||
$this->cat[] = $p[1];
|
||||
|
||||
if (count($params) > 1)
|
||||
for ($i = 1; $i < count($params); $i++)
|
||||
$this->cat[] = $params[$i];
|
||||
|
||||
$opts = ['parentCats' => $this->cat];
|
||||
|
||||
switch ($p[0])
|
||||
{
|
||||
case 'achievements':
|
||||
$this->filter = (new AchievementListFilter(true, $opts));
|
||||
break;
|
||||
case 'enchantments':
|
||||
$this->filter = (new EnchantmentListFilter(true, $opts));
|
||||
break;
|
||||
case 'icons':
|
||||
$this->filter = (new IconListFilter(true, $opts));
|
||||
break;
|
||||
case 'items':
|
||||
$this->filter = (new ItemListFilter(true, $opts));
|
||||
break;
|
||||
case 'itemsets':
|
||||
$this->filter = (new ItemsetListFilter(true, $opts));
|
||||
break;
|
||||
case 'npcs':
|
||||
$this->filter = (new CreatureListFilter(true, $opts));
|
||||
break;
|
||||
case 'objects':
|
||||
$this->filter = (new GameObjectListFilter(true, $opts));
|
||||
break;
|
||||
case 'quests':
|
||||
$this->filter = (new QuestListFilter(true, $opts));
|
||||
break;
|
||||
case 'sounds':
|
||||
$this->filter = (new SoundListFilter(true, $opts));
|
||||
break;
|
||||
case 'spells':
|
||||
$this->filter = (new SpellListFilter(true, $opts));
|
||||
break;
|
||||
case 'profiles':
|
||||
$this->filter = (new ProfileListFilter(true, $opts));
|
||||
break;
|
||||
case 'guilds':
|
||||
$this->filter = (new GuildListFilter(true, $opts));
|
||||
break;
|
||||
case 'arena-teams':
|
||||
$this->filter = (new ArenaTeamListFilter(true, $opts));
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
parent::__construct($params);
|
||||
|
||||
// always this one
|
||||
$this->handler = 'handleFilter';
|
||||
}
|
||||
|
||||
protected function handleFilter()
|
||||
{
|
||||
$url = '?'.$this->page;
|
||||
|
||||
$this->filter->mergeCat($this->cat);
|
||||
|
||||
if ($this->cat)
|
||||
$url .= '='.implode('.', $this->cat);
|
||||
|
||||
$fi = [];
|
||||
if ($x = $this->filter->getFilterString())
|
||||
$url .= '&filter='.$x;
|
||||
|
||||
if ($this->filter->error)
|
||||
$_SESSION['fiError'] = get_class($this->filter);
|
||||
|
||||
if ($fi)
|
||||
$url .= '&filter='.implode(';', $fi);
|
||||
|
||||
// do get request
|
||||
return $url;
|
||||
}
|
||||
|
||||
}
|
||||
36
includes/ajaxHandler/gotocomment.class.php
Normal file
36
includes/ajaxHandler/gotocomment.class.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
class AjaxGotocomment extends AjaxHandler
|
||||
{
|
||||
protected $_get = array(
|
||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']]
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
// always this one
|
||||
$this->handler = 'handleGoToComment';
|
||||
$this->doRedirect = true;
|
||||
}
|
||||
|
||||
/* responses
|
||||
header()
|
||||
*/
|
||||
protected function handleGoToComment()
|
||||
{
|
||||
if (!$this->_get['id'])
|
||||
exit; // just be blank
|
||||
|
||||
if ($_ = DB::Aowow()->selectRow('SELECT IFNULL(c2.id, c1.id) AS id, IFNULL(c2.type, c1.type) AS type, IFNULL(c2.typeId, c1.typeId) AS typeId FROM ?_comments c1 LEFT JOIN ?_comments c2 ON c1.replyTo = c2.id WHERE c1.id = ?d', $this->_get['id']))
|
||||
return '?'.Util::$typeStrings[$_['type']].'='.$_['typeId'].'#comments:id='.$_['id'].($_['id'] != $this->_get['id'] ? ':reply='.$this->_get['id'] : null);
|
||||
else
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
82
includes/ajaxHandler/guild.class.php
Normal file
82
includes/ajaxHandler/guild.class.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('invalid access');
|
||||
|
||||
class AjaxGuild extends AjaxHandler
|
||||
{
|
||||
protected $validParams = ['resync', 'status'];
|
||||
protected $_get = array(
|
||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdList']],
|
||||
'profile' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkEmptySet']],
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
if (!$this->params)
|
||||
return;
|
||||
|
||||
switch ($this->params[0])
|
||||
{
|
||||
case 'resync':
|
||||
$this->handler = 'handleResync';
|
||||
break;
|
||||
case 'status':
|
||||
$this->handler = 'handleStatus';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* params
|
||||
id: <prId1,prId2,..,prIdN>
|
||||
user: <string> [optional, not used]
|
||||
profile: <empty> [optional, also get related chars]
|
||||
return: 1
|
||||
*/
|
||||
protected function handleResync()
|
||||
{
|
||||
if ($guilds = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_guild WHERE id IN (?a)', $this->_get['id']))
|
||||
foreach ($guilds as $g)
|
||||
Profiler::scheduleResync(TYPE_GUILD, $g['realm'], $g['realmGUID']);
|
||||
|
||||
if ($this->_get['profile'])
|
||||
if ($chars = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_profiles WHERE guild IN (?a)', $this->_get['id']))
|
||||
foreach ($chars as $c)
|
||||
Profiler::scheduleResync(TYPE_PROFILE, $c['realm'], $c['realmGUID']);
|
||||
|
||||
return '1';
|
||||
}
|
||||
|
||||
/* params
|
||||
id: <prId1,prId2,..,prIdN>
|
||||
return
|
||||
<status object>
|
||||
[
|
||||
nQueueProcesses,
|
||||
[statusCode, timeToRefresh, curQueuePos, errorCode, nResyncTries],
|
||||
[<anotherStatus>]
|
||||
...
|
||||
]
|
||||
|
||||
not all fields are required, if zero they are omitted
|
||||
statusCode:
|
||||
0: end the request
|
||||
1: waiting
|
||||
2: working...
|
||||
3: ready; click to view
|
||||
4: error / retry
|
||||
errorCode:
|
||||
0: unk error
|
||||
1: char does not exist
|
||||
2: armory gone
|
||||
*/
|
||||
protected function handleStatus()
|
||||
{
|
||||
$response = Profiler::resyncStatus(TYPE_GUILD, $this->_get['id']);
|
||||
return Util::toJSON($response);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
33
includes/ajaxHandler/locale.class.php
Normal file
33
includes/ajaxHandler/locale.class.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
class AjaxLocale extends AjaxHandler
|
||||
{
|
||||
protected $_get = array(
|
||||
'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale']]
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
// always this one
|
||||
$this->handler = 'handleLocale';
|
||||
$this->doRedirect = true;
|
||||
}
|
||||
|
||||
/* responses
|
||||
header()
|
||||
*/
|
||||
protected function handleLocale()
|
||||
{
|
||||
User::setLocale($this->_get['locale']);
|
||||
User::save();
|
||||
|
||||
return isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '.';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
716
includes/ajaxHandler/profile.class.php
Normal file
716
includes/ajaxHandler/profile.class.php
Normal file
@@ -0,0 +1,716 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
class AjaxProfile extends AjaxHandler
|
||||
{
|
||||
private $undo = false;
|
||||
|
||||
protected $validParams = ['link', 'unlink', 'pin', 'unpin', 'public', 'private', 'avatar', 'resync', 'status', 'save', 'delete', 'purge', 'summary', 'load'];
|
||||
protected $_get = array(
|
||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdList']],
|
||||
'items' => [FILTER_CALLBACK, ['options' => 'AjaxProfile::checkItemList']],
|
||||
'size' => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
|
||||
'guild' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkEmptySet']],
|
||||
'arena-team' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkEmptySet']],
|
||||
);
|
||||
|
||||
protected $_post = array(
|
||||
'name' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkFulltext']],
|
||||
'level' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'class' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'race' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'gender' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'nomodel' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'talenttree1' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'talenttree2' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'talenttree3' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'activespec' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'talentbuild1' => [FILTER_SANITIZE_STRING, 0xC],// FILTER_FLAG_STRIP_LOW | *_HIGH
|
||||
'glyphs1' => [FILTER_SANITIZE_STRING, 0xC],
|
||||
'talentbuild2' => [FILTER_SANITIZE_STRING, 0xC],
|
||||
'glyphs2' => [FILTER_SANITIZE_STRING, 0xC],
|
||||
'icon' => [FILTER_SANITIZE_STRING, 0xC],
|
||||
'description' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkFulltext']],
|
||||
'source' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'copy' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'public' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'gearscore' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||
'inv' => [FILTER_CALLBACK, ['options' => 'AjaxProfile::checkItemString', 'flags' => FILTER_REQUIRE_ARRAY]],
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
if (!$this->params)
|
||||
return;
|
||||
|
||||
switch ($this->params[0])
|
||||
{
|
||||
case 'unlink':
|
||||
$this->undo = true;
|
||||
case 'link':
|
||||
$this->handler = 'handleLink'; // always returns null
|
||||
break;
|
||||
case 'unpin':
|
||||
$this->undo = true;
|
||||
case 'pin':
|
||||
$this->handler = 'handlePin'; // always returns null
|
||||
break;
|
||||
case 'private':
|
||||
$this->undo = true;
|
||||
case 'public':
|
||||
$this->handler = 'handlePrivacy'; // always returns null
|
||||
break;
|
||||
case 'avatar':
|
||||
$this->handler = 'handleAvatar'; // sets an image header
|
||||
break; // so it has to die here or another header will be set
|
||||
case 'resync':
|
||||
$this->handler = 'handleResync'; // always returns "1"
|
||||
break;
|
||||
case 'status':
|
||||
$this->handler = 'handleStatus'; // returns status object
|
||||
break;
|
||||
case 'save':
|
||||
$this->handler = 'handleSave';
|
||||
break;
|
||||
case 'delete':
|
||||
$this->handler = 'handleDelete';
|
||||
break;
|
||||
case 'purge':
|
||||
$this->handler = 'handlePurge';
|
||||
break;
|
||||
case 'summary': // page is generated by jScript
|
||||
die(); // just be empty
|
||||
case 'load':
|
||||
$this->handler = 'handleLoad';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* params
|
||||
id: <prId1,prId2,..,prIdN>
|
||||
user: <string> [optional]
|
||||
return: null
|
||||
*/
|
||||
protected function handleLink() // links char with account
|
||||
{
|
||||
if (!User::$id || empty($this->_get['id']))
|
||||
return;
|
||||
|
||||
$uid = User::$id;
|
||||
if ($this->_get['user'] && User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
|
||||
$uid = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE user = ?', $this->_get['user']);
|
||||
else if ($this->_get['user'])
|
||||
return;
|
||||
|
||||
if ($this->undo)
|
||||
DB::Aowow()->query('DELETE FROM ?_account_profiles WHERE accountId = ?d AND profileId IN (?a)', $uid, $this->_get['id']);
|
||||
else
|
||||
foreach ($this->_get['id'] as $prId) // only link characters, not custom profiles
|
||||
if ($prId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_profiles WHERE id = ?d AND realm IS NOT NULL', $prId))
|
||||
DB::Aowow()->query('INSERT IGNORE INTO ?_account_profiles VALUES (?d, ?d, 0)', $uid, $prId);
|
||||
}
|
||||
|
||||
/* params
|
||||
id: <prId1,prId2,..,prIdN>
|
||||
user: <string> [optional]
|
||||
return: null
|
||||
*/
|
||||
protected function handlePin() // (un)favorite
|
||||
{
|
||||
if (!User::$id || empty($this->_get['id'][0]))
|
||||
return;
|
||||
|
||||
$uid = User::$id;
|
||||
if ($this->_get['user'] && User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
|
||||
$uid = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE user = ?', $this->_get['user']);
|
||||
else if ($this->_get['user'])
|
||||
return;
|
||||
|
||||
// since only one character can be pinned at a time we can reset everything
|
||||
DB::Aowow()->query('UPDATE ?_account_profiles SET extraFlags = extraFlags & ?d WHERE accountId = ?d', ~PROFILER_CU_PINNED, $uid);
|
||||
// and set a single char if nesecary
|
||||
if (!$this->undo)
|
||||
DB::Aowow()->query('UPDATE ?_account_profiles SET extraFlags = extraFlags | ?d WHERE profileId = ?d AND accountId = ?d', PROFILER_CU_PINNED, $this->_get['id'][0], $uid);
|
||||
}
|
||||
|
||||
/* params
|
||||
id: <prId1,prId2,..,prIdN>
|
||||
user: <string> [optional]
|
||||
return: null
|
||||
*/
|
||||
protected function handlePrivacy() // public visibility
|
||||
{
|
||||
if (!User::$id || empty($this->_get['id'][0]))
|
||||
return;
|
||||
|
||||
$uid = User::$id;
|
||||
if ($this->_get['user'] && User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
|
||||
$uid = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE user = ?', $this->_get['user']);
|
||||
else if ($this->_get['user'])
|
||||
return;
|
||||
|
||||
if ($this->undo)
|
||||
{
|
||||
DB::Aowow()->query('UPDATE ?_account_profiles SET extraFlags = extraFlags & ?d WHERE profileId IN (?a) AND accountId = ?d', ~PROFILER_CU_PUBLISHED, $this->_get['id'], $uid);
|
||||
DB::Aowow()->query('UPDATE ?_profiler_profiles SET cuFlags = cuFlags & ?d WHERE id IN (?a) AND user = ?d', ~PROFILER_CU_PUBLISHED, $this->_get['id'], $uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
DB::Aowow()->query('UPDATE ?_account_profiles SET extraFlags = extraFlags | ?d WHERE profileId IN (?a) AND accountId = ?d', PROFILER_CU_PUBLISHED, $this->_get['id'], $uid);
|
||||
DB::Aowow()->query('UPDATE ?_profiler_profiles SET cuFlags = cuFlags | ?d WHERE id IN (?a) AND user = ?d', PROFILER_CU_PUBLISHED, $this->_get['id'], $uid);
|
||||
}
|
||||
}
|
||||
|
||||
/* params
|
||||
id: <prId>
|
||||
size: <string> [optional]
|
||||
return: image-header
|
||||
*/
|
||||
protected function handleAvatar() // image
|
||||
{
|
||||
// something happened in the last years: those textures do not include tiny icons
|
||||
$sizes = [/* 'tiny' => 15, */'small' => 18, 'medium' => 36, 'large' => 56];
|
||||
$aPath = 'uploads/avatars/%d.jpg';
|
||||
$s = $this->_get['size'] ?: 'medium';
|
||||
|
||||
if (!$this->_get['id'] || !preg_match('/^([0-9]+)\.(jpg|gif)$/', $this->_get['id'][0], $matches) || !in_array($s, array_keys($sizes)))
|
||||
return;
|
||||
|
||||
$this->contentType = 'image/'.$matches[2];
|
||||
|
||||
$id = $matches[1];
|
||||
$dest = imageCreateTruecolor($sizes[$s], $sizes[$s]);
|
||||
|
||||
if (file_exists(sprintf($aPath, $id)))
|
||||
{
|
||||
$offsetX = $offsetY = 0;
|
||||
|
||||
switch ($s)
|
||||
{
|
||||
case 'tiny':
|
||||
$offsetX += $sizes['small'];
|
||||
case 'small':
|
||||
$offsetY += $sizes['medium'];
|
||||
case 'medium':
|
||||
$offsetX += $sizes['large'];
|
||||
}
|
||||
|
||||
$src = imageCreateFromJpeg(printf($aPath, $id));
|
||||
imagecopymerge($dest, $src, 0, 0, $offsetX, $offsetY, $sizes[$s], $sizes[$s], 100);
|
||||
}
|
||||
|
||||
if ($matches[2] == 'gif')
|
||||
imageGif($dest);
|
||||
else
|
||||
imageJpeg($dest);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* params
|
||||
id: <prId1,prId2,..,prIdN>
|
||||
user: <string> [optional, not used]
|
||||
return: 1
|
||||
*/
|
||||
protected function handleResync()
|
||||
{
|
||||
if ($chars = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_profiles WHERE id IN (?a)', $this->_get['id']))
|
||||
foreach ($chars as $c)
|
||||
Profiler::scheduleResync(TYPE_PROFILE, $c['realm'], $c['realmGUID']);
|
||||
|
||||
return '1';
|
||||
}
|
||||
|
||||
/* params
|
||||
id: <prId1,prId2,..,prIdN>
|
||||
return
|
||||
<status object>
|
||||
[
|
||||
nQueueProcesses,
|
||||
[statusCode, timeToRefresh, curQueuePos, errorCode, nResyncTries],
|
||||
[<anotherStatus>]
|
||||
...
|
||||
]
|
||||
|
||||
not all fields are required, if zero they are omitted
|
||||
statusCode:
|
||||
0: end the request
|
||||
1: waiting
|
||||
2: working...
|
||||
3: ready; click to view
|
||||
4: error / retry
|
||||
errorCode:
|
||||
0: unk error
|
||||
1: char does not exist
|
||||
2: armory gone
|
||||
*/
|
||||
protected function handleStatus()
|
||||
{
|
||||
// roster resync for this guild was requested -> get char list
|
||||
if ($this->_get['guild'])
|
||||
$ids = DB::Aowow()->selectCol('SELECT id FROM ?_profiler_profiles WHERE guild IN (?a)', $this->_get['id']);
|
||||
else if ($this->_get['arena-team'])
|
||||
$ids = DB::Aowow()->selectCol('SELECT profileId FROM ?_profiler_arena_team_member WHERE arenaTeamId IN (?a)', $this->_get['id']);
|
||||
else
|
||||
$ids = $this->_get['id'];
|
||||
|
||||
$response = Profiler::resyncStatus(TYPE_PROFILE, $ids);
|
||||
return Util::toJSON($response);
|
||||
}
|
||||
|
||||
/* params (get))
|
||||
id: <prId1,0> [0: new profile]
|
||||
params (post)
|
||||
<various char data> [see below]
|
||||
return:
|
||||
proileId [onSuccess]
|
||||
-1 [onError]
|
||||
*/
|
||||
protected function handleSave() // unKill a profile
|
||||
{
|
||||
// todo (med): detail check this post-data
|
||||
$cuProfile = array(
|
||||
'user' => User::$id,
|
||||
// 'userName' => User::$displayName,
|
||||
'name' => $this->_post['name'],
|
||||
'level' => $this->_post['level'],
|
||||
'class' => $this->_post['class'],
|
||||
'race' => $this->_post['race'],
|
||||
'gender' => $this->_post['gender'],
|
||||
'nomodelMask' => $this->_post['nomodel'],
|
||||
'talenttree1' => $this->_post['talenttree1'],
|
||||
'talenttree2' => $this->_post['talenttree2'],
|
||||
'talenttree3' => $this->_post['talenttree3'],
|
||||
'talentbuild1' => $this->_post['talentbuild1'],
|
||||
'talentbuild2' => $this->_post['talentbuild2'],
|
||||
'activespec' => $this->_post['activespec'],
|
||||
'glyphs1' => $this->_post['glyphs1'],
|
||||
'glyphs2' => $this->_post['glyphs2'],
|
||||
'gearscore' => $this->_post['gearscore'],
|
||||
'icon' => $this->_post['icon'],
|
||||
'cuFlags' => PROFILER_CU_PROFILE | ($this->_post['public'] ? PROFILER_CU_PUBLISHED : 0)
|
||||
);
|
||||
|
||||
if (strstr($cuProfile['icon'], 'profile=avatar')) // how the profiler is supposed to handle icons is beyond me
|
||||
$cuProfile['icon'] = '';
|
||||
|
||||
if ($_ = $this->_post['description'])
|
||||
$cuProfile['description'] = $_;
|
||||
|
||||
if ($_ = $this->_post['source']) // should i also set sourcename?
|
||||
$cuProfile['sourceId'] = $_;
|
||||
|
||||
if ($_ = $this->_post['copy']) // gets set to source profileId when "save as" is clicked. Whats the difference to 'source' though?
|
||||
{
|
||||
// get character origin info if possible
|
||||
if ($r = DB::Aowow()->selectCell('SELECT realm FROM ?_profiler_profiles WHERE id = ?d AND realm IS NOT NULL', $_))
|
||||
$cuProfile['realm'] = $r;
|
||||
|
||||
$cuProfile['sourceId'] = $_;
|
||||
}
|
||||
|
||||
if ($cuProfile['sourceId'])
|
||||
$cuProfile['sourceName'] = DB::Aowow()->selectCell('SELECT name FROM ?_profiler_profiles WHERE id = ?d', $cuProfile['sourceId']);
|
||||
|
||||
$charId = -1;
|
||||
if ($id = $this->_get['id'][0]) // update
|
||||
{
|
||||
if ($charId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_profiles WHERE id = ?d', $id))
|
||||
DB::Aowow()->query('UPDATE ?_profiler_profiles SET ?a WHERE id = ?d', $cuProfile, $id);
|
||||
}
|
||||
else // new
|
||||
{
|
||||
$nProfiles = DB::Aowow()->selectCell('SELECT COUNT(*) FROM ?_profiler_profiles WHERE user = ?d AND realmGUID IS NULL', User::$id);
|
||||
if ($nProfiles < 10 || User::isPremium())
|
||||
if ($newId = DB::Aowow()->query('INSERT INTO ?_profiler_profiles (?#) VALUES (?a)', array_keys($cuProfile), array_values($cuProfile)))
|
||||
$charId = $newId;
|
||||
}
|
||||
|
||||
// update items
|
||||
if ($charId != -1)
|
||||
{
|
||||
// ok, 'funny' thing: wether an item has en extra prismatic sockel is determined contextual
|
||||
// either the socket is -1 or it has an itemId in a socket where there shouldn't be one
|
||||
$keys = ['id', 'slot', 'item', 'subitem', 'permEnchant', 'tempEnchant', 'gem1', 'gem2', 'gem3', 'gem4'];
|
||||
|
||||
// validate Enchantments
|
||||
$enchIds = array_merge(
|
||||
array_column($this->_post['inv'], 3), // perm enchantments
|
||||
array_column($this->_post['inv'], 4) // temp enchantments (not used..?)
|
||||
);
|
||||
$enchs = new EnchantmentList(array(['id', $enchIds]));
|
||||
|
||||
// validate items
|
||||
$itemIds = array_merge(
|
||||
array_column($this->_post['inv'], 1), // base item
|
||||
array_column($this->_post['inv'], 5), // gem slot 1
|
||||
array_column($this->_post['inv'], 6), // gem slot 2
|
||||
array_column($this->_post['inv'], 7), // gem slot 3
|
||||
array_column($this->_post['inv'], 8) // gem slot 4
|
||||
);
|
||||
|
||||
$items = new ItemList(array(['id', $itemIds]));
|
||||
if (!$items->error)
|
||||
{
|
||||
foreach ($this->_post['inv'] as $slot => $itemData)
|
||||
{
|
||||
if ($slot + 1 == array_sum($itemData)) // only slot definition set => empty slot
|
||||
{
|
||||
DB::Aowow()->query('DELETE FROM ?_profiler_items WHERE id = ?d AND slot = ?d', $charId, $itemData[0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// item does not exist
|
||||
if (!$items->getEntry($itemData[1]))
|
||||
continue;
|
||||
|
||||
// sub-item check
|
||||
if (!$items->getRandEnchantForItem($itemData[1]))
|
||||
$itemData[2] = 0;
|
||||
|
||||
// item sockets are fubar
|
||||
$nSockets = $items->json[$itemData[1]]['nsockets'];
|
||||
$nSockets += in_array($slot, [SLOT_WAIST, SLOT_WRISTS, SLOT_HANDS]) ? 1 : 0;
|
||||
for ($i = 5; $i < 9; $i++)
|
||||
if ($itemData[$i] > 0 && (!$items->getEntry($itemData[$i]) || $i >= (5 + $nSockets)))
|
||||
$itemData[$i] = 0;
|
||||
|
||||
// item enchantments are borked
|
||||
if ($itemData[3] && !$enchs->getEntry($itemData[3]))
|
||||
$itemData[3] = 0;
|
||||
|
||||
if ($itemData[4] && !$enchs->getEntry($itemData[4]))
|
||||
$itemData[4] = 0;
|
||||
|
||||
// looks good
|
||||
array_unshift($itemData, $charId);
|
||||
DB::Aowow()->query('REPLACE INTO ?_profiler_items (?#) VALUES (?a)', $keys, $itemData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $charId;
|
||||
}
|
||||
|
||||
/* params
|
||||
id: <prId1,prId2,..,prIdN>
|
||||
return
|
||||
null
|
||||
*/
|
||||
protected function handleDelete() // kill a profile
|
||||
{
|
||||
if (!$this->_get['id'])
|
||||
return;
|
||||
|
||||
// only flag as deleted; only custom profiles
|
||||
DB::Aowow()->query(
|
||||
'UPDATE ?_profiler_profiles SET cuFlags = cuFlags | ?d WHERE id IN (?a) AND cuFlags & ?d {AND user = ?d}',
|
||||
PROFILER_CU_DELETED,
|
||||
$this->_get['id'],
|
||||
PROFILER_CU_PROFILE,
|
||||
User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU) ? DBSIMPLE_SKIP : User::$id
|
||||
);
|
||||
}
|
||||
|
||||
/* params
|
||||
id: profileId
|
||||
items: string [itemIds.join(':')]
|
||||
unnamed: unixtime [only to force the browser to reload instead of cache]
|
||||
return
|
||||
lots...
|
||||
*/
|
||||
protected function handleLoad()
|
||||
{
|
||||
// titles, achievements, characterData, talents, pets
|
||||
// and some onLoad-hook to .. load it registerProfile($data)
|
||||
// everything else goes through data.php .. strangely enough
|
||||
|
||||
if (!$this->_get['id'])
|
||||
return;
|
||||
|
||||
$pBase = DB::Aowow()->selectRow('SELECT pg.name AS guildname, p.* FROM ?_profiler_profiles p LEFT JOIN ?_profiler_guild pg ON pg.id = p.guild WHERE p.id = ?d', $this->_get['id'][0]);
|
||||
if (!$pBase)
|
||||
{
|
||||
trigger_error('Profiler::handleLoad() - called with invalid profileId #'.$this->_get['id'][0], E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
if (($pBase['cuFlags'] & PROFILER_CU_DELETED) && !User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
|
||||
return;
|
||||
|
||||
|
||||
$rData = [];
|
||||
foreach (Profiler::getRealms() as $rId => $rData)
|
||||
if ($rId == $pBase['realm'])
|
||||
break;
|
||||
|
||||
$profile = array(
|
||||
'id' => $pBase['id'],
|
||||
'source' => $pBase['id'],
|
||||
'level' => $pBase['level'],
|
||||
'classs' => $pBase['class'],
|
||||
'race' => $pBase['race'],
|
||||
'faction' => Game::sideByRaceMask(1 << ($pBase['race'] - 1)) - 1,
|
||||
'gender' => $pBase['gender'],
|
||||
'skincolor' => $pBase['skincolor'],
|
||||
'hairstyle' => $pBase['hairstyle'],
|
||||
'haircolor' => $pBase['haircolor'],
|
||||
'facetype' => $pBase['facetype'],
|
||||
'features' => $pBase['features'],
|
||||
'title' => $pBase['title'],
|
||||
'name' => $pBase['name'],
|
||||
'guild' => "$'".$pBase['guildname']."'",
|
||||
'published' => !!($pBase['cuFlags'] & PROFILER_CU_PUBLISHED),
|
||||
'pinned' => !!($pBase['cuFlags'] & PROFILER_CU_PINNED),
|
||||
'nomodel' => $pBase['nomodelMask'],
|
||||
'playedtime' => $pBase['playedtime'],
|
||||
'lastupdated' => $pBase['lastupdated'] * 1000,
|
||||
'talents' => array(
|
||||
'builds' => array( // notice the bullshit to prevent the talent-string from becoming a float! NOTICE IT!!
|
||||
['talents' => '$"'.$pBase['talentbuild1'].'"', 'glyphs' => $pBase['glyphs1']],
|
||||
['talents' => '$"'.$pBase['talentbuild2'].'"', 'glyphs' => $pBase['glyphs2']]
|
||||
),
|
||||
'active' => $pBase['activespec']
|
||||
),
|
||||
// set later
|
||||
'inventory' => [],
|
||||
'bookmarks' => [], // list of userIds who claimed this profile (claiming and owning are two different things)
|
||||
|
||||
// completion lists: [subjectId => amount/timestamp/1]
|
||||
'skills' => [], // skillId => [curVal, maxVal]
|
||||
'reputation' => [], // factionId => curVal
|
||||
'titles' => [], // titleId => 1
|
||||
'spells' => [], // spellId => 1; recipes, vanity pets, mounts
|
||||
'achievements' => [], // achievementId => timestamp
|
||||
'quests' => [], // questId => 1
|
||||
'achievementpoints' => 0, // max you have
|
||||
'statistics' => [], // all raid activity [achievementId => killCount]
|
||||
'activity' => [], // recent raid activity [achievementId => 1] (is a subset of statistics)
|
||||
);
|
||||
|
||||
if ($pBase['cuFlags'] & PROFILER_CU_PROFILE)
|
||||
{
|
||||
// this parameter is _really_ strange .. probably still not doing this right
|
||||
$profile['source'] = $pBase['realm'] ? $pBase['sourceId'] : 0;
|
||||
|
||||
$profile['sourcename'] = $pBase['sourceName'];
|
||||
$profile['description'] = $pBase['description'];
|
||||
$profile['user'] = $pBase['user'];
|
||||
$profile['username'] = DB::Aowow()->selectCell('SELECT displayName FROM ?_account WHERE id = ?d', $pBase['user']);
|
||||
}
|
||||
|
||||
// custom profiles inherit this when copied from real char :(
|
||||
if ($pBase['realm'])
|
||||
{
|
||||
$profile['region'] = [$rData['region'], Lang::profiler('regions', $rData['region'])];
|
||||
$profile['battlegroup'] = [Profiler::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP];
|
||||
$profile['realm'] = [Profiler::urlize($rData['name']), $rData['name']];
|
||||
}
|
||||
|
||||
// bookmarks
|
||||
if ($_ = DB::Aowow()->selectCol('SELECT accountId FROM ?_account_profiles WHERE profileId = ?d', $pBase['id']))
|
||||
$profile['bookmarks'] = $_;
|
||||
|
||||
// arena teams - [size(2|3|5) => DisplayName]; DisplayName gets urlized to use as link
|
||||
if ($at = DB::Aowow()->selectCol('SELECT type AS ARRAY_KEY, name FROM ?_profiler_arena_team at JOIN ?_profiler_arena_team_member atm ON atm.arenaTeamId = at.id WHERE atm.profileId = ?d', $pBase['id']))
|
||||
$profile['arenateams'] = $at;
|
||||
|
||||
// pets if hunter fields: [name:name, family:petFamily, npc:npcId, displayId:modelId, talents:talentString]
|
||||
if ($pets = DB::Aowow()->select('SELECT name, family, npc, displayId, talents FROM ?_profiler_pets WHERE owner = ?d', $pBase['id']))
|
||||
$profile['pets'] = $pets;
|
||||
|
||||
// source for custom profiles; profileId => [name, ownerId, iconString(optional)]
|
||||
if ($customs = DB::Aowow()->select('SELECT id AS ARRAY_KEY, name, user, icon FROM ?_profiler_profiles WHERE sourceId = ?d AND sourceId <> id', $pBase['id']))
|
||||
{
|
||||
foreach ($customs as $id => $cu)
|
||||
{
|
||||
if (!$cu['icon'])
|
||||
unset($cu['icon']);
|
||||
|
||||
$profile['customs'][$id] = array_values($cu);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* $profile[]
|
||||
// CUSTOM
|
||||
'auras' => [], // custom list of buffs, debuffs [spellId]
|
||||
|
||||
// UNUSED
|
||||
'glyphs' => [], // provided list of already known glyphs (post cataclysm feature)
|
||||
*/
|
||||
|
||||
|
||||
$completion = DB::Aowow()->select('SELECT type AS ARRAY_KEY, typeId AS ARRAY_KEY2, cur, max FROM ?_profiler_completion WHERE id = ?d', $pBase['id']);
|
||||
foreach ($completion as $type => $data)
|
||||
{
|
||||
switch ($type)
|
||||
{
|
||||
case TYPE_FACTION: // factionId => amount
|
||||
$profile['reputation'] = array_combine(array_keys($data), array_column($data, 'cur'));
|
||||
break;
|
||||
case TYPE_TITLE:
|
||||
foreach ($data as &$d)
|
||||
$d = 1;
|
||||
|
||||
$profile['titles'] = $data;
|
||||
break;
|
||||
case TYPE_QUEST:
|
||||
foreach ($data as &$d)
|
||||
$d = 1;
|
||||
|
||||
$profile['quests'] = $data;
|
||||
break;
|
||||
case TYPE_SPELL:
|
||||
foreach ($data as &$d)
|
||||
$d = 1;
|
||||
|
||||
$profile['spells'] = $data;
|
||||
break;
|
||||
case TYPE_ACHIEVEMENT:
|
||||
$achievements = array_filter($data, function ($x) { return $x['max'] === null; });
|
||||
$statistics = array_filter($data, function ($x) { return $x['max'] !== null; });
|
||||
|
||||
// achievements
|
||||
$profile['achievements'] = array_combine(array_keys($achievements), array_column($achievements, 'cur'));
|
||||
$profile['achievementpoints'] = DB::Aowow()->selectCell('SELECT SUM(points) FROM ?_achievement WHERE id IN (?a)', array_keys($achievements));
|
||||
|
||||
// raid progression
|
||||
$activity = array_filter($statistics, function ($x) { return $x['cur'] > (time() - MONTH); });
|
||||
foreach ($activity as &$r)
|
||||
$r = 1;
|
||||
|
||||
// ony .. subtract 10-man from 25-man
|
||||
|
||||
$profile['statistics'] = array_combine(array_keys($statistics), array_column($statistics, 'max'));
|
||||
$profile['activity'] = $activity;
|
||||
break;
|
||||
case TYPE_SKILL:
|
||||
foreach ($data as &$d)
|
||||
$d = [$d['cur'], $d['max']];
|
||||
|
||||
$profile['skills'] = $data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$buff = '';
|
||||
|
||||
$usedSlots = [];
|
||||
if ($this->_get['items'])
|
||||
{
|
||||
$phItems = new ItemList(array(['id', $this->_get['items']], ['slot', INVTYPE_NON_EQUIP, '!']));
|
||||
if (!$phItems->error)
|
||||
{
|
||||
$data = $phItems->getListviewData(ITEMINFO_JSON | ITEMINFO_SUBITEMS);
|
||||
foreach ($phItems->iterate() as $iId => $__)
|
||||
{
|
||||
$sl = $phItems->getField('slot');
|
||||
foreach (Profiler::$slot2InvType as $slot => $invTypes)
|
||||
{
|
||||
if (in_array($sl, $invTypes) && !in_array($slot, $usedSlots))
|
||||
{
|
||||
// get and apply inventory
|
||||
$buff .= 'g_items.add('.$iId.', {name_'.User::$localeString.":'".Util::jsEscape($phItems->getField('name', true))."', quality:".$phItems->getField('quality').", icon:'".$phItems->getField('iconString')."', jsonequip:".Util::toJSON($data[$iId])."});\n";
|
||||
$profile['inventory'][$slot] = [$iId, 0, 0, 0, 0, 0, 0, 0];
|
||||
|
||||
$usedSlots[] = $slot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($items = DB::Aowow()->select('SELECT * FROM ?_profiler_items WHERE id = ?d', $pBase['id']))
|
||||
{
|
||||
$itemz = new ItemList(array(['id', array_column($items, 'item')], CFG_SQL_LIMIT_NONE));
|
||||
if (!$itemz->error)
|
||||
{
|
||||
$data = $itemz->getListviewData(ITEMINFO_JSON | ITEMINFO_SUBITEMS);
|
||||
|
||||
foreach ($items as $i)
|
||||
{
|
||||
if ($itemz->getEntry($i['item']) && !in_array($i['slot'], $usedSlots))
|
||||
{
|
||||
// get and apply inventory
|
||||
$buff .= 'g_items.add('.$i['item'].', {name_'.User::$localeString.":'".Util::jsEscape($itemz->getField('name', true))."', quality:".$itemz->getField('quality').", icon:'".$itemz->getField('iconString')."', jsonequip:".Util::toJSON($data[$i['item']])."});\n";
|
||||
$profile['inventory'][$i['slot']] = [$i['item'], $i['subItem'], $i['permEnchant'], $i['tempEnchant'], $i['gem1'], $i['gem2'], $i['gem3'], $i['gem4']];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($buff)
|
||||
$buff .= "\n";
|
||||
|
||||
|
||||
// if ($au = $char->getField('auras'))
|
||||
// {
|
||||
// $auraz = new SpellList(array(['id', $char->getField('auras')], CFG_SQL_LIMIT_NONE));
|
||||
// $dataz = $auraz->getListviewData();
|
||||
// $modz = $auraz->getProfilerMods();
|
||||
|
||||
// // get and apply aura-mods
|
||||
// foreach ($dataz as $id => $data)
|
||||
// {
|
||||
// $mods = [];
|
||||
// if (!empty($modz[$id]))
|
||||
// {
|
||||
// foreach ($modz[$id] as $k => $v)
|
||||
// {
|
||||
// if (is_array($v))
|
||||
// $mods[] = $v;
|
||||
// else if ($str = @Game::$itemMods[$k])
|
||||
// $mods[$str] = $v;
|
||||
// }
|
||||
// }
|
||||
|
||||
// $buff .= 'g_spells.add('.$id.", {id:".$id.", name:'".Util::jsEscape(mb_substr($data['name'], 1))."', icon:'".$data['icon']."', modifier:".Util::toJSON($mods)."});\n";
|
||||
// }
|
||||
// $buff .= "\n";
|
||||
// }
|
||||
|
||||
|
||||
// load available titles
|
||||
Util::loadStaticFile('p-titles-'.$pBase['gender'], $buff, true);
|
||||
|
||||
// add profile to buffer
|
||||
$buff .= "\n\n\$WowheadProfiler.registerProfile(".Util::toJSON($profile).");";
|
||||
|
||||
return $buff."\n";
|
||||
}
|
||||
|
||||
/* params
|
||||
id: <prId>
|
||||
data: <mode> [string, tabName]
|
||||
return
|
||||
null
|
||||
*/
|
||||
protected function handlePurge() { } // removes completion data (as uploaded by the wowhead client) Just fail silently if someone triggers this manually
|
||||
|
||||
protected function checkItemList($val)
|
||||
{
|
||||
// expecting item-list
|
||||
if (preg_match('/\d+(:\d+)*/', $val))
|
||||
return array_map('intval', explode(':', $val));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function checkItemString($val)
|
||||
{
|
||||
// expecting item-list
|
||||
if (preg_match('/\d+(,\d+)*/', $val))
|
||||
return array_map('intval', explode(',', $val));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,8 +29,8 @@ class CommunityContent
|
||||
a3.displayName AS deleteUser,
|
||||
a4.displayName AS responseUser,
|
||||
IFNULL(SUM(cr.value), 0) AS rating,
|
||||
SUM(IF (cr.userId = ?d, value, 0)) AS userRating,
|
||||
SUM(IF (r.userId = ?d, 1, 0)) AS userReported
|
||||
SUM(IF(cr.userId > 0 AND cr.userId = ?d, cr.value, 0)) AS userRating,
|
||||
SUM(IF( r.userId > 0 AND r.userId = ?d, 1, 0)) AS userReported
|
||||
FROM
|
||||
?_comments c
|
||||
JOIN
|
||||
@@ -71,7 +71,7 @@ class CommunityContent
|
||||
JOIN
|
||||
?_account a ON c.userId = a.id
|
||||
LEFT JOIN
|
||||
?_comments_rates cr ON cr.commentId = c.id
|
||||
?_comments_rates cr ON cr.commentId = c.id AND cr.userId <> 0
|
||||
LEFT JOIN
|
||||
?_comments c2 ON c.replyTo = c2.id
|
||||
WHERE
|
||||
@@ -121,6 +121,10 @@ class CommunityContent
|
||||
case TYPE_RACE: $obj = new CharRaceList($cnd); break;
|
||||
case TYPE_SKILL: $obj = new SkillList($cnd); break;
|
||||
case TYPE_CURRENCY: $obj = new CurrencyList($cnd); break;
|
||||
case TYPE_EMOTE: $obj = new EmoteList($cnd); break;
|
||||
case TYPE_ENCHANTMENT: $obj = new EnchantmentList($cnd); break;
|
||||
case TYPE_SOUND: $obj = new SoundList($cnd); break;
|
||||
case TYPE_ICON: $obj = new IconList($cnd); break;
|
||||
default: continue;
|
||||
}
|
||||
|
||||
@@ -173,7 +177,7 @@ class CommunityContent
|
||||
// limit whitespaces to one at a time
|
||||
$c['preview'] = preg_replace('/\s+/', ' ', $c['preview']);
|
||||
// limit previews to 100 chars + whatever it takes to make the last word full
|
||||
if (strlen($c['preview']) > 100)
|
||||
if (mb_strlen($c['preview']) > 100)
|
||||
{
|
||||
$n = 0;
|
||||
$b = [];
|
||||
@@ -181,7 +185,7 @@ class CommunityContent
|
||||
while ($n < 100 && $parts)
|
||||
{
|
||||
$_ = array_shift($parts);
|
||||
$n += strlen($_);
|
||||
$n += mb_strlen($_);
|
||||
$b[] = $_;
|
||||
}
|
||||
|
||||
@@ -190,7 +194,7 @@ class CommunityContent
|
||||
}
|
||||
else
|
||||
{
|
||||
Util::addNote(U_GROUP_STAFF, 'CommunityClass::getCommentPreviews - comment '.$c['id'].' belongs to nonexistant subject');
|
||||
trigger_error('Comment '.$c['id'].' belongs to nonexistant subject.', E_USER_NOTICE);
|
||||
unset($comments[$idx]);
|
||||
}
|
||||
}
|
||||
@@ -238,7 +242,7 @@ class CommunityContent
|
||||
{
|
||||
$screenshots = DB::Aowow()->select('
|
||||
SELECT s.id, a.displayName AS user, s.date, s.width, s.height, s.type, s.typeId, s.caption, s.status, s.status AS "flags"
|
||||
FROM ?_screenshots s,
|
||||
FROM ?_screenshots s
|
||||
LEFT JOIN ?_account a ON s.userIdOwner = a.id
|
||||
WHERE
|
||||
{ s.type = ?d}
|
||||
@@ -306,14 +310,14 @@ class CommunityContent
|
||||
|
||||
public static function getScreenshotPagesForManager($all, &$nFound)
|
||||
{
|
||||
// i GUESS .. ss_getALL ? everything : unapproved
|
||||
// i GUESS .. ss_getALL ? everything : pending
|
||||
$nFound = 0;
|
||||
$pages = DB::Aowow()->select('
|
||||
SELECT s.`type`, s.`typeId`, count(1) AS "count", MIN(s.`date`) AS "date"
|
||||
FROM ?_screenshots s
|
||||
{WHERE (s.status & ?d) = 0}
|
||||
GROUP BY s.`type`, s.`typeId`',
|
||||
$all ? DBSIMPLE_SKIP : CC_FLAG_APPROVED
|
||||
$all ? DBSIMPLE_SKIP : CC_FLAG_APPROVED | CC_FLAG_DELETED
|
||||
);
|
||||
|
||||
if ($pages)
|
||||
@@ -330,11 +334,7 @@ class CommunityContent
|
||||
if (!$ids)
|
||||
continue;
|
||||
|
||||
$cnd = [['id', $ids]];
|
||||
if ($t == TYPE_WORLDEVENT) // FKIN HOLIDAYS
|
||||
array_push($cnd, ['holidayId', $ids], 'OR');
|
||||
|
||||
$tClass = new Util::$typeClasses[$t]($cnd);
|
||||
$tClass = new Util::$typeClasses[$t](array(['id', $ids], CFG_SQL_LIMIT_NONE));
|
||||
foreach ($pages as &$p)
|
||||
if ($p['type'] == $t)
|
||||
if ($tClass->getEntry($p['typeId']))
|
||||
@@ -345,7 +345,7 @@ class CommunityContent
|
||||
{
|
||||
if (empty($p['name']))
|
||||
{
|
||||
Util::addNote(U_GROUP_STAFF | U_GROUP_SCREENSHOT, 'AdminPage::handleScreenshots() - Screenshot linked to nonexistant type/typeId combination '.$p['type'].'/'.$p['typeId']);
|
||||
trigger_error('Screenshot linked to nonexistant type/typeId combination: '.$p['type'].'/'.$p['typeId'], E_USER_NOTICE);
|
||||
unset($p);
|
||||
}
|
||||
else
|
||||
@@ -417,22 +417,26 @@ class CommunityContent
|
||||
return $comments;
|
||||
}
|
||||
|
||||
public static function getVideos($typeOrUser, $typeId = 0, &$nFound = 0)
|
||||
public static function getVideos($typeOrUser = 0, $typeId = 0, &$nFound = 0)
|
||||
{
|
||||
$videos = DB::Aowow()->selectPage($nFound, "
|
||||
SELECT v.id, a.displayName AS user, v.date, v.videoId, v.caption, IF(v.status & ?d, 1, 0) AS 'sticky', v.type, v.typeId
|
||||
FROM ?_videos v
|
||||
LEFT JOIN ?_account a ON v.userIdOwner = a.id
|
||||
WHERE {v.userIdOwner = ?d }{v.type = ? }{AND v.typeId = ? }AND v.status & ?d AND (v.status & ?d) = 0",
|
||||
WHERE {v.userIdOwner = ?d AND }{v.type = ? AND }{v.typeId = ? AND }v.status & ?d AND (v.status & ?d) = 0
|
||||
{ORDER BY ?# DESC}
|
||||
{LIMIT ?d}",
|
||||
CC_FLAG_STICKY,
|
||||
$typeOrUser < 0 ? -$typeOrUser : DBSIMPLE_SKIP,
|
||||
$typeOrUser > 0 ? $typeOrUser : DBSIMPLE_SKIP,
|
||||
$typeOrUser > 0 ? $typeId : DBSIMPLE_SKIP,
|
||||
$typeOrUser < 0 ? -$typeOrUser : DBSIMPLE_SKIP,
|
||||
$typeOrUser > 0 ? $typeOrUser : DBSIMPLE_SKIP,
|
||||
$typeOrUser > 0 ? $typeId : DBSIMPLE_SKIP,
|
||||
CC_FLAG_APPROVED,
|
||||
CC_FLAG_DELETED
|
||||
CC_FLAG_DELETED,
|
||||
!$typeOrUser ? 'date' : DBSIMPLE_SKIP,
|
||||
!$typeOrUser ? CFG_SQL_LIMIT_SEARCH : DBSIMPLE_SKIP
|
||||
);
|
||||
|
||||
if ($typeOrUser < 0) // only for user page
|
||||
if ($typeOrUser <= 0) // not for search by type/typeId
|
||||
{
|
||||
foreach ($videos as $v)
|
||||
self::addSubject($v['type'], $v['typeId']);
|
||||
@@ -443,7 +447,7 @@ class CommunityContent
|
||||
// format data to meet requirements of the js
|
||||
foreach ($videos as &$v)
|
||||
{
|
||||
if ($typeOrUser < 0) // only for user page
|
||||
if ($typeOrUser <= 0) // not for search by type/typeId
|
||||
{
|
||||
if (!empty(self::$subjCache[$v['type']][$v['typeId']]) && !is_numeric(self::$subjCache[$v['type']][$v['typeId']]))
|
||||
$v['subject'] = self::$subjCache[$v['type']][$v['typeId']];
|
||||
@@ -452,7 +456,7 @@ class CommunityContent
|
||||
}
|
||||
|
||||
$v['date'] = date(Util::$dateFormatInternal, $v['date']);
|
||||
$v['videoType'] = 1; // always youtube
|
||||
$v['videoType'] = 1; // always youtube
|
||||
|
||||
if (!$v['sticky'])
|
||||
unset($v['sticky']);
|
||||
@@ -464,22 +468,26 @@ class CommunityContent
|
||||
return $videos;
|
||||
}
|
||||
|
||||
public static function getScreenshots($typeOrUser, $typeId = 0, &$nFound = 0)
|
||||
public static function getScreenshots($typeOrUser = 0, $typeId = 0, &$nFound = 0)
|
||||
{
|
||||
$screenshots = DB::Aowow()->selectPage($nFound, "
|
||||
SELECT s.id, a.displayName AS user, s.date, s.width, s.height, s.caption, IF(s.status & ?d, 1, 0) AS 'sticky', s.type, s.typeId
|
||||
FROM ?_screenshots s
|
||||
LEFT JOIN ?_account a ON s.userIdOwner = a.id
|
||||
WHERE {s.userIdOwner = ?d }{s.type = ? }{AND s.typeId = ? }AND s.status & ?d AND (s.status & ?d) = 0",
|
||||
WHERE {s.userIdOwner = ?d AND }{s.type = ? AND }{s.typeId = ? AND }s.status & ?d AND (s.status & ?d) = 0
|
||||
{ORDER BY ?# DESC}
|
||||
{LIMIT ?d}",
|
||||
CC_FLAG_STICKY,
|
||||
$typeOrUser < 0 ? -$typeOrUser : DBSIMPLE_SKIP,
|
||||
$typeOrUser > 0 ? $typeOrUser : DBSIMPLE_SKIP,
|
||||
$typeOrUser > 0 ? $typeId : DBSIMPLE_SKIP,
|
||||
$typeOrUser < 0 ? -$typeOrUser : DBSIMPLE_SKIP,
|
||||
$typeOrUser > 0 ? $typeOrUser : DBSIMPLE_SKIP,
|
||||
$typeOrUser > 0 ? $typeId : DBSIMPLE_SKIP,
|
||||
CC_FLAG_APPROVED,
|
||||
CC_FLAG_DELETED
|
||||
CC_FLAG_DELETED,
|
||||
!$typeOrUser ? 'date' : DBSIMPLE_SKIP,
|
||||
!$typeOrUser ? CFG_SQL_LIMIT_SEARCH : DBSIMPLE_SKIP
|
||||
);
|
||||
|
||||
if ($typeOrUser < 0) // only for user page
|
||||
if ($typeOrUser <= 0) // not for search by type/typeId
|
||||
{
|
||||
foreach ($screenshots as $s)
|
||||
self::addSubject($s['type'], $s['typeId']);
|
||||
@@ -490,7 +498,7 @@ class CommunityContent
|
||||
// format data to meet requirements of the js
|
||||
foreach ($screenshots as &$s)
|
||||
{
|
||||
if ($typeOrUser < 0) // only for user page
|
||||
if ($typeOrUser <= 0) // not for search by type/typeId
|
||||
{
|
||||
if (!empty(self::$subjCache[$s['type']][$s['typeId']]) && !is_numeric(self::$subjCache[$s['type']][$s['typeId']]))
|
||||
$s['subject'] = self::$subjCache[$s['type']][$s['typeId']];
|
||||
|
||||
@@ -36,6 +36,13 @@ class DB
|
||||
if ($options['prefix'])
|
||||
$interface->setIdentPrefix($options['prefix']);
|
||||
|
||||
// disable STRICT_TRANS_TABLES and STRICT_ALL_TABLES off. It prevents usage of implicit default values.
|
||||
if ($idx == DB_AOWOW)
|
||||
$interface->query("SET SESSION sql_mode = 'NO_ENGINE_SUBSTITUTION'");
|
||||
// disable ONLY_FULL_GROUP_BY (Allows for non-aggregated selects in a group-by query)
|
||||
else
|
||||
$interface->query("SET SESSION sql_mode = ''");
|
||||
|
||||
self::$interfaceCache[$idx] = &$interface;
|
||||
self::$connectionCache[$idx] = true;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('invalid access');
|
||||
die('illegal access');
|
||||
|
||||
/*
|
||||
* Page
|
||||
*/
|
||||
|
||||
define('E_AOWOW', E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT));
|
||||
|
||||
// TypeIds
|
||||
define('TYPE_NPC', 1);
|
||||
define('TYPE_OBJECT', 2);
|
||||
@@ -24,7 +26,16 @@ define('TYPE_CLASS', 13);
|
||||
define('TYPE_RACE', 14);
|
||||
define('TYPE_SKILL', 15);
|
||||
define('TYPE_CURRENCY', 17);
|
||||
define('TYPE_USER', 100); // internal use only
|
||||
define('TYPE_SOUND', 19);
|
||||
define('TYPE_ICON', 29);
|
||||
define('TYPE_PROFILE', 100);
|
||||
// internal types (not published to js)
|
||||
define('TYPE_GUILD', 101);
|
||||
define('TYPE_ARENA_TEAM', 102);
|
||||
define('TYPE_USER', 500);
|
||||
define('TYPE_EMOTE', 501);
|
||||
define('TYPE_ENCHANTMENT', 502);
|
||||
define('TYPE_AREATRIGGER', 503); // not for display, but indexing in ?_spawns-table
|
||||
|
||||
define('CACHE_TYPE_NONE', 0); // page will not be cached
|
||||
define('CACHE_TYPE_PAGE', 1);
|
||||
@@ -39,7 +50,7 @@ define('SEARCH_TYPE_REGULAR', 0x10000000);
|
||||
define('SEARCH_TYPE_OPEN', 0x20000000);
|
||||
define('SEARCH_TYPE_JSON', 0x40000000);
|
||||
define('SEARCH_MASK_OPEN', 0x007DC1FF); // open search
|
||||
define('SEARCH_MASK_ALL', 0x07FFFFFF); // normal search
|
||||
define('SEARCH_MASK_ALL', 0x0FFFFFFF); // normal search
|
||||
|
||||
// Databases
|
||||
define('DB_AOWOW', 0);
|
||||
@@ -129,12 +140,13 @@ define('U_GROUP_LOCALIZER', 0x0200);
|
||||
define('U_GROUP_SALESAGENT', 0x0400);
|
||||
define('U_GROUP_SCREENSHOT', 0x0800);
|
||||
define('U_GROUP_VIDEO', 0x1000);
|
||||
// define('U_GROUP_APIONLY, 0x2000); // the heck..?
|
||||
// define('U_GROUP_PENDING, 0x4000); // would restrict some markup like urls
|
||||
define('U_GROUP_APIONLY', 0x2000); // not used
|
||||
define('U_GROUP_PENDING', 0x4000); // restricts usage of urls in comments
|
||||
|
||||
define('U_GROUP_STAFF', (U_GROUP_ADMIN|U_GROUP_EDITOR|U_GROUP_MOD|U_GROUP_BUREAU|U_GROUP_DEV|U_GROUP_BLOGGER|U_GROUP_LOCALIZER|U_GROUP_SALESAGENT));
|
||||
define('U_GROUP_EMPLOYEE', (U_GROUP_ADMIN|U_GROUP_BUREAU|U_GROUP_DEV));
|
||||
define('U_GROUP_GREEN_TEXT', (U_GROUP_MOD|U_GROUP_BUREAU|U_GROUP_DEV));
|
||||
define('U_GROUP_PREMIUMISH', (U_GROUP_PREMIUM|U_GROUP_EDITOR));
|
||||
define('U_GROUP_MODERATOR', (U_GROUP_ADMIN|U_GROUP_MOD|U_GROUP_BUREAU));
|
||||
define('U_GROUP_COMMENTS_MODERATOR', (U_GROUP_MODERATOR|U_GROUP_LOCALIZER));
|
||||
define('U_GROUP_PREMIUM_PERMISSIONS', (U_GROUP_PREMIUM|U_GROUP_STAFF|U_GROUP_VIP));
|
||||
@@ -155,6 +167,8 @@ define('BUTTON_LINKS', 4);
|
||||
define('BUTTON_FORUM', 5);
|
||||
define('BUTTON_TALENT', 6);
|
||||
define('BUTTON_EQUIP', 7);
|
||||
define('BUTTON_PLAYLIST', 8);
|
||||
define('BUTTON_RESYNC', 9);
|
||||
|
||||
// generic filter handler
|
||||
define('FILTER_CR_BOOLEAN', 1);
|
||||
@@ -163,6 +177,13 @@ define('FILTER_CR_NUMERIC', 3);
|
||||
define('FILTER_CR_STRING', 4);
|
||||
define('FILTER_CR_ENUM', 5);
|
||||
define('FILTER_CR_STAFFFLAG', 6);
|
||||
define('FILTER_CR_CALLBACK', 7);
|
||||
define('FILTER_CR_NYI_PH', 999);
|
||||
define('FILTER_V_EQUAL', 8);
|
||||
define('FILTER_V_RANGE', 9);
|
||||
define('FILTER_V_LIST', 10);
|
||||
define('FILTER_V_CALLBACK', 11);
|
||||
define('FILTER_V_REGEX', 12);
|
||||
|
||||
define('FILTER_ENUM_ANY', -2323);
|
||||
define('FILTER_ENUM_NONE', -2324);
|
||||
@@ -183,12 +204,20 @@ define('ITEMINFO_MODEL', 0x20);
|
||||
|
||||
define('NPCINFO_TAMEABLE', 0x1);
|
||||
define('NPCINFO_MODEL', 0x2);
|
||||
define('NPCINFO_REP', 0x4);
|
||||
|
||||
define('ACHIEVEMENTINFO_PROFILE', 0x1);
|
||||
|
||||
define('PROFILEINFO_PROFILE', 0x1);
|
||||
define('PROFILEINFO_CHARACTER', 0x2);
|
||||
define('PROFILEINFO_GUILD', 0x10); // like &roster
|
||||
define('PROFILEINFO_ARENA', 0x20);
|
||||
|
||||
define('SPAWNINFO_ZONES', 1); // not a mask, mutually exclusive
|
||||
define('SPAWNINFO_SHORT', 2);
|
||||
define('SPAWNINFO_FULL', 3);
|
||||
define('SPAWNINFO_QUEST', 4);
|
||||
|
||||
|
||||
// Community Content
|
||||
define('CC_FLAG_STICKY', 0x1);
|
||||
@@ -196,6 +225,25 @@ define('CC_FLAG_DELETED', 0x2);
|
||||
define('CC_FLAG_OUTDATED', 0x4);
|
||||
define('CC_FLAG_APPROVED', 0x8);
|
||||
|
||||
define('SOUND_TYPE_OGG', 1);
|
||||
define('SOUND_TYPE_MP3', 2);
|
||||
|
||||
define('CONTRIBUTE_NONE', 0x0);
|
||||
define('CONTRIBUTE_CO', 0x1);
|
||||
define('CONTRIBUTE_SS', 0x2);
|
||||
define('CONTRIBUTE_VI', 0x4);
|
||||
define('CONTRIBUTE_ANY', CONTRIBUTE_CO | CONTRIBUTE_SS | CONTRIBUTE_VI);
|
||||
|
||||
define('NUM_ANY', 0);
|
||||
define('NUM_CAST_INT', 1);
|
||||
define('NUM_CAST_FLOAT', 2);
|
||||
define('NUM_REQ_INT', 3);
|
||||
define('NUM_REQ_FLOAT', 4);
|
||||
|
||||
define('STR_LOCALIZED', 0x1);
|
||||
define('STR_MATCH_EXACT', 0x2);
|
||||
define('STR_ALLOW_SHORT', 0x4);
|
||||
|
||||
/*
|
||||
* Game
|
||||
*/
|
||||
@@ -204,9 +252,9 @@ define('CC_FLAG_APPROVED', 0x8);
|
||||
define('CUSTOM_HAS_COMMENT', 0x01000000);
|
||||
define('CUSTOM_HAS_SCREENSHOT', 0x02000000);
|
||||
define('CUSTOM_HAS_VIDEO', 0x04000000);
|
||||
define('CUSTOM_DISABLED', 0x08000000);
|
||||
define('CUSTOM_DISABLED', 0x08000000); // contained in world.disables
|
||||
define('CUSTOM_SERVERSIDE', 0x10000000);
|
||||
define('CUSTOM_UNAVAILABLE', 0x20000000);
|
||||
define('CUSTOM_UNAVAILABLE', 0x20000000); // no source for X or questFlag
|
||||
define('CUSTOM_EXCLUDE_FOR_LISTVIEW', 0x40000000); // will not show up in search or on listPage (override for staff)
|
||||
|
||||
// Custom Flags (per type)
|
||||
@@ -249,6 +297,12 @@ define('QUEST_CU_SKIP_LOG', 0x10);
|
||||
define('QUEST_CU_AUTO_ACCEPT', 0x20);
|
||||
define('QUEST_CU_PVP_ENABLED', 0x40);
|
||||
|
||||
define('PROFILER_CU_PUBLISHED', 0x01);
|
||||
define('PROFILER_CU_PINNED', 0x02);
|
||||
define('PROFILER_CU_DELETED', 0x04);
|
||||
define('PROFILER_CU_PROFILE', 0x08);
|
||||
define('PROFILER_CU_NEEDS_RESYNC', 0x10);
|
||||
|
||||
define('MAX_LEVEL', 80);
|
||||
define('WOW_BUILD', 12340);
|
||||
|
||||
@@ -356,6 +410,7 @@ define('SPELL_SCHOOL_NATURE', 3);
|
||||
define('SPELL_SCHOOL_FROST', 4);
|
||||
define('SPELL_SCHOOL_SHADOW', 5);
|
||||
define('SPELL_SCHOOL_ARCANE', 6);
|
||||
define('SPELL_MAGIC_SCHOOLS', 0x7E);
|
||||
define('SPELL_ALL_SCHOOLS', 0x7F);
|
||||
|
||||
// CharacterSlot
|
||||
@@ -710,7 +765,7 @@ define('ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION', 46);
|
||||
// define('ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT', 51);
|
||||
define('ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS', 52);
|
||||
define('ACHIEVEMENT_CRITERIA_TYPE_HK_RACE', 53);
|
||||
// define('ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE', 54);
|
||||
define('ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE', 54);
|
||||
// define('ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE', 55);
|
||||
// define('ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS', 56);
|
||||
define('ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM', 57);
|
||||
@@ -830,4 +885,31 @@ define('CND_DISTANCE_TO', 35); // distance to targe
|
||||
define('CND_ALIVE', 36); // target is alive: NULL, NULL, NULL
|
||||
define('CND_HP_VAL', 37); // targets absolute health: amount, operator, NULL
|
||||
define('CND_HP_PCT', 38); // targets relative health: amount, operator, NULL
|
||||
|
||||
// profiler queue interactions
|
||||
define('PR_QUEUE_STATUS_ENDED', 0);
|
||||
define('PR_QUEUE_STATUS_WAITING', 1);
|
||||
define('PR_QUEUE_STATUS_WORKING', 2);
|
||||
define('PR_QUEUE_STATUS_READY', 3);
|
||||
define('PR_QUEUE_STATUS_ERROR', 4);
|
||||
define('PR_QUEUE_ERROR_UNK', 0);
|
||||
define('PR_QUEUE_ERROR_CHAR', 1);
|
||||
define('PR_QUEUE_ERROR_ARMORY', 2);
|
||||
|
||||
// profiler completion manager
|
||||
define('PR_EXCLUDE_GROUP_UNAVAILABLE', 0x001);
|
||||
define('PR_EXCLUDE_GROUP_TCG', 0x002);
|
||||
define('PR_EXCLUDE_GROUP_COLLECTORS_EDITION', 0x004);
|
||||
define('PR_EXCLUDE_GROUP_PROMOTION', 0x008);
|
||||
define('PR_EXCLUDE_GROUP_WRONG_REGION', 0x010);
|
||||
define('PR_EXCLUDE_GROUP_REQ_ALLIANCE', 0x020);
|
||||
define('PR_EXCLUDE_GROUP_REQ_HORDE', 0x040);
|
||||
define('PR_EXCLUDE_GROUP_OTHER_FACTION', PR_EXCLUDE_GROUP_REQ_ALLIANCE | PR_EXCLUDE_GROUP_REQ_HORDE);
|
||||
define('PR_EXCLUDE_GROUP_REQ_FISHING', 0x080);
|
||||
define('PR_EXCLUDE_GROUP_REQ_ENGINEERING', 0x100);
|
||||
define('PR_EXCLUDE_GROUP_REQ_TAILORING', 0x200);
|
||||
define('PR_EXCLUDE_GROUP_WRONG_PROFESSION', PR_EXCLUDE_GROUP_REQ_FISHING | PR_EXCLUDE_GROUP_REQ_ENGINEERING | PR_EXCLUDE_GROUP_REQ_TAILORING);
|
||||
define('PR_EXCLUDE_GROUP_REQ_CANT_BE_EXALTED', 0x400);
|
||||
define('PR_EXCLUDE_GROUP_ANY', 0x7FF);
|
||||
|
||||
?>
|
||||
|
||||
242
includes/game.php
Normal file
242
includes/game.php
Normal file
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class Game
|
||||
{
|
||||
public static $resistanceFields = array(
|
||||
null, 'resHoly', 'resFire', 'resNature', 'resFrost', 'resShadow', 'resArcane'
|
||||
);
|
||||
|
||||
public static $rarityColorStings = array( // zero-indexed
|
||||
'9d9d9d', 'ffffff', '1eff00', '0070dd', 'a335ee', 'ff8000', 'e5cc80', 'e6cc80'
|
||||
);
|
||||
|
||||
private static $combatRatingToItemMod = array( // zero-indexed idx:CR; val:Mod
|
||||
null, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||
20, 21, 22, 23, 24, 25, 26, 27, 28,
|
||||
29, 30, null, null, null, 37, 44
|
||||
);
|
||||
|
||||
public static $lvlIndepRating = array( // rating doesn't scale with level
|
||||
ITEM_MOD_MANA, ITEM_MOD_HEALTH, ITEM_MOD_ATTACK_POWER, ITEM_MOD_MANA_REGENERATION, ITEM_MOD_SPELL_POWER,
|
||||
ITEM_MOD_HEALTH_REGEN, ITEM_MOD_SPELL_PENETRATION, ITEM_MOD_BLOCK_VALUE
|
||||
);
|
||||
|
||||
public static $questClasses = array( // taken from old aowow: 2 & 3 partially point to pointless mini-areas in front of dungeons
|
||||
-2 => [ 0],
|
||||
0 => [ 1, 3, 4, 8, 10, 11, 12, 25, 28, 33, 36, 38, 40, 41, 44, 45, 46, 47, 51, 85, 130, 139, 267, 279, 1497, 1519, 1537, 2257, 3430, 3433, 3487, 4080, 4298],
|
||||
1 => [ 14, 15, 16, 17, 141, 148, 215, 331, 357, 361, 400, 405, 406, 440, 490, 493, 618, 1216, 1377, 1637, 1638, 1657, 3524, 3525, 3557],
|
||||
/*todo*/ 2 => [ 133, 206, 209, 491, 717, 718, 719, 722, 796, 978, 1196, 1337, 1417, 1581, 1583, 1584, 1941, 2017, 2057, 2100, 2366, 2367, 2437, 2557, 3477, 3562, 3713, 3714, 3715, 3716, 3717, 3789, 3790, 3791, 3792, 3845, 3846, 3847, 3849, 3905, 4095, 4100, 4120, 4196, 4228, 4264, 4272, 4375, 4415, 4494, 4723],
|
||||
/*todo*/ 3 => [ 1977, 2159, 2562, 2677, 2717, 3428, 3429, 3456, 3606, 3805, 3836, 3840, 3842, 4273, 4500, 4722, 4812],
|
||||
4 => [ -372, -263, -262, -261, -162, -161, -141, -82, -81, -61],
|
||||
5 => [ -373, -371, -324, -304, -264, -201, -182, -181, -121, -101, -24],
|
||||
6 => [ -25, 2597, 3277, 3358, 3820, 4384, 4710],
|
||||
7 => [-1010, -368, -367, -365, -344, -241, -1],
|
||||
8 => [ 3483, 3518, 3519, 3520, 3521, 3522, 3523, 3679, 3703], // Skettis is no parent
|
||||
9 => [-1006, -1005, -1003, -1002, -1001, -376, -375, -374, -370, -369, -366, -364, -284, -41, -22], // 22: seasonal, 284: special => not in the actual menu
|
||||
10 => [ 65, 66, 67, 210, 394, 495, 3537, 3711, 4024, 4197, 4395, 4742] // Coldara is no parent
|
||||
);
|
||||
|
||||
/* why:
|
||||
Because petSkills (and ranged weapon skills) are the only ones with more than two skillLines attached. Because Left Joining ?_spell with ?_skillLineability causes more trouble than it has uses.
|
||||
Because this is more or less the only reaonable way to fit all that information into one database field, so..
|
||||
.. the indizes of this array are bits of skillLine2OrMask in ?_spell if skillLineId1 is negative
|
||||
*/
|
||||
public static $skillLineMask = array( // idx => [familyId, skillLineId]
|
||||
-1 => array( // Pets (Hunter)
|
||||
[ 1, 208], [ 2, 209], [ 3, 203], [ 4, 210], [ 5, 211], [ 6, 212], [ 7, 213], // Wolf, Cat, Spider, Bear, Boar, Crocolisk, Carrion Bird
|
||||
[ 8, 214], [ 9, 215], [11, 217], [12, 218], [20, 236], [21, 251], [24, 653], // Crab, Gorilla, Raptor, Tallstrider, Scorpid, Turtle, Bat
|
||||
[25, 654], [26, 655], [27, 656], [30, 763], [31, 767], [32, 766], [33, 765], // Hyena, Bird of Prey, Wind Serpent, Dragonhawk, Ravager, Warp Stalker, Sporebat
|
||||
[34, 764], [35, 768], [37, 775], [38, 780], [39, 781], [41, 783], [42, 784], // Nether Ray, Serpent, Moth, Chimaera, Devilsaur, Silithid, Worm
|
||||
[43, 786], [44, 785], [45, 787], [46, 788] // Rhino, Wasp, Core Hound, Spirit Beast
|
||||
),
|
||||
-2 => array( // Pets (Warlock)
|
||||
[15, 189], [16, 204], [17, 205], [19, 207], [23, 188], [29, 761] // Felhunter, Voidwalker, Succubus, Doomguard, Imp, Felguard
|
||||
),
|
||||
-3 => array( // Ranged Weapons
|
||||
[null, 45], [null, 46], [null, 226] // Bow, Gun, Crossbow
|
||||
)
|
||||
);
|
||||
|
||||
public static $trainerTemplates = array( // TYPE => Id => templateList
|
||||
TYPE_CLASS => array(
|
||||
1 => [-200001, -200002], // Warrior
|
||||
2 => [-200003, -200004, -200020, -200021], // Paladin
|
||||
3 => [-200013, -200014], // Hunter
|
||||
4 => [-200015, -200016], // Rogue
|
||||
5 => [-200011, -200012], // Priest
|
||||
6 => [-200019], // DK
|
||||
7 => [-200017, -200018], // Shaman (HighlevelAlly Id missing..?)
|
||||
8 => [-200007, -200008], // Mage
|
||||
9 => [-200009, -200010], // Warlock
|
||||
11 => [-200005, -200006] // Druid
|
||||
),
|
||||
TYPE_SKILL => array(
|
||||
171 => [-201001, -201002, -201003], // Alchemy
|
||||
164 => [-201004, -201005, -201006, -201007, -201008],// Blacksmithing
|
||||
333 => [-201009, -201010, -201011], // Enchanting
|
||||
202 => [-201012, -201013, -201014, -201015, -201016, -201017], // Engineering
|
||||
182 => [-201018, -201019, -201020], // Herbalism
|
||||
773 => [-201021, -201022, -201023], // Inscription
|
||||
755 => [-201024, -201025, -201026], // Jewelcrafting
|
||||
165 => [-201027, -201028, -201029, -201030, -201031, -201032], // Leatherworking
|
||||
186 => [-201033, -201034, -201035], // Mining
|
||||
393 => [-201036, -201037, -201038], // Skinning
|
||||
197 => [-201039, -201040, -201041, -201042], // Tailoring
|
||||
356 => [-202001, -202002, -202003], // Fishing
|
||||
185 => [-202004, -202005, -202006], // Cooking
|
||||
129 => [-202007, -202008, -202009], // First Aid
|
||||
762 => [-202010, -202011, -202012] // Riding
|
||||
)
|
||||
);
|
||||
|
||||
public static $sockets = array( // jsStyle Strings
|
||||
'meta', 'red', 'yellow', 'blue'
|
||||
);
|
||||
|
||||
// 'replicates' $WH.g_statToJson
|
||||
public static $itemMods = array( // zero-indexed; "mastrtng": unused mastery; _[a-z] => taken mods..
|
||||
'dmg', 'mana', 'health', 'agi', 'str', 'int', 'spi',
|
||||
'sta', 'energy', 'rage', 'focus', 'runicpwr', 'defrtng', 'dodgertng',
|
||||
'parryrtng', 'blockrtng', 'mlehitrtng', 'rgdhitrtng', 'splhitrtng', 'mlecritstrkrtng', 'rgdcritstrkrtng',
|
||||
'splcritstrkrtng', '_mlehitrtng', '_rgdhitrtng', '_splhitrtng', '_mlecritstrkrtng', '_rgdcritstrkrtng', '_splcritstrkrtng',
|
||||
'mlehastertng', 'rgdhastertng', 'splhastertng', 'hitrtng', 'critstrkrtng', '_hitrtng', '_critstrkrtng',
|
||||
'resirtng', 'hastertng', 'exprtng', 'atkpwr', 'rgdatkpwr', 'feratkpwr', 'splheal',
|
||||
'spldmg', 'manargn', 'armorpenrtng', 'splpwr', 'healthrgn', 'splpen', 'block', // ITEM_MOD_BLOCK_VALUE
|
||||
'mastrtng', 'armor', 'firres', 'frores', 'holres', 'shares', 'natres',
|
||||
'arcres', 'firsplpwr', 'frosplpwr', 'holsplpwr', 'shasplpwr', 'natsplpwr', 'arcsplpwr'
|
||||
);
|
||||
|
||||
public static $class2SpellFamily = array(
|
||||
// null Warrior Paladin Hunter Rogue Priest DK Shaman Mage Warlock null Druid
|
||||
null, 4, 10, 9, 8, 6, 15, 11, 3, 5, null, 7
|
||||
);
|
||||
|
||||
public static function itemModByRatingMask($mask)
|
||||
{
|
||||
if (($mask & 0x1C000) == 0x1C000) // special case resilience
|
||||
return ITEM_MOD_RESILIENCE_RATING;
|
||||
|
||||
if (($mask & 0x00E0) == 0x00E0) // hit rating - all subcats (mle, rgd, spl)
|
||||
return ITEM_MOD_HIT_RATING;
|
||||
|
||||
if (($mask & 0x0700) == 0x0700) // crit rating - all subcats (mle, rgd, spl)
|
||||
return ITEM_MOD_CRIT_RATING;
|
||||
|
||||
for ($j = 0; $j < count(self::$combatRatingToItemMod); $j++)
|
||||
{
|
||||
if (!self::$combatRatingToItemMod[$j])
|
||||
continue;
|
||||
|
||||
if (!($mask & (1 << $j)))
|
||||
continue;
|
||||
|
||||
return self::$combatRatingToItemMod[$j];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function sideByRaceMask($race)
|
||||
{
|
||||
// Any
|
||||
if (!$race || ($race & RACE_MASK_ALL) == RACE_MASK_ALL)
|
||||
return SIDE_BOTH;
|
||||
|
||||
// Horde
|
||||
if ($race & RACE_MASK_HORDE && !($race & RACE_MASK_ALLIANCE))
|
||||
return SIDE_HORDE;
|
||||
|
||||
// Alliance
|
||||
if ($race & RACE_MASK_ALLIANCE && !($race & RACE_MASK_HORDE))
|
||||
return SIDE_ALLIANCE;
|
||||
|
||||
return SIDE_BOTH;
|
||||
}
|
||||
|
||||
public static function getReputationLevelForPoints($pts)
|
||||
{
|
||||
if ($pts >= 41999)
|
||||
return REP_EXALTED;
|
||||
else if ($pts >= 20999)
|
||||
return REP_REVERED;
|
||||
else if ($pts >= 8999)
|
||||
return REP_HONORED;
|
||||
else if ($pts >= 2999)
|
||||
return REP_FRIENDLY;
|
||||
else if ($pts >= 0)
|
||||
return REP_NEUTRAL;
|
||||
else if ($pts >= -3000)
|
||||
return REP_UNFRIENDLY;
|
||||
else if ($pts >= -6000)
|
||||
return REP_HOSTILE;
|
||||
else
|
||||
return REP_HATED;
|
||||
}
|
||||
|
||||
public static function getTaughtSpells(&$spell)
|
||||
{
|
||||
$extraIds = [-1]; // init with -1 to prevent empty-array errors
|
||||
$lookup = [-1];
|
||||
switch (gettype($spell))
|
||||
{
|
||||
case 'object':
|
||||
if (get_class($spell) != 'SpellList')
|
||||
return [];
|
||||
|
||||
$lookup[] = $spell->id;
|
||||
foreach ($spell->canTeachSpell() as $idx)
|
||||
$extraIds[] = $spell->getField('effect'.$idx.'TriggerSpell');
|
||||
|
||||
break;
|
||||
case 'integer':
|
||||
$lookup[] = $spell;
|
||||
break;
|
||||
case 'array':
|
||||
$lookup = $spell;
|
||||
break;
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
|
||||
// note: omits required spell and chance in skill_discovery_template
|
||||
$data = array_merge(
|
||||
DB::World()->selectCol('SELECT spellId FROM spell_learn_spell WHERE entry IN (?a)', $lookup),
|
||||
DB::World()->selectCol('SELECT spellId FROM skill_discovery_template WHERE reqSpell IN (?a)', $lookup),
|
||||
$extraIds
|
||||
);
|
||||
|
||||
// return list of integers, not strings
|
||||
array_walk($data, function (&$v, $k) {
|
||||
$v = intVal($v);
|
||||
});
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public static function getPageText($ptId)
|
||||
{
|
||||
$pages = [];
|
||||
while ($ptId)
|
||||
{
|
||||
if ($row = DB::World()->selectRow('SELECT ptl.Text AS Text_loc?d, pt.* FROM page_text pt LEFT JOIN page_text_locale ptl ON pt.ID = ptl.ID AND locale = ? WHERE pt.ID = ?d', User::$localeId, User::$localeString, $ptId))
|
||||
{
|
||||
$ptId = $row['NextPageID'];
|
||||
$pages[] = Util::parseHtmlText(Util::localizedString($row, 'Text'));
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error('Referenced PageTextId #'.$ptId.' is not in DB', E_USER_WARNING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $pages;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -9,10 +9,18 @@ if (file_exists('config/config.php'))
|
||||
else
|
||||
$AoWoWconf = [];
|
||||
|
||||
|
||||
mb_internal_encoding('UTF-8');
|
||||
|
||||
|
||||
define('OS_WIN', substr(PHP_OS, 0, 3) == 'WIN');
|
||||
|
||||
|
||||
require_once 'includes/defines.php';
|
||||
require_once 'includes/libs/DbSimple/Generic.php'; // Libraray: http://en.dklab.ru/lib/DbSimple (using variant: https://github.com/ivan1986/DbSimple/tree/master)
|
||||
require_once 'includes/utilities.php'; // misc™ data 'n func
|
||||
require_once 'includes/ajaxHandler.class.php'; // handles ajax and jsonp requests
|
||||
require_once 'includes/utilities.php'; // helper functions
|
||||
require_once 'includes/game.php'; // game related data & functions
|
||||
require_once 'includes/profiler.class.php';
|
||||
require_once 'includes/user.class.php';
|
||||
require_once 'includes/markup.class.php'; // manipulate markup text
|
||||
require_once 'includes/database.class.php'; // wrap DBSimple
|
||||
@@ -24,7 +32,7 @@ require_once 'pages/genericPage.class.php';
|
||||
|
||||
// autoload List-classes, associated filters and pages
|
||||
spl_autoload_register(function ($class) {
|
||||
$class = strtolower(str_replace('Filter', '', $class));
|
||||
$class = strtolower(str_replace('ListFilter', 'List', $class));
|
||||
|
||||
if (class_exists($class)) // already registered
|
||||
return;
|
||||
@@ -32,18 +40,37 @@ spl_autoload_register(function ($class) {
|
||||
if (preg_match('/[^\w]/i', $class)) // name should contain only letters
|
||||
return;
|
||||
|
||||
if (strpos($class, 'list'))
|
||||
if (stripos($class, 'list'))
|
||||
{
|
||||
if (!class_exists('BaseType'))
|
||||
require_once 'includes/types/basetype.class.php';
|
||||
require_once 'includes/basetype.class.php';
|
||||
|
||||
if (file_exists('includes/types/'.strtr($class, ['list' => '']).'.class.php'))
|
||||
require_once 'includes/types/'.strtr($class, ['list' => '']).'.class.php';
|
||||
$cl = strtr($class, ['list' => '']);
|
||||
if ($cl == 'remoteprofile' || $cl == 'localprofile')
|
||||
$cl = 'profile';
|
||||
if ($cl == 'remotearenateam' || $cl == 'localarenateam')
|
||||
$cl = 'arenateam';
|
||||
if ($cl == 'remoteguild' || $cl == 'localguild')
|
||||
$cl = 'guild';
|
||||
|
||||
if (file_exists('includes/types/'.$cl.'.class.php'))
|
||||
require_once 'includes/types/'.$cl.'.class.php';
|
||||
else
|
||||
throw new Exception('could not register type class: '.$cl);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (stripos($class, 'ajax') === 0)
|
||||
{
|
||||
require_once 'includes/ajaxHandler.class.php'; // handles ajax and jsonp requests
|
||||
|
||||
if (file_exists('pages/'.strtr($class, ['page' => '']).'.php'))
|
||||
if (file_exists('includes/ajaxHandler/'.strtr($class, ['ajax' => '']).'.class.php'))
|
||||
require_once 'includes/ajaxHandler/'.strtr($class, ['ajax' => '']).'.class.php';
|
||||
else
|
||||
throw new Exception('could not register ajaxHandler class: '.$class);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (file_exists('pages/'.strtr($class, ['page' => '']).'.php'))
|
||||
require_once 'pages/'.strtr($class, ['page' => '']).'.php';
|
||||
});
|
||||
|
||||
@@ -68,12 +95,15 @@ if (!empty($AoWoWconf['characters']))
|
||||
$sets = DB::isConnectable(DB_AOWOW) ? DB::Aowow()->select('SELECT `key` AS ARRAY_KEY, `value`, `flags` FROM ?_config') : [];
|
||||
foreach ($sets as $k => $v)
|
||||
{
|
||||
// this should not have been possible
|
||||
if (!strlen($v['value']))
|
||||
continue;
|
||||
|
||||
$php = $v['flags'] & CON_FLAG_PHP;
|
||||
|
||||
// this should not have been possible
|
||||
if (!strlen($v['value']) && !($v['flags'] & CON_FLAG_TYPE_STRING) && !$php)
|
||||
{
|
||||
trigger_error('Aowow config value CFG_'.strtoupper($k).' is empty - config will not be used!', E_USER_ERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($v['flags'] & CON_FLAG_TYPE_INT)
|
||||
$val = intVal($v['value']);
|
||||
else if ($v['flags'] & CON_FLAG_TYPE_FLOAT)
|
||||
@@ -81,10 +111,15 @@ foreach ($sets as $k => $v)
|
||||
else if ($v['flags'] & CON_FLAG_TYPE_BOOL)
|
||||
$val = (bool)$v['value'];
|
||||
else if ($v['flags'] & CON_FLAG_TYPE_STRING)
|
||||
$val = preg_replace('/[^\p{L}0-9~\s_\-\'\/\.:,]/ui', '', $v['value']);
|
||||
else
|
||||
$val = preg_replace("/[\p{C}]/ui", '', $v['value']);
|
||||
else if ($php)
|
||||
{
|
||||
Util::addNote(U_GROUP_ADMIN | U_GROUP_DEV, 'Kernel: '.($php ? 'PHP' : 'Aowow').' config value '.($php ? strtolower($k) : 'CFG_'.strtoupper($k)).' has no type set. Value forced to 0!');
|
||||
trigger_error('PHP config value '.strtolower($k).' has no type set - config will not be used!', E_USER_ERROR);
|
||||
continue;
|
||||
}
|
||||
else // if (!$php)
|
||||
{
|
||||
trigger_error('Aowow config value CFG_'.strtoupper($k).' has no type set - value forced to 0!', E_USER_ERROR);
|
||||
$val = 0;
|
||||
}
|
||||
|
||||
@@ -95,11 +130,13 @@ foreach ($sets as $k => $v)
|
||||
}
|
||||
|
||||
|
||||
// handle occuring errors
|
||||
error_reporting(!empty($AoWoWconf['aowow']) && CFG_DEBUG ? (E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT)) : 0);
|
||||
$errHandled = false;
|
||||
set_error_handler(function($errNo, $errStr, $errFile, $errLine) use (&$errHandled) {
|
||||
// handle non-fatal errors and notices
|
||||
error_reporting(!empty($AoWoWconf['aowow']) && CFG_DEBUG ? E_AOWOW : 0);
|
||||
set_error_handler(function($errNo, $errStr, $errFile, $errLine)
|
||||
{
|
||||
$errName = 'unknown error'; // errors not in this list can not be handled by set_error_handler (as per documentation) or are ignored
|
||||
$uGroup = U_GROUP_EMPLOYEE;
|
||||
|
||||
if ($errNo == E_WARNING) // 0x0002
|
||||
$errName = 'E_WARNING';
|
||||
else if ($errNo == E_PARSE) // 0x0004
|
||||
@@ -111,29 +148,58 @@ set_error_handler(function($errNo, $errStr, $errFile, $errLine) use (&$errHandle
|
||||
else if ($errNo == E_USER_WARNING) // 0x0200
|
||||
$errName = 'E_USER_WARNING';
|
||||
else if ($errNo == E_USER_NOTICE) // 0x0400
|
||||
{
|
||||
$errName = 'E_USER_NOTICE';
|
||||
$uGroup = U_GROUP_STAFF;
|
||||
}
|
||||
else if ($errNo == E_RECOVERABLE_ERROR) // 0x1000
|
||||
$errName = 'E_RECOVERABLE_ERROR';
|
||||
|
||||
if (User::isInGroup(U_GROUP_STAFF))
|
||||
{
|
||||
if (!$errHandled)
|
||||
{
|
||||
Util::addNote(U_GROUP_STAFF, 'one or more php related error occured, while generating this page.');
|
||||
$errHandled = true;
|
||||
}
|
||||
|
||||
Util::addNote(U_GROUP_STAFF, $errName.' - '.$errStr.' @ '.$errFile. ':'.$errLine);
|
||||
}
|
||||
Util::addNote($uGroup, $errName.' - '.$errStr.' @ '.$errFile. ':'.$errLine);
|
||||
|
||||
if (DB::isConnectable(DB_AOWOW))
|
||||
DB::Aowow()->query('INSERT INTO ?_errors (`date`, `version`, `phpError`, `file`, `line`, `query`, `userGroups`, `message`) VALUES (UNIX_TIMESTAMP(), ?d, ?d, ?, ?d, ?, ?d, ?) ON DUPLICATE KEY UPDATE `date` = UNIX_TIMESTAMP()',
|
||||
AOWOW_REVISION, $errNo, $errFile, $errLine, CLI ? 'CLI' : $_SERVER['QUERY_STRING'], User::$groups, $errStr
|
||||
);
|
||||
|
||||
return !((User::isInGroup(U_GROUP_STAFF) && defined('CFG_DEBUG') && CFG_DEBUG) || CLI);
|
||||
}, E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT));
|
||||
return true;
|
||||
}, E_AOWOW);
|
||||
|
||||
// handle exceptions
|
||||
set_exception_handler(function ($ex)
|
||||
{
|
||||
Util::addNote(U_GROUP_EMPLOYEE, 'Exception - '.$ex->getMessage().' @ '.$ex->getFile(). ':'.$ex->getLine()."\n".$ex->getTraceAsString());
|
||||
|
||||
if (DB::isConnectable(DB_AOWOW))
|
||||
DB::Aowow()->query('INSERT INTO ?_errors (`date`, `version`, `phpError`, `file`, `line`, `query`, `userGroups`, `message`) VALUES (UNIX_TIMESTAMP(), ?d, ?d, ?, ?d, ?, ?d, ?) ON DUPLICATE KEY UPDATE `date` = UNIX_TIMESTAMP()',
|
||||
AOWOW_REVISION, $ex->getCode(), $ex->getFile(), $ex->getLine(), CLI ? 'CLI' : $_SERVER['QUERY_STRING'], User::$groups, $ex->getMessage()
|
||||
);
|
||||
|
||||
if (!CLI)
|
||||
(new GenericPage(null))->error();
|
||||
else
|
||||
echo 'Exception - '.$ex->getMessage()."\n ".$ex->getFile(). '('.$ex->getLine().")\n".$ex->getTraceAsString()."\n";
|
||||
});
|
||||
|
||||
// handle fatal errors
|
||||
register_shutdown_function(function()
|
||||
{
|
||||
if (($e = error_get_last()) && $e['type'] & (E_ERROR | E_COMPILE_ERROR | E_CORE_ERROR))
|
||||
{
|
||||
Util::addNote(U_GROUP_EMPLOYEE, 'Fatal Error - '.$e['message'].' @ '.$e['file']. ':'.$e['line']);
|
||||
|
||||
if (DB::isConnectable(DB_AOWOW))
|
||||
DB::Aowow()->query('INSERT INTO ?_errors (`date`, `version`, `phpError`, `file`, `line`, `query`, `userGroups`, `message`) VALUES (UNIX_TIMESTAMP(), ?d, ?d, ?, ?d, ?, ?d, ?) ON DUPLICATE KEY UPDATE `date` = UNIX_TIMESTAMP()',
|
||||
AOWOW_REVISION, $e['type'], $e['file'], $e['line'], CLI ? 'CLI' : $_SERVER['QUERY_STRING'], User::$groups, $e['message']
|
||||
);
|
||||
|
||||
if (CLI)
|
||||
echo 'Fatal Error - '.$e['message'].' @ '.$e['file']. ':'.$e['line']."\n";
|
||||
|
||||
// cant generate a page for web view :(
|
||||
die();
|
||||
}
|
||||
});
|
||||
|
||||
$secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || (!empty($AoWoWconf['aowow']) && CFG_FORCE_SSL);
|
||||
if (defined('CFG_STATIC_HOST')) // points js to images & scripts
|
||||
@@ -145,30 +211,19 @@ if (defined('CFG_SITE_HOST')) // points js to exec
|
||||
|
||||
if (!CLI)
|
||||
{
|
||||
if (!defined('CFG_SITE_HOST') || !defined('CFG_STATIC_HOST'))
|
||||
die('error: SITE_HOST or STATIC_HOST not configured');
|
||||
|
||||
// Setup Session
|
||||
if (CFG_SESSION_CACHE_DIR && Util::writeDir(CFG_SESSION_CACHE_DIR))
|
||||
session_save_path(getcwd().'/'.CFG_SESSION_CACHE_DIR);
|
||||
|
||||
session_set_cookie_params(15 * YEAR, '/', '', $secure, true);
|
||||
session_cache_limiter('private');
|
||||
session_start();
|
||||
if (!empty($AoWoWconf['aowow']) && User::init())
|
||||
User::save(); // save user-variables in session
|
||||
|
||||
// todo: (low) - move to setup web-interface (when it begins its existance)
|
||||
if (!defined('CFG_SITE_HOST') || !defined('CFG_STATIC_HOST'))
|
||||
{
|
||||
$host = substr($_SERVER['SERVER_NAME'].strtr($_SERVER['SCRIPT_NAME'], ['index.php' => '']), 0, -1);
|
||||
|
||||
define('HOST_URL', ($secure ? 'https://' : 'http://').$host);
|
||||
define('STATIC_URL', ($secure ? 'https://' : 'http://').$host.'/static');
|
||||
|
||||
if (User::isInGroup(U_GROUP_ADMIN)) // initial set
|
||||
{
|
||||
DB::Aowow()->query('REPLACE INTO ?_config VALUES (?a)',
|
||||
[['site_host', $host, CON_FLAG_TYPE_STRING | CON_FLAG_PERSISTENT, 'default: '.$host.' - points js to executable files (automaticly set on first run)'],
|
||||
['static_host', $host.'/static', CON_FLAG_TYPE_STRING | CON_FLAG_PERSISTENT, 'default: '.$host.'/static - points js to images & scripts (automaticly set on first run)']]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// hard-override locale for this call (should this be here..?)
|
||||
// all strings attached..
|
||||
if (!empty($AoWoWconf['aowow']))
|
||||
|
||||
@@ -30,7 +30,7 @@ class DbSimple_Mysqli extends DbSimple_Database
|
||||
* constructor(string $dsn)
|
||||
* Connect to MySQL server.
|
||||
*/
|
||||
function DbSimple_Mysqli($dsn)
|
||||
function __construct($dsn)
|
||||
{
|
||||
|
||||
if (!is_callable("mysqli_connect"))
|
||||
@@ -178,7 +178,7 @@ class DbSimple_Mysqli extends DbSimple_Database
|
||||
protected function _performFetch($result)
|
||||
{
|
||||
$row = mysqli_fetch_assoc($result);
|
||||
if (mysql_error()) return $this->_setDbError($this->_lastQuery);
|
||||
if (mysqli_error($this->link)) return $this->_setDbError($this->_lastQuery);
|
||||
if ($row === false) return null;
|
||||
return $row;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('invalid access');
|
||||
die('illegal access');
|
||||
|
||||
|
||||
/* from TC wiki
|
||||
@@ -63,7 +63,7 @@ class Loot
|
||||
$stack[$i] = round(100 / (1 + $l['max'] - $l['min']), 3);
|
||||
|
||||
// yes, it wants a string .. how weired is that..
|
||||
return json_encode($stack, JSON_NUMERIC_CHECK);
|
||||
return json_encode($stack, JSON_NUMERIC_CHECK); // do not replace with Util::toJSON !
|
||||
}
|
||||
|
||||
private function storeJSGlobals($data)
|
||||
@@ -175,7 +175,7 @@ class Loot
|
||||
}
|
||||
else // shouldn't have happened
|
||||
{
|
||||
Util::addNote(U_GROUP_EMPLOYEE, 'Loot::getByContainerRecursive: unhandled case in calculating chance for item '.$entry['Item'].'!');
|
||||
trigger_error('Unhandled case in calculating chance for item '.$entry['Item'].'!', E_USER_WARNING);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ class Loot
|
||||
$sum = 0;
|
||||
else if ($sum >= 100.01)
|
||||
{
|
||||
Util::addNote(U_GROUP_EMPLOYEE, 'Loot::getByContainerRecursive: entry '.$lootId.' / group '.$k.' has a total chance of '.number_format($sum, 2).'%. Some items cannot drop!');
|
||||
trigger_error('Loot entry '.$lootId.' / group '.$k.' has a total chance of '.number_format($sum, 2).'%. Some items cannot drop!', E_USER_WARNING);
|
||||
$sum = 100;
|
||||
}
|
||||
|
||||
@@ -312,10 +312,10 @@ class Loot
|
||||
break;
|
||||
}
|
||||
|
||||
$this->extraCols[] = "Listview.funcBox.createSimpleCol('group', 'Group', '7%', 'group')";
|
||||
$this->extraCols[] = "\$Listview.funcBox.createSimpleCol('group', 'Group', '7%', 'group')";
|
||||
foreach ($fields as $idx => $field)
|
||||
if ($set & (1 << $idx))
|
||||
$this->extraCols[] = "Listview.funcBox.createSimpleCol('".$field."', '".Util::ucFirst($field)."', '7%', '".$field."')";
|
||||
$this->extraCols[] = "\$Listview.funcBox.createSimpleCol('".$field."', '".Util::ucFirst($field)."', '7%', '".$field."')";
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -378,13 +378,13 @@ class Loot
|
||||
{
|
||||
// check for possible database inconsistencies
|
||||
if (!$ref['chance'] && !$ref['isGrouped'])
|
||||
Util::addNote(U_GROUP_EMPLOYEE, 'Loot by Item: ungrouped Item/Ref '.$ref['item'].' has 0% chance assigned!');
|
||||
trigger_error('Loot by Item: Ungrouped Item/Ref '.$ref['item'].' has 0% chance assigned!', E_USER_WARNING);
|
||||
|
||||
if ($ref['isGrouped'] && $ref['sumChance'] > 100)
|
||||
Util::addNote(U_GROUP_EMPLOYEE, 'Loot by Item: group with Item/Ref '.$ref['item'].' has '.number_format($ref['sumChance'], 2).'% total chance! Some items cannot drop!');
|
||||
trigger_error('Loot by Item: Group with Item/Ref '.$ref['item'].' has '.number_format($ref['sumChance'], 2).'% total chance! Some items cannot drop!', E_USER_WARNING);
|
||||
|
||||
if ($ref['isGrouped'] && $ref['sumChance'] >= 100 && !$ref['chance'])
|
||||
Util::addNote(U_GROUP_EMPLOYEE, 'Loot by Item: Item/Ref '.$ref['item'].' with adaptive chance cannot drop. Group already at 100%!');
|
||||
trigger_error('Loot by Item: Item/Ref '.$ref['item'].' with adaptive chance cannot drop. Group already at 100%!', E_USER_WARNING);
|
||||
|
||||
$chance = abs($ref['chance'] ?: (100 - $ref['sumChance']) / $ref['nZeroItems']) / 100;
|
||||
|
||||
@@ -505,7 +505,7 @@ class Loot
|
||||
}
|
||||
|
||||
$tabsFinal[$tabId][1][] = array_merge($srcData[$srcObj->id], $result[$srcObj->getField('lootId')]);
|
||||
$tabsFinal[$tabId][4][] = 'Listview.extraCols.percent';
|
||||
$tabsFinal[$tabId][4][] = '$Listview.extraCols.percent';
|
||||
if ($tabId != 15)
|
||||
$tabsFinal[$tabId][6][] = 'skill';
|
||||
}
|
||||
@@ -530,7 +530,7 @@ class Loot
|
||||
|
||||
// achievement part
|
||||
$conditions = array(['itemExtra', $this->entry]);
|
||||
if ($ar = DB::World()->selectCol('SELECT entry FROM achievement_reward WHERE item = ?d{ OR mailTemplate IN (?a)}', $this->entry, $ids ?: DBSIMPLE_SKIP))
|
||||
if ($ar = DB::World()->selectCol('SELECT ID FROM achievement_reward WHERE ItemID = ?d{ OR MailTemplateID IN (?a)}', $this->entry, $ids ?: DBSIMPLE_SKIP))
|
||||
array_push($conditions, ['id', $ar], 'OR');
|
||||
|
||||
$srcObj = new AchievementList($conditions);
|
||||
@@ -563,7 +563,7 @@ class Loot
|
||||
$srcData = $srcObj->getListviewData();
|
||||
|
||||
if (!empty($result))
|
||||
$tabsFinal[16][4][] = 'Listview.extraCols.percent';
|
||||
$tabsFinal[16][4][] = '$Listview.extraCols.percent';
|
||||
|
||||
if ($srcObj->hasSetFields(['reagent1']))
|
||||
$tabsFinal[16][6][] = 'reagents';
|
||||
@@ -601,14 +601,33 @@ class Loot
|
||||
$tabId = abs($tabId); // general case (skinning)
|
||||
|
||||
$tabsFinal[$tabId][1][] = array_merge($srcData[$srcObj->id], $result[$srcObj->getField($field)]);
|
||||
$tabsFinal[$tabId][4][] = 'Listview.extraCols.percent';
|
||||
$tabsFinal[$tabId][4][] = '$Listview.extraCols.percent';
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->results = $tabsFinal;
|
||||
foreach ($tabsFinal as $tabId => $data)
|
||||
{
|
||||
$tabData = array(
|
||||
'data' => $data[1],
|
||||
'name' => $data[2],
|
||||
'id' => $data[3]
|
||||
);
|
||||
|
||||
if ($data[4])
|
||||
$tabData['extraCols'] = array_unique($data[4]);
|
||||
|
||||
if ($data[5])
|
||||
$tabData['hiddenCols'] = array_unique($data[5]);
|
||||
|
||||
if ($data[6])
|
||||
$tabData['visibleCols'] = array_unique($data[6]);
|
||||
|
||||
$this->results[$tabId] = [$data[0], $tabData];
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('invalid access');
|
||||
die('illegal access');
|
||||
|
||||
/*
|
||||
this is just a skeleton for now
|
||||
@@ -14,6 +14,8 @@ class Markup
|
||||
private $text = '';
|
||||
private $jsGlobals = [];
|
||||
|
||||
private static $dbTagPattern = '/(?<!\\\\)\[(npc|object|item|itemset|quest|spell|zone|faction|pet|achievement|statistic|title|event|class|race|skill|currency|emote|enchantment|money|sound|icondb)=(-?\d+)[^\]]*\]/i';
|
||||
|
||||
public function __construct($text)
|
||||
{
|
||||
$this->text = $text;
|
||||
@@ -21,14 +23,37 @@ class Markup
|
||||
|
||||
public function parseGlobalsFromText(&$jsg = [])
|
||||
{
|
||||
if (preg_match_all('/(?<!\\\\)\[(npc|object|item|itemset|quest|spell|zone|faction|pet|achievement|statistic|title|event|class|race|skill|currency)=(\d+)[^\]]*\]/i', $this->text, $matches, PREG_SET_ORDER))
|
||||
if (preg_match_all(self::$dbTagPattern, $this->text, $matches, PREG_SET_ORDER))
|
||||
{
|
||||
foreach ($matches as $match)
|
||||
{
|
||||
if ($match[1] == 'statistic')
|
||||
$match[1] = 'achievement';
|
||||
else if ($match[1] == 'icondb')
|
||||
$match[1] = 'icon';
|
||||
else if ($match[1] == 'money')
|
||||
{
|
||||
if (stripos($match[0], 'items'))
|
||||
{
|
||||
if (preg_match('/items=([0-9,]+)/i', $match[0], $submatch))
|
||||
{
|
||||
$sm = explode(',', $submatch[1]);
|
||||
for ($i = 0; $i < count($sm); $i+=2)
|
||||
$this->jsGlobals[TYPE_ITEM][$sm[$i]] = $sm[$i];
|
||||
}
|
||||
}
|
||||
|
||||
if ($type = array_search($match[1], Util::$typeStrings))
|
||||
if (stripos($match[0], 'currency'))
|
||||
{
|
||||
if (preg_match('/currency=([0-9,]+)/i', $match[0], $submatch))
|
||||
{
|
||||
$sm = explode(',', $submatch[1]);
|
||||
for ($i = 0; $i < count($sm); $i+=2)
|
||||
$this->jsGlobals[TYPE_CURRENCY][$sm[$i]] = $sm[$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($type = array_search($match[1], Util::$typeStrings))
|
||||
$this->jsGlobals[$type][$match[2]] = $match[2];
|
||||
}
|
||||
}
|
||||
@@ -38,6 +63,79 @@ class Markup
|
||||
return $this->jsGlobals;
|
||||
}
|
||||
|
||||
public function stripTags($globals = [])
|
||||
{
|
||||
// since this is an article the db-tags should already be parsed
|
||||
$text = preg_replace_callback(self::$dbTagPattern, function ($match) use ($globals) {
|
||||
if ($match[1] == 'statistic')
|
||||
$match[1] = 'achievement';
|
||||
else if ($match[1] == 'icondb')
|
||||
$match[1] = 'icon';
|
||||
else if ($match[1] == 'money')
|
||||
{
|
||||
$moneys = [];
|
||||
if (stripos($match[0], 'items'))
|
||||
{
|
||||
if (preg_match('/items=([0-9,]+)/i', $match[0], $submatch))
|
||||
{
|
||||
$sm = explode(',', $submatch[1]);
|
||||
for ($i = 0; $i < count($sm); $i += 2)
|
||||
{
|
||||
if (!empty($globals[TYPE_ITEM][1][$sm[$i]]))
|
||||
$moneys[] = $globals[TYPE_ITEM][1][$sm[$i]]['name'];
|
||||
else
|
||||
$moneys[] = Util::ucFirst(Lang::game('item')).' #'.$sm[$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stripos($match[0], 'currency'))
|
||||
{
|
||||
if (preg_match('/currency=([0-9,]+)/i', $match[0], $submatch))
|
||||
{
|
||||
$sm = explode(',', $submatch[1]);
|
||||
for ($i = 0; $i < count($sm); $i += 2)
|
||||
{
|
||||
if (!empty($globals[TYPE_CURRENCY][1][$sm[$i]]))
|
||||
$moneys[] = $globals[TYPE_CURRENCY][1][$sm[$i]]['name'];
|
||||
else
|
||||
$moneys[] = Util::ucFirst(Lang::game('curency')).' #'.$sm[$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Lang::concat($moneys);
|
||||
}
|
||||
|
||||
if ($type = array_search($match[1], Util::$typeStrings))
|
||||
{
|
||||
if (!empty($globals[$type][1][$match[2]]))
|
||||
return $globals[$type][1][$match[2]]['name'];
|
||||
else
|
||||
return Util::ucFirst(Lang::game($match[1])).' #'.$match[2];
|
||||
}
|
||||
|
||||
trigger_error('Markup::stripTags() - encountered unhandled db-tag: '.var_export($match));
|
||||
return '';
|
||||
}, $this->text);
|
||||
|
||||
$text = str_replace('[br]', "\n", $text);
|
||||
$stripped = '';
|
||||
|
||||
$inTag = false;
|
||||
for ($i = 0; $i < strlen($text); $i++)
|
||||
{
|
||||
if ($text[$i] == '[')
|
||||
$inTag = true;
|
||||
if (!$inTag)
|
||||
$stripped .= $text[$i];
|
||||
if ($text[$i] == ']')
|
||||
$inTag = false;
|
||||
}
|
||||
|
||||
return $stripped;
|
||||
}
|
||||
|
||||
public function fromHtml()
|
||||
{
|
||||
}
|
||||
|
||||
828
includes/profiler.class.php
Normal file
828
includes/profiler.class.php
Normal file
@@ -0,0 +1,828 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class Profiler
|
||||
{
|
||||
const PID_FILE = 'config/pr-queue-pid';
|
||||
const CHAR_GMFLAGS = 0x1 | 0x8 | 0x10 | 0x20; // PLAYER_EXTRA_ :: GM_ON | TAXICHEAT | GM_INVISIBLE | GM_CHAT
|
||||
|
||||
private static $realms = [];
|
||||
|
||||
public static $slot2InvType = array(
|
||||
1 => [INVTYPE_HEAD], // head
|
||||
2 => [INVTYPE_NECK], // neck
|
||||
3 => [INVTYPE_SHOULDERS], // shoulder
|
||||
4 => [INVTYPE_BODY], // shirt
|
||||
5 => [INVTYPE_CHEST, INVTYPE_ROBE], // chest
|
||||
6 => [INVTYPE_WAIST], // waist
|
||||
7 => [INVTYPE_LEGS], // legs
|
||||
8 => [INVTYPE_FEET], // feet
|
||||
9 => [INVTYPE_WRISTS], // wrists
|
||||
10 => [INVTYPE_HANDS], // hands
|
||||
11 => [INVTYPE_FINGER], // finger1
|
||||
12 => [INVTYPE_FINGER], // finger2
|
||||
13 => [INVTYPE_TRINKET], // trinket1
|
||||
14 => [INVTYPE_TRINKET], // trinket2
|
||||
15 => [INVTYPE_CLOAK], // chest
|
||||
16 => [INVTYPE_WEAPONMAINHAND, INVTYPE_WEAPON, INVTYPE_2HWEAPON], // mainhand
|
||||
17 => [INVTYPE_WEAPONOFFHAND, INVTYPE_WEAPON, INVTYPE_HOLDABLE, INVTYPE_SHIELD], // offhand
|
||||
18 => [INVTYPE_RANGED, INVTYPE_THROWN, INVTYPE_RELIC], // ranged + relic
|
||||
19 => [INVTYPE_TABARD], // tabard
|
||||
);
|
||||
|
||||
public static $raidProgression = array( // statisticAchievement => relevantCriterium
|
||||
1098 => 3271, // Onyxia's Lair 10
|
||||
1756 => 13345, // Onyxia's Lair 25
|
||||
4031 => 12230, 4034 => 12234, 4038 => 12238, 4042 => 12242, 4046 => 12246, // Trial of the Crusader 25 nh
|
||||
4029 => 12231, 4035 => 12235, 4039 => 12239, 4043 => 12243, 4047 => 12247, // Trial of the Crusader 25 hc
|
||||
4030 => 12229, 4033 => 12233, 4037 => 12237, 4041 => 12241, 4045 => 12245, // Trial of the Crusader 10 hc
|
||||
4028 => 12228, 4032 => 12232, 4036 => 12236, 4040 => 12240, 4044 => 12244, // Trial of the Crusader 10 nh
|
||||
4642 => 13091, 4656 => 13106, 4661 => 13111, 4664 => 13114, 4667 => 13117, 4670 => 13120, 4673 => 13123, 4676 => 13126, 4679 => 13129, 4682 => 13132, 4685 => 13135, 4688 => 13138, // Icecrown Citadel 25 hc
|
||||
4641 => 13092, 4655 => 13105, 4660 => 13109, 4663 => 13112, 4666 => 13115, 4669 => 13118, 4672 => 13121, 4675 => 13124, 4678 => 13127, 4681 => 13130, 4683 => 13133, 4687 => 13136, // Icecrown Citadel 25 nh
|
||||
4640 => 13090, 4654 => 13104, 4659 => 13110, 4662 => 13113, 4665 => 13116, 4668 => 13119, 4671 => 13122, 4674 => 13125, 4677 => 13128, 4680 => 13131, 4684 => 13134, 4686 => 13137, // Icecrown Citadel 10 hc
|
||||
4639 => 13089, 4643 => 13093, 4644 => 13094, 4645 => 13095, 4646 => 13096, 4647 => 13097, 4648 => 13098, 4649 => 13099, 4650 => 13100, 4651 => 13101, 4652 => 13102, 4653 => 13103, // Icecrown Citadel 10 nh
|
||||
// 4823 => 13467, // Ruby Sanctum 25 hc
|
||||
// 4820 => 13465, // Ruby Sanctum 25 nh
|
||||
// 4822 => 13468, // Ruby Sanctum 10 hc
|
||||
// 4821 => 13466, // Ruby Sanctum 10 nh
|
||||
);
|
||||
|
||||
public static function getBuyoutForItem($itemId)
|
||||
{
|
||||
if (!$itemId)
|
||||
return 0;
|
||||
|
||||
// try, when having filled char-DB at hand
|
||||
// return DB::Characters()->selectCell('SELECT SUM(a.buyoutprice) / SUM(ii.count) FROM auctionhouse a JOIN item_instance ii ON ii.guid = a.itemguid WHERE ii.itemEntry = ?d', $itemId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function queueStart(&$msg = '')
|
||||
{
|
||||
$queuePID = self::queueStatus();
|
||||
|
||||
if ($queuePID)
|
||||
{
|
||||
$msg = 'queue already running';
|
||||
return true;
|
||||
}
|
||||
|
||||
if (OS_WIN) // here be gremlins! .. suggested was "start /B php prQueue" as background process. but that closes itself
|
||||
pclose(popen('start php prQueue --log=cache/profiling.log', 'r'));
|
||||
else
|
||||
exec('php prQueue --log=cache/profiling.log > /dev/null 2>/dev/null &');
|
||||
|
||||
usleep(500000);
|
||||
if (self::queueStatus())
|
||||
return true;
|
||||
else
|
||||
{
|
||||
$msg = 'failed to start queue';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function queueStatus()
|
||||
{
|
||||
if (!file_exists(self::PID_FILE))
|
||||
return 0;
|
||||
|
||||
$pid = file_get_contents(self::PID_FILE);
|
||||
$cmd = OS_WIN ? 'tasklist /NH /FO CSV /FI "PID eq %d"' : 'ps --no-headers p %d';
|
||||
|
||||
exec(sprintf($cmd, $pid), $out);
|
||||
if ($out && stripos($out[0], $pid) !== false)
|
||||
return $pid;
|
||||
|
||||
// have pidFile but no process with this pid
|
||||
self::queueFree();
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function queueLock($pid)
|
||||
{
|
||||
$queuePID = self::queueStatus();
|
||||
if ($queuePID && $queuePID != $pid)
|
||||
{
|
||||
trigger_error('pSync - another queue with PID #'.$queuePID.' is already running', E_USER_ERROR);
|
||||
CLI::write('Profiler::queueLock() - another queue with PID #'.$queuePID.' is already runnung', CLI::LOG_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
// no queue running; create or overwrite pidFile
|
||||
$ok = false;
|
||||
if ($fh = fopen(self::PID_FILE, 'w'))
|
||||
{
|
||||
if (fwrite($fh, $pid))
|
||||
$ok = true;
|
||||
|
||||
fclose($fh);
|
||||
}
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
||||
public static function queueFree()
|
||||
{
|
||||
unlink(self::PID_FILE);
|
||||
}
|
||||
|
||||
public static function urlize($str, $allowLocales = false, $profile = false)
|
||||
{
|
||||
$search = ['<', '>', ' / ', "'"];
|
||||
$replace = ['<', '>', '-', '' ];
|
||||
$str = str_replace($search, $replace, $str);
|
||||
|
||||
if ($profile)
|
||||
{
|
||||
$str = str_replace(['(', ')'], ['', ''], $str);
|
||||
$accents = array(
|
||||
"ß" => "ss",
|
||||
"á" => "a", "ä" => "a", "à" => "a", "â" => "a",
|
||||
"è" => "e", "ê" => "e", "é" => "e", "ë" => "e",
|
||||
"í" => "i", "î" => "i", "ì" => "i", "ï" => "i",
|
||||
"ñ" => "n",
|
||||
"ò" => "o", "ó" => "o", "ö" => "o", "ô" => "o",
|
||||
"ú" => "u", "ü" => "u", "û" => "u", "ù" => "u",
|
||||
"œ" => "oe",
|
||||
"Á" => "A", "Ä" => "A", "À" => "A", "Â" => "A",
|
||||
"È" => "E", "Ê" => "E", "É" => "E", "Ë" => "E",
|
||||
"Í" => "I", "Î" => "I", "Ì" => "I", "Ï" => "I",
|
||||
"Ñ" => "N",
|
||||
"Ò" => "O", "Ó" => "O", "Ö" => "O", "Ô" => "O",
|
||||
"Ú" => "U", "Ü" => "U", "Û" => "U", "Ù" => "U",
|
||||
"Œ" => "Oe"
|
||||
);
|
||||
$str = strtr($str, $accents);
|
||||
}
|
||||
|
||||
$str = trim($str);
|
||||
|
||||
if ($allowLocales)
|
||||
$str = str_replace(' ', '-', $str);
|
||||
else
|
||||
$str = preg_replace('/[^a-z0-9]/i', '-', $str);
|
||||
|
||||
$str = str_replace('--', '-', $str);
|
||||
$str = str_replace('--', '-', $str);
|
||||
|
||||
$str = rtrim($str, '-');
|
||||
$str = strtolower($str);
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
public static function getRealms()
|
||||
{
|
||||
if (DB::isConnectable(DB_AUTH) && !self::$realms)
|
||||
{
|
||||
self::$realms = DB::Auth()->select('SELECT id AS ARRAY_KEY, name, IF(timezone IN (8, 9, 10, 11, 12), "eu", "us") AS region FROM realmlist WHERE allowedSecurityLevel = 0 AND gamebuild = ?d', WOW_BUILD);
|
||||
foreach (self::$realms as $rId => $rData)
|
||||
{
|
||||
if (DB::isConnectable(DB_CHARACTERS . $rId))
|
||||
continue;
|
||||
|
||||
// realm in db but no connection info set
|
||||
unset(self::$realms[$rId]);
|
||||
}
|
||||
}
|
||||
|
||||
return self::$realms;
|
||||
}
|
||||
|
||||
private static function queueInsert($realmId, $guid, $type, $localId)
|
||||
{
|
||||
if ($rData = DB::Aowow()->selectRow('SELECT requestTime AS time, status FROM ?_profiler_sync WHERE realm = ?d AND realmGUID = ?d AND `type` = ?d AND typeId = ?d AND status <> ?d', $realmId, $guid, $type, $localId, PR_QUEUE_STATUS_WORKING))
|
||||
{
|
||||
// not on already scheduled - recalc time and set status to PR_QUEUE_STATUS_WAITING
|
||||
if ($rData['status'] != PR_QUEUE_STATUS_WAITING)
|
||||
{
|
||||
$newTime = CFG_DEBUG ? time() : max($rData['time'] + CFG_PROFILER_RESYNC_DELAY, time());
|
||||
DB::Aowow()->query('UPDATE ?_profiler_sync SET requestTime = ?d, status = ?d, errorCode = 0 WHERE realm = ?d AND realmGUID = ?d AND `type` = ?d AND typeId = ?d', $newTime, PR_QUEUE_STATUS_WAITING, $realmId, $guid, $type, $localId);
|
||||
}
|
||||
}
|
||||
else
|
||||
DB::Aowow()->query('REPLACE INTO ?_profiler_sync (realm, realmGUID, `type`, typeId, requestTime, status, errorCode) VALUES (?d, ?d, ?d, ?d, UNIX_TIMESTAMP(), ?d, 0)', $realmId, $guid, $type, $localId, PR_QUEUE_STATUS_WAITING);
|
||||
}
|
||||
|
||||
public static function scheduleResync($type, $realmId, $guid)
|
||||
{
|
||||
$newId = 0;
|
||||
|
||||
switch ($type)
|
||||
{
|
||||
case TYPE_PROFILE:
|
||||
if ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d', $realmId, $guid))
|
||||
self::queueInsert($realmId, $guid, TYPE_PROFILE, $newId);
|
||||
|
||||
break;
|
||||
case TYPE_GUILD:
|
||||
if ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_guild WHERE realm = ?d AND realmGUID = ?d', $realmId, $guid))
|
||||
self::queueInsert($realmId, $guid, TYPE_GUILD, $newId);
|
||||
|
||||
break;
|
||||
case TYPE_ARENA_TEAM:
|
||||
if ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_arena_team WHERE realm = ?d AND realmGUID = ?d', $realmId, $guid))
|
||||
self::queueInsert($realmId, $guid, TYPE_ARENA_TEAM, $newId);
|
||||
|
||||
break;
|
||||
default:
|
||||
trigger_error('scheduling resync for unknown type #'.$type.' omiting..', E_USER_WARNING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!$newId)
|
||||
trigger_error('Profiler::scheduleResync() - tried to resync type #'.$type.' guid #'.$guid.' from realm #'.$realmId.' without preloaded data', E_USER_ERROR);
|
||||
else if (!self::queueStart($msg))
|
||||
trigger_error('Profiler::scheduleResync() - '.$msg, E_USER_ERROR);
|
||||
|
||||
return $newId;
|
||||
}
|
||||
|
||||
public static function resyncStatus($type, array $subjectGUIDs)
|
||||
{
|
||||
$response = [CFG_PROFILER_QUEUE ? 2 : 0]; // in theory you could have multiple queues; used as divisor for: (15 / x) + 2
|
||||
if (!$subjectGUIDs)
|
||||
$response[] = [PR_QUEUE_STATUS_ENDED, 0, 0, PR_QUEUE_ERROR_CHAR];
|
||||
else
|
||||
{
|
||||
// error out all profiles with status WORKING, that are older than 60sec
|
||||
DB::Aowow()->query('UPDATE ?_profiler_sync SET status = ?d, errorCode = ?d WHERE status = ?d AND requestTime < ?d', PR_QUEUE_STATUS_ERROR, PR_QUEUE_ERROR_UNK, PR_QUEUE_STATUS_WORKING, time() - MINUTE);
|
||||
|
||||
$subjectStatus = DB::Aowow()->select('SELECT typeId AS ARRAY_KEY, status, realm FROM ?_profiler_sync WHERE `type` = ?d AND typeId IN (?a)', $type, $subjectGUIDs);
|
||||
$queue = DB::Aowow()->selectCol('SELECT CONCAT(type, ":", typeId) FROM ?_profiler_sync WHERE status = ?d AND requestTime < UNIX_TIMESTAMP() ORDER BY requestTime ASC', PR_QUEUE_STATUS_WAITING);
|
||||
foreach ($subjectGUIDs as $guid)
|
||||
{
|
||||
if (empty($subjectStatus[$guid])) // whelp, thats some error..
|
||||
$response[] = [PR_QUEUE_STATUS_ERROR, 0, 0, PR_QUEUE_ERROR_UNK];
|
||||
else if ($subjectStatus[$guid]['status'] == PR_QUEUE_STATUS_ERROR)
|
||||
$response[] = [PR_QUEUE_STATUS_ERROR, 0, 0, $subjectStatus[$guid]['errCode']];
|
||||
else
|
||||
$response[] = array(
|
||||
$subjectStatus[$guid]['status'],
|
||||
$subjectStatus[$guid]['status'] != PR_QUEUE_STATUS_READY ? CFG_PROFILER_RESYNC_PING : 0,
|
||||
array_search($type.':'.$guid, $queue) + 1,
|
||||
0,
|
||||
1 // nResycTries - unsure about this one
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public static function getCharFromRealm($realmId, $charGuid)
|
||||
{
|
||||
$char = DB::Characters($realmId)->selectRow('SELECT c.* FROM characters c WHERE c.guid = ?d', $charGuid);
|
||||
if (!$char)
|
||||
return false;
|
||||
|
||||
// reminder: this query should not fail: a placeholder entry is created as soon as a char listview is created or profile detail page is called
|
||||
$profileId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d', $realmId, $char['guid']);
|
||||
|
||||
CLI::write('fetching char #'.$charGuid.' from realm #'.$realmId);
|
||||
CLI::write('writing...');
|
||||
|
||||
|
||||
/*************/
|
||||
/* equipment */
|
||||
/*************/
|
||||
|
||||
/* enchantment-Indizes
|
||||
* 0: permEnchant
|
||||
* 3: tempEnchant
|
||||
* 6: gem1
|
||||
* 9: gem2
|
||||
* 12: gem3
|
||||
* 15: socketBonus [not used]
|
||||
* 18: extraSocket [only check existance]
|
||||
* 21 - 30: randomProp enchantments
|
||||
*/
|
||||
|
||||
|
||||
DB::Aowow()->query('DELETE FROM ?_profiler_items WHERE id = ?d', $profileId);
|
||||
$items = DB::Characters($realmId)->select('SELECT ci.slot AS ARRAY_KEY, ii.itemEntry, ii.enchantments, ii.randomPropertyId FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid WHERE ci.guid = ?d AND bag = 0 AND slot BETWEEN 0 AND 18', $char['guid']);
|
||||
|
||||
$gemItems = [];
|
||||
$permEnch = [];
|
||||
$mhItem = 0;
|
||||
$ohItem = 0;
|
||||
|
||||
foreach ($items as $slot => $item)
|
||||
{
|
||||
$ench = explode(' ', $item['enchantments']);
|
||||
$gEnch = [];
|
||||
foreach ([6, 9, 12] as $idx)
|
||||
if ($ench[$idx])
|
||||
$gEnch[$idx] = $ench[$idx];
|
||||
|
||||
if ($gEnch)
|
||||
{
|
||||
$gi = DB::Aowow()->selectCol('SELECT gemEnchantmentId AS ARRAY_KEY, id FROM ?_items WHERE class = 3 AND gemEnchantmentId IN (?a)', $gEnch);
|
||||
foreach ($gEnch as $eId)
|
||||
{
|
||||
if (isset($gemItems[$eId]))
|
||||
$gemItems[$eId][1]++;
|
||||
else
|
||||
$gemItems[$eId] = [$gi[$eId], 1];
|
||||
}
|
||||
}
|
||||
|
||||
if ($slot + 1 == 16)
|
||||
$mhItem = $item['itemEntry'];
|
||||
if ($slot + 1 == 17)
|
||||
$ohItem = $item['itemEntry'];
|
||||
|
||||
if ($ench[0])
|
||||
$permEnch[$slot] = $ench[0];
|
||||
|
||||
$data = array(
|
||||
'id' => $profileId,
|
||||
'slot' => $slot + 1,
|
||||
'item' => $item['itemEntry'],
|
||||
'subItem' => $item['randomPropertyId'],
|
||||
'permEnchant' => $ench[0],
|
||||
'tempEnchant' => $ench[3],
|
||||
'extraSocket' => (int)!!$ench[18],
|
||||
'gem1' => isset($gemItems[$ench[6]]) ? $gemItems[$ench[6]][0] : 0,
|
||||
'gem2' => isset($gemItems[$ench[9]]) ? $gemItems[$ench[9]][0] : 0,
|
||||
'gem3' => isset($gemItems[$ench[12]]) ? $gemItems[$ench[12]][0] : 0,
|
||||
'gem4' => 0 // serverside items cant have more than 3 sockets. (custom profile thing)
|
||||
);
|
||||
|
||||
DB::Aowow()->query('INSERT INTO ?_profiler_items (?#) VALUES (?a)', array_keys($data), array_values($data));
|
||||
}
|
||||
|
||||
CLI::write(' ..inventory');
|
||||
|
||||
|
||||
/**************/
|
||||
/* basic info */
|
||||
/**************/
|
||||
|
||||
$data = array(
|
||||
'realm' => $realmId,
|
||||
'realmGUID' => $charGuid,
|
||||
'name' => $char['name'],
|
||||
'race' => $char['race'],
|
||||
'class' => $char['class'],
|
||||
'level' => $char['level'],
|
||||
'gender' => $char['gender'],
|
||||
'skincolor' => $char['playerBytes'] & 0xFF,
|
||||
'facetype' => ($char['playerBytes'] >> 8) & 0xFF, // maybe features
|
||||
'hairstyle' => ($char['playerBytes'] >> 16) & 0xFF,
|
||||
'haircolor' => ($char['playerBytes'] >> 24) & 0xFF,
|
||||
'features' => $char['playerBytes2'] & 0xFF, // maybe facetype
|
||||
'title' => $char['chosenTitle'] ? DB::Aowow()->selectCell('SELECT id FROM ?_titles WHERE bitIdx = ?d', $char['chosenTitle']) : 0,
|
||||
'playedtime' => $char['totaltime'],
|
||||
'nomodelMask' => ($char['playerFlags'] & 0x400 ? (1 << SLOT_HEAD) : 0) | ($char['playerFlags'] & 0x800 ? (1 << SLOT_BACK) : 0),
|
||||
'talenttree1' => 0,
|
||||
'talenttree2' => 0,
|
||||
'talenttree3' => 0,
|
||||
'talentbuild1' => '',
|
||||
'talentbuild2' => '',
|
||||
'glyphs1' => '',
|
||||
'glyphs2' => '',
|
||||
'activespec' => $char['activespec'],
|
||||
'guild' => null,
|
||||
'guildRank' => null,
|
||||
'gearscore' => 0,
|
||||
'achievementpoints' => 0
|
||||
);
|
||||
|
||||
|
||||
/********************/
|
||||
/* talents + glyphs */
|
||||
/********************/
|
||||
|
||||
$t = DB::Characters($realmId)->selectCol('SELECT spec AS ARRAY_KEY, spell AS ARRAY_KEY2, spell FROM character_talent WHERE guid = ?d', $char['guid']);
|
||||
$g = DB::Characters($realmId)->select('SELECT spec AS ARRAY_KEY, glyph1 AS g1, glyph2 AS g4, glyph3 AS g5, glyph4 AS g2, glyph5 AS g3, glyph6 AS g6 FROM character_glyphs WHERE guid = ?d', $char['guid']);
|
||||
for ($i = 0; $i < 2; $i++)
|
||||
{
|
||||
// talents
|
||||
for ($j = 0; $j < 3; $j++)
|
||||
{
|
||||
$_ = DB::Aowow()->selectCol('SELECT spell AS ARRAY_KEY, MAX(IF(spell in (?a), rank, 0)) FROM ?_talents WHERE class = ?d AND tab = ?d GROUP BY id ORDER BY row, col ASC', !empty($t[$i]) ? $t[$i] : [0], $char['class'], $j);
|
||||
$data['talentbuild'.($i + 1)] .= implode('', $_);
|
||||
if ($char['activespec'] == $i)
|
||||
$data['talenttree'.($j + 1)] = array_sum($_);
|
||||
}
|
||||
|
||||
// glyphs
|
||||
if (isset($g[$i]))
|
||||
{
|
||||
$gProps = [];
|
||||
for ($j = 1; $j <= 6; $j++)
|
||||
if ($g[$i]['g'.$j])
|
||||
$gProps[$j] = $g[$i]['g'.$j];
|
||||
|
||||
if ($gProps)
|
||||
if ($gItems = DB::Aowow()->selectCol('SELECT i.id FROM ?_glyphproperties gp JOIN ?_spell s ON s.effect1MiscValue = gp.id AND s.effect1Id = 74 JOIN ?_items i ON i.class = 16 AND i.spellId1 = s.id WHERE gp.id IN (?a)', $gProps))
|
||||
$data['glyphs'.($i + 1)] = implode(':', $gItems);
|
||||
}
|
||||
}
|
||||
|
||||
$t = array(
|
||||
'spent' => [$data['talenttree1'], $data['talenttree2'], $data['talenttree3']],
|
||||
'spec' => 0
|
||||
);
|
||||
if ($t['spent'][0] > $t['spent'][1] && $t['spent'][0] > $t['spent'][2])
|
||||
$t['spec'] = 1;
|
||||
else if ($t['spent'][1] > $t['spent'][0] && $t['spent'][1] > $t['spent'][2])
|
||||
$t['spec'] = 2;
|
||||
else if ($t['spent'][2] > $t['spent'][1] && $t['spent'][2] > $t['spent'][0])
|
||||
$t['spec'] = 3;
|
||||
|
||||
// calc gearscore
|
||||
if ($items)
|
||||
$data['gearscore'] += (new ItemList(array(['id', array_column($items, 'itemEntry')])))->getScoreTotal($data['class'], $t, $mhItem, $ohItem);
|
||||
|
||||
if ($gemItems)
|
||||
{
|
||||
$gemScores = new ItemList(array(['id', array_column($gemItems, 0)]));
|
||||
foreach ($gemItems as list($itemId, $mult))
|
||||
if (isset($gemScores->json[$itemId]['gearscore']))
|
||||
$data['gearscore'] += $gemScores->json[$itemId]['gearscore'] * $mult;
|
||||
}
|
||||
|
||||
if ($permEnch) // fuck this shit .. we are guestimating this!
|
||||
{
|
||||
// enchantId => multiple spells => multiple items with varying itemlevels, quality, whatevs
|
||||
// cant reasonably get to the castItem from enchantId and slot
|
||||
|
||||
$profSpec = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, skillLevel AS "1", skillLine AS "0" FROM ?_itemenchantment WHERE id IN (?a)', $permEnch);
|
||||
foreach ($permEnch as $eId)
|
||||
{
|
||||
if ($x = Util::getEnchantmentScore(0, 0, !!$profSpec[$eId][1], $eId))
|
||||
$data['gearscore'] += $x;
|
||||
else if ($profSpec[$eId][0] != 776) // not runeforging
|
||||
$data['gearscore'] += 17; // assume high quality enchantment for unknown cases
|
||||
}
|
||||
}
|
||||
|
||||
$data['lastupdated'] = time();
|
||||
|
||||
CLI::write(' ..basic info');
|
||||
|
||||
|
||||
/***************/
|
||||
/* hunter pets */
|
||||
/***************/
|
||||
|
||||
if ((1 << ($char['class'] - 1)) == CLASS_HUNTER)
|
||||
{
|
||||
DB::Aowow()->query('DELETE FROM ?_profiler_pets WHERE owner = ?d', $profileId);
|
||||
$pets = DB::Characters($realmId)->select('SELECT id AS ARRAY_KEY, id, entry, modelId, name FROM character_pet WHERE owner = ?d', $charGuid);
|
||||
foreach ($pets as $petGuid => $petData)
|
||||
{
|
||||
$morePet = DB::Aowow()->selectRow('SELECT p.`type`, c.family FROM ?_pet p JOIN ?_creature c ON c.family = p.id WHERE c.id = ?d', $petData['entry']);
|
||||
$petSpells = DB::Characters($realmId)->selectCol('SELECT spell FROM pet_spell WHERE guid = ?d', $petGuid);
|
||||
|
||||
$_ = DB::Aowow()->selectCol('SELECT spell AS ARRAY_KEY, MAX(IF(spell in (?a), rank, 0)) FROM ?_talents WHERE class = 0 AND petTypeMask = ?d GROUP BY id ORDER BY row, col ASC', $petSpells ?: [0], 1 << $morePet['type']);
|
||||
$pet = array(
|
||||
'id' => $petGuid,
|
||||
'owner' => $profileId,
|
||||
'name' => $petData['name'],
|
||||
'family' => $morePet['family'],
|
||||
'npc' => $petData['entry'],
|
||||
'displayId' => $petData['modelId'],
|
||||
'talents' => implode('', $_)
|
||||
);
|
||||
|
||||
DB::Aowow()->query('INSERT INTO ?_profiler_pets (?#) VALUES (?a)', array_keys($pet), array_values($pet));
|
||||
}
|
||||
|
||||
CLI::write(' ..hunter pets');
|
||||
}
|
||||
|
||||
|
||||
/*******************/
|
||||
/* completion data */
|
||||
/*******************/
|
||||
|
||||
DB::Aowow()->query('DELETE FROM ?_profiler_completion WHERE id = ?d', $profileId);
|
||||
|
||||
// done quests
|
||||
if ($quests = DB::Characters($realmId)->select('SELECT ?d AS id, ?d AS `type`, quest AS typeId FROM character_queststatus_rewarded WHERE guid = ?d', $profileId, TYPE_QUEST, $char['guid']))
|
||||
foreach (Util::createSqlBatchInsert($quests) as $q)
|
||||
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$q, array_keys($quests[0]));
|
||||
|
||||
CLI::write(' ..quests');
|
||||
|
||||
|
||||
// known skills (professions only)
|
||||
$skAllowed = DB::Aowow()->selectCol('SELECT id FROM ?_skillline WHERE typeCat IN (9, 11) AND (cuFlags & ?d) = 0', CUSTOM_EXCLUDE_FOR_LISTVIEW);
|
||||
$skills = DB::Characters($realmId)->select('SELECT ?d AS id, ?d AS `type`, skill AS typeId, `value` AS cur, max FROM character_skills WHERE guid = ?d AND skill IN (?a)', $profileId, TYPE_SKILL, $char['guid'], $skAllowed);
|
||||
|
||||
// manually apply racial profession bonuses
|
||||
foreach ($skills as &$sk)
|
||||
{
|
||||
// Blood Elves - Arcane Affinity
|
||||
if ($sk['typeId'] == 333 && $char['race'] == 10)
|
||||
{
|
||||
$sk['cur'] += 10;
|
||||
$sk['max'] += 10;
|
||||
}
|
||||
// Draenei - Gemcutting
|
||||
if ($sk['typeId'] == 755 && $char['race'] == 11)
|
||||
{
|
||||
$sk['cur'] += 5;
|
||||
$sk['max'] += 5;
|
||||
}
|
||||
// Tauren - Cultivation
|
||||
// Gnomes - Engineering Specialization
|
||||
if (($sk['typeId'] == 182 && $char['race'] == 6) ||
|
||||
($sk['typeId'] == 202 && $char['race'] == 7))
|
||||
{
|
||||
$sk['cur'] += 15;
|
||||
$sk['max'] += 15;
|
||||
}
|
||||
}
|
||||
unset($sk);
|
||||
|
||||
if ($skills)
|
||||
foreach (Util::createSqlBatchInsert($skills) as $sk)
|
||||
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$sk, array_keys($skills[0]));
|
||||
|
||||
CLI::write(' ..professions');
|
||||
|
||||
|
||||
// reputation
|
||||
if ($reputation = DB::Characters($realmId)->select('SELECT ?d AS id, ?d AS `type`, faction AS typeId, standing AS cur FROM character_reputation WHERE guid = ?d AND (flags & 0xC) = 0', $profileId, TYPE_FACTION, $char['guid']))
|
||||
foreach (Util::createSqlBatchInsert($reputation) as $rep)
|
||||
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$rep, array_keys($reputation[0]));
|
||||
|
||||
CLI::write(' ..reputation');
|
||||
|
||||
|
||||
// known titles
|
||||
$tBlocks = explode(' ', $char['knownTitles']);
|
||||
$indizes = [];
|
||||
for ($i = 0; $i < 6; $i++)
|
||||
for ($j = 0; $j < 32; $j++)
|
||||
if ($tBlocks[$i] & (1 << $j))
|
||||
$indizes[] = $j + ($i * 32);
|
||||
|
||||
if ($indizes)
|
||||
DB::Aowow()->query('INSERT INTO ?_profiler_completion SELECT ?d, ?d, id, NULL, NULL FROM ?_titles WHERE bitIdx IN (?a)', $profileId, TYPE_TITLE, $indizes);
|
||||
|
||||
CLI::write(' ..titles');
|
||||
|
||||
|
||||
// achievements
|
||||
if ($achievements = DB::Characters($realmId)->select('SELECT ?d AS id, ?d AS `type`, achievement AS typeId, date AS cur FROM character_achievement WHERE guid = ?d', $profileId, TYPE_ACHIEVEMENT, $char['guid']))
|
||||
{
|
||||
foreach (Util::createSqlBatchInsert($achievements) as $a)
|
||||
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$a, array_keys($achievements[0]));
|
||||
|
||||
$data['achievementpoints'] = DB::Aowow()->selectCell('SELECT SUM(points) FROM ?_achievement WHERE id IN (?a)', array_column($achievements, 'typeId'));
|
||||
}
|
||||
|
||||
CLI::write(' ..achievements');
|
||||
|
||||
|
||||
// raid progression
|
||||
if ($progress = DB::Characters($realmId)->select('SELECT ?d AS id, ?d AS `type`, criteria AS typeId, date AS cur, counter AS `max` FROM character_achievement_progress WHERE guid = ?d AND criteria IN (?a)', $profileId, TYPE_ACHIEVEMENT, $char['guid'], self::$raidProgression))
|
||||
{
|
||||
array_walk($progress, function (&$val) { $val['typeId'] = array_search($val['typeId'], self::$raidProgression); });
|
||||
foreach (Util::createSqlBatchInsert($progress) as $p)
|
||||
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$p, array_keys($progress[0]));
|
||||
}
|
||||
|
||||
CLI::write(' ..raid progression');
|
||||
|
||||
|
||||
// known spells
|
||||
if ($spells = DB::Characters($realmId)->select('SELECT ?d AS id, ?d AS `type`, spell AS typeId FROM character_spell WHERE guid = ?d AND disabled = 0', $profileId, TYPE_SPELL, $char['guid']))
|
||||
foreach (Util::createSqlBatchInsert($spells) as $s)
|
||||
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$s, array_keys($spells[0]));
|
||||
|
||||
CLI::write(' ..known spells (vanity pets & mounts)');
|
||||
|
||||
|
||||
/****************/
|
||||
/* related data */
|
||||
/****************/
|
||||
|
||||
// guilds
|
||||
if ($guild = DB::Characters($realmId)->selectRow('SELECT g.name AS name, g.guildid AS id, gm.rank FROM guild_member gm JOIN guild g ON g.guildid = gm.guildid WHERE gm.guid = ?d', $char['guid']))
|
||||
{
|
||||
$guildId = 0;
|
||||
if (!($guildId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_guild WHERE realm = ?d AND realmGUID = ?d', $realmId, $guild['id'])))
|
||||
{
|
||||
$gData = array( // only most basic data
|
||||
'realm' => $realmId,
|
||||
'realmGUID' => $guild['id'],
|
||||
'name' => $guild['name'],
|
||||
'nameUrl' => self::urlize($guild['name']),
|
||||
'cuFlags' => PROFILER_CU_NEEDS_RESYNC
|
||||
);
|
||||
|
||||
$guildId = DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_guild (?#) VALUES (?a)', array_keys($gData), array_values($gData));
|
||||
}
|
||||
|
||||
$data['guild'] = $guildId;
|
||||
$data['guildRank'] = $guild['rank'];
|
||||
}
|
||||
|
||||
|
||||
// arena teams
|
||||
$teams = DB::Characters($realmId)->select('SELECT at.arenaTeamId AS ARRAY_KEY, at.name, at.type, IF(at.captainGuid = atm.guid, 1, 0) AS captain, atm.* FROM arena_team at JOIN arena_team_member atm ON atm.arenaTeamId = at.arenaTeamId WHERE atm.guid = ?d', $char['guid']);
|
||||
foreach ($teams as $rGuid => $t)
|
||||
{
|
||||
$teamId = 0;
|
||||
if (!($teamId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_arena_team WHERE realm = ?d AND realmGUID = ?d', $realmId, $rGuid)))
|
||||
{
|
||||
$team = array( // only most basic data
|
||||
'realm' => $realmId,
|
||||
'realmGUID' => $rGuid,
|
||||
'name' => $t['name'],
|
||||
'nameUrl' => self::urlize($t['name']),
|
||||
'type' => $t['type'],
|
||||
'cuFlags' => PROFILER_CU_NEEDS_RESYNC
|
||||
);
|
||||
|
||||
$teamId = DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_arena_team (?#) VALUES (?a)', array_keys($team), array_values($team));
|
||||
}
|
||||
|
||||
$member = array(
|
||||
'arenaTeamId' => $teamId,
|
||||
'profileId' => $profileId,
|
||||
'captain' => $t['captain'],
|
||||
'weekGames' => $t['weekGames'],
|
||||
'weekWins' => $t['weekWins'],
|
||||
'seasonGames' => $t['seasonGames'],
|
||||
'seasonWins' => $t['seasonWins'],
|
||||
'personalRating' => $t['personalRating']
|
||||
);
|
||||
|
||||
DB::Aowow()->query('INSERT INTO ?_profiler_arena_team_member (?#) VALUES (?a) ON DUPLICATE KEY UPDATE ?a', array_keys($member), array_values($member), array_slice($member, 2));
|
||||
}
|
||||
|
||||
CLI::write(' ..associated arena teams');
|
||||
|
||||
/*********************/
|
||||
/* mark char as done */
|
||||
/*********************/
|
||||
|
||||
if (DB::Aowow()->query('UPDATE ?_profiler_profiles SET ?a WHERE realm = ?d AND realmGUID = ?d', $data, $realmId, $charGuid) !== null)
|
||||
DB::Aowow()->query('UPDATE ?_profiler_profiles SET cuFlags = cuFlags & ?d WHERE id = ?d', ~PROFILER_CU_NEEDS_RESYNC, $profileId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getGuildFromRealm($realmId, $guildGuid)
|
||||
{
|
||||
$guild = DB::Characters($realmId)->selectRow('SELECT guildId, name, createDate, info, backgroundColor, emblemStyle, emblemColor, borderStyle, borderColor FROM guild WHERE guildId = ?d', $guildGuid);
|
||||
if (!$guild)
|
||||
return false;
|
||||
|
||||
// reminder: this query should not fail: a placeholder entry is created as soon as a team listview is created or team detail page is called
|
||||
$guildId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_guild WHERE realm = ?d AND realmGUID = ?d', $realmId, $guild['guildId']);
|
||||
|
||||
CLI::write('fetching guild #'.$guildGuid.' from realm #'.$realmId);
|
||||
CLI::write('writing...');
|
||||
|
||||
|
||||
/**************/
|
||||
/* Guild Data */
|
||||
/**************/
|
||||
|
||||
unset($guild['guildId']);
|
||||
$guild['nameUrl'] = self::urlize($guild['name']);
|
||||
|
||||
DB::Aowow()->query('UPDATE ?_profiler_guild SET ?a WHERE realm = ?d AND realmGUID = ?d', $guild, $realmId, $guildGuid);
|
||||
|
||||
// ranks
|
||||
DB::Aowow()->query('DELETE FROM ?_profiler_guild_rank WHERE guildId = ?d', $guildId);
|
||||
if ($ranks = DB::Characters($realmId)->select('SELECT ?d AS guildId, rid AS rank, rname AS name FROM guild_rank WHERE guildid = ?d', $guildId, $guildGuid))
|
||||
foreach (Util::createSqlBatchInsert($ranks) as $r)
|
||||
DB::Aowow()->query('INSERT INTO ?_profiler_guild_rank (?#) VALUES '.$r, array_keys(reset($ranks)));
|
||||
|
||||
CLI::write(' ..guild data');
|
||||
|
||||
|
||||
/***************/
|
||||
/* Member Data */
|
||||
/***************/
|
||||
|
||||
$conditions = array(
|
||||
['g.guildid', $guildGuid],
|
||||
['deleteInfos_Account', null],
|
||||
['level', MAX_LEVEL, '<='], // prevents JS errors
|
||||
[['extra_flags', self::CHAR_GMFLAGS, '&'], 0] // not a staff char
|
||||
);
|
||||
|
||||
// this here should all happen within ProfileList
|
||||
$members = new RemoteProfileList($conditions, ['sv' => $realmId]);
|
||||
if (!$members->error)
|
||||
$members->initializeLocalEntries();
|
||||
else
|
||||
return false;
|
||||
|
||||
CLI::write(' ..guild members');
|
||||
|
||||
|
||||
/*********************/
|
||||
/* mark guild as done */
|
||||
/*********************/
|
||||
|
||||
DB::Aowow()->query('UPDATE ?_profiler_guild SET cuFlags = cuFlags & ?d WHERE id = ?d', ~PROFILER_CU_NEEDS_RESYNC, $guildId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getArenaTeamFromRealm($realmId, $teamGuid)
|
||||
{
|
||||
$team = DB::Characters($realmId)->selectRow('SELECT arenaTeamId, name, type, captainGuid, rating, seasonGames, seasonWins, weekGames, weekWins, rank, backgroundColor, emblemStyle, emblemColor, borderStyle, borderColor FROM arena_team WHERE arenaTeamId = ?d', $teamGuid);
|
||||
if (!$team)
|
||||
return false;
|
||||
|
||||
// reminder: this query should not fail: a placeholder entry is created as soon as a team listview is created or team detail page is called
|
||||
$teamId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_arena_team WHERE realm = ?d AND realmGUID = ?d', $realmId, $team['arenaTeamId']);
|
||||
|
||||
CLI::write('fetching arena team #'.$teamGuid.' from realm #'.$realmId);
|
||||
CLI::write('writing...');
|
||||
|
||||
|
||||
/*************/
|
||||
/* Team Data */
|
||||
/*************/
|
||||
|
||||
$captain = $team['captainGuid'];
|
||||
unset($team['captainGuid']);
|
||||
unset($team['arenaTeamId']);
|
||||
$team['nameUrl'] = self::urlize($team['name']);
|
||||
|
||||
DB::Aowow()->query('UPDATE ?_profiler_arena_team SET ?a WHERE realm = ?d AND realmGUID = ?d', $team, $realmId, $teamGuid);
|
||||
|
||||
CLI::write(' ..team data');
|
||||
|
||||
|
||||
/***************/
|
||||
/* Member Data */
|
||||
/***************/
|
||||
|
||||
$members = DB::Characters($realmId)->select('
|
||||
SELECT
|
||||
atm.guid AS ARRAY_KEY, atm.arenaTeamId, atm.weekGames, atm.weekWins, atm.seasonGames, atm.seasonWins, atm.personalrating
|
||||
FROM
|
||||
arena_team_member atm
|
||||
JOIN
|
||||
characters c ON c.guid = atm.guid AND
|
||||
c.deleteInfos_Account IS NULL AND
|
||||
c.level <= ?d AND
|
||||
(c.extra_flags & ?d) = 0
|
||||
WHERE
|
||||
arenaTeamId = ?d',
|
||||
MAX_LEVEL,
|
||||
self::CHAR_GMFLAGS,
|
||||
$teamGuid
|
||||
);
|
||||
|
||||
$conditions = array(
|
||||
['c.guid', array_keys($members)],
|
||||
['deleteInfos_Account', null],
|
||||
['level', MAX_LEVEL, '<='], // prevents JS errors
|
||||
[['extra_flags', self::CHAR_GMFLAGS, '&'], 0] // not a staff char
|
||||
);
|
||||
|
||||
$mProfiles = new RemoteProfileList($conditions, ['sv' => $realmId]);
|
||||
if (!$mProfiles->error)
|
||||
{
|
||||
$mProfiles->initializeLocalEntries();
|
||||
foreach ($mProfiles->iterate() as $__)
|
||||
{
|
||||
|
||||
$mGuid = $mProfiles->getField('guid');
|
||||
|
||||
$members[$mGuid]['arenaTeamId'] = $teamId;
|
||||
$members[$mGuid]['captain'] = (int)($mGuid == $captain);
|
||||
$members[$mGuid]['profileId'] = $mProfiles->getField('id');
|
||||
}
|
||||
|
||||
DB::Aowow()->query('DELETE FROM ?_profiler_arena_team_member WHERE arenaTeamId = ?d', $teamId);
|
||||
|
||||
foreach (Util::createSqlBatchInsert($members) as $m)
|
||||
DB::Aowow()->query('INSERT INTO ?_profiler_arena_team_member (?#) VALUES '.$m, array_keys(reset($members)));
|
||||
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
CLI::write(' ..team members');
|
||||
|
||||
/*********************/
|
||||
/* mark team as done */
|
||||
/*********************/
|
||||
|
||||
DB::Aowow()->query('UPDATE ?_profiler_arena_team SET cuFlags = cuFlags & ?d WHERE id = ?d', ~PROFILER_CU_NEEDS_RESYNC, $teamId);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,26 +1,26 @@
|
||||
<?php
|
||||
|
||||
define('AOWOW_REVISION', 1);
|
||||
define('CLI', PHP_SAPI === 'cli');
|
||||
|
||||
|
||||
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring'];
|
||||
$error = '';
|
||||
foreach ($reqExt as $r)
|
||||
if (!extension_loaded($r))
|
||||
$error .= 'Required Extension <b>'.$r."</b> was not found. Please check if it should exist, using \"<i>php -m</i>\"\n\n";
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.5.0') < 0)
|
||||
$error .= 'PHP Version <b>5.5.0</b> or higher required! Your version is <b>'.PHP_VERSION."</b>.\nCore functions are unavailable!\n";
|
||||
|
||||
if ($error)
|
||||
{
|
||||
echo CLI ? strip_tags($error) : $error;
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
// include all necessities, set up basics
|
||||
require_once 'includes/kernel.php';
|
||||
|
||||
?>
|
||||
<?php
|
||||
|
||||
define('AOWOW_REVISION', 27);
|
||||
define('CLI', PHP_SAPI === 'cli');
|
||||
|
||||
|
||||
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo'];
|
||||
$error = '';
|
||||
foreach ($reqExt as $r)
|
||||
if (!extension_loaded($r))
|
||||
$error .= 'Required Extension <b>'.$r."</b> was not found. Please check if it should exist, using \"<i>php -m</i>\"\n\n";
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.5.0') < 0)
|
||||
$error .= 'PHP Version <b>5.5.0</b> or higher required! Your version is <b>'.PHP_VERSION."</b>.\nCore functions are unavailable!\n";
|
||||
|
||||
if ($error)
|
||||
{
|
||||
echo CLI ? strip_tags($error) : $error;
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
// include all necessities, set up basics
|
||||
require_once 'includes/kernel.php';
|
||||
|
||||
?>
|
||||
|
||||
Submodule includes/tools/BLPConverter deleted from 7217e13598
Submodule includes/tools/MPQExtractor deleted from 32c72bb5f0
@@ -8,17 +8,18 @@ class AchievementList extends BaseType
|
||||
{
|
||||
use listviewHelper;
|
||||
|
||||
public static $type = TYPE_ACHIEVEMENT;
|
||||
public static $brickFile = 'achievement';
|
||||
public static $type = TYPE_ACHIEVEMENT;
|
||||
public static $brickFile = 'achievement';
|
||||
public static $dataTable = '?_achievement';
|
||||
|
||||
public $criteria = [];
|
||||
public $criteria = [];
|
||||
|
||||
protected $queryBase = 'SELECT `a`.*, `a`.`id` AS ARRAY_KEY FROM ?_achievement a';
|
||||
protected $queryOpts = array(
|
||||
'a' => [['si'], 'o' => 'orderInGroup ASC'],
|
||||
'si' => ['j' => ['?_icons si ON si.id = a.iconId', true], 's' => ', si.iconString'],
|
||||
'ac' => ['j' => ['?_achievementcriteria AS `ac` ON `ac`.`refAchievementId` = `a`.`id`', true], 'g' => '`a`.`id`']
|
||||
);
|
||||
protected $queryBase = 'SELECT `a`.*, `a`.`id` AS ARRAY_KEY FROM ?_achievement a';
|
||||
protected $queryOpts = array(
|
||||
'a' => [['ic'], 'o' => 'orderInGroup ASC'],
|
||||
'ic' => ['j' => ['?_icons ic ON ic.id = a.iconId', true], 's' => ', ic.name AS iconString'],
|
||||
'ac' => ['j' => ['?_achievementcriteria AS `ac` ON `ac`.`refAchievementId` = `a`.`id`', true], 'g' => '`a`.`id`']
|
||||
);
|
||||
|
||||
/*
|
||||
todo: evaluate TC custom-data-tables: a*_criteria_data should be merged on installation
|
||||
@@ -33,7 +34,22 @@ class AchievementList extends BaseType
|
||||
|
||||
// post processing
|
||||
$rewards = DB::World()->select('
|
||||
SELECT ar.entry AS ARRAY_KEY, ar.*, lar.* FROM achievement_reward ar LEFT JOIN locales_achievement_reward lar ON lar.entry = ar.entry WHERE ar.entry IN (?a)',
|
||||
SELECT
|
||||
ar.ID AS ARRAY_KEY, ar.TitleA, ar.TitleH, ar.ItemID, ar.Sender AS sender, ar.MailTemplateID,
|
||||
ar.Subject AS subject_loc0, IFNULL(arl2.Subject, "") AS subject_loc2, IFNULL(arl3.Subject, "") AS subject_loc3, IFNULL(arl6.Subject, "") AS subject_loc6, IFNULL(arl8.Subject, "") AS subject_loc8,
|
||||
ar.Text AS text_loc0, IFNULL(arl2.Text, "") AS text_loc2, IFNULL(arl3.Text, "") AS text_loc3, IFNULL(arl6.Text, "") AS text_loc6, IFNULL(arl8.Text, "") AS text_loc8
|
||||
FROM
|
||||
achievement_reward ar
|
||||
LEFT JOIN
|
||||
achievement_reward_locale arl2 ON arl2.ID = ar.ID AND arl2.Locale = "frFR"
|
||||
LEFT JOIN
|
||||
achievement_reward_locale arl3 ON arl3.ID = ar.ID AND arl3.Locale = "deDE"
|
||||
LEFT JOIN
|
||||
achievement_reward_locale arl6 ON arl6.ID = ar.ID AND arl6.Locale = "esES"
|
||||
LEFT JOIN
|
||||
achievement_reward_locale arl8 ON arl8.ID = ar.ID AND arl8.Locale = "ruRU"
|
||||
WHERE
|
||||
ar.ID IN (?a)',
|
||||
$this->getFoundIDs()
|
||||
);
|
||||
|
||||
@@ -45,7 +61,7 @@ class AchievementList extends BaseType
|
||||
{
|
||||
$_curTpl = array_merge($rewards[$_id], $_curTpl);
|
||||
|
||||
if ($rewards[$_id]['mailTemplate'])
|
||||
if ($rewards[$_id]['MailTemplateID'])
|
||||
{
|
||||
// using class Loot creates an inifinite loop cirling between Loot, ItemList and SpellList or something
|
||||
// $mailSrc = new Loot();
|
||||
@@ -54,22 +70,22 @@ class AchievementList extends BaseType
|
||||
// $_curTpl['rewards'][] = [TYPE_ITEM, $loot['id']];
|
||||
|
||||
// lets just assume for now, that mailRewards for achievements do not contain references
|
||||
$mailRew = DB::World()->selectCol('SELECT Item FROM mail_loot_template WHERE Reference <= 0 AND entry = ?d', $rewards[$_id]['mailTemplate']);
|
||||
$mailRew = DB::World()->selectCol('SELECT Item FROM mail_loot_template WHERE Reference <= 0 AND entry = ?d', $rewards[$_id]['MailTemplateID']);
|
||||
foreach ($mailRew AS $mr)
|
||||
$_curTpl['rewards'][] = [TYPE_ITEM, $mr];
|
||||
}
|
||||
}
|
||||
|
||||
//"rewards":[[11,137],[3,138]] [type, typeId]
|
||||
if (!empty($_curTpl['item']))
|
||||
$_curTpl['rewards'][] = [TYPE_ITEM, $_curTpl['item']];
|
||||
if (!empty($_curTpl['ItemID']))
|
||||
$_curTpl['rewards'][] = [TYPE_ITEM, $_curTpl['ItemID']];
|
||||
if (!empty($_curTpl['itemExtra']))
|
||||
$_curTpl['rewards'][] = [TYPE_ITEM, $_curTpl['itemExtra']];
|
||||
if (!empty($_curTpl['title_A']))
|
||||
$_curTpl['rewards'][] = [TYPE_TITLE, $_curTpl['title_A']];
|
||||
if (!empty($_curTpl['title_H']))
|
||||
if (empty($_curTpl['title_A']) || $_curTpl['title_A'] != $_curTpl['title_H'])
|
||||
$_curTpl['rewards'][] = [TYPE_TITLE, $_curTpl['title_H']];
|
||||
if (!empty($_curTpl['TitleA']))
|
||||
$_curTpl['rewards'][] = [TYPE_TITLE, $_curTpl['TitleA']];
|
||||
if (!empty($_curTpl['TitleH']))
|
||||
if (empty($_curTpl['TitleA']) || $_curTpl['TitleA'] != $_curTpl['TitleH'])
|
||||
$_curTpl['rewards'][] = [TYPE_TITLE, $_curTpl['TitleH']];
|
||||
|
||||
// icon
|
||||
$_curTpl['iconString'] = $_curTpl['iconString'] ?: 'trade_engineering';
|
||||
@@ -206,10 +222,12 @@ class AchievementList extends BaseType
|
||||
break;
|
||||
}
|
||||
|
||||
$criteria .= '<!--cr'.$crt['id'].':'.$crt['type'].':'.$crt['value1'].'-->- '.Util::jsEscape($crtName);
|
||||
|
||||
if ($crt['completionFlags'] & ACHIEVEMENT_CRITERIA_FLAG_MONEY_COUNTER)
|
||||
$criteria .= '- '.Util::jsEscape($crtName).' <span class="moneygold">'.number_format($crt['value2' ] / 10000).'</span><br />';
|
||||
else
|
||||
$criteria .= '- '.Util::jsEscape($crtName).'<br />';
|
||||
$criteria .= ' <span class="moneygold">'.Lang::nf($crt['value2' ] / 10000).'</span>';
|
||||
|
||||
$criteria .= '<br />';
|
||||
|
||||
if (++$i == round(count($rows)/2))
|
||||
$criteria .= '</small></td><th class="q0" style="white-space: nowrap; text-align: left"><small>';
|
||||
@@ -278,62 +296,42 @@ class AchievementListFilter extends Filter
|
||||
321 => -1, 424 => -1, 301 => -1
|
||||
)
|
||||
);
|
||||
|
||||
protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet
|
||||
2 => [FILTER_CR_BOOLEAN, 'reward_loc0', true ], // givesreward
|
||||
3 => [FILTER_CR_STRING, 'reward', true ], // rewardtext
|
||||
7 => [FILTER_CR_BOOLEAN, 'chainId', ], // partseries
|
||||
9 => [FILTER_CR_NUMERIC, 'id', null, true], // id
|
||||
10 => [FILTER_CR_STRING, 'si.iconString', ], // icon
|
||||
18 => [FILTER_CR_STAFFFLAG, 'flags', ], // flags
|
||||
14 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||
15 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
||||
16 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
||||
2 => [FILTER_CR_BOOLEAN, 'reward_loc0', true ], // givesreward
|
||||
3 => [FILTER_CR_STRING, 'reward', STR_LOCALIZED ], // rewardtext
|
||||
4 => [FILTER_CR_NYI_PH, null, 1, ], // location [enum]
|
||||
5 => [FILTER_CR_CALLBACK, 'cbSeries', ACHIEVEMENT_CU_FIRST_SERIES, null], // first in series [yn]
|
||||
6 => [FILTER_CR_CALLBACK, 'cbSeries', ACHIEVEMENT_CU_LAST_SERIES, null], // last in series [yn]
|
||||
7 => [FILTER_CR_BOOLEAN, 'chainId', ], // partseries
|
||||
9 => [FILTER_CR_NUMERIC, 'id', NUM_CAST_INT, true], // id
|
||||
10 => [FILTER_CR_STRING, 'ic.name', ], // icon
|
||||
11 => [FILTER_CR_CALLBACK, 'cbRelEvent', null, null], // related event [enum]
|
||||
14 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||
15 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
||||
16 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
||||
18 => [FILTER_CR_STAFFFLAG, 'flags', ] // flags
|
||||
);
|
||||
|
||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||
protected $inputFields = array(
|
||||
'cr' => [FILTER_V_RANGE, [2, 18], true ], // criteria ids
|
||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 99999]], true ], // criteria operators
|
||||
'crv' => [FILTER_V_REGEX, '/[\p{C};:]/ui', true ], // criteria values - only printable chars, no delimiters
|
||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name / description - only printable chars, no delimiter
|
||||
'ex' => [FILTER_V_EQUAL, 'on', false], // extended name search
|
||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||
'si' => [FILTER_V_LIST, [1, 2, 3, -1, -2], false], // side
|
||||
'minpt' => [FILTER_V_RANGE, [1, 99], false], // required level min
|
||||
'maxpt' => [FILTER_V_RANGE, [1, 99], false] // required level max
|
||||
);
|
||||
|
||||
protected function createSQLForCriterium(&$cr)
|
||||
{
|
||||
if (in_array($cr[0], array_keys($this->genericFilter)))
|
||||
{
|
||||
if ($genCr = $this->genericCriterion($cr))
|
||||
return $genCr;
|
||||
|
||||
unset($cr);
|
||||
$this->error = true;
|
||||
return [1];
|
||||
}
|
||||
|
||||
switch ($cr[0])
|
||||
{
|
||||
case 4: // location [enum]
|
||||
/* todo */ return [1]; // no plausible locations parsed yet
|
||||
case 5: // first in series [yn]
|
||||
if ($this->int2Bool($cr[1]))
|
||||
return $cr[1] ? ['AND', ['chainId', 0, '!'], ['cuFlags', ACHIEVEMENT_CU_FIRST_SERIES, '&']] : ['AND', ['chainId', 0, '!'], [['cuFlags', ACHIEVEMENT_CU_FIRST_SERIES, '&'], 0]];
|
||||
|
||||
break;
|
||||
case 6: // last in series [yn]
|
||||
if ($this->int2Bool($cr[1]))
|
||||
return $cr[1] ? ['AND', ['chainId', 0, '!'], ['cuFlags', ACHIEVEMENT_CU_LAST_SERIES, '&']] : ['AND', ['chainId', 0, '!'], [['cuFlags', ACHIEVEMENT_CU_LAST_SERIES, '&'], 0]];
|
||||
|
||||
break;
|
||||
case 11: // Related Event [enum]
|
||||
$_ = isset($this->enums[$cr[0]][$cr[1]]) ? $this->enums[$cr[0]][$cr[1]] : null;
|
||||
if ($_ !== null)
|
||||
{
|
||||
if (is_int($_))
|
||||
return ($_ > 0) ? ['category', $_] : ['id', abs($_)];
|
||||
else
|
||||
{
|
||||
$ids = array_filter($this->enums[$cr[0]], function($x) {
|
||||
return is_int($x) && $x > 0;
|
||||
});
|
||||
|
||||
return ['category', $ids, $_ ? null : '!'];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
unset($cr);
|
||||
$this->error = true;
|
||||
return [1];
|
||||
@@ -359,45 +357,57 @@ class AchievementListFilter extends Filter
|
||||
|
||||
// points min
|
||||
if (isset($_v['minpt']))
|
||||
{
|
||||
if ($this->isSaneNumeric($_v['minpt']))
|
||||
$parts[] = ['points', $_v['minpt'], '>='];
|
||||
else
|
||||
unset($_v['minpt']);
|
||||
}
|
||||
$parts[] = ['points', $_v['minpt'], '>='];
|
||||
|
||||
// points max
|
||||
if (isset($_v['maxpt']))
|
||||
{
|
||||
if ($this->isSaneNumeric($_v['maxpt']))
|
||||
$parts[] = ['points', $_v['maxpt'], '<='];
|
||||
else
|
||||
unset($_v['maxpt']);
|
||||
}
|
||||
$parts[] = ['points', $_v['maxpt'], '<='];
|
||||
|
||||
// faction (side)
|
||||
if (isset($_v['si']))
|
||||
{
|
||||
switch ($_v['si'])
|
||||
{
|
||||
case 3: // both
|
||||
$parts[] = ['faction', 0];
|
||||
break;
|
||||
case -1: // faction, exclusive both
|
||||
case -2:
|
||||
$parts[] = ['faction', -$_v['si']];
|
||||
break;
|
||||
case 1: // faction, inclusive both
|
||||
case 2:
|
||||
$parts[] = ['OR', ['faction', 0], ['faction', $_v['si']]];
|
||||
case 3: // both
|
||||
$parts[] = ['faction', $_v['si'], '&'];
|
||||
break;
|
||||
default:
|
||||
unset($_v['si']);
|
||||
}
|
||||
}
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
protected function cbRelEvent($cr, $value)
|
||||
{
|
||||
if (!isset($this->enums[$cr[0]][$cr[1]]))
|
||||
return false;
|
||||
|
||||
$_ = $this->enums[$cr[0]][$cr[1]];
|
||||
if (is_int($_))
|
||||
return ($_ > 0) ? ['category', $_] : ['id', abs($_)];
|
||||
else
|
||||
{
|
||||
$ids = array_filter($this->enums[$cr[0]], function($x) { return is_int($x) && $x > 0; });
|
||||
|
||||
return ['category', $ids, $_ ? null : '!'];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbSeries($cr, $value)
|
||||
{
|
||||
if ($this->int2Bool($cr[1]))
|
||||
return $cr[1] ? ['AND', ['chainId', 0, '!'], ['cuFlags', $value, '&']] : ['AND', ['chainId', 0, '!'], [['cuFlags', $value, '&'], 0]];
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
346
includes/types/arenateam.class.php
Normal file
346
includes/types/arenateam.class.php
Normal file
@@ -0,0 +1,346 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class ArenaTeamList extends BaseType
|
||||
{
|
||||
use profilerHelper, listviewHelper;
|
||||
|
||||
private $rankOrder = [];
|
||||
|
||||
public function getListviewData()
|
||||
{
|
||||
$data = [];
|
||||
foreach ($this->iterate() as $__)
|
||||
{
|
||||
$data[$this->id] = array(
|
||||
'name' => $this->curTpl['name'],
|
||||
'realm' => Profiler::urlize($this->curTpl['realmName']),
|
||||
'realmname' => $this->curTpl['realmName'],
|
||||
// 'battlegroup' => Profiler::urlize($this->curTpl['battlegroup']), // was renamed to subregion somewhere around cata release
|
||||
// 'battlegroupname' => $this->curTpl['battlegroup'],
|
||||
'region' => Profiler::urlize($this->curTpl['region']),
|
||||
'faction' => $this->curTpl['faction'],
|
||||
'size' => $this->curTpl['type'],
|
||||
'rank' => $this->curTpl['rank'],
|
||||
'wins' => $this->curTpl['seasonWins'],
|
||||
'games' => $this->curTpl['seasonGames'],
|
||||
'rating' => $this->curTpl['rating'],
|
||||
'members' => $this->curTpl['members']
|
||||
);
|
||||
}
|
||||
|
||||
return array_values($data);
|
||||
}
|
||||
|
||||
public function renderTooltip() {}
|
||||
public function getJSGlobals($addMask = 0) {}
|
||||
}
|
||||
|
||||
|
||||
class ArenaTeamListFilter extends Filter
|
||||
{
|
||||
public $extraOpts = [];
|
||||
protected $genericFilter = [];
|
||||
|
||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||
protected $inputFields = array(
|
||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name - only printable chars, no delimiter
|
||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||
'ex' => [FILTER_V_EQUAL, 'on', false], // only match exact
|
||||
'si' => [FILTER_V_LIST, [1, 2], false], // side
|
||||
'sz' => [FILTER_V_LIST, [2, 3, 5], false], // tema size
|
||||
'rg' => [FILTER_V_CALLBACK, 'cbRegionCheck', false], // region
|
||||
'sv' => [FILTER_V_CALLBACK, 'cbServerCheck', false], // server
|
||||
);
|
||||
|
||||
protected function createSQLForCriterium(&$cr) { }
|
||||
|
||||
protected function createSQLForValues()
|
||||
{
|
||||
$parts = [];
|
||||
$_v = $this->fiData['v'];
|
||||
|
||||
// region (rg), battlegroup (bg) and server (sv) are passed to ArenaTeamList as miscData and handled there
|
||||
|
||||
// name [str]
|
||||
if (!empty($_v['na']))
|
||||
if ($_ = $this->modularizeString(['at.name'], $_v['na'], !empty($_v['ex']) && $_v['ex'] == 'on'))
|
||||
$parts[] = $_;
|
||||
|
||||
// side [list]
|
||||
if (!empty($_v['si']))
|
||||
{
|
||||
if ($_v['si'] == 1)
|
||||
$parts[] = ['c.race', [1, 3, 4, 7, 11]];
|
||||
else if ($_v['si'] == 2)
|
||||
$parts[] = ['c.race', [2, 5, 6, 8, 10]];
|
||||
}
|
||||
|
||||
// size [int]
|
||||
if (!empty($_v['sz']))
|
||||
$parts[] = ['at.type', $_v['sz']];
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
protected function cbRegionCheck(&$v)
|
||||
{
|
||||
if ($v == 'eu' || $v == 'us')
|
||||
{
|
||||
$this->parentCats[0] = $v; // directly redirect onto this region
|
||||
$v = ''; // remove from filter
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbServerCheck(&$v)
|
||||
{
|
||||
foreach (Profiler::getRealms() as $realm)
|
||||
if ($realm['name'] == $v)
|
||||
{
|
||||
$this->parentCats[1] = Profiler::urlize($v);// directly redirect onto this server
|
||||
$v = ''; // remove from filter
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class RemoteArenaTeamList extends ArenaTeamList
|
||||
{
|
||||
protected $queryBase = 'SELECT `at`.*, `at`.`arenaTeamId` AS ARRAY_KEY FROM arena_team at';
|
||||
protected $queryOpts = array(
|
||||
'at' => [['atm', 'c'], 'g' => 'ARRAY_KEY', 'o' => 'rating DESC'],
|
||||
'atm' => ['j' => 'arena_team_member atm ON atm.arenaTeamId = at.arenaTeamId'],
|
||||
'c' => ['j' => 'characters c ON c.guid = atm.guid AND c.deleteInfos_Account IS NULL AND c.level <= 80 AND (c.extra_flags & '.Profiler::CHAR_GMFLAGS.') = 0', 's' => ', BIT_OR(IF(c.race IN (1, 3, 4, 7, 11), 1, 2)) - 1 AS faction']
|
||||
);
|
||||
|
||||
private $members = [];
|
||||
|
||||
public function __construct($conditions = [], $miscData = null)
|
||||
{
|
||||
// select DB by realm
|
||||
if (!$this->selectRealms($miscData))
|
||||
{
|
||||
trigger_error('no access to auth-db or table realmlist is empty', E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
parent::__construct($conditions, $miscData);
|
||||
|
||||
if ($this->error)
|
||||
return;
|
||||
|
||||
// ranks in DB are inaccurate. recalculate from rating (fetched as DESC from DB)
|
||||
foreach ($this->dbNames as $rId => $__)
|
||||
foreach ([2, 3, 5] as $type)
|
||||
$this->rankOrder[$rId][$type] = DB::Characters($rId)->selectCol('SELECT arenaTeamId FROM arena_team WHERE `type` = ?d ORDER BY rating DESC', $type);
|
||||
|
||||
reset($this->dbNames); // only use when querying single realm
|
||||
$realmId = key($this->dbNames);
|
||||
$realms = Profiler::getRealms();
|
||||
$distrib = [];
|
||||
|
||||
// post processing
|
||||
foreach ($this->iterate() as $guid => &$curTpl)
|
||||
{
|
||||
// battlegroup
|
||||
$curTpl['battlegroup'] = CFG_BATTLEGROUP;
|
||||
|
||||
// realm, rank
|
||||
$r = explode(':', $guid);
|
||||
if (!empty($realms[$r[0]]))
|
||||
{
|
||||
$curTpl['realm'] = $r[0];
|
||||
$curTpl['realmName'] = $realms[$r[0]]['name'];
|
||||
$curTpl['region'] = $realms[$r[0]]['region'];
|
||||
$curTpl['rank'] = array_search($curTpl['arenaTeamId'], $this->rankOrder[$r[0]][$curTpl['type']]) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error('arena team "'.$curTpl['name'].'" belongs to nonexistant realm #'.$r, E_USER_WARNING);
|
||||
unset($this->templates[$guid]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// team members
|
||||
$this->members[$r[0]][$r[1]] = $r[1];
|
||||
|
||||
// equalize distribution
|
||||
if (empty($distrib[$curTpl['realm']]))
|
||||
$distrib[$curTpl['realm']] = 1;
|
||||
else
|
||||
$distrib[$curTpl['realm']]++;
|
||||
}
|
||||
|
||||
// get team members
|
||||
foreach ($this->members as $realmId => &$teams)
|
||||
$teams = DB::Characters($realmId)->select('
|
||||
SELECT
|
||||
at.arenaTeamId AS ARRAY_KEY, c.guid AS ARRAY_KEY2, c.name AS "0", c.class AS "1", IF(at.captainguid = c.guid, 1, 0) AS "2"
|
||||
FROM
|
||||
arena_team at
|
||||
JOIN
|
||||
arena_team_member atm ON atm.arenaTeamId = at.arenaTeamId JOIN characters c ON c.guid = atm.guid
|
||||
WHERE
|
||||
at.arenaTeamId IN (?a) AND
|
||||
c.deleteInfos_Account IS NULL AND
|
||||
c.level <= ?d AND
|
||||
(c.extra_flags & ?d) = 0',
|
||||
$teams,
|
||||
MAX_LEVEL,
|
||||
Profiler::CHAR_GMFLAGS
|
||||
);
|
||||
|
||||
// equalize subject distribution across realms
|
||||
$limit = CFG_SQL_LIMIT_DEFAULT;
|
||||
foreach ($conditions as $c)
|
||||
if (is_int($c))
|
||||
$limit = $c;
|
||||
|
||||
$total = array_sum($distrib);
|
||||
foreach ($distrib as &$d)
|
||||
$d = ceil($limit * $d / $total);
|
||||
|
||||
foreach ($this->iterate() as $guid => &$curTpl)
|
||||
{
|
||||
if ($limit <= 0 || $distrib[$curTpl['realm']] <= 0)
|
||||
{
|
||||
unset($this->templates[$guid]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$r = explode(':', $guid);
|
||||
if (isset($this->members[$r[0]][$r[1]]))
|
||||
$curTpl['members'] = array_values($this->members[$r[0]][$r[1]]); // [name, classId, isCaptain]
|
||||
|
||||
$distrib[$curTpl['realm']]--;
|
||||
$limit--;
|
||||
}
|
||||
}
|
||||
|
||||
public function initializeLocalEntries()
|
||||
{
|
||||
$profiles = [];
|
||||
// init members for tooltips
|
||||
foreach ($this->members as $realmId => $teams)
|
||||
{
|
||||
$gladiators = [];
|
||||
foreach ($teams as $team)
|
||||
$gladiators = array_merge($gladiators, array_keys($team));
|
||||
|
||||
$profiles[$realmId] = new RemoteProfileList(array(['c.guid', $gladiators], CFG_SQL_LIMIT_NONE), ['sv' => $realmId]);
|
||||
|
||||
if (!$profiles[$realmId]->error)
|
||||
$profiles[$realmId]->initializeLocalEntries();
|
||||
}
|
||||
|
||||
$data = [];
|
||||
foreach ($this->iterate() as $guid => $__)
|
||||
{
|
||||
$data[$guid] = array(
|
||||
'realm' => $this->getField('realm'),
|
||||
'realmGUID' => $this->getField('arenaTeamId'),
|
||||
'name' => $this->getField('name'),
|
||||
'nameUrl' => Profiler::urlize($this->getField('name')),
|
||||
'type' => $this->getField('type'),
|
||||
'rating' => $this->getField('rating'),
|
||||
'cuFlags' => PROFILER_CU_NEEDS_RESYNC
|
||||
);
|
||||
}
|
||||
|
||||
// basic arena team data
|
||||
foreach (Util::createSqlBatchInsert($data) as $ins)
|
||||
DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_arena_team (?#) VALUES '.$ins, array_keys(reset($data)));
|
||||
|
||||
// merge back local ids
|
||||
$localIds = DB::Aowow()->selectCol(
|
||||
'SELECT CONCAT(realm, ":", realmGUID) AS ARRAY_KEY, id FROM ?_profiler_arena_team WHERE realm IN (?a) AND realmGUID IN (?a)',
|
||||
array_column($data, 'realm'),
|
||||
array_column($data, 'realmGUID')
|
||||
);
|
||||
|
||||
foreach ($this->iterate() as $guid => &$_curTpl)
|
||||
if (isset($localIds[$guid]))
|
||||
$_curTpl['id'] = $localIds[$guid];
|
||||
|
||||
|
||||
// profiler_arena_team_member requires profiles and arena teams to be filled
|
||||
foreach ($this->members as $realmId => $teams)
|
||||
{
|
||||
if (empty($profiles[$realmId]))
|
||||
continue;
|
||||
|
||||
$memberData = [];
|
||||
foreach ($teams as $teamId => $team)
|
||||
foreach ($team as $memberId => $member)
|
||||
$memberData[] = array(
|
||||
'arenaTeamId' => $localIds[$realmId.':'.$teamId],
|
||||
'profileId' => $profiles[$realmId]->getEntry($realmId.':'.$memberId)['id'],
|
||||
'captain' => $member[2]
|
||||
);
|
||||
|
||||
foreach (Util::createSqlBatchInsert($memberData) as $ins)
|
||||
DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_arena_team_member (?#) VALUES '.$ins, array_keys(reset($memberData)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class LocalArenaTeamList extends ArenaTeamList
|
||||
{
|
||||
protected $queryBase = 'SELECT at.*, at.id AS ARRAY_KEY FROM ?_profiler_arena_team at';
|
||||
|
||||
public function __construct($conditions = [], $miscData = null)
|
||||
{
|
||||
parent::__construct($conditions, $miscData);
|
||||
|
||||
if ($this->error)
|
||||
return;
|
||||
|
||||
$realms = Profiler::getRealms();
|
||||
|
||||
// post processing
|
||||
$members = DB::Aowow()->selectCol('SELECT *, arenaTeamId AS ARRAY_KEY, profileId AS ARRAY_KEY2 FROM ?_profiler_arena_team_member WHERE arenaTeamId IN (?a)', $this->getFoundIDs());
|
||||
|
||||
foreach ($this->iterate() as $id => &$curTpl)
|
||||
{
|
||||
if ($curTpl['realm'] && !isset($realms[$curTpl['realm']]))
|
||||
continue;
|
||||
|
||||
if (isset($realms[$curTpl['realm']]))
|
||||
{
|
||||
$curTpl['realmName'] = $realms[$curTpl['realm']]['name'];
|
||||
$curTpl['region'] = $realms[$curTpl['realm']]['region'];
|
||||
}
|
||||
|
||||
// battlegroup
|
||||
$curTpl['battlegroup'] = CFG_BATTLEGROUP;
|
||||
|
||||
$curTpl['members'] = $members[$id];
|
||||
}
|
||||
}
|
||||
|
||||
public function getProfileUrl()
|
||||
{
|
||||
$url = '?arena-team=';
|
||||
|
||||
return $url.implode('.', array(
|
||||
Profiler::urlize($this->getField('region')),
|
||||
Profiler::urlize($this->getField('realmName')),
|
||||
Profiler::urlize($this->getField('name'))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
@@ -6,10 +6,11 @@ if (!defined('AOWOW_REVISION'))
|
||||
|
||||
class CharClassList extends BaseType
|
||||
{
|
||||
public static $type = TYPE_CLASS;
|
||||
public static $brickFile = 'class';
|
||||
public static $type = TYPE_CLASS;
|
||||
public static $brickFile = 'class';
|
||||
public static $dataTable = '?_classes';
|
||||
|
||||
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_classes c';
|
||||
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_classes c';
|
||||
|
||||
public function __construct($conditions = [])
|
||||
{
|
||||
|
||||
@@ -6,10 +6,11 @@ if (!defined('AOWOW_REVISION'))
|
||||
|
||||
class CharRaceList extends BaseType
|
||||
{
|
||||
public static $type = TYPE_RACE;
|
||||
public static $brickFile = 'race';
|
||||
public static $type = TYPE_RACE;
|
||||
public static $brickFile = 'race';
|
||||
public static $dataTable = '?_races';
|
||||
|
||||
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_races r';
|
||||
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_races r';
|
||||
|
||||
public function getListviewData()
|
||||
{
|
||||
|
||||
@@ -8,11 +8,12 @@ class CreatureList extends BaseType
|
||||
{
|
||||
use spawnHelper;
|
||||
|
||||
public static $type = TYPE_NPC;
|
||||
public static $brickFile = 'creature';
|
||||
public static $type = TYPE_NPC;
|
||||
public static $brickFile = 'creature';
|
||||
public static $dataTable = '?_creature';
|
||||
|
||||
protected $queryBase = 'SELECT ct.*, ct.id AS ARRAY_KEY FROM ?_creature ct';
|
||||
public $queryOpts = array(
|
||||
protected $queryBase = 'SELECT ct.*, ct.id AS ARRAY_KEY FROM ?_creature ct';
|
||||
public $queryOpts = array(
|
||||
'ct' => [['ft', 'qse', 'dct1', 'dct2', 'dct3'], 's' => ', IFNULL(dct1.id, IFNULL(dct2.id, IFNULL(dct3.id, 0))) AS parentId, IFNULL(dct1.name_loc0, IFNULL(dct2.name_loc0, IFNULL(dct3.name_loc0, ""))) AS parent_loc0, IFNULL(dct1.name_loc2, IFNULL(dct2.name_loc2, IFNULL(dct3.name_loc2, ""))) AS parent_loc2, IFNULL(dct1.name_loc3, IFNULL(dct2.name_loc3, IFNULL(dct3.name_loc3, ""))) AS parent_loc3, IFNULL(dct1.name_loc6, IFNULL(dct2.name_loc6, IFNULL(dct3.name_loc6, ""))) AS parent_loc6, IFNULL(dct1.name_loc8, IFNULL(dct2.name_loc8, IFNULL(dct3.name_loc8, ""))) AS parent_loc8, IF(dct1.difficultyEntry1 = ct.id, 1, IF(dct2.difficultyEntry2 = ct.id, 2, IF(dct3.difficultyEntry3 = ct.id, 3, 0))) AS difficultyMode'],
|
||||
'dct1' => ['j' => ['?_creature dct1 ON ct.cuFlags & 0x02 AND dct1.difficultyEntry1 = ct.id', true]],
|
||||
'dct2' => ['j' => ['?_creature dct2 ON ct.cuFlags & 0x02 AND dct2.difficultyEntry2 = ct.id', true]],
|
||||
@@ -76,7 +77,8 @@ class CreatureList extends BaseType
|
||||
if ($type)
|
||||
$row3[] = Lang::game('ct', $type);
|
||||
|
||||
$row3[] = '('.Lang::npc('rank', $this->curTpl['rank']).')';
|
||||
if ($_ = Lang::npc('rank', $this->curTpl['rank']))
|
||||
$row3[] = '('.$_.')';
|
||||
|
||||
$x = '<table>';
|
||||
$x .= '<tr><td><b class="q">'.$this->getField('name', true).'</b></td></tr>';
|
||||
@@ -161,9 +163,22 @@ class CreatureList extends BaseType
|
||||
*
|
||||
* NPCINFO_TAMEABLE (0x1): include texture & react
|
||||
* NPCINFO_MODEL (0x2):
|
||||
* NPCINFO_REP (0x4): include repreward
|
||||
*/
|
||||
|
||||
$data = [];
|
||||
$data = [];
|
||||
$rewRep = [];
|
||||
|
||||
if ($addInfoMask & NPCINFO_REP && $this->getFoundIDs())
|
||||
{
|
||||
$rewRep = DB::World()->selectCol('
|
||||
SELECT creature_id AS ARRAY_KEY, RewOnKillRepFaction1 AS ARRAY_KEY2, RewOnKillRepValue1 FROM creature_onkill_reputation WHERE creature_id IN (?a) AND RewOnKillRepFaction1 > 0 UNION
|
||||
SELECT creature_id AS ARRAY_KEY, RewOnKillRepFaction2 AS ARRAY_KEY2, RewOnKillRepValue2 FROM creature_onkill_reputation WHERE creature_id IN (?a) AND RewOnKillRepFaction2 > 0',
|
||||
$this->getFoundIDs(),
|
||||
$this->getFoundIDs()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
foreach ($this->iterate() as $__)
|
||||
{
|
||||
@@ -207,6 +222,7 @@ class CreatureList extends BaseType
|
||||
'react' => [$this->curTpl['A'], $this->curTpl['H']],
|
||||
);
|
||||
|
||||
|
||||
if ($this->getField('startsQuests'))
|
||||
$data[$this->id]['hasQuests'] = 1;
|
||||
|
||||
@@ -215,6 +231,14 @@ class CreatureList extends BaseType
|
||||
|
||||
if ($addInfoMask & NPCINFO_TAMEABLE) // only first skin of first model ... we're omitting potentially 11 skins here .. but the lv accepts only one .. w/e
|
||||
$data[$this->id]['skin'] = $this->curTpl['textureString'];
|
||||
|
||||
if ($addInfoMask & NPCINFO_REP)
|
||||
{
|
||||
$data[$this->id]['reprewards'] = [];
|
||||
if ($rewRep[$this->id])
|
||||
foreach ($rewRep[$this->id] as $fac => $val)
|
||||
$data[$this->id]['reprewards'][] = [$fac, $val];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,6 +277,7 @@ class CreatureList extends BaseType
|
||||
|
||||
public function addRewardsToJScript(&$refs) { }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -268,228 +293,66 @@ class CreatureListFilter extends Filter
|
||||
|
||||
// cr => [type, field, misc, extraCol]
|
||||
protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet
|
||||
5 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_REPAIRER ], // canrepair
|
||||
6 => [FILTER_CR_ENUM, 's.areaId', null ], // foundin
|
||||
9 => [FILTER_CR_BOOLEAN, 'lootId', ], // lootable
|
||||
11 => [FILTER_CR_BOOLEAN, 'pickpocketLootId', ], // pickpocketable
|
||||
18 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_AUCTIONEER ], // auctioneer
|
||||
19 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BANKER ], // banker
|
||||
20 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BATTLEMASTER ], // battlemaster
|
||||
21 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_FLIGHT_MASTER ], // flightmaster
|
||||
22 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_GUILD_MASTER ], // guildmaster
|
||||
23 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_INNKEEPER ], // innkeeper
|
||||
24 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_CLASS_TRAINER ], // talentunlearner
|
||||
25 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_GUILD_MASTER ], // tabardvendor
|
||||
27 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_STABLE_MASTER ], // stablemaster
|
||||
28 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_TRAINER ], // trainer
|
||||
29 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_VENDOR ], // vendor
|
||||
19 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BANKER ], // banker
|
||||
37 => [FILTER_CR_NUMERIC, 'id', null, true], // id
|
||||
35 => [FILTER_CR_STRING, 'textureString' ], // useskin
|
||||
32 => [FILTER_CR_FLAG, 'cuFlags', NPC_CU_INSTANCE_BOSS ], // instanceboss
|
||||
33 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||
31 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
||||
40 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
||||
1 => [FILTER_CR_CALLBACK, 'cbHealthMana', 'healthMax', 'healthMin'], // health [num]
|
||||
2 => [FILTER_CR_CALLBACK, 'cbHealthMana', 'manaMin', 'manaMax' ], // mana [num]
|
||||
3 => [FILTER_CR_CALLBACK, 'cbFaction', null, null ], // faction [enum]
|
||||
5 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_REPAIRER ], // canrepair
|
||||
6 => [FILTER_CR_ENUM, 's.areaId', null ], // foundin
|
||||
7 => [FILTER_CR_CALLBACK, 'cbQuestRelation', 'startsQuests', 0x1 ], // startsquest [enum]
|
||||
8 => [FILTER_CR_CALLBACK, 'cbQuestRelation', 'endsQuests', 0x2 ], // endsquest [enum]
|
||||
9 => [FILTER_CR_BOOLEAN, 'lootId', ], // lootable
|
||||
10 => [FILTER_CR_BOOLEAN, 'cbRegularSkinLoot', NPC_TYPEFLAG_SPECIALLOOT ], // skinnable [yn]
|
||||
11 => [FILTER_CR_BOOLEAN, 'pickpocketLootId', ], // pickpocketable
|
||||
12 => [FILTER_CR_CALLBACK, 'cbMoneyDrop', null, null ], // averagemoneydropped [op] [int]
|
||||
15 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_HERBLOOT, null ], // gatherable [yn]
|
||||
16 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_ENGINEERLOOT, null ], // minable [yn]
|
||||
18 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_AUCTIONEER ], // auctioneer
|
||||
19 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BANKER ], // banker
|
||||
20 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BATTLEMASTER ], // battlemaster
|
||||
21 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_FLIGHT_MASTER ], // flightmaster
|
||||
22 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_GUILD_MASTER ], // guildmaster
|
||||
23 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_INNKEEPER ], // innkeeper
|
||||
24 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_CLASS_TRAINER ], // talentunlearner
|
||||
25 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_GUILD_MASTER ], // tabardvendor
|
||||
27 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_STABLE_MASTER ], // stablemaster
|
||||
28 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_TRAINER ], // trainer
|
||||
29 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_VENDOR ], // vendor
|
||||
31 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
||||
32 => [FILTER_CR_FLAG, 'cuFlags', NPC_CU_INSTANCE_BOSS ], // instanceboss
|
||||
33 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||
34 => [FILTER_CR_NYI_PH, 1, null ], // usemodel [str] - displayId -> id:creatureDisplayInfo.dbc/model -> id:cratureModelData.dbc/modelPath
|
||||
35 => [FILTER_CR_STRING, 'textureString' ], // useskin
|
||||
37 => [FILTER_CR_NUMERIC, 'id', NUM_CAST_INT, true ], // id
|
||||
38 => [FILTER_CR_CALLBACK, 'cbRelEvent', null, null ], // relatedevent [enum]
|
||||
40 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
||||
41 => [FILTER_CR_NYI_PH, 1, null ], // haslocation [yn] [staff]
|
||||
42 => [FILTER_CR_CALLBACK, 'cbReputation', '>', null ], // increasesrepwith [enum]
|
||||
43 => [FILTER_CR_CALLBACK, 'cbReputation', '<', null ], // decreasesrepwith [enum]
|
||||
44 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_MININGLOOT, null ] // salvageable [yn]
|
||||
);
|
||||
|
||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||
protected $inputFields = array(
|
||||
'cr' => [FILTER_V_LIST, [[1, 3],[5, 12], 15, 16, [18, 25], [27, 29], [31, 35], 37, 38, [40, 44]], true ], // criteria ids
|
||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 9999]], true ], // criteria operators
|
||||
'crv' => [FILTER_V_REGEX, '/[\p{C}:;]/ui', true ], // criteria values - only printable chars, no delimiter
|
||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name / subname - only printable chars, no delimiter
|
||||
'ex' => [FILTER_V_EQUAL, 'on', false], // also match subname
|
||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||
'fa' => [FILTER_V_CALLBACK, 'cbPetFamily', true ], // pet family [list] - cat[0] == 1
|
||||
'minle' => [FILTER_V_RANGE, [1, 99], false], // min level [int]
|
||||
'maxle' => [FILTER_V_RANGE, [1, 99], false], // max level [int]
|
||||
'cl' => [FILTER_V_RANGE, [0, 4], true ], // classification [list]
|
||||
'ra' => [FILTER_V_LIST, [-1, 0, 1], false], // react alliance [int]
|
||||
'rh' => [FILTER_V_LIST, [-1, 0, 1], false] // react horde [int]
|
||||
);
|
||||
|
||||
protected function createSQLForCriterium(&$cr)
|
||||
{
|
||||
if (in_array($cr[0], array_keys($this->genericFilter)))
|
||||
{
|
||||
if ($genCr = $this->genericCriterion($cr))
|
||||
return $genCr;
|
||||
|
||||
unset($cr);
|
||||
$this->error = true;
|
||||
return [1];
|
||||
}
|
||||
|
||||
switch ($cr[0])
|
||||
{
|
||||
case 1: // health [num]
|
||||
if (!$this->isSaneNumeric($cr[2]) || !$this->int2Op($cr[1]))
|
||||
break;
|
||||
|
||||
// remap OP for this special case
|
||||
switch ($cr[1])
|
||||
{
|
||||
case '=': // min > max is totally possible
|
||||
$this->extraOpts['ct']['h'][] = 'healthMin = healthMax AND healthMin = '.$cr[2];
|
||||
break;
|
||||
case '>':
|
||||
$this->extraOpts['ct']['h'][] = 'IF(healthMin > healthMax, healthMax, healthMin) > '.$cr[2];
|
||||
break;
|
||||
case '>=':
|
||||
$this->extraOpts['ct']['h'][] = 'IF(healthMin > healthMax, healthMax, healthMin) >= '.$cr[2];
|
||||
break;
|
||||
case '<':
|
||||
$this->extraOpts['ct']['h'][] = 'IF(healthMin > healthMax, healthMin, healthMax) < '.$cr[2];
|
||||
break;
|
||||
case '<=':
|
||||
$this->extraOpts['ct']['h'][] = 'IF(healthMin > healthMax, healthMin, healthMax) <= '.$cr[2];
|
||||
break;
|
||||
}
|
||||
return [1]; // always true, use post-filter
|
||||
case 2: // mana [num]
|
||||
if (!$this->isSaneNumeric($cr[2]) || !$this->int2Op($cr[1]))
|
||||
break;
|
||||
|
||||
// remap OP for this special case
|
||||
switch ($cr[1])
|
||||
{
|
||||
case '=':
|
||||
$this->extraOpts['ct']['h'][] = 'manaMin = manaMax AND manaMin = '.$cr[2];
|
||||
break;
|
||||
case '>':
|
||||
$this->extraOpts['ct']['h'][] = 'IF(manaMin > manaMax, manaMin, manaMax) > '.$cr[2];
|
||||
break;
|
||||
case '>=':
|
||||
$this->extraOpts['ct']['h'][] = 'IF(manaMin > manaMax, manaMin, manaMax) >= '.$cr[2];
|
||||
break;
|
||||
case '<':
|
||||
$this->extraOpts['ct']['h'][] = 'IF(manaMin > manaMax, manaMax, manaMin) < '.$cr[2];
|
||||
break;
|
||||
case '<=':
|
||||
$this->extraOpts['ct']['h'][] = 'IF(manaMin > manaMax, manaMax, manaMin) <= '.$cr[2];
|
||||
break;
|
||||
}
|
||||
return [1]; // always true, use post-filter
|
||||
case 7: // startsquest [enum]
|
||||
switch ($cr[1])
|
||||
{
|
||||
case 1: // any
|
||||
return ['AND', ['qse.method', 0x1, '&'], ['qse.questId', null, '!']];
|
||||
case 2: // alliance
|
||||
return ['AND', ['qse.method', 0x1, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_HORDE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&']];
|
||||
case 3: // horde
|
||||
return ['AND', ['qse.method', 0x1, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']];
|
||||
case 4: // both
|
||||
return ['AND', ['qse.method', 0x1, '&'], ['qse.questId', null, '!'], ['OR', ['AND', ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']], ['qt.reqRaceMask', 0]]];
|
||||
case 5: // none
|
||||
$this->extraOpts['ct']['h'][] = 'startsQuests = 0';
|
||||
return [1];
|
||||
}
|
||||
break;
|
||||
case 8: // endsquest [enum]
|
||||
switch ($cr[1])
|
||||
{
|
||||
case 1: // any
|
||||
return ['AND', ['qse.method', 0x2, '&'], ['qse.questId', null, '!']];
|
||||
case 2: // alliance
|
||||
return ['AND', ['qse.method', 0x2, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_HORDE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&']];
|
||||
case 3: // horde
|
||||
return ['AND', ['qse.method', 0x2, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']];
|
||||
case 4: // both
|
||||
return ['AND', ['qse.method', 0x2, '&'], ['qse.questId', null, '!'], ['OR', ['AND', ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']], ['qt.reqRaceMask', 0]]];
|
||||
case 5: // none
|
||||
$this->extraOpts['ct']['h'][] = 'endsQuests = 0';
|
||||
return [1];
|
||||
}
|
||||
break;
|
||||
case 3: // faction [enum]
|
||||
if (in_array($cr[1], $this->enums[$cr[0]]))
|
||||
{
|
||||
$facTpls = [];
|
||||
$facs = new FactionList(array('OR', ['parentFactionId', $cr[1]], ['id', $cr[1]]));
|
||||
foreach ($facs->iterate() as $__)
|
||||
$facTpls = array_merge($facTpls, $facs->getField('templateIds'));
|
||||
|
||||
if (!$facTpls)
|
||||
return [0];
|
||||
|
||||
return ['faction', $facTpls];
|
||||
}
|
||||
break;
|
||||
case 38; // relatedevent
|
||||
if (!$this->isSaneNumeric($cr[1]))
|
||||
break;
|
||||
|
||||
if ($cr[1] == FILTER_ENUM_ANY)
|
||||
{
|
||||
$eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId <> 0');
|
||||
$cGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_creature WHERE eventEntry IN (?a)', $eventIds);
|
||||
return ['s.guid', $cGuids];
|
||||
}
|
||||
else if ($cr[1] == FILTER_ENUM_NONE)
|
||||
{
|
||||
$eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId <> 0');
|
||||
$cGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_creature WHERE eventEntry IN (?a)', $eventIds);
|
||||
return ['s.guid', $cGuids, '!'];
|
||||
}
|
||||
else if ($cr[1])
|
||||
{
|
||||
$eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId = ?d', $cr[1]);
|
||||
$cGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_creature WHERE eventEntry IN (?a)', $eventIds);
|
||||
return ['s.guid', $cGuids];
|
||||
}
|
||||
|
||||
break;
|
||||
case 42: // increasesrepwith [enum]
|
||||
if (in_array($cr[1], $this->enums[3])) // reuse
|
||||
{
|
||||
if ($cIds = DB::World()->selectCol('SELECT creature_id FROM creature_onkill_reputation WHERE (RewOnKillRepFaction1 = ?d AND RewOnKillRepValue1 > 0) OR (RewOnKillRepFaction2 = ?d AND RewOnKillRepValue2 > 0)', $cr[1], $cr[1]))
|
||||
return ['id', $cIds];
|
||||
else
|
||||
return [0];
|
||||
}
|
||||
|
||||
break;
|
||||
case 43: // decreasesrepwith [enum]
|
||||
if (in_array($cr[1], $this->enums[3])) // reuse
|
||||
{
|
||||
if ($cIds = DB::World()->selectCol('SELECT creature_id FROM creature_onkill_reputation WHERE (RewOnKillRepFaction1 = ?d AND RewOnKillRepValue1 < 0) OR (RewOnKillRepFaction2 = ?d AND RewOnKillRepValue2 < 0)', $cr[1], $cr[1]))
|
||||
return ['id', $cIds];
|
||||
else
|
||||
return [0];
|
||||
}
|
||||
|
||||
break;
|
||||
case 12: // averagemoneydropped [op] [int]
|
||||
if (!$this->isSaneNumeric($cr[2]) || !$this->int2Op($cr[1]))
|
||||
break;
|
||||
|
||||
return ['AND', ['((minGold + maxGold) / 2)', $cr[2], $cr[1]]];
|
||||
case 15: // gatherable [yn]
|
||||
if ($this->int2Bool($cr[1]))
|
||||
{
|
||||
if ($cr[1])
|
||||
return ['AND', ['skinLootId', 0, '>'], ['typeFlags', NPC_TYPEFLAG_HERBLOOT, '&']];
|
||||
else
|
||||
return ['OR', ['skinLootId', 0], [['typeFlags', NPC_TYPEFLAG_HERBLOOT, '&'], 0]];
|
||||
}
|
||||
break;
|
||||
case 44: // salvageable [yn]
|
||||
if ($this->int2Bool($cr[1]))
|
||||
{
|
||||
if ($cr[1])
|
||||
return ['AND', ['skinLootId', 0, '>'], ['typeFlags', NPC_TYPEFLAG_ENGINEERLOOT, '&']];
|
||||
else
|
||||
return ['OR', ['skinLootId', 0], [['typeFlags', NPC_TYPEFLAG_ENGINEERLOOT, '&'], 0]];
|
||||
}
|
||||
break;
|
||||
case 16: // minable [yn]
|
||||
if ($this->int2Bool($cr[1]))
|
||||
{
|
||||
if ($cr[1])
|
||||
return ['AND', ['skinLootId', 0, '>'], ['typeFlags', NPC_TYPEFLAG_MININGLOOT, '&']];
|
||||
else
|
||||
return ['OR', ['skinLootId', 0], [['typeFlags', NPC_TYPEFLAG_MININGLOOT, '&'], 0]];
|
||||
}
|
||||
break;
|
||||
case 10: // skinnable [yn]
|
||||
if ($this->int2Bool($cr[1]))
|
||||
{
|
||||
if ($cr[1])
|
||||
return ['AND', ['skinLootId', 0, '>'], [['typeFlags', NPC_TYPEFLAG_SPECIALLOOT, '&'], 0]];
|
||||
else
|
||||
return ['OR', ['skinLootId', 0], [['typeFlags', NPC_TYPEFLAG_SPECIALLOOT, '&'], 0, '!']];
|
||||
}
|
||||
break;
|
||||
case 34: // usemodel [str] // displayId -> id:creatureDisplayInfo.dbc/model -> id:cratureModelData.dbc/modelPath
|
||||
case 41: // haslocation [yn] [staff]
|
||||
/* todo */ return [1];
|
||||
}
|
||||
|
||||
unset($cr);
|
||||
$this->error = true;
|
||||
return [1];
|
||||
@@ -515,65 +378,176 @@ class CreatureListFilter extends Filter
|
||||
|
||||
// pet family [list]
|
||||
if (isset($_v['fa']))
|
||||
{
|
||||
$_ = (array)$_v['fa'];
|
||||
if (!array_diff($_, [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 20, 21, 24, 25, 26, 27, 30, 31, 32, 33, 34, 35, 37, 38, 39, 41, 42, 43, 44, 45, 46]))
|
||||
$parts[] = ['family', $_];
|
||||
else
|
||||
unset($_v['cl']);
|
||||
}
|
||||
$parts[] = ['family', $_v['fa']];
|
||||
|
||||
// creatureLevel min [int]
|
||||
if (isset($_v['minle']))
|
||||
{
|
||||
if (is_int($_v['minle']) && $_v['minle'] > 0)
|
||||
$parts[] = ['minLevel', $_v['minle'], '>='];
|
||||
else
|
||||
unset($_v['minle']);
|
||||
}
|
||||
$parts[] = ['minLevel', $_v['minle'], '>='];
|
||||
|
||||
// creatureLevel max [int]
|
||||
if (isset($_v['maxle']))
|
||||
{
|
||||
if (is_int($_v['maxle']) && $_v['maxle'] > 0)
|
||||
$parts[] = ['maxLevel', $_v['maxle'], '<='];
|
||||
else
|
||||
unset($_v['maxle']);
|
||||
}
|
||||
$parts[] = ['maxLevel', $_v['maxle'], '<='];
|
||||
|
||||
// classification [list]
|
||||
if (isset($_v['cl']))
|
||||
{
|
||||
$_ = (array)$_v['cl'];
|
||||
if (!array_diff($_, [0, 1, 2, 3, 4]))
|
||||
$parts[] = ['rank', $_];
|
||||
else
|
||||
unset($_v['cl']);
|
||||
}
|
||||
$parts[] = ['rank', $_v['cl']];
|
||||
|
||||
// react Alliance [int]
|
||||
if (isset($_v['ra']))
|
||||
{
|
||||
$_ = (int)$_v['ra'];
|
||||
if (in_array($_, [-1, 0, 1]))
|
||||
$parts[] = ['ft.A', $_];
|
||||
else
|
||||
unset($_v['ra']);
|
||||
}
|
||||
$parts[] = ['ft.A', $_v['ra']];
|
||||
|
||||
// react Horde [int]
|
||||
if (isset($_v['rh']))
|
||||
{
|
||||
$_ = (int)$_v['rh'];
|
||||
if (in_array($_, [-1, 0, 1]))
|
||||
$parts[] = ['ft.H', $_];
|
||||
else
|
||||
unset($_v['rh']);
|
||||
}
|
||||
$parts[] = ['ft.H', $_v['rh']];
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
protected function cbPetFamily(&$val)
|
||||
{
|
||||
if (!$this->parentCats || $this->parentCats[0] != 1)
|
||||
return false;
|
||||
|
||||
if (!Util::checkNumeric($val, NUM_REQ_INT))
|
||||
return false;
|
||||
|
||||
$type = FILTER_V_LIST;
|
||||
$valid = [[1, 9], 11, 12, 20, 21, [24, 27], [30, 35], [37, 39], [41, 46]];
|
||||
|
||||
return $this->checkInput($type, $valid, $val);
|
||||
}
|
||||
|
||||
protected function cbRelEvent($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[1], NUM_REQ_INT))
|
||||
return false;
|
||||
|
||||
if ($cr[1] == FILTER_ENUM_ANY)
|
||||
{
|
||||
$eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId <> 0');
|
||||
$cGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_creature WHERE eventEntry IN (?a)', $eventIds);
|
||||
return ['s.guid', $cGuids];
|
||||
}
|
||||
else if ($cr[1] == FILTER_ENUM_NONE)
|
||||
{
|
||||
$eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId <> 0');
|
||||
$cGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_creature WHERE eventEntry IN (?a)', $eventIds);
|
||||
return ['s.guid', $cGuids, '!'];
|
||||
}
|
||||
else if ($cr[1])
|
||||
{
|
||||
$eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId = ?d', $cr[1]);
|
||||
$cGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_creature WHERE eventEntry IN (?a)', $eventIds);
|
||||
return ['s.guid', $cGuids];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbMoneyDrop($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[2], NUM_CAST_INT) || !$this->int2Op($cr[1]))
|
||||
return false;
|
||||
|
||||
return ['AND', ['((minGold + maxGold) / 2)', $cr[2], $cr[1]]];
|
||||
}
|
||||
|
||||
protected function cbQuestRelation($cr, $field, $val)
|
||||
{
|
||||
switch ($cr[1])
|
||||
{
|
||||
case 1: // any
|
||||
return ['AND', ['qse.method', $val, '&'], ['qse.questId', null, '!']];
|
||||
case 2: // alliance
|
||||
return ['AND', ['qse.method', $val, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_HORDE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&']];
|
||||
case 3: // horde
|
||||
return ['AND', ['qse.method', $val, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']];
|
||||
case 4: // both
|
||||
return ['AND', ['qse.method', $val, '&'], ['qse.questId', null, '!'], ['OR', ['AND', ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']], ['qt.reqRaceMask', 0]]];
|
||||
case 5: // none
|
||||
$this->extraOpts['ct']['h'][] = $field.' = 0';
|
||||
return [1];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbHealthMana($cr, $minField, $maxField)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[2], NUM_CAST_INT) || !$this->int2Op($cr[1]))
|
||||
return false;
|
||||
|
||||
// remap OP for this special case
|
||||
switch ($cr[1])
|
||||
{
|
||||
case '=': // min > max is totally possible
|
||||
$this->extraOpts['ct']['h'][] = $minField.' = '.$maxField.' AND '.$minField.' = '.$cr[2];
|
||||
break;
|
||||
case '>':
|
||||
case '>=':
|
||||
case '<':
|
||||
case '<=':
|
||||
$this->extraOpts['ct']['h'][] = 'IF('.$minField.' > '.$maxField.', '.$maxField.', '.$minField.') '.$cr[1].' '.$cr[2];
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return [1]; // always true, use post-filter
|
||||
}
|
||||
|
||||
protected function cbSpecialSkinLoot($cr, $typeFlag)
|
||||
{
|
||||
if (!$this->int2Bool($cr[1]))
|
||||
return false;
|
||||
|
||||
|
||||
if ($cr[1])
|
||||
return ['AND', ['skinLootId', 0, '>'], ['typeFlags', $typeFlag, '&']];
|
||||
else
|
||||
return ['OR', ['skinLootId', 0], [['typeFlags', $typeFlag, '&'], 0]];
|
||||
}
|
||||
|
||||
protected function cbRegularSkinLoot($cr, $typeFlag)
|
||||
{
|
||||
if (!$this->int2Bool($cr[1]))
|
||||
return false;
|
||||
|
||||
if ($cr[1])
|
||||
return ['AND', ['skinLootId', 0, '>'], [['typeFlags', $typeFlag, '&'], 0]];
|
||||
else
|
||||
return ['OR', ['skinLootId', 0], ['typeFlags', $typeFlag, '&']];
|
||||
}
|
||||
|
||||
protected function cbReputation($cr, $op)
|
||||
{
|
||||
if (!in_array($cr[1], $this->enums[3])) // reuse
|
||||
return false;
|
||||
|
||||
if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_factions WHERE id = ?d', $cr[1]))
|
||||
$this->formData['reputationCols'][] = [$cr[1], Util::localizedString($_, 'name')];
|
||||
|
||||
if ($cIds = DB::World()->selectCol('SELECT creature_id FROM creature_onkill_reputation WHERE (RewOnKillRepFaction1 = ?d AND RewOnKillRepValue1 '.$op.' 0) OR (RewOnKillRepFaction2 = ?d AND RewOnKillRepValue2 '.$op.' 0)', $cr[1], $cr[1]))
|
||||
return ['id', $cIds];
|
||||
else
|
||||
return [0];
|
||||
}
|
||||
|
||||
protected function cbFaction($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[1], NUM_REQ_INT))
|
||||
return false;
|
||||
|
||||
if (!in_array($cr[1], $this->enums[$cr[0]]))
|
||||
return false;
|
||||
|
||||
|
||||
$facTpls = [];
|
||||
$facs = new FactionList(array('OR', ['parentFactionId', $cr[1]], ['id', $cr[1]]));
|
||||
foreach ($facs->iterate() as $__)
|
||||
$facTpls = array_merge($facTpls, $facs->getField('templateIds'));
|
||||
|
||||
return $facTpls ? ['faction', $facTpls] : [0];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -6,14 +6,25 @@ if (!defined('AOWOW_REVISION'))
|
||||
|
||||
class CurrencyList extends BaseType
|
||||
{
|
||||
public static $type = TYPE_CURRENCY;
|
||||
public static $brickFile = 'currency';
|
||||
public static $type = TYPE_CURRENCY;
|
||||
public static $brickFile = 'currency';
|
||||
public static $dataTable = '?_currencies';
|
||||
|
||||
protected $queryBase = 'SELECT *, c.id AS ARRAY_KEY FROM ?_currencies c';
|
||||
protected $queryOpts = array(
|
||||
'c' => [['ic']],
|
||||
'ic' => ['j' => ['?_icons ic ON ic.id = c.iconId', true], 's' => ', ic.name AS iconString']
|
||||
);
|
||||
|
||||
public function __construct($conditions = [])
|
||||
{
|
||||
parent::__construct($conditions);
|
||||
|
||||
foreach ($this->iterate() as &$_curTpl)
|
||||
if (!$_curTpl['iconString'])
|
||||
$_curTpl['iconString'] = 'inv_misc_questionmark';
|
||||
}
|
||||
|
||||
protected $queryBase = 'SELECT *, c.id AS ARRAY_KEY FROM ?_currencies c';
|
||||
protected $queryOpts = array(
|
||||
'c' => [['ic']],
|
||||
'ic' => ['j' => ['?_icons ic ON ic.id = c.iconId', true], 's' => ', ic.iconString']
|
||||
);
|
||||
|
||||
public function getListviewData()
|
||||
{
|
||||
@@ -52,7 +63,25 @@ class CurrencyList extends BaseType
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function renderTooltip() { }
|
||||
public function renderTooltip()
|
||||
{
|
||||
if (!$this->curTpl)
|
||||
return array();
|
||||
|
||||
$x = '<table><tr><td>';
|
||||
$x .= '<b>'.Util::jsEscape($this->getField('name', true)).'</b><br>';
|
||||
|
||||
// cata+ (or go fill it by hand)
|
||||
if ($_ = $this->getField('description', true))
|
||||
$x .= '<div style="max-width: 300px" class="q">'.Util::jsEscape($_).'</div>';
|
||||
|
||||
if ($_ = $this->getField('cap'))
|
||||
$x .= '<br><span class="q">'.Lang::currency('cap').Lang::main('colon').'</span>'.Lang::nf($_).'<br>';
|
||||
|
||||
$x .= '</td></tr></table>';
|
||||
|
||||
return $x;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
58
includes/types/emote.class.php
Normal file
58
includes/types/emote.class.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class EmoteList extends BaseType
|
||||
{
|
||||
public static $type = TYPE_EMOTE;
|
||||
public static $brickFile = 'emote';
|
||||
public static $dataTable = '?_emotes';
|
||||
|
||||
protected $queryBase = 'SELECT *, e.id AS ARRAY_KEY FROM ?_emotes e';
|
||||
|
||||
public function __construct($conditions = [])
|
||||
{
|
||||
parent::__construct($conditions);
|
||||
|
||||
// post processing
|
||||
foreach ($this->iterate() as &$curTpl)
|
||||
{
|
||||
// remap for generic access
|
||||
$curTpl['name'] = $curTpl['cmd'];
|
||||
}
|
||||
}
|
||||
|
||||
public function getListviewData()
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($this->iterate() as $__)
|
||||
{
|
||||
$data[$this->id] = array(
|
||||
'id' => $this->curTpl['id'],
|
||||
'name' => $this->curTpl['cmd'],
|
||||
'preview' => $this->getField('self', true) ?: ($this->getField('noTarget', true) ?: $this->getField('target', true))
|
||||
);
|
||||
|
||||
// [nyi] sounds
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getJSGlobals($addMask = GLOBALINFO_ANY)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($this->iterate() as $__)
|
||||
$data[TYPE_EMOTE][$this->id] = ['name' => $this->getField('cmd')];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function renderTooltip() { }
|
||||
}
|
||||
|
||||
?>
|
||||
353
includes/types/enchantment.class.php
Normal file
353
includes/types/enchantment.class.php
Normal file
@@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class EnchantmentList extends BaseType
|
||||
{
|
||||
use listviewHelper;
|
||||
|
||||
public static $type = TYPE_ENCHANTMENT;
|
||||
public static $brickFile = 'enchantment';
|
||||
public static $dataTable = '?_itemenchantment';
|
||||
|
||||
private $jsonStats = [];
|
||||
private $relSpells = [];
|
||||
private $triggerIds = [];
|
||||
|
||||
protected $queryBase = 'SELECT ie.*, ie.id AS ARRAY_KEY FROM ?_itemenchantment ie';
|
||||
protected $queryOpts = array( // 502 => TYPE_ENCHANTMENT
|
||||
'ie' => [['is']],
|
||||
'is' => ['j' => ['?_item_stats `is` ON `is`.`type` = 502 AND `is`.`typeId` = `ie`.`id`', true], 's' => ', `is`.*'],
|
||||
);
|
||||
|
||||
public function __construct($conditions = [])
|
||||
{
|
||||
parent::__construct($conditions);
|
||||
|
||||
// post processing
|
||||
foreach ($this->iterate() as &$curTpl)
|
||||
{
|
||||
$curTpl['spells'] = []; // [spellId, triggerType, charges, chanceOrPpm]
|
||||
for ($i = 1; $i <=3; $i++)
|
||||
{
|
||||
if ($curTpl['object'.$i] <= 0)
|
||||
continue;
|
||||
|
||||
switch ($curTpl['type'.$i])
|
||||
{
|
||||
case 1:
|
||||
$proc = -$this->getField('ppmRate') ?: ($this->getField('procChance') ?: $this->getField('amount'.$i));
|
||||
$curTpl['spells'][$i] = [$curTpl['object'.$i], 2, $curTpl['charges'], $proc];
|
||||
$this->relSpells[] = $curTpl['object'.$i];
|
||||
break;
|
||||
case 3:
|
||||
$curTpl['spells'][$i] = [$curTpl['object'.$i], 1, $curTpl['charges'], 0];
|
||||
$this->relSpells[] = $curTpl['object'.$i];
|
||||
break;
|
||||
case 7:
|
||||
$curTpl['spells'][$i] = [$curTpl['object'.$i], 0, $curTpl['charges'], 0];
|
||||
$this->relSpells[] = $curTpl['object'.$i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// floats are fetched as string from db :<
|
||||
$curTpl['dmg'] = floatVal($curTpl['dmg']);
|
||||
$curTpl['dps'] = floatVal($curTpl['dps']);
|
||||
|
||||
// remove zero-stats
|
||||
foreach (Game::$itemMods as $str)
|
||||
if ($curTpl[$str] == 0) // empty(0.0f) => true .. yeah, sure
|
||||
unset($curTpl[$str]);
|
||||
|
||||
if ($curTpl['dps'] == 0)
|
||||
unset($curTpl['dps']);
|
||||
}
|
||||
|
||||
if ($this->relSpells)
|
||||
$this->relSpells = new SpellList(array(['id', $this->relSpells]));
|
||||
}
|
||||
|
||||
// use if you JUST need the name
|
||||
public static function getName($id)
|
||||
{
|
||||
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM ?_itemenchantment WHERE id = ?d', $id );
|
||||
return Util::localizedString($n, 'name');
|
||||
}
|
||||
// end static use
|
||||
|
||||
public function getListviewData($addInfoMask = 0x0)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($this->iterate() as $__)
|
||||
{
|
||||
$data[$this->id] = array(
|
||||
'id' => $this->id,
|
||||
'name' => $this->getField('name', true),
|
||||
'spells' => []
|
||||
);
|
||||
|
||||
if ($this->curTpl['skillLine'] > 0)
|
||||
$data[$this->id]['reqskill'] = $this->curTpl['skillLine'];
|
||||
|
||||
if ($this->curTpl['skillLevel'] > 0)
|
||||
$data[$this->id]['reqskillrank'] = $this->curTpl['skillLevel'];
|
||||
|
||||
if ($this->curTpl['requiredLevel'] > 0)
|
||||
$data[$this->id]['reqlevel'] = $this->curTpl['requiredLevel'];
|
||||
|
||||
foreach ($this->curTpl['spells'] as $s)
|
||||
{
|
||||
// enchant is procing or onUse
|
||||
if ($s[1] == 2 || $s[1] == 0)
|
||||
$data[$this->id]['spells'][$s[0]] = $s[2];
|
||||
// spell is procing
|
||||
else if ($this->relSpells && $this->relSpells->getEntry($s[0]) && ($_ = $this->relSpells->canTriggerSpell()))
|
||||
{
|
||||
foreach ($_ as $idx)
|
||||
{
|
||||
$this->triggerIds[] = $this->relSpells->getField('effect'.$idx.'TriggerSpell');
|
||||
$data[$this->id]['spells'][$this->relSpells->getField('effect'.$idx.'TriggerSpell')] = $s[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$data[$this->id]['spells'])
|
||||
unset($data[$this->id]['spells']);
|
||||
|
||||
Util::arraySumByKey($data[$this->id], $this->getStatGain());
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getStatGain($addScalingKeys = false)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach (Game::$itemMods as $str)
|
||||
if (isset($this->curTpl[$str]))
|
||||
$data[$str] = $this->curTpl[$str];
|
||||
|
||||
if (isset($this->curTpl['dps']))
|
||||
$data['dps'] = $this->curTpl['dps'];
|
||||
|
||||
// scaling enchantments are saved as 0 to item_stats, thus return empty
|
||||
if ($addScalingKeys)
|
||||
{
|
||||
$spellStats = [];
|
||||
if ($this->relSpells)
|
||||
$spellStats = $this->relSpells->getStatGain();
|
||||
|
||||
for ($h = 1; $h <= 3; $h++)
|
||||
{
|
||||
$obj = (int)$this->curTpl['object'.$h];
|
||||
|
||||
switch ($this->curTpl['type'.$h])
|
||||
{
|
||||
case 3: // TYPE_EQUIP_SPELL Spells from ObjectX (use of amountX?)
|
||||
if (!empty($spellStats[$obj]))
|
||||
foreach ($spellStats[$obj] as $mod => $_)
|
||||
if ($str = Game::$itemMods[$mod])
|
||||
Util::arraySumByKey($data, [$str => 0]);
|
||||
|
||||
$obj = null;
|
||||
break;
|
||||
case 4: // TYPE_RESISTANCE +AmountX resistance for ObjectX School
|
||||
switch ($obj)
|
||||
{
|
||||
case 0: // Physical
|
||||
$obj = ITEM_MOD_ARMOR;
|
||||
break;
|
||||
case 1: // Holy
|
||||
$obj = ITEM_MOD_HOLY_RESISTANCE;
|
||||
break;
|
||||
case 2: // Fire
|
||||
$obj = ITEM_MOD_FIRE_RESISTANCE;
|
||||
break;
|
||||
case 3: // Nature
|
||||
$obj = ITEM_MOD_NATURE_RESISTANCE;
|
||||
break;
|
||||
case 4: // Frost
|
||||
$obj = ITEM_MOD_FROST_RESISTANCE;
|
||||
break;
|
||||
case 5: // Shadow
|
||||
$obj = ITEM_MOD_SHADOW_RESISTANCE;
|
||||
break;
|
||||
case 6: // Arcane
|
||||
$obj = ITEM_MOD_ARCANE_RESISTANCE;
|
||||
break;
|
||||
default:
|
||||
$obj = null;
|
||||
}
|
||||
break;
|
||||
case 5: // TYPE_STAT +AmountX for Statistic by type of ObjectX
|
||||
if ($obj < 2) // [mana, health] are on [0, 1] respectively and are expected on [1, 2] ..
|
||||
$obj++; // 0 is weaponDmg .. ehh .. i messed up somewhere
|
||||
|
||||
break; // stats are directly assigned below
|
||||
default: // TYPE_NONE dnd stuff; skip assignment below
|
||||
$obj = null;
|
||||
}
|
||||
|
||||
if ($obj !== null)
|
||||
if ($str = Game::$itemMods[$obj]) // check if we use these mods
|
||||
Util::arraySumByKey($data, [$str => 0]);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getRelSpell($id)
|
||||
{
|
||||
if ($this->relSpells)
|
||||
return $this->relSpells->getEntry($id);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getJSGlobals($addMask = GLOBALINFO_ANY)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
if ($addMask & GLOBALINFO_SELF)
|
||||
foreach ($this->iterate() as $__)
|
||||
$data[TYPE_ENCHANTMENT][$this->id] = ['name' => $this->getField('name', true)];
|
||||
|
||||
if ($addMask & GLOBALINFO_RELATED)
|
||||
{
|
||||
if ($this->relSpells)
|
||||
$data = $this->relSpells->getJSGlobals(GLOBALINFO_SELF);
|
||||
|
||||
foreach ($this->triggerIds as $tId)
|
||||
if (empty($data[TYPE_SPELL][$tId]))
|
||||
$data[TYPE_SPELL][$tId] = $tId;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function renderTooltip() { }
|
||||
}
|
||||
|
||||
|
||||
class EnchantmentListFilter extends Filter
|
||||
{
|
||||
protected $enums = array(
|
||||
3 => array( // requiresprof
|
||||
null, 171, 164, 185, 333, 202, 129, 755, 165, 186, 197, true, false, 356, 182, 773
|
||||
)
|
||||
);
|
||||
|
||||
protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet
|
||||
2 => [FILTER_CR_NUMERIC, 'id', NUM_CAST_INT, true], // id
|
||||
3 => [FILTER_CR_ENUM, 'skillLine' ], // requiresprof
|
||||
4 => [FILTER_CR_NUMERIC, 'skillLevel', NUM_CAST_INT ], // reqskillrank
|
||||
5 => [FILTER_CR_BOOLEAN, 'conditionId' ], // hascondition
|
||||
10 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||
11 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
||||
12 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
||||
20 => [FILTER_CR_NUMERIC, 'is.str', NUM_CAST_INT, true], // str
|
||||
21 => [FILTER_CR_NUMERIC, 'is.agi', NUM_CAST_INT, true], // agi
|
||||
22 => [FILTER_CR_NUMERIC, 'is.sta', NUM_CAST_INT, true], // sta
|
||||
23 => [FILTER_CR_NUMERIC, 'is.int', NUM_CAST_INT, true], // int
|
||||
24 => [FILTER_CR_NUMERIC, 'is.spi', NUM_CAST_INT, true], // spi
|
||||
25 => [FILTER_CR_NUMERIC, 'is.arcres', NUM_CAST_INT, true], // arcres
|
||||
26 => [FILTER_CR_NUMERIC, 'is.firres', NUM_CAST_INT, true], // firres
|
||||
27 => [FILTER_CR_NUMERIC, 'is.natres', NUM_CAST_INT, true], // natres
|
||||
28 => [FILTER_CR_NUMERIC, 'is.frores', NUM_CAST_INT, true], // frores
|
||||
29 => [FILTER_CR_NUMERIC, 'is.shares', NUM_CAST_INT, true], // shares
|
||||
30 => [FILTER_CR_NUMERIC, 'is.holres', NUM_CAST_INT, true], // holres
|
||||
32 => [FILTER_CR_NUMERIC, 'is.dps', NUM_CAST_FLOAT, true], // dps
|
||||
34 => [FILTER_CR_NUMERIC, 'is.dmg', NUM_CAST_FLOAT, true], // dmg
|
||||
37 => [FILTER_CR_NUMERIC, 'is.mleatkpwr', NUM_CAST_INT, true], // mleatkpwr
|
||||
38 => [FILTER_CR_NUMERIC, 'is.rgdatkpwr', NUM_CAST_INT, true], // rgdatkpwr
|
||||
39 => [FILTER_CR_NUMERIC, 'is.rgdhitrtng', NUM_CAST_INT, true], // rgdhitrtng
|
||||
40 => [FILTER_CR_NUMERIC, 'is.rgdcritstrkrtng', NUM_CAST_INT, true], // rgdcritstrkrtng
|
||||
41 => [FILTER_CR_NUMERIC, 'is.armor' , NUM_CAST_INT, true], // armor
|
||||
42 => [FILTER_CR_NUMERIC, 'is.defrtng', NUM_CAST_INT, true], // defrtng
|
||||
43 => [FILTER_CR_NUMERIC, 'is.block', NUM_CAST_INT, true], // block
|
||||
44 => [FILTER_CR_NUMERIC, 'is.blockrtng', NUM_CAST_INT, true], // blockrtng
|
||||
45 => [FILTER_CR_NUMERIC, 'is.dodgertng', NUM_CAST_INT, true], // dodgertng
|
||||
46 => [FILTER_CR_NUMERIC, 'is.parryrtng', NUM_CAST_INT, true], // parryrtng
|
||||
48 => [FILTER_CR_NUMERIC, 'is.splhitrtng', NUM_CAST_INT, true], // splhitrtng
|
||||
49 => [FILTER_CR_NUMERIC, 'is.splcritstrkrtng', NUM_CAST_INT, true], // splcritstrkrtng
|
||||
50 => [FILTER_CR_NUMERIC, 'is.splheal', NUM_CAST_INT, true], // splheal
|
||||
51 => [FILTER_CR_NUMERIC, 'is.spldmg', NUM_CAST_INT, true], // spldmg
|
||||
52 => [FILTER_CR_NUMERIC, 'is.arcsplpwr', NUM_CAST_INT, true], // arcsplpwr
|
||||
53 => [FILTER_CR_NUMERIC, 'is.firsplpwr', NUM_CAST_INT, true], // firsplpwr
|
||||
54 => [FILTER_CR_NUMERIC, 'is.frosplpwr', NUM_CAST_INT, true], // frosplpwr
|
||||
55 => [FILTER_CR_NUMERIC, 'is.holsplpwr', NUM_CAST_INT, true], // holsplpwr
|
||||
56 => [FILTER_CR_NUMERIC, 'is.natsplpwr', NUM_CAST_INT, true], // natsplpwr
|
||||
57 => [FILTER_CR_NUMERIC, 'is.shasplpwr', NUM_CAST_INT, true], // shasplpwr
|
||||
60 => [FILTER_CR_NUMERIC, 'is.healthrgn', NUM_CAST_INT, true], // healthrgn
|
||||
61 => [FILTER_CR_NUMERIC, 'is.manargn', NUM_CAST_INT, true], // manargn
|
||||
77 => [FILTER_CR_NUMERIC, 'is.atkpwr', NUM_CAST_INT, true], // atkpwr
|
||||
78 => [FILTER_CR_NUMERIC, 'is.mlehastertng', NUM_CAST_INT, true], // mlehastertng
|
||||
79 => [FILTER_CR_NUMERIC, 'is.resirtng', NUM_CAST_INT, true], // resirtng
|
||||
84 => [FILTER_CR_NUMERIC, 'is.mlecritstrkrtng', NUM_CAST_INT, true], // mlecritstrkrtng
|
||||
94 => [FILTER_CR_NUMERIC, 'is.splpen', NUM_CAST_INT, true], // splpen
|
||||
95 => [FILTER_CR_NUMERIC, 'is.mlehitrtng', NUM_CAST_INT, true], // mlehitrtng
|
||||
96 => [FILTER_CR_NUMERIC, 'is.critstrkrtng', NUM_CAST_INT, true], // critstrkrtng
|
||||
97 => [FILTER_CR_NUMERIC, 'is.feratkpwr', NUM_CAST_INT, true], // feratkpwr
|
||||
101 => [FILTER_CR_NUMERIC, 'is.rgdhastertng', NUM_CAST_INT, true], // rgdhastertng
|
||||
102 => [FILTER_CR_NUMERIC, 'is.splhastertng', NUM_CAST_INT, true], // splhastertng
|
||||
103 => [FILTER_CR_NUMERIC, 'is.hastertng', NUM_CAST_INT, true], // hastertng
|
||||
114 => [FILTER_CR_NUMERIC, 'is.armorpenrtng', NUM_CAST_INT, true], // armorpenrtng
|
||||
115 => [FILTER_CR_NUMERIC, 'is.health', NUM_CAST_INT, true], // health
|
||||
116 => [FILTER_CR_NUMERIC, 'is.mana', NUM_CAST_INT, true], // mana
|
||||
117 => [FILTER_CR_NUMERIC, 'is.exprtng', NUM_CAST_INT, true], // exprtng
|
||||
119 => [FILTER_CR_NUMERIC, 'is.hitrtng', NUM_CAST_INT, true], // hitrtng
|
||||
123 => [FILTER_CR_NUMERIC, 'is.splpwr', NUM_CAST_INT, true] // splpwr
|
||||
);
|
||||
|
||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||
protected $inputFields = array(
|
||||
'cr' => [FILTER_V_RANGE, [2, 123], true ], // criteria ids
|
||||
'crs' => [FILTER_V_RANGE, [1, 15], true ], // criteria operators
|
||||
'crv' => [FILTER_V_RANGE, [0, 99999], true ], // criteria values - only numerals
|
||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name - only printable chars, no delimiter
|
||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||
'ty' => [FILTER_V_RANGE, [1, 8], true ] // types
|
||||
);
|
||||
|
||||
protected function createSQLForCriterium(&$cr)
|
||||
{
|
||||
if (in_array($cr[0], array_keys($this->genericFilter)))
|
||||
if ($genCr = $this->genericCriterion($cr))
|
||||
return $genCr;
|
||||
|
||||
unset($cr);
|
||||
$this->error = true;
|
||||
return [1];
|
||||
}
|
||||
|
||||
protected function createSQLForValues()
|
||||
{
|
||||
$parts = [];
|
||||
$_v = &$this->fiData['v'];
|
||||
|
||||
//string
|
||||
if (isset($_v['na']))
|
||||
if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
|
||||
$parts[] = $_;
|
||||
|
||||
// type
|
||||
if (isset($_v['ty']))
|
||||
{
|
||||
$_ = (array)$_v['ty'];
|
||||
if (!array_diff($_, [1, 2, 3, 4, 5, 6, 7, 8]))
|
||||
$parts[] = ['OR', ['type1', $_], ['type2', $_], ['type3', $_]];
|
||||
else
|
||||
unset($_v['ty']);
|
||||
}
|
||||
|
||||
return $parts;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -6,15 +6,16 @@ if (!defined('AOWOW_REVISION'))
|
||||
|
||||
class FactionList extends BaseType
|
||||
{
|
||||
public static $type = TYPE_FACTION;
|
||||
public static $brickFile = 'faction';
|
||||
public static $type = TYPE_FACTION;
|
||||
public static $brickFile = 'faction';
|
||||
public static $dataTable = '?_factions';
|
||||
|
||||
protected $queryBase = 'SELECT f.*, f.parentFactionId AS cat, f.id AS ARRAY_KEY FROM ?_factions f';
|
||||
protected $queryOpts = array(
|
||||
'f' => [['f2']],
|
||||
'f2' => ['j' => ['?_factions f2 ON f.parentFactionId = f2.id', true], 's' => ', IFNULL(f2.parentFactionId, 0) AS cat2'],
|
||||
'ft' => ['j' => '?_factiontemplate ft ON ft.factionId = f.id']
|
||||
);
|
||||
protected $queryBase = 'SELECT f.*, f.parentFactionId AS cat, f.id AS ARRAY_KEY FROM ?_factions f';
|
||||
protected $queryOpts = array(
|
||||
'f' => [['f2']],
|
||||
'f2' => ['j' => ['?_factions f2 ON f.parentFactionId = f2.id', true], 's' => ', IFNULL(f2.parentFactionId, 0) AS cat2'],
|
||||
'ft' => ['j' => '?_factiontemplate ft ON ft.factionId = f.id']
|
||||
);
|
||||
|
||||
public function __construct($conditions = [])
|
||||
{
|
||||
|
||||
@@ -8,11 +8,12 @@ class GameObjectList extends BaseType
|
||||
{
|
||||
use listviewHelper, spawnHelper;
|
||||
|
||||
public static $type = TYPE_OBJECT;
|
||||
public static $brickFile = 'object';
|
||||
public static $type = TYPE_OBJECT;
|
||||
public static $brickFile = 'object';
|
||||
public static $dataTable = '?_objects';
|
||||
|
||||
protected $queryBase = 'SELECT o.*, o.id AS ARRAY_KEY FROM ?_objects o';
|
||||
protected $queryOpts = array(
|
||||
protected $queryBase = 'SELECT o.*, o.id AS ARRAY_KEY FROM ?_objects o';
|
||||
protected $queryOpts = array(
|
||||
'o' => [['ft', 'qse']],
|
||||
'ft' => ['j' => ['?_factiontemplate ft ON ft.id = o.faction', true], 's' => ', ft.factionId, ft.A, ft.H'],
|
||||
'qse' => ['j' => ['?_quests_startend qse ON qse.type = 2 AND qse.typeId = o.id', true], 's' => ', IF(min(qse.method) = 1 OR max(qse.method) = 3, 1, 0) AS startsQuests, IF(min(qse.method) = 2 OR max(qse.method) = 3, 1, 0) AS endsQuests', 'g' => 'o.id'],
|
||||
@@ -92,8 +93,9 @@ class GameObjectList extends BaseType
|
||||
|
||||
$x = '<table>';
|
||||
$x .= '<tr><td><b class="q">'.$this->getField('name', true).'</b></td></tr>';
|
||||
if ($_ = Lang::gameObject('type', $this->curTpl['typeCat']))
|
||||
$x .= '<tr><td>'.$_.'</td></tr>';
|
||||
if ($this->curTpl['typeCat'])
|
||||
if ($_ = Lang::gameObject('type', $this->curTpl['typeCat']))
|
||||
$x .= '<tr><td>'.$_.'</td></tr>';
|
||||
|
||||
if (isset($this->curTpl['lockId']))
|
||||
if ($locks = Lang::getLocks($this->curTpl['lockId']))
|
||||
@@ -140,98 +142,36 @@ class GameObjectListFilter extends Filter
|
||||
public $extraOpts = [];
|
||||
|
||||
protected $genericFilter = array(
|
||||
1 => [FILTER_CR_ENUM, 's.areaId', null ], // foundin
|
||||
7 => [FILTER_CR_NUMERIC, 'reqSkill', null ], // requiredskilllevel
|
||||
11 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT], // hasscreenshots
|
||||
13 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||
15 => [FILTER_CR_NUMERIC, 'id', null ], // id
|
||||
18 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
||||
1 => [FILTER_CR_ENUM, 's.areaId', null ], // foundin
|
||||
2 => [FILTER_CR_CALLBACK, 'cbQuestRelation', 'startsQuests', 0x1 ], // startsquest [side]
|
||||
3 => [FILTER_CR_CALLBACK, 'cbQuestRelation', 'endsQuests', 0x2 ], // endsquest [side]
|
||||
4 => [FILTER_CR_CALLBACK, 'cbOpenable', null, null], // openable [yn]
|
||||
5 => [FILTER_CR_NYI_PH, null, null ], // averagemoneycontained [op] [int] - GOs don't contain money, match against 0
|
||||
7 => [FILTER_CR_NUMERIC, 'reqSkill', NUM_CAST_INT ], // requiredskilllevel
|
||||
11 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
||||
13 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||
15 => [FILTER_CR_NUMERIC, 'id', NUM_CAST_INT ], // id
|
||||
16 => [FILTER_CR_CALLBACK, 'cbRelEvent', null, null], // relatedevent (ignore removed by event)
|
||||
18 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ] // hasvideos
|
||||
);
|
||||
|
||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||
protected $inputFields = array(
|
||||
'cr' => [FILTER_V_LIST, [[1, 5], 7, 11, 13, 15, 16, 18], true ], // criteria ids
|
||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 5000]], true ], // criteria operators
|
||||
'crv' => [FILTER_V_RANGE, [0, 99999], true ], // criteria values - only numeric input values expected
|
||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name - only printable chars, no delimiter
|
||||
'ma' => [FILTER_V_EQUAL, 1, false] // match any / all filter
|
||||
);
|
||||
|
||||
protected function createSQLForCriterium(&$cr)
|
||||
{
|
||||
if (in_array($cr[0], array_keys($this->genericFilter)))
|
||||
{
|
||||
if ($genCR = $this->genericCriterion($cr))
|
||||
return $genCR;
|
||||
|
||||
unset($cr);
|
||||
$this->error = true;
|
||||
return [1];
|
||||
}
|
||||
|
||||
switch ($cr[0])
|
||||
{
|
||||
case 4:
|
||||
if (!$this->int2Bool($cr[1]))
|
||||
break;
|
||||
|
||||
return $cr[1] ? ['OR', ['flags', 0x2, '&'], ['type', 3]] : ['AND', [['flags', 0x2, '&'], 0], ['type', 3, '!']];
|
||||
case 5: // averagemoneycontained [op] [int] GOs don't contain money .. eval to 0 == true
|
||||
if (!$this->isSaneNumeric($cr[2], false) || !$this->int2Op($cr[1]))
|
||||
break;
|
||||
|
||||
return eval('return ('.$cr[2].' '.$cr[1].' 0)') ? [1] : [0];
|
||||
case 2: // startsquest [side]
|
||||
switch ($cr[1])
|
||||
{
|
||||
case 1: // any
|
||||
return ['AND', ['qse.method', 0x1, '&'], ['qse.questId', null, '!']];
|
||||
case 2: // alliance only
|
||||
return ['AND', ['qse.method', 0x1, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_HORDE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&']];
|
||||
case 3: // horde only
|
||||
return ['AND', ['qse.method', 0x1, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']];
|
||||
case 4: // both
|
||||
return ['AND', ['qse.method', 0x1, '&'], ['qse.questId', null, '!'], ['OR', ['AND', ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']], ['qt.reqRaceMask', 0]]];
|
||||
case 5: // none
|
||||
$this->extraOpts['o']['h'][] = 'startsQuests = 0';
|
||||
return [1];
|
||||
}
|
||||
break;
|
||||
case 3: // endsquest [side]
|
||||
switch ($cr[1])
|
||||
{
|
||||
case 1: // any
|
||||
return ['AND', ['qse.method', 0x2, '&'], ['qse.questId', null, '!']];
|
||||
case 2: // alliance only
|
||||
return ['AND', ['qse.method', 0x2, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_HORDE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&']];
|
||||
case 3: // horde only
|
||||
return ['AND', ['qse.method', 0x2, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']];
|
||||
case 4: // both
|
||||
return ['AND', ['qse.method', 0x2, '&'], ['qse.questId', null, '!'], ['OR', ['AND', ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']], ['qt.reqRaceMask', 0]]];
|
||||
case 5: // none todo: broken, if entry starts and ends quests...
|
||||
$this->extraOpts['o']['h'][] = 'endsQuests = 0';
|
||||
return [1];
|
||||
}
|
||||
break;
|
||||
case 16; // relatedevent (ignore removed by event)
|
||||
if (!$this->isSaneNumeric($cr[1]))
|
||||
break;
|
||||
|
||||
if ($cr[1] == FILTER_ENUM_ANY)
|
||||
{
|
||||
$eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId <> 0');
|
||||
$goGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_gameobject WHERE eventEntry IN (?a)', $eventIds);
|
||||
return ['s.guid', $goGuids];
|
||||
}
|
||||
else if ($cr[1] == FILTER_ENUM_NONE)
|
||||
{
|
||||
$eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId <> 0');
|
||||
$goGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_gameobject WHERE eventEntry IN (?a)', $eventIds);
|
||||
return ['s.guid', $goGuids, '!'];
|
||||
}
|
||||
else if ($cr[1])
|
||||
{
|
||||
$eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId = ?d', $cr[1]);
|
||||
$goGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_gameobject WHERE eventEntry IN (?a)', $eventIds);
|
||||
return ['s.guid', $goGuids];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
unset($cr);
|
||||
$this->error = 1;
|
||||
$this->error = true;
|
||||
return [1];
|
||||
}
|
||||
|
||||
@@ -247,6 +187,61 @@ class GameObjectListFilter extends Filter
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
protected function cbOpenable($cr)
|
||||
{
|
||||
if ($this->int2Bool($cr[1]))
|
||||
return $cr[1] ? ['OR', ['flags', 0x2, '&'], ['type', 3]] : ['AND', [['flags', 0x2, '&'], 0], ['type', 3, '!']];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbQuestRelation($cr, $field, $value)
|
||||
{
|
||||
switch ($cr[1])
|
||||
{
|
||||
case 1: // any
|
||||
return ['AND', ['qse.method', $value, '&'], ['qse.questId', null, '!']];
|
||||
case 2: // alliance only
|
||||
return ['AND', ['qse.method', $value, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_HORDE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&']];
|
||||
case 3: // horde only
|
||||
return ['AND', ['qse.method', $value, '&'], ['qse.questId', null, '!'], [['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], 0], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']];
|
||||
case 4: // both
|
||||
return ['AND', ['qse.method', $value, '&'], ['qse.questId', null, '!'], ['OR', ['AND', ['qt.reqRaceMask', RACE_MASK_ALLIANCE, '&'], ['qt.reqRaceMask', RACE_MASK_HORDE, '&']], ['qt.reqRaceMask', 0]]];
|
||||
case 5: // none todo (low): broken, if entry starts and ends quests...
|
||||
$this->extraOpts['o']['h'][] = $field.' = 0';
|
||||
return [1];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbRelEvent($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[1], NUM_REQ_INT))
|
||||
return false;;
|
||||
|
||||
if ($cr[1] == FILTER_ENUM_ANY)
|
||||
{
|
||||
$eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId <> 0');
|
||||
$goGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_gameobject WHERE eventEntry IN (?a)', $eventIds);
|
||||
return ['s.guid', $goGuids];
|
||||
}
|
||||
else if ($cr[1] == FILTER_ENUM_NONE)
|
||||
{
|
||||
$eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId <> 0');
|
||||
$goGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_gameobject WHERE eventEntry IN (?a)', $eventIds);
|
||||
return ['s.guid', $goGuids, '!'];
|
||||
}
|
||||
else if ($cr[1])
|
||||
{
|
||||
$eventIds = DB::Aowow()->selectCol('SELECT id FROM ?_events WHERE holidayId = ?d', $cr[1]);
|
||||
$goGuids = DB::World()->selectCol('SELECT DISTINCT guid FROM game_event_gameobject WHERE eventEntry IN (?a)', $eventIds);
|
||||
return ['s.guid', $goGuids];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
307
includes/types/guild.class.php
Normal file
307
includes/types/guild.class.php
Normal file
@@ -0,0 +1,307 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class GuildList extends BaseType
|
||||
{
|
||||
use profilerHelper, listviewHelper;
|
||||
|
||||
public function getListviewData()
|
||||
{
|
||||
$this->getGuildScores();
|
||||
|
||||
$data = [];
|
||||
foreach ($this->iterate() as $__)
|
||||
{
|
||||
$data[$this->id] = array(
|
||||
'name' => "$'".$this->curTpl['name']."'", // MUST be a string
|
||||
'members' => $this->curTpl['members'],
|
||||
'faction' => $this->curTpl['faction'],
|
||||
'achievementpoints' => $this->getField('achievementpoints'),
|
||||
'gearscore' => $this->getField('gearscore'),
|
||||
'realm' => Profiler::urlize($this->curTpl['realmName']),
|
||||
'realmname' => $this->curTpl['realmName'],
|
||||
// 'battlegroup' => Profiler::urlize($this->curTpl['battlegroup']), // was renamed to subregion somewhere around cata release
|
||||
// 'battlegroupname' => $this->curTpl['battlegroup'],
|
||||
'region' => Profiler::urlize($this->curTpl['region'])
|
||||
);
|
||||
}
|
||||
|
||||
return array_values($data);
|
||||
}
|
||||
|
||||
private function getGuildScores()
|
||||
{
|
||||
/*
|
||||
Guild gear scores and achievement points are derived using a weighted average of all of the known characters in that guild.
|
||||
Guilds with at least 25 level 80 players receive full benefit of the top 25 characters' gear scores, while guilds with at least 10 level 80 characters receive a slight penalty,
|
||||
at least 1 level 80 a moderate penalty, and no level 80 characters a severe penalty. [...]
|
||||
Instead of being based on level, achievement point averages are based around 1,500 points, but the same penalties apply.
|
||||
*/
|
||||
$guilds = array_column($this->templates, 'id');
|
||||
if (!$guilds)
|
||||
return;
|
||||
|
||||
$stats = DB::Aowow()->select('SELECT guild AS ARRAY_KEY, id AS ARRAY_KEY2, level, gearscore, achievementpoints, IF(cuFlags & ?d, 0, 1) AS synced FROM ?_profiler_profiles WHERE guild IN (?a) ORDER BY gearscore DESC', PROFILER_CU_NEEDS_RESYNC, $guilds);
|
||||
foreach ($this->iterate() as &$_curTpl)
|
||||
{
|
||||
$id = $_curTpl['id'];
|
||||
if (empty($stats[$id]))
|
||||
continue;
|
||||
|
||||
$guildStats = array_filter($stats[$id], function ($x) { return $x['synced']; } );
|
||||
if (!$guildStats)
|
||||
continue;
|
||||
|
||||
$nMaxLevel = count(array_filter($stats[$id], function ($x) { return $x['level'] >= MAX_LEVEL; } ));
|
||||
$levelMod = 1.0;
|
||||
|
||||
if ($nMaxLevel < 25)
|
||||
$levelMod = 0.85;
|
||||
if ($nMaxLevel < 10)
|
||||
$levelMod = 0.66;
|
||||
if ($nMaxLevel < 1)
|
||||
$levelMod = 0.20;
|
||||
|
||||
$totalGS = $totalAP = $nMembers = 0;
|
||||
foreach ($guildStats as $gs)
|
||||
{
|
||||
$totalGS += $gs['gearscore'] * $levelMod * min($gs['level'], MAX_LEVEL) / MAX_LEVEL;
|
||||
$totalAP += $gs['achievementpoints'] * $levelMod * min($gs['achievementpoints'], 1500) / 1500;
|
||||
$nMembers += min($gs['level'], MAX_LEVEL) / MAX_LEVEL;
|
||||
}
|
||||
|
||||
$_curTpl['gearscore'] = intval($totalGS / $nMembers);
|
||||
$_curTpl['achievementpoints'] = intval($totalAP / $nMembers);
|
||||
}
|
||||
}
|
||||
|
||||
public function renderTooltip() {}
|
||||
public function getJSGlobals($addMask = 0) {}
|
||||
}
|
||||
|
||||
|
||||
class GuildListFilter extends Filter
|
||||
{
|
||||
public $extraOpts = [];
|
||||
protected $genericFilter = [];
|
||||
|
||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||
protected $inputFields = array(
|
||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name - only printable chars, no delimiter
|
||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||
'ex' => [FILTER_V_EQUAL, 'on', false], // only match exact
|
||||
'si' => [FILTER_V_LIST, [1, 2], false], // side
|
||||
'rg' => [FILTER_V_CALLBACK, 'cbRegionCheck', false], // region
|
||||
'sv' => [FILTER_V_CALLBACK, 'cbServerCheck', false], // server
|
||||
);
|
||||
|
||||
protected function createSQLForCriterium(&$cr) { }
|
||||
|
||||
protected function createSQLForValues()
|
||||
{
|
||||
$parts = [];
|
||||
$_v = $this->fiData['v'];
|
||||
|
||||
// region (rg), battlegroup (bg) and server (sv) are passed to GuildList as miscData and handled there
|
||||
|
||||
// name [str]
|
||||
if (!empty($_v['na']))
|
||||
if ($_ = $this->modularizeString(['g.name'], $_v['na'], !empty($_v['ex']) && $_v['ex'] == 'on'))
|
||||
$parts[] = $_;
|
||||
|
||||
// side [list]
|
||||
if (!empty($_v['si']))
|
||||
{
|
||||
if ($_v['si'] == 1)
|
||||
$parts[] = ['c.race', [1, 3, 4, 7, 11]];
|
||||
else if ($_v['si'] == 2)
|
||||
$parts[] = ['c.race', [2, 5, 6, 8, 10]];
|
||||
}
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
protected function cbRegionCheck(&$v)
|
||||
{
|
||||
if ($v == 'eu' || $v == 'us')
|
||||
{
|
||||
$this->parentCats[0] = $v; // directly redirect onto this region
|
||||
$v = ''; // remove from filter
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbServerCheck(&$v)
|
||||
{
|
||||
foreach (Profiler::getRealms() as $realm)
|
||||
if ($realm['name'] == $v)
|
||||
{
|
||||
$this->parentCats[1] = Profiler::urlize($v);// directly redirect onto this server
|
||||
$v = ''; // remove from filter
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class RemoteGuildList extends GuildList
|
||||
{
|
||||
protected $queryBase = 'SELECT `g`.*, `g`.`guildid` AS ARRAY_KEY FROM guild g';
|
||||
protected $queryOpts = array(
|
||||
'g' => [['gm', 'c'], 'g' => 'ARRAY_KEY'],
|
||||
'gm' => ['j' => 'guild_member gm ON gm.guildid = g.guildid', 's' => ', COUNT(1) AS members'],
|
||||
'c' => ['j' => 'characters c ON c.guid = gm.guid', 's' => ', BIT_OR(IF(c.race IN (1, 3, 4, 7, 11), 1, 2)) - 1 AS faction']
|
||||
);
|
||||
|
||||
public function __construct($conditions = [], $miscData = null)
|
||||
{
|
||||
// select DB by realm
|
||||
if (!$this->selectRealms($miscData))
|
||||
{
|
||||
trigger_error('no access to auth-db or table realmlist is empty', E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
parent::__construct($conditions, $miscData);
|
||||
|
||||
if ($this->error)
|
||||
return;
|
||||
|
||||
reset($this->dbNames); // only use when querying single realm
|
||||
$realmId = key($this->dbNames);
|
||||
$realms = Profiler::getRealms();
|
||||
$distrib = [];
|
||||
|
||||
// post processing
|
||||
foreach ($this->iterate() as $guid => &$curTpl)
|
||||
{
|
||||
// battlegroup
|
||||
$curTpl['battlegroup'] = CFG_BATTLEGROUP;
|
||||
|
||||
$r = explode(':', $guid)[0];
|
||||
if (!empty($realms[$r]))
|
||||
{
|
||||
$curTpl['realm'] = $r;
|
||||
$curTpl['realmName'] = $realms[$r]['name'];
|
||||
$curTpl['region'] = $realms[$r]['region'];
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error('character "'.$curTpl['name'].'" belongs to nonexistant realm #'.$r, E_USER_WARNING);
|
||||
unset($this->templates[$guid]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// equalize distribution
|
||||
if (empty($distrib[$curTpl['realm']]))
|
||||
$distrib[$curTpl['realm']] = 1;
|
||||
else
|
||||
$distrib[$curTpl['realm']]++;
|
||||
}
|
||||
|
||||
$limit = CFG_SQL_LIMIT_DEFAULT;
|
||||
foreach ($conditions as $c)
|
||||
if (is_int($c))
|
||||
$limit = $c;
|
||||
|
||||
$total = array_sum($distrib);
|
||||
foreach ($distrib as &$d)
|
||||
$d = ceil($limit * $d / $total);
|
||||
|
||||
foreach ($this->iterate() as $guid => &$curTpl)
|
||||
{
|
||||
if ($limit <= 0 || $distrib[$curTpl['realm']] <= 0)
|
||||
{
|
||||
unset($this->templates[$guid]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$distrib[$curTpl['realm']]--;
|
||||
$limit--;
|
||||
}
|
||||
}
|
||||
|
||||
public function initializeLocalEntries()
|
||||
{
|
||||
$data = [];
|
||||
foreach ($this->iterate() as $guid => $__)
|
||||
{
|
||||
$data[$guid] = array(
|
||||
'realm' => $this->getField('realm'),
|
||||
'realmGUID' => $this->getField('guildid'),
|
||||
'name' => $this->getField('name'),
|
||||
'nameUrl' => Profiler::urlize($this->getField('name')),
|
||||
'cuFlags' => PROFILER_CU_NEEDS_RESYNC
|
||||
);
|
||||
}
|
||||
|
||||
// basic guild data
|
||||
foreach (Util::createSqlBatchInsert($data) as $ins)
|
||||
DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_guild (?#) VALUES '.$ins, array_keys(reset($data)));
|
||||
|
||||
// merge back local ids
|
||||
$localIds = DB::Aowow()->selectCol(
|
||||
'SELECT CONCAT(realm, ":", realmGUID) AS ARRAY_KEY, id FROM ?_profiler_guild WHERE realm IN (?a) AND realmGUID IN (?a)',
|
||||
array_column($data, 'realm'),
|
||||
array_column($data, 'realmGUID')
|
||||
);
|
||||
|
||||
foreach ($this->iterate() as $guid => &$_curTpl)
|
||||
if (isset($localIds[$guid]))
|
||||
$_curTpl['id'] = $localIds[$guid];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class LocalGuildList extends GuildList
|
||||
{
|
||||
protected $queryBase = 'SELECT g.*, g.id AS ARRAY_KEY FROM ?_profiler_guild g';
|
||||
|
||||
public function __construct($conditions = [], $miscData = null)
|
||||
{
|
||||
parent::__construct($conditions, $miscData);
|
||||
|
||||
if ($this->error)
|
||||
return;
|
||||
|
||||
$realms = Profiler::getRealms();
|
||||
|
||||
foreach ($this->iterate() as $id => &$curTpl)
|
||||
{
|
||||
if ($curTpl['realm'] && !isset($realms[$curTpl['realm']]))
|
||||
continue;
|
||||
|
||||
if (isset($realms[$curTpl['realm']]))
|
||||
{
|
||||
$curTpl['realmName'] = $realms[$curTpl['realm']]['name'];
|
||||
$curTpl['region'] = $realms[$curTpl['realm']]['region'];
|
||||
}
|
||||
|
||||
// battlegroup
|
||||
$curTpl['battlegroup'] = CFG_BATTLEGROUP;
|
||||
}
|
||||
}
|
||||
|
||||
public function getProfileUrl()
|
||||
{
|
||||
$url = '?guild=';
|
||||
|
||||
return $url.implode('.', array(
|
||||
Profiler::urlize($this->getField('region')),
|
||||
Profiler::urlize($this->getField('realmName')),
|
||||
Profiler::urlize($this->getField('name'))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
237
includes/types/icon.class.php
Normal file
237
includes/types/icon.class.php
Normal file
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class IconList extends BaseType
|
||||
{
|
||||
use listviewHelper;
|
||||
|
||||
public static $type = TYPE_ICON;
|
||||
public static $brickFile = 'icon';
|
||||
public static $dataTable = '?_icons';
|
||||
public static $contribute = CONTRIBUTE_CO;
|
||||
|
||||
private $pseudoQry = 'SELECT iconId AS ARRAY_KEY, COUNT(*) FROM ?# WHERE iconId IN (?a) GROUP BY iconId';
|
||||
private $pseudoJoin = array(
|
||||
'nItems' => '?_items',
|
||||
'nSpells' => '?_spell',
|
||||
'nAchievements' => '?_achievement',
|
||||
'nCurrencies' => '?_currencies',
|
||||
'nPets' => '?_pet'
|
||||
);
|
||||
|
||||
protected $queryBase = 'SELECT ic.*, ic.id AS ARRAY_KEY FROM ?_icons ic';
|
||||
/* this works, but takes ~100x more time than i'm comfortable with .. kept as reference
|
||||
protected $queryOpts = array( // 29 => TYPE_ICON
|
||||
'ic' => [['s', 'i', 'a', 'c', 'p'], 'g' => 'ic.id'],
|
||||
'i' => ['j' => ['?_items `i` ON `i`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `i`.`id`) AS nItems'],
|
||||
's' => ['j' => ['?_spell `s` ON `s`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `s`.`id`) AS nSpells'],
|
||||
'a' => ['j' => ['?_achievement `a` ON `a`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `a`.`id`) AS nAchievements'],
|
||||
'c' => ['j' => ['?_currencies `c` ON `c`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `c`.`id`) AS nCurrencies'],
|
||||
'p' => ['j' => ['?_pet `p` ON `p`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `p`.`id`) AS nPets']
|
||||
);
|
||||
*/
|
||||
|
||||
public function __construct($conditions)
|
||||
{
|
||||
parent::__construct($conditions);
|
||||
|
||||
if (!$this->getFoundIDs())
|
||||
return;
|
||||
|
||||
foreach ($this->pseudoJoin as $var => $tbl)
|
||||
{
|
||||
$res = DB::Aowow()->selectCol($this->pseudoQry, $tbl, $this->getFoundIDs());
|
||||
foreach ($res as $icon => $qty)
|
||||
$this->templates[$icon][$var] = $qty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// use if you JUST need the name
|
||||
public static function getName($id)
|
||||
{
|
||||
$n = DB::Aowow()->SelectRow('SELECT name FROM ?_icons WHERE id = ?d', $id );
|
||||
return Util::localizedString($n, 'name');
|
||||
}
|
||||
// end static use
|
||||
|
||||
public function getListviewData($addInfoMask = 0x0)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($this->iterate() as $__)
|
||||
{
|
||||
$data[$this->id] = array(
|
||||
'id' => $this->id,
|
||||
'name' => $this->getField('name', true, true),
|
||||
'icon' => $this->getField('name', true, true),
|
||||
'itemcount' => (int)$this->getField('nItems'),
|
||||
'spellcount' => (int)$this->getField('nSpells'),
|
||||
'achievementcount' => (int)$this->getField('nAchievements'),
|
||||
'npccount' => 0, // UNUSED
|
||||
'petabilitycount' => 0, // UNUSED
|
||||
'currencycount' => (int)$this->getField('nCurrencies'),
|
||||
'missionabilitycount' => 0, // UNUSED
|
||||
'buildingcount' => 0, // UNUSED
|
||||
'petcount' => (int)$this->getField('nPets'),
|
||||
'threatcount' => 0, // UNUSED
|
||||
'classcount' => 0 // class icons are hardcoded and not referenced in dbc
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getJSGlobals($addMask = GLOBALINFO_ANY)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($this->iterate() as $__)
|
||||
$data[TYPE_ICON][$this->id] = ['name' => $this->getField('name', true, true), 'icon' => $this->getField('name', true, true)];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function renderTooltip() { }
|
||||
}
|
||||
|
||||
|
||||
class IconListFilter extends Filter
|
||||
{
|
||||
public $extraOpts = null;
|
||||
|
||||
// cr => [type, field, misc, extraCol]
|
||||
private $criterion2field = array(
|
||||
1 => '?_items', // items [num]
|
||||
2 => '?_spell', // spells [num]
|
||||
3 => '?_achievement', // achievements [num]
|
||||
// 4 => '', // battlepets [num]
|
||||
// 5 => '', // battlepetabilities [num]
|
||||
6 => '?_currencies', // currencies [num]
|
||||
// 7 => '', // garrisonabilities [num]
|
||||
// 8 => '', // garrisonbuildings [num]
|
||||
9 => '?_pet', // hunterpets [num]
|
||||
// 10 => '', // garrisonmissionthreats [num]
|
||||
11 => '', // classes [num]
|
||||
13 => '' // used [num]
|
||||
);
|
||||
private $totalUses = [];
|
||||
|
||||
protected $genericFilter = array(
|
||||
1 => [FILTER_CR_CALLBACK, 'cbUseAny' ], // items [num]
|
||||
2 => [FILTER_CR_CALLBACK, 'cbUseAny' ], // spells [num]
|
||||
3 => [FILTER_CR_CALLBACK, 'cbUseAny' ], // achievements [num]
|
||||
6 => [FILTER_CR_CALLBACK, 'cbUseAny' ], // currencies [num]
|
||||
9 => [FILTER_CR_CALLBACK, 'cbUseAny' ], // hunterpets [num]
|
||||
11 => [FILTER_CR_NYI_PH, null, null], // classes [num]
|
||||
13 => [FILTER_CR_CALLBACK, 'cbUseAll' ] // used [num]
|
||||
);
|
||||
|
||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||
protected $inputFields = array(
|
||||
'cr' => [FILTER_V_LIST, [1, 2, 3, 6, 9, 11, 13], true ], // criteria ids
|
||||
'crs' => [FILTER_V_RANGE, [1, 6], true ], // criteria operators
|
||||
'crv' => [FILTER_V_RANGE, [0, 99999], true ], // criteria values - all criteria are numeric here
|
||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name - only printable chars, no delimiter
|
||||
'ma' => [FILTER_V_EQUAL, 1, false] // match any / all filter
|
||||
);
|
||||
|
||||
private function _getCnd($op, $val, $tbl)
|
||||
{
|
||||
switch ($op)
|
||||
{
|
||||
case '>':
|
||||
case '>=':
|
||||
case '=':
|
||||
$ids = DB::Aowow()->selectCol('SELECT iconId AS ARRAY_KEY, COUNT(*) AS n FROM ?# GROUP BY iconId HAVING n '.$op.' '.$val, $tbl);
|
||||
return $ids ? ['id', array_keys($ids)] : [1];
|
||||
case '<=':
|
||||
if ($val)
|
||||
$op = '>';
|
||||
break;
|
||||
case '<':
|
||||
if ($val)
|
||||
$op = '>=';
|
||||
break;
|
||||
case '!=':
|
||||
if ($val)
|
||||
$op = '=';
|
||||
break;
|
||||
}
|
||||
|
||||
$ids = DB::Aowow()->selectCol('SELECT iconId AS ARRAY_KEY, COUNT(*) AS n FROM ?# GROUP BY iconId HAVING n '.$op.' '.$val, $tbl);
|
||||
return $ids ? ['id', array_keys($ids), '!'] : [1];
|
||||
}
|
||||
|
||||
protected function createSQLForCriterium(&$cr)
|
||||
{
|
||||
if (in_array($cr[0], array_keys($this->genericFilter)))
|
||||
if ($genCr = $this->genericCriterion($cr))
|
||||
return $genCr;
|
||||
|
||||
unset($cr);
|
||||
$this->error = true;
|
||||
return [1];
|
||||
}
|
||||
|
||||
protected function createSQLForValues()
|
||||
{
|
||||
$parts = [];
|
||||
$_v = &$this->fiData['v'];
|
||||
|
||||
//string
|
||||
if (isset($_v['na']))
|
||||
if ($_ = $this->modularizeString(['name']))
|
||||
$parts[] = $_;
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
protected function cbUseAny($cr, $value)
|
||||
{
|
||||
if (Util::checkNumeric($cr[2], NUM_CAST_INT) && $this->int2Op($cr[1]))
|
||||
return $this->_getCnd($cr[1], $cr[2], $this->criterion2field[$cr[0]]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbUseAll($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[2], NUM_CAST_INT) || !$this->int2Op($cr[1]))
|
||||
return false;
|
||||
|
||||
if (!$this->totalUses)
|
||||
{
|
||||
foreach ($this->criterion2field as $tbl)
|
||||
{
|
||||
if (!$tbl)
|
||||
continue;
|
||||
|
||||
$res = DB::Aowow()->selectCol('SELECT iconId AS ARRAY_KEY, COUNT(*) AS n FROM ?# GROUP BY iconId', $tbl);
|
||||
Util::arraySumByKey($this->totalUses, $res);
|
||||
}
|
||||
}
|
||||
|
||||
if ($cr[1] == '=')
|
||||
$cr[1] = '==';
|
||||
|
||||
$op = $cr[1];
|
||||
if ($cr[1] == '<=' && $cr[2])
|
||||
$op = '>';
|
||||
else if ($cr[1] == '<' && $cr[2])
|
||||
$op = '>=';
|
||||
else if ($cr[1] == '!=' && $cr[2])
|
||||
$op = '==';
|
||||
$ids = array_filter($this->totalUses, function ($x) use ($op, $cr) { return eval('return '.$x.' '.$op.' '.$cr[2].';'); });
|
||||
|
||||
if ($cr[1] != $op)
|
||||
return $ids ? ['id', array_keys($ids), '!'] : [1];
|
||||
else
|
||||
return $ids ? ['id', array_keys($ids)] : ['id', array_keys($this->totalUses), '!'];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,14 +8,18 @@ class ItemsetList extends BaseType
|
||||
{
|
||||
use ListviewHelper;
|
||||
|
||||
public static $type = TYPE_ITEMSET;
|
||||
public static $brickFile = 'itemset';
|
||||
public static $type = TYPE_ITEMSET;
|
||||
public static $brickFile = 'itemset';
|
||||
public static $dataTable = '?_itemset';
|
||||
|
||||
public $pieceToSet = []; // used to build g_items and search
|
||||
private $classes = []; // used to build g_classes
|
||||
public $pieceToSet = []; // used to build g_items and search
|
||||
private $classes = []; // used to build g_classes
|
||||
|
||||
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_itemset `set`';
|
||||
protected $queryOpts = ['set' => ['o' => 'maxlevel DESC']];
|
||||
protected $queryBase = 'SELECT `set`.*, `set`.id AS ARRAY_KEY FROM ?_itemset `set`';
|
||||
protected $queryOpts = array(
|
||||
'set' => ['o' => 'maxlevel DESC'],
|
||||
'e' => ['j' => ['?_events e ON e.id = `set`.eventId', true], 's' => ', e.holidayId']
|
||||
);
|
||||
|
||||
public function __construct($conditions = [])
|
||||
{
|
||||
@@ -88,7 +92,77 @@ class ItemsetList extends BaseType
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function renderTooltip() { }
|
||||
public function renderTooltip()
|
||||
{
|
||||
if (!$this->curTpl)
|
||||
return array();
|
||||
|
||||
$x = '<table><tr><td>';
|
||||
$x .= '<span class="q'.$this->getField('quality').'">'.Util::jsEscape($this->getField('name', true)).'</span><br />';
|
||||
|
||||
$nClasses = 0;
|
||||
if ($_ = $this->getField('classMask'))
|
||||
{
|
||||
$cl = Lang::getClassString($_, $__, $nClasses);
|
||||
$x .= Util::ucFirst($nClasses > 1 ? Lang::game('classes') : Lang::game('class')).Lang::main('colon').$cl.'<br />';
|
||||
}
|
||||
|
||||
if ($_ = $this->getField('contentGroup'))
|
||||
$x .= Util::jsEscape(Lang::itemset('notes', $_)).($this->getField('heroic') ? ' <i class="q2">('.Lang::item('heroic').')</i>' : '').'<br />';
|
||||
|
||||
if (!$nClasses || !$this->getField('contentGroup'))
|
||||
$x.= Lang::itemset('types', $this->getField('type')).'<br />';
|
||||
|
||||
if ($bonuses = $this->getBonuses())
|
||||
{
|
||||
$x .= '<span>';
|
||||
|
||||
foreach ($bonuses as $b)
|
||||
$x .= '<br /><span class=\"q13\">'.$b['bonus'].' '.Lang::itemset('_pieces').Lang::main('colon').'</span>'.Util::jsEscape($b['desc']);
|
||||
|
||||
$x .= '</span>';
|
||||
}
|
||||
|
||||
$x .= '</td></tr></table>';
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
public function getBonuses()
|
||||
{
|
||||
$spells = [];
|
||||
for ($i = 1; $i < 9; $i++)
|
||||
{
|
||||
$spl = $this->getField('spell'.$i);
|
||||
$qty = $this->getField('bonus'.$i);
|
||||
|
||||
// cant use spell as index, would change order
|
||||
if ($spl && $qty)
|
||||
$spells[] = ['id' => $spl, 'bonus' => $qty];
|
||||
}
|
||||
|
||||
// sort by required pieces ASC
|
||||
usort($spells, function($a, $b) {
|
||||
if ($a['bonus'] == $b['bonus'])
|
||||
return 0;
|
||||
|
||||
return ($a['bonus'] > $b['bonus']) ? 1 : -1;
|
||||
});
|
||||
|
||||
$setSpells = new SpellList(array(['s.id', array_column($spells, 'id')]));
|
||||
foreach ($setSpells->iterate() as $spellId => $__)
|
||||
{
|
||||
foreach ($spells as &$s)
|
||||
{
|
||||
if ($spellId != $s['id'])
|
||||
continue;
|
||||
|
||||
$s['desc'] = $setSpells->parseText('description', $this->getField('reqLevel') ?: MAX_LEVEL)[0];
|
||||
}
|
||||
}
|
||||
|
||||
return $spells;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,34 +171,40 @@ class ItemsetListFilter extends Filter
|
||||
{
|
||||
// cr => [type, field, misc, extraCol]
|
||||
protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet
|
||||
2 => [FILTER_CR_NUMERIC, 'id', null, true], // id
|
||||
3 => [FILTER_CR_NUMERIC, 'npieces', ], // pieces
|
||||
4 => [FILTER_CR_STRING, 'bonusText', true ], // bonustext
|
||||
5 => [FILTER_CR_BOOLEAN, 'heroic', ], // heroic
|
||||
6 => [FILTER_CR_ENUM, 'holidayId', ], // relatedevent
|
||||
8 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||
9 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
||||
10 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
||||
2 => [FILTER_CR_NUMERIC, 'id', NUM_CAST_INT, true], // id
|
||||
3 => [FILTER_CR_NUMERIC, 'npieces', NUM_CAST_INT ], // pieces
|
||||
4 => [FILTER_CR_STRING, 'bonusText', STR_LOCALIZED ], // bonustext
|
||||
5 => [FILTER_CR_BOOLEAN, 'heroic', ], // heroic
|
||||
6 => [FILTER_CR_ENUM, 'e.holidayId', ], // relatedevent
|
||||
8 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||
9 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
||||
10 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
||||
12 => [FILTER_CR_NYI_PH, null, 1 ] // available to players [yn] - ugh .. scan loot, quest and vendor templates and write to ?_itemset
|
||||
);
|
||||
|
||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||
protected $inputFields = array(
|
||||
'cr' => [FILTER_V_RANGE, [2, 12], true ], // criteria ids
|
||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 424]], true ], // criteria operators
|
||||
'crv' => [FILTER_V_REGEX, '/[\p{C};:]/ui', true ], // criteria values - only printable chars, no delimiters
|
||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name / description - only printable chars, no delimiter
|
||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||
'qu' => [FILTER_V_RANGE, [0, 7], true ], // quality
|
||||
'ty' => [FILTER_V_RANGE, [1, 12], true ], // set type
|
||||
'minle' => [FILTER_V_RANGE, [1, 999], false], // min item level
|
||||
'maxle' => [FILTER_V_RANGE, [1, 999], false], // max itemlevel
|
||||
'minrl' => [FILTER_V_RANGE, [1, MAX_LEVEL], false], // min required level
|
||||
'maxrl' => [FILTER_V_RANGE, [1, MAX_LEVEL], false], // max required level
|
||||
'cl' => [FILTER_V_LIST, [[1, 9], 11], false], // class
|
||||
'ta' => [FILTER_V_RANGE, [1, 30], false] // tag / content group
|
||||
);
|
||||
|
||||
protected function createSQLForCriterium(&$cr)
|
||||
{
|
||||
if (in_array($cr[0], array_keys($this->genericFilter)))
|
||||
{
|
||||
if ($genCR = $this->genericCriterion($cr))
|
||||
return $genCR;
|
||||
|
||||
unset($cr);
|
||||
$this->error = true;
|
||||
return [1];
|
||||
}
|
||||
|
||||
switch ($cr[0])
|
||||
{
|
||||
case 12: // available to players [yn] ugh .. scan loot, quest and vendor templates and write to ?_itemset
|
||||
/* todo */ return [1];
|
||||
}
|
||||
|
||||
unset($cr);
|
||||
$this->error = true;
|
||||
return [1];
|
||||
@@ -142,65 +222,35 @@ class ItemsetListFilter extends Filter
|
||||
|
||||
// quality [enum]
|
||||
if (isset($_v['qu']))
|
||||
$parts[] = ['quality', (array)$_v['qu']];
|
||||
$parts[] = ['quality', $_v['qu']];
|
||||
|
||||
// type [enum]
|
||||
if (isset($_v['ty']))
|
||||
$parts[] = ['type', (array)$_v['ty']];
|
||||
$parts[] = ['type', $_v['ty']];
|
||||
|
||||
// itemLevel min [int]
|
||||
if (isset($_v['minle']))
|
||||
{
|
||||
if (is_int($_v['minle']) && $_v['minle'] > 0)
|
||||
$parts[] = ['minLevel', $_v['minle'], '>='];
|
||||
else
|
||||
unset($_v['minle']);
|
||||
}
|
||||
$parts[] = ['minLevel', $_v['minle'], '>='];
|
||||
|
||||
// itemLevel max [int]
|
||||
if (isset($_v['maxle']))
|
||||
{
|
||||
if (is_int($_v['maxle']) && $_v['maxle'] > 0)
|
||||
$parts[] = ['maxLevel', $_v['maxle'], '<='];
|
||||
else
|
||||
unset($_v['maxle']);
|
||||
}
|
||||
$parts[] = ['maxLevel', $_v['maxle'], '<='];
|
||||
|
||||
// reqLevel min [int]
|
||||
if (isset($_v['minrl']))
|
||||
{
|
||||
if (is_int($_v['minrl']) && $_v['minrl'] > 0)
|
||||
$parts[] = ['reqLevel', $_v['minrl'], '>='];
|
||||
else
|
||||
unset($_v['minrl']);
|
||||
}
|
||||
$parts[] = ['reqLevel', $_v['minrl'], '>='];
|
||||
|
||||
// reqLevel max [int]
|
||||
if (isset($_v['maxrl']))
|
||||
{
|
||||
if (is_int($_v['maxrl']) && $_v['maxrl'] > 0)
|
||||
$parts[] = ['reqLevel', $_v['maxrl'], '<='];
|
||||
else
|
||||
unset($_v['maxrl']);
|
||||
}
|
||||
$parts[] = ['reqLevel', $_v['maxrl'], '<='];
|
||||
|
||||
// class [enum]
|
||||
if (isset($_v['cl']))
|
||||
{
|
||||
if (in_array($_v['cl'], [1, 2, 3, 4, 5, 6, 7, 8, 9, 11]))
|
||||
$parts[] = ['classMask', $this->list2Mask($_v['cl']), '&'];
|
||||
else
|
||||
unset($_v['cl']);
|
||||
}
|
||||
$parts[] = ['classMask', $this->list2Mask([$_v['cl']]), '&'];
|
||||
|
||||
// tag [enum]
|
||||
if (isset($_v['ta']))
|
||||
{
|
||||
if ($_v['ta'] > 0 && $_v['ta'] < 31)
|
||||
$parts[] = ['contentGroup', intVal($_v['ta'])];
|
||||
else
|
||||
unset($_v['ta']);
|
||||
}
|
||||
$parts[] = ['contentGroup', intVal($_v['ta'])];
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
@@ -8,10 +8,15 @@ class PetList extends BaseType
|
||||
{
|
||||
use ListviewHelper;
|
||||
|
||||
public static $type = TYPE_PET;
|
||||
public static $brickFile = 'pet';
|
||||
public static $type = TYPE_PET;
|
||||
public static $brickFile = 'pet';
|
||||
public static $dataTable = '?_pet';
|
||||
|
||||
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_pet p';
|
||||
protected $queryBase = 'SELECT *, p.id AS ARRAY_KEY FROM ?_pet p';
|
||||
protected $queryOpts = array(
|
||||
'p' => [['ic']],
|
||||
'ic' => ['j' => ['?_icons ic ON p.iconId = ic.id', true], 's' => ', ic.name AS iconString'],
|
||||
);
|
||||
|
||||
public function getListviewData()
|
||||
{
|
||||
|
||||
@@ -4,144 +4,81 @@ if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// class CharacterList extends BaseType // new profiler-related parent: ProfilerType?; maybe a trait is enough => use ProfileHelper;
|
||||
// class GuildList extends BaseType
|
||||
// class ArenaTeamList extends BaseType
|
||||
class ProfileList extends BaseType
|
||||
{
|
||||
public static $type = 0; // profiles dont actually have one
|
||||
public static $brickFile = 'profile';
|
||||
use profilerHelper, listviewHelper;
|
||||
|
||||
protected $queryBase = ''; // SELECT p.*, p.id AS ARRAY_KEY FROM ?_profiles p';
|
||||
protected $queryOpts = array(
|
||||
'p' => [['pa', 'pg']],
|
||||
'pam' => [['?_profiles_arenateam_member pam ON pam.memberId = p.id', true], 's' => ', pam.status'],
|
||||
'pa' => ['?_profiles_arenateam pa ON pa.id = pam.teamId', 's' => ', pa.mode, pa.name'],
|
||||
'pgm' => [['?_profiles_guid_member pgm ON pgm.memberId = p.Id', true], 's' => ', pgm.rankId'],
|
||||
'pg' => ['?_profiles_guild pg ON pg.if = pgm.guildId', 's' => ', pg.name']
|
||||
);
|
||||
|
||||
public function __construct($conditions = [], $miscData = null)
|
||||
{
|
||||
$character = array(
|
||||
'id' => 2,
|
||||
'name' => 'CharName',
|
||||
'region' => ['eu', 'Europe'],
|
||||
'battlegroup' => ['pure-pwnage', 'Pure Pwnage'],
|
||||
'realm' => ['dafuque', 'da\'Fuqúe'],
|
||||
'level' => 80,
|
||||
'classs' => 11,
|
||||
'race' => 6,
|
||||
'faction' => 1, // 0:alliance; 1:horde
|
||||
'gender' => 1, // 0:male, 1:female
|
||||
'skincolor' => 0, // playerbytes % 256
|
||||
'hairstyle' => 0, // (playerbytes >> 16) % 256
|
||||
'haircolor' => 0, // (playerbytes >> 24) % 256
|
||||
'facetype' => 0, // (playerbytes >> 8) % 256 [maybe features]
|
||||
'features' => 0, // playerBytes2 % 256 [maybe facetype]
|
||||
'source' => 2, // source: used if you create a profile from a genuine character. It inherites region, realm and bGroup
|
||||
'sourcename' => 'SourceCharName', // > if these three are false we get a 'genuine' profile [0 for genuine characters..?]
|
||||
'user' => 1, // > 'genuine' is the parameter for _isArmoryProfile(allowCustoms) ['' for genuine characters..?]
|
||||
'username' => 'TestUser', // > also, if 'source' <> 0, the char-icon is requestet via profile.php?avatar
|
||||
'published' => 1, // public / private
|
||||
'pinned' => 1, // usable for some utility funcs on site
|
||||
'nomodel' => 0x0, // unchecks DisplayOnCharacter by (1 << slotId - 1)
|
||||
'title' => 0, // titleId currently in use or null
|
||||
'guild' => 'GuildName', // only on chars; id or null
|
||||
'description' => 'this is a profile', // only on custom profiles
|
||||
'arenateams' => [], // [size(2|3|5) => DisplayName]; DisplayName gets urlized to use as link
|
||||
'playedtime' => 0, // exact to the day
|
||||
'lastupdated' => 0, // timestamp in ms
|
||||
'achievementpoints' => 0, // max you have
|
||||
'talents' => array(
|
||||
'builds' => array(
|
||||
['talents' => '', 'glyphs' => ''], // talents:string of 0-5 points; glyphs: itemIds.join(':')
|
||||
),
|
||||
'active' => 1 // 1|2
|
||||
),
|
||||
'customs' => [], // custom profiles created from this char; profileId => [name, ownerId, iconString(optional)]
|
||||
'skills' => [], // skillId => [curVal, maxVal]; can contain anything, should be limited to prim/sec professions
|
||||
'inventory' => [], // slotId => [itemId, subItemId, permEnchantId, tempEnchantId, gemItemId1, gemItemId2, gemItemId3, gemItemId4]
|
||||
'auras' => [], // custom list of buffs, debuffs [spellId]
|
||||
|
||||
// completion lists: [subjectId => amount/timestamp/1]
|
||||
'reputation' => [], // factionId => amount
|
||||
'titles' => [], // titleId => 1
|
||||
'spells' => [], // spellId => 1; recipes, pets, mounts
|
||||
'achievements' => [], // achievementId => timestamp
|
||||
'quests' => [], // questId => 1
|
||||
|
||||
// UNKNOWN
|
||||
'bookmarks' => [2], // UNK pinned or claimed userId => profileIds..?
|
||||
'statistics' => [], // UNK all statistics? [achievementId => killCount]
|
||||
'activity' => [], // UNK recent achievements? [achievementId => killCount]
|
||||
'glyphs' => [], // not really used .. i guess..?
|
||||
'pets' => array( // UNK
|
||||
[], // one array per pet, structure UNK
|
||||
),
|
||||
);
|
||||
|
||||
// parent::__construct($conditions, $miscData);
|
||||
@include('datasets/ProfilerExampleChar'); // tmp char data
|
||||
|
||||
$this->templates[2] = $character;
|
||||
$this->curTpl = $character;
|
||||
|
||||
if ($this->error)
|
||||
return;
|
||||
|
||||
// post processing
|
||||
// foreach ($this->iterate() as $_id => &$curTpl)
|
||||
// {
|
||||
// }
|
||||
}
|
||||
|
||||
public function getListviewData()
|
||||
public function getListviewData($addInfo = 0, array $reqCols = [])
|
||||
{
|
||||
$data = [];
|
||||
foreach ($this->iterate() as $__)
|
||||
{
|
||||
$tDistrib = $this->getTalentDistribution();
|
||||
if ($this->getField('user') && User::$id != $this->getField('user') && !($this->getField('cuFlags') & PROFILER_CU_PUBLISHED))
|
||||
continue;
|
||||
|
||||
if (($addInfo & PROFILEINFO_PROFILE) && !$this->isCustom())
|
||||
continue;
|
||||
|
||||
if (($addInfo & PROFILEINFO_CHARACTER) && $this->isCustom())
|
||||
continue;
|
||||
|
||||
$data[$this->id] = array(
|
||||
'id' => 0,
|
||||
'name' => $this->curTpl['name'],
|
||||
'achievementpoints' => $this->curTpl['achievementpoints'],
|
||||
'guild' => $this->curTpl['guild'], // 0 if none
|
||||
'guildRank' => -1,
|
||||
'realm' => $this->curTpl['realm'][0],
|
||||
'realmname' => $this->curTpl['realm'][1],
|
||||
'battlegroup' => $this->curTpl['battlegroup'][0],
|
||||
'battlegroupname' => $this->curTpl['battlegroup'][0],
|
||||
'region' => $this->curTpl['region'][0],
|
||||
'level' => $this->curTpl['level'],
|
||||
'race' => $this->curTpl['race'],
|
||||
'gender' => $this->curTpl['gender'],
|
||||
'classs' => $this->curTpl['classs'],
|
||||
'faction' => $this->curTpl['faction'],
|
||||
'talenttree1' => $tDistrib[0],
|
||||
'talenttree2' => $tDistrib[1],
|
||||
'talenttree3' => $tDistrib[2],
|
||||
'talentspec' => $this->curTpl['talents']['active']
|
||||
'id' => $this->getField('id'),
|
||||
'name' => $this->getField('name'),
|
||||
'race' => $this->getField('race'),
|
||||
'classs' => $this->getField('class'),
|
||||
'gender' => $this->getField('gender'),
|
||||
'level' => $this->getField('level'),
|
||||
'faction' => (1 << ($this->getField('race') - 1)) & RACE_MASK_ALLIANCE ? 0 : 1,
|
||||
'talenttree1' => $this->getField('talenttree1'),
|
||||
'talenttree2' => $this->getField('talenttree2'),
|
||||
'talenttree3' => $this->getField('talenttree3'),
|
||||
'talentspec' => $this->getField('activespec') + 1, // 0 => 1; 1 => 2
|
||||
'achievementpoints' => $this->getField('achievementpoints'),
|
||||
'guild' => '$"'.$this->getField('guildname').'"', // force this to be a string
|
||||
'guildrank' => $this->getField('guildrank'),
|
||||
'realm' => Profiler::urlize($this->getField('realmName')),
|
||||
'realmname' => $this->getField('realmName'),
|
||||
// 'battlegroup' => Profiler::urlize($this->getField('battlegroup')), // was renamed to subregion somewhere around cata release
|
||||
// 'battlegroupname' => $this->getField('battlegroup'),
|
||||
'gearscore' => $this->getField('gearscore')
|
||||
);
|
||||
|
||||
if (!empty($this->curTpl['description']))
|
||||
$data[$this->id]['description'] = $this->curTpl['description'];
|
||||
|
||||
if (!empty($this->curTpl['icon']))
|
||||
$data[$this->id]['icon'] = $this->curTpl['icon'];
|
||||
// for the lv this determins if the link is profile=<id> or profile=<region>.<realm>.<name>
|
||||
if ($this->isCustom())
|
||||
$data[$this->id]['published'] = (int)!!($this->getField('cuFlags') & PROFILER_CU_PUBLISHED);
|
||||
else
|
||||
$data[$this->id]['region'] = Profiler::urlize($this->getField('region'));
|
||||
|
||||
if ($this->curTpl['cuFlags'] & PROFILE_CU_PUBLISHED)
|
||||
$data[$this->id]['published'] = 1;
|
||||
if ($addInfo & PROFILEINFO_ARENA)
|
||||
{
|
||||
$data[$this->id]['rating'] = $this->getField('rating');
|
||||
$data[$this->id]['captain'] = $this->getField('captain');
|
||||
$data[$this->id]['games'] = $this->getField('seasonGames');
|
||||
$data[$this->id]['wins'] = $this->getField('seasonWins');
|
||||
}
|
||||
|
||||
if ($this->curTpl['cuFlags'] & PROFILE_CU_PINNED)
|
||||
// Filter asked for skills - add them
|
||||
foreach ($reqCols as $col)
|
||||
$data[$this->id][$col] = $this->getField($col);
|
||||
|
||||
if ($addInfo & PROFILEINFO_PROFILE)
|
||||
if ($_ = $this->getField('description'))
|
||||
$data[$this->id]['description'] = $_;
|
||||
|
||||
if ($addInfo & PROFILEINFO_PROFILE)
|
||||
if ($_ = $this->getField('icon'))
|
||||
$data[$this->id]['icon'] = $_;
|
||||
|
||||
if ($this->getField('cuFlags') & PROFILER_CU_PINNED)
|
||||
$data[$this->id]['pinned'] = 1;
|
||||
|
||||
if ($this->curTpl['cuFlags'] & PROFILE_CU_DELETED)
|
||||
if ($this->getField('cuFlags') & PROFILER_CU_DELETED)
|
||||
$data[$this->id]['deleted'] = 1;
|
||||
}
|
||||
|
||||
return $data;
|
||||
return array_values($data);
|
||||
}
|
||||
|
||||
public function renderTooltip($interactive = false)
|
||||
@@ -149,65 +86,178 @@ class ProfileList extends BaseType
|
||||
if (!$this->curTpl)
|
||||
return [];
|
||||
|
||||
$title = '';
|
||||
$name = $this->getField('name');
|
||||
if ($_ = $this->getField('chosenTitle'))
|
||||
$title = (new TitleList(array(['bitIdx', $_])))->getField($this->getField('gender') ? 'female' : 'male', true);
|
||||
|
||||
if ($this->isCustom())
|
||||
$name .= ' (Custom Profile)';
|
||||
else if ($title)
|
||||
$name = sprintf($title, $name);
|
||||
|
||||
$x = '<table>';
|
||||
$x .= '<tr><td><b class="q">'.$this->getField('name').'</b></td></tr>';
|
||||
if ($g = $this->getField('name'))
|
||||
$x .= '<tr><td><'.$g.'> ('.$this->getField('guildrank').')</td></tr>';
|
||||
$x .= '<tr><td><b class="q">'.$name.'</b></td></tr>';
|
||||
if ($g = $this->getField('guildname'))
|
||||
$x .= '<tr><td><'.$g.'></td></tr>';
|
||||
else if ($d = $this->getField('description'))
|
||||
$x .= '<tr><td>'.$d.'</td></tr>';
|
||||
$x .= '<tr><td>'.Lang::game('level').' '.$this->getField('level').' '.Lang::game('ra', $this->curTpl['race']).' '.Lang::game('cl', $this->curTpl['classs']).'</td></tr>';
|
||||
$x .= '<tr><td>'.Lang::game('level').' '.$this->getField('level').' '.Lang::game('ra', $this->getField('race')).' '.Lang::game('cl', $this->getField('class')).'</td></tr>';
|
||||
$x .= '</table>';
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
public function getJSGlobals($addMask = 0) {}
|
||||
|
||||
private function getTalentDistribution()
|
||||
public function getJSGlobals($addMask = 0)
|
||||
{
|
||||
if (!empty($this->tDistribution))
|
||||
$this->tDistribution[$this->curTpl['classId']] = DB::Aowow()->selectCol('SELECT COUNT(t.id) FROM dbc_talent t JOIN dbc_talenttab tt ON t.tabId = tt.id WHERE tt.classMask & ?d GROUP BY tt.id ORDER BY tt.tabNumber ASC', 1 << ($this->curTpl['classId'] - 1));
|
||||
$data = [];
|
||||
$realms = Profiler::getRealms();
|
||||
|
||||
$result = [];
|
||||
$start = 0;
|
||||
foreach ($this->tDistribution[$this->curTpl['classId']] as $len)
|
||||
foreach ($this->iterate() as $id => $__)
|
||||
{
|
||||
$result[] = array_sum(str_split(substr($this->curTpl['talentString'], $start, $len)));
|
||||
$start += $len;
|
||||
if (($addMask & PROFILEINFO_PROFILE) && ($this->getField('cuFlags') & PROFILER_CU_PROFILE))
|
||||
{
|
||||
$profile = array(
|
||||
'id' => $this->getField('id'),
|
||||
'name' => $this->getField('name'),
|
||||
'race' => $this->getField('race'),
|
||||
'classs' => $this->getField('class'),
|
||||
'level' => $this->getField('level'),
|
||||
'gender' => $this->getField('gender')
|
||||
);
|
||||
|
||||
if ($_ = $this->getField('icon'))
|
||||
$profile['icon'] = $_;
|
||||
|
||||
$data[] = $profile;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($addMask & PROFILEINFO_CHARACTER && !($this->getField('cuFlags') & PROFILER_CU_PROFILE))
|
||||
{
|
||||
if (!isset($realms[$this->getField('realm')]))
|
||||
continue;
|
||||
|
||||
$data[] = array(
|
||||
'id' => $this->getField('id'),
|
||||
'name' => $this->getField('name'),
|
||||
'realmname' => $realms[$this->getField('realm')]['name'],
|
||||
'region' => $realms[$this->getField('realm')]['region'],
|
||||
'realm' => Profiler::urlize($realms[$this->getField('realm')]['name']),
|
||||
'race' => $this->getField('race'),
|
||||
'classs' => $this->getField('class'),
|
||||
'level' => $this->getField('level'),
|
||||
'gender' => $this->getField('gender'),
|
||||
'pinned' => $this->getField('cuFlags') & PROFILER_CU_PINNED ? 1 : 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function isCustom()
|
||||
{
|
||||
return $this->getField('cuFlags') & PROFILER_CU_PROFILE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ProfileListFilter extends Filter
|
||||
{
|
||||
public $extraOpts = [];
|
||||
public $useLocalList = false;
|
||||
public $extraOpts = [];
|
||||
|
||||
protected $genericFilter = array(
|
||||
private $realms = [];
|
||||
|
||||
protected $enums = array(
|
||||
-1 => array( // arena team sizes
|
||||
// by name by rating by contrib
|
||||
12 => 2, 13 => 2, 14 => 2,
|
||||
15 => 3, 16 => 3, 17 => 3,
|
||||
18 => 5, 19 => 5, 20 => 5
|
||||
)
|
||||
);
|
||||
|
||||
protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet
|
||||
2 => [FILTER_CR_NUMERIC, 'gearscore', NUM_CAST_INT ], // gearscore [num]
|
||||
3 => [FILTER_CR_NUMERIC, 'achievementpoints', NUM_CAST_INT ], // achievementpoints [num]
|
||||
5 => [FILTER_CR_NUMERIC, 'talenttree1', NUM_CAST_INT ], // talenttree1 [num]
|
||||
6 => [FILTER_CR_NUMERIC, 'talenttree2', NUM_CAST_INT ], // talenttree2 [num]
|
||||
7 => [FILTER_CR_NUMERIC, 'talenttree3', NUM_CAST_INT ], // talenttree3 [num]
|
||||
9 => [FILTER_CR_STRING, 'g.name', ], // guildname
|
||||
10 => [FILTER_CR_CALLBACK, 'cbHasGuildRank', null, null], // guildrank
|
||||
12 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname2v2
|
||||
15 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname3v3
|
||||
18 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname5v5
|
||||
13 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng2v2
|
||||
16 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng3v3
|
||||
19 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng5v5
|
||||
14 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib2v2 [num]
|
||||
17 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib3v3 [num]
|
||||
20 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib5v5 [num]
|
||||
21 => [FILTER_CR_CALLBACK, 'cbWearsItems', null, null], // wearingitem [str]
|
||||
23 => [FILTER_CR_CALLBACK, 'cbCompletedAcv', null, null], // completedachievement
|
||||
25 => [FILTER_CR_CALLBACK, 'cbProfession', 171, null], // alchemy [num]
|
||||
26 => [FILTER_CR_CALLBACK, 'cbProfession', 164, null], // blacksmithing [num]
|
||||
27 => [FILTER_CR_CALLBACK, 'cbProfession', 333, null], // enchanting [num]
|
||||
28 => [FILTER_CR_CALLBACK, 'cbProfession', 202, null], // engineering [num]
|
||||
29 => [FILTER_CR_CALLBACK, 'cbProfession', 182, null], // herbalism [num]
|
||||
30 => [FILTER_CR_CALLBACK, 'cbProfession', 773, null], // inscription [num]
|
||||
31 => [FILTER_CR_CALLBACK, 'cbProfession', 755, null], // jewelcrafting [num]
|
||||
32 => [FILTER_CR_CALLBACK, 'cbProfession', 165, null], // leatherworking [num]
|
||||
33 => [FILTER_CR_CALLBACK, 'cbProfession', 186, null], // mining [num]
|
||||
34 => [FILTER_CR_CALLBACK, 'cbProfession', 393, null], // skinning [num]
|
||||
35 => [FILTER_CR_CALLBACK, 'cbProfession', 197, null], // tailoring [num]
|
||||
36 => [FILTER_CR_CALLBACK, 'cbHasGuild', null, null] // hasguild [yn]
|
||||
);
|
||||
|
||||
|
||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||
protected $inputFields = array(
|
||||
'cr' => [FILTER_V_RANGE, [1, 36], true ], // criteria ids
|
||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 5000]], true ], // criteria operators
|
||||
'crv' => [FILTER_V_REGEX, '/[\p{C};]/ui', true ], // criteria values
|
||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name - only printable chars, no delimiter
|
||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||
'ex' => [FILTER_V_EQUAL, 'on', false], // only match exact
|
||||
'si' => [FILTER_V_LIST, [1, 2], false], // side
|
||||
'ra' => [FILTER_V_LIST, [[1, 8], 10, 11], true ], // race
|
||||
'cl' => [FILTER_V_LIST, [[1, 9], 11], true ], // class
|
||||
'minle' => [FILTER_V_RANGE, [1, MAX_LEVEL], false], // min level
|
||||
'maxle' => [FILTER_V_RANGE, [1, MAX_LEVEL], false], // max level
|
||||
'rg' => [FILTER_V_CALLBACK, 'cbRegionCheck', false], // region
|
||||
'sv' => [FILTER_V_CALLBACK, 'cbServerCheck', false], // server
|
||||
);
|
||||
|
||||
/* heads up!
|
||||
a couple of filters are too complex to be run against the characters database
|
||||
if they are selected, force useage of LocalProfileList
|
||||
*/
|
||||
|
||||
public function __construct($fromPOST = false, $opts = [])
|
||||
{
|
||||
if (!empty($opts['realms']))
|
||||
$this->realms = $opts['realms'];
|
||||
else
|
||||
$this->realms = array_keys(Profiler::getRealms());
|
||||
|
||||
parent::__construct($fromPOST, $opts);
|
||||
|
||||
if (!empty($this->fiData['c']['cr']))
|
||||
if (array_intersect($this->fiData['c']['cr'], [2, 3, 5, 6, 7, 21]))
|
||||
$this->useLocalList = true;
|
||||
}
|
||||
|
||||
protected function createSQLForCriterium(&$cr)
|
||||
{
|
||||
if (in_array($cr[0], array_keys($this->genericFilter)))
|
||||
{
|
||||
if ($genCR = $this->genericCriterion($cr))
|
||||
return $genCR;
|
||||
|
||||
unset($cr);
|
||||
$this->error = true;
|
||||
return [1];
|
||||
}
|
||||
|
||||
switch ($cr[0])
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
unset($cr);
|
||||
$this->error = 1;
|
||||
$this->error = true;
|
||||
return [1];
|
||||
}
|
||||
|
||||
@@ -216,13 +266,446 @@ class ProfileListFilter extends Filter
|
||||
$parts = [];
|
||||
$_v = $this->fiData['v'];
|
||||
|
||||
// name
|
||||
if (isset($_v['na']))
|
||||
if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
|
||||
$parts[] = $_;
|
||||
// region (rg), battlegroup (bg) and server (sv) are passed to ProflieList as miscData and handled there
|
||||
|
||||
// table key differs between remote and local :<
|
||||
$k = $this->useLocalList ? 'p' : 'c';
|
||||
|
||||
// name [str] - the table is case sensitive. Since i down't want to destroy indizes, lets alter the search terms
|
||||
if (!empty($_v['na']))
|
||||
{
|
||||
$lower = $this->modularizeString([$k.'.name'], Util::lower($_v['na']), !empty($_v['ex']) && $_v['ex'] == 'on');
|
||||
$proper = $this->modularizeString([$k.'.name'], Util::ucWords($_v['na']), !empty($_v['ex']) && $_v['ex'] == 'on');
|
||||
|
||||
$parts[] = ['OR', $lower, $proper];
|
||||
}
|
||||
|
||||
// side [list]
|
||||
if (!empty($_v['si']))
|
||||
{
|
||||
if ($_v['si'] == 1)
|
||||
$parts[] = [$k.'.race', [1, 3, 4, 7, 11]];
|
||||
else if ($_v['si'] == 2)
|
||||
$parts[] = [$k.'.race', [2, 5, 6, 8, 10]];
|
||||
}
|
||||
|
||||
// race [list]
|
||||
if (!empty($_v['ra']))
|
||||
$parts[] = [$k.'.race', $_v['ra']];
|
||||
|
||||
// class [list]
|
||||
if (!empty($_v['cl']))
|
||||
$parts[] = [$k.'.class', $_v['cl']];
|
||||
|
||||
// min level [int]
|
||||
if (isset($_v['minle']))
|
||||
$parts[] = [$k.'.level', $_v['minle'], '>='];
|
||||
|
||||
// max level [int]
|
||||
if (isset($_v['maxle']))
|
||||
$parts[] = [$k.'.level', $_v['maxle'], '<='];
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
protected function cbRegionCheck(&$v)
|
||||
{
|
||||
if ($v == 'eu' || $v == 'us')
|
||||
{
|
||||
$this->parentCats[0] = $v; // directly redirect onto this region
|
||||
$v = ''; // remove from filter
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbServerCheck(&$v)
|
||||
{
|
||||
foreach (Profiler::getRealms() as $realm)
|
||||
if ($realm['name'] == $v)
|
||||
{
|
||||
$this->parentCats[1] = Profiler::urlize($v);// directly redirect onto this server
|
||||
$v = ''; // remove from filter
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbProfession($cr, $skillId)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[2], NUM_CAST_INT) || !$this->int2Op($cr[1]))
|
||||
return;
|
||||
|
||||
$k = 'sk_'.Util::createHash(12);
|
||||
$col = 'skill'.$skillId;
|
||||
|
||||
$this->formData['extraCols'][$skillId] = $col;
|
||||
|
||||
if ($this->useLocalList)
|
||||
{
|
||||
$this->extraOpts[$k] = array(
|
||||
'j' => ['?_profiler_completion '.$k.' ON '.$k.'.id = p.id AND '.$k.'.`type` = '.TYPE_SKILL.' AND '.$k.'.typeId = '.$skillId.' AND '.$k.'.cur '.$cr[1].' '.$cr[2], true],
|
||||
's' => [', '.$k.'.cur AS '.$col]
|
||||
);
|
||||
return [$k.'.typeId', null, '!'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->extraOpts[$k] = array(
|
||||
'j' => ['character_skills '.$k.' ON '.$k.'.guid = c.guid AND '.$k.'.skill = '.$skillId.' AND '.$k.'.value '.$cr[1].' '.$cr[2], true],
|
||||
's' => [', '.$k.'.value AS '.$col]
|
||||
);
|
||||
return [$k.'.skill', null, '!'];
|
||||
}
|
||||
}
|
||||
|
||||
protected function cbCompletedAcv($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[2], NUM_CAST_INT))
|
||||
return false;
|
||||
|
||||
if (!DB::Aowow()->selectCell('SELECT 1 FROM ?_achievement WHERE id = ?d', $cr[2]))
|
||||
return false;
|
||||
|
||||
$k = 'acv_'.Util::createHash(12);
|
||||
|
||||
if ($this->useLocalList)
|
||||
{
|
||||
$this->extraOpts[$k] = ['j' => ['?_profiler_completion '.$k.' ON '.$k.'.id = p.id AND '.$k.'.`type` = '.TYPE_ACHIEVEMENT.' AND '.$k.'.typeId = '.$cr[2], true]];
|
||||
return [$k.'.typeId', null, '!'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->extraOpts[$k] = ['j' => ['character_achievement '.$k.' ON '.$k.'.guid = c.guid AND '.$k.'.achievement = '.$cr[2], true]];
|
||||
return [$k.'.achievement', null, '!'];
|
||||
}
|
||||
}
|
||||
|
||||
protected function cbWearsItems($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[2], NUM_CAST_INT))
|
||||
return false;
|
||||
|
||||
if (!DB::Aowow()->selectCell('SELECT 1 FROM ?_items WHERE id = ?d', $cr[2]))
|
||||
return false;
|
||||
|
||||
$k = 'i_'.Util::createHash(12);
|
||||
|
||||
$this->extraOpts[$k] = ['j' => ['?_profiler_items '.$k.' ON '.$k.'.id = p.id AND '.$k.'.item = '.$cr[2], true]];
|
||||
return [$k.'.item', null, '!'];
|
||||
}
|
||||
|
||||
protected function cbHasGuild($cr)
|
||||
{
|
||||
if (!$this->int2Bool($cr[1]))
|
||||
return false;
|
||||
|
||||
if ($this->useLocalList)
|
||||
return ['p.guild', null, $cr[1] ? '!' : null];
|
||||
else
|
||||
return ['gm.guildId', null, $cr[1] ? '!' : null];
|
||||
}
|
||||
|
||||
protected function cbHasGuildRank($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[2], NUM_CAST_INT) || !$this->int2Op($cr[1]))
|
||||
return false;
|
||||
|
||||
if ($this->useLocalList)
|
||||
return ['p.guildrank', $cr[2], $cr[1]];
|
||||
else
|
||||
return ['gm.rank', $cr[2], $cr[1]];
|
||||
}
|
||||
|
||||
protected function cbTeamName($cr)
|
||||
{
|
||||
if ($_ = $this->modularizeString(['at.name'], $cr[2]))
|
||||
return ['AND', ['at.type', $this->enums[-1][$cr[0]]], $_];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbTeamRating($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[2], NUM_CAST_INT) || !$this->int2Op($cr[1]))
|
||||
return false;
|
||||
|
||||
return ['AND', ['at.type', $this->enums[-1][$cr[0]]], ['at.rating', $cr[2], $cr[1]]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class RemoteProfileList extends ProfileList
|
||||
{
|
||||
protected $queryBase = 'SELECT `c`.*, `c`.`guid` AS ARRAY_KEY FROM characters c';
|
||||
protected $queryOpts = array(
|
||||
'c' => [['gm', 'g', 'ca', 'ct'], 'g' => 'ARRAY_KEY', 'o' => 'level DESC, name ASC'],
|
||||
'ca' => ['j' => ['character_achievement ca ON ca.guid = c.guid', true], 's' => ', GROUP_CONCAT(DISTINCT ca.achievement SEPARATOR " ") AS _acvs'],
|
||||
'ct' => ['j' => ['character_talent ct ON ct.guid = c.guid AND ct.spec = c.activespec', true], 's' => ', GROUP_CONCAT(DISTINCT ct.spell SEPARATOR " ") AS _talents'],
|
||||
'gm' => ['j' => ['guild_member gm ON gm.guid = c.guid', true], 's' => ', gm.rank AS guildrank'],
|
||||
'g' => ['j' => ['guild g ON g.guildid = gm.guildid', true], 's' => ', g.guildid AS guild, g.name AS guildname'],
|
||||
'atm' => ['j' => ['arena_team_member atm ON atm.guid = c.guid', true], 's' => ', atm.personalRating AS rating'],
|
||||
'at' => [['atm'], 'j' => 'arena_team at ON atm.arenaTeamId = at.arenaTeamId', 's' => ', at.name AS arenateam, IF(at.captainGuid = c.guid, 1, 0) AS captain']
|
||||
);
|
||||
|
||||
public function __construct($conditions = [], $miscData = null)
|
||||
{
|
||||
// select DB by realm
|
||||
if (!$this->selectRealms($miscData))
|
||||
{
|
||||
trigger_error('no access to auth-db or table realmlist is empty', E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
parent::__construct($conditions, $miscData);
|
||||
|
||||
if ($this->error)
|
||||
return;
|
||||
|
||||
reset($this->dbNames); // only use when querying single realm
|
||||
$realmId = key($this->dbNames);
|
||||
$realms = Profiler::getRealms();
|
||||
$acvCache = [];
|
||||
$talentCache = [];
|
||||
$atCache = [];
|
||||
$distrib = null;
|
||||
$talentData = [];
|
||||
$limit = CFG_SQL_LIMIT_DEFAULT;
|
||||
|
||||
foreach ($conditions as $c)
|
||||
if (is_int($c))
|
||||
$limit = $c;
|
||||
|
||||
// post processing
|
||||
foreach ($this->iterate() as $guid => &$curTpl)
|
||||
{
|
||||
// battlegroup
|
||||
$curTpl['battlegroup'] = CFG_BATTLEGROUP;
|
||||
|
||||
// realm
|
||||
$r = explode(':', $guid)[0];
|
||||
if (!empty($realms[$r]))
|
||||
{
|
||||
$curTpl['realm'] = $r;
|
||||
$curTpl['realmName'] = $realms[$r]['name'];
|
||||
$curTpl['region'] = $realms[$r]['region'];
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error('character "'.$curTpl['name'].'" belongs to nonexistant realm #'.$r, E_USER_WARNING);
|
||||
unset($this->templates[$guid]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// temp id
|
||||
$curTpl['id'] = 0;
|
||||
|
||||
// achievement points pre
|
||||
if ($acvs = explode(' ', $curTpl['_acvs']))
|
||||
foreach ($acvs as $a)
|
||||
if ($a && !isset($acvCache[$a]))
|
||||
$acvCache[$a] = $a;
|
||||
|
||||
// talent points pre
|
||||
if ($talents = explode(' ', $curTpl['_talents']))
|
||||
foreach ($talents as $t)
|
||||
if ($t && !isset($talentCache[$t]))
|
||||
$talentCache[$t] = $t;
|
||||
|
||||
// equalize distribution
|
||||
if ($limit != CFG_SQL_LIMIT_NONE)
|
||||
{
|
||||
if (empty($distrib[$curTpl['realm']]))
|
||||
$distrib[$curTpl['realm']] = 1;
|
||||
else
|
||||
$distrib[$curTpl['realm']]++;
|
||||
}
|
||||
|
||||
$curTpl['cuFlags'] = 0;
|
||||
}
|
||||
|
||||
if ($talentCache)
|
||||
$talentData = DB::Aowow()->select('SELECT spell AS ARRAY_KEY, tab, rank FROM ?_talents WHERE spell IN (?a)', $talentCache);
|
||||
|
||||
if ($distrib !== null)
|
||||
{
|
||||
$total = array_sum($distrib);
|
||||
foreach ($distrib as &$d)
|
||||
$d = ceil($limit * $d / $total);
|
||||
}
|
||||
|
||||
if ($acvCache)
|
||||
$acvCache = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, points FROM ?_achievement WHERE id IN (?a)', $acvCache);
|
||||
|
||||
foreach ($this->iterate() as $guid => &$curTpl)
|
||||
{
|
||||
if ($distrib !== null)
|
||||
{
|
||||
if ($limit <= 0 || $distrib[$curTpl['realm']] <= 0)
|
||||
{
|
||||
unset($this->templates[$guid]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$distrib[$curTpl['realm']]--;
|
||||
$limit--;
|
||||
}
|
||||
|
||||
|
||||
$a = explode(' ', $curTpl['_acvs']);
|
||||
$t = explode(' ', $curTpl['_talents']);
|
||||
unset($curTpl['_acvs']);
|
||||
unset($curTpl['_talents']);
|
||||
|
||||
// achievement points post
|
||||
$curTpl['achievementpoints'] = array_sum(array_intersect_key($acvCache, array_combine($a, $a)));
|
||||
|
||||
// talent points post
|
||||
$curTpl['talenttree1'] = 0;
|
||||
$curTpl['talenttree2'] = 0;
|
||||
$curTpl['talenttree3'] = 0;
|
||||
foreach ($talentData as $spell => $data)
|
||||
if (in_array($spell, $t))
|
||||
$curTpl['talenttree'.($data['tab'] + 1)] += $data['rank'];
|
||||
}
|
||||
}
|
||||
|
||||
public function getListviewData($addInfoMask = 0, array $reqCols = [])
|
||||
{
|
||||
$data = parent::getListviewData($addInfoMask, $reqCols);
|
||||
|
||||
// not wanted on server list
|
||||
foreach ($data as &$d)
|
||||
unset($d['published']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function initializeLocalEntries()
|
||||
{
|
||||
$baseData = $guildData = [];
|
||||
foreach ($this->iterate() as $guid => $__)
|
||||
{
|
||||
$baseData[$guid] = array(
|
||||
'realm' => $this->getField('realm'),
|
||||
'realmGUID' => $this->getField('guid'),
|
||||
'name' => $this->getField('name'),
|
||||
'race' => $this->getField('race'),
|
||||
'class' => $this->getField('class'),
|
||||
'level' => $this->getField('level'),
|
||||
'gender' => $this->getField('gender'),
|
||||
'guild' => $this->getField('guild') ?: null,
|
||||
'guildrank' => $this->getField('guild') ? $this->getField('guildrank') : null,
|
||||
'cuFlags' => PROFILER_CU_NEEDS_RESYNC
|
||||
);
|
||||
|
||||
if ($this->getField('guild'))
|
||||
$guildData[] = array(
|
||||
'realm' => $this->getField('realm'),
|
||||
'realmGUID' => $this->getField('guild'),
|
||||
'name' => $this->getField('guildname'),
|
||||
'nameUrl' => Profiler::urlize($this->getField('guildname')),
|
||||
'cuFlags' => PROFILER_CU_NEEDS_RESYNC
|
||||
);
|
||||
}
|
||||
|
||||
// basic guild data (satisfying table constraints)
|
||||
if ($guildData)
|
||||
{
|
||||
foreach (Util::createSqlBatchInsert($guildData) as $ins)
|
||||
DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_guild (?#) VALUES '.$ins, array_keys(reset($guildData)));
|
||||
|
||||
// merge back local ids
|
||||
$localGuilds = DB::Aowow()->selectCol('SELECT realm AS ARRAY_KEY, realmGUID AS ARRAY_KEY2, id FROM ?_profiler_guild WHERE realm IN (?a) AND realmGUID IN (?a)',
|
||||
array_column($guildData, 'realm'), array_column($guildData, 'realmGUID')
|
||||
);
|
||||
|
||||
foreach ($baseData as &$bd)
|
||||
if ($bd['guild'])
|
||||
$bd['guild'] = $localGuilds[$bd['realm']][$bd['guild']];
|
||||
}
|
||||
|
||||
// basic char data (enough for tooltips)
|
||||
if ($baseData)
|
||||
{
|
||||
foreach (Util::createSqlBatchInsert($baseData) as $ins)
|
||||
DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_profiles (?#) VALUES '.$ins, array_keys(reset($baseData)));
|
||||
|
||||
// merge back local ids
|
||||
$localIds = DB::Aowow()->select(
|
||||
'SELECT CONCAT(realm, ":", realmGUID) AS ARRAY_KEY, id, gearscore FROM ?_profiler_profiles WHERE (cuFlags & ?d) = 0 AND realm IN (?a) AND realmGUID IN (?a)',
|
||||
PROFILER_CU_PROFILE,
|
||||
array_column($baseData, 'realm'),
|
||||
array_column($baseData, 'realmGUID')
|
||||
);
|
||||
|
||||
foreach ($this->iterate() as $guid => &$_curTpl)
|
||||
if (isset($localIds[$guid]))
|
||||
$_curTpl = array_merge($_curTpl, $localIds[$guid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class LocalProfileList extends ProfileList
|
||||
{
|
||||
protected $queryBase = 'SELECT p.*, p.id AS ARRAY_KEY FROM ?_profiler_profiles p';
|
||||
protected $queryOpts = array(
|
||||
'p' => [['g'], 'g' => 'p.id'],
|
||||
'ap' => ['j' => ['?_account_profiles ap ON ap.profileId = p.id', true], 's' => ', (IFNULL(ap.ExtraFlags, 0) | p.cuFlags) AS cuFlags'],
|
||||
'atm' => ['j' => ['?_profiler_arena_team_member atm ON atm.profileId = p.id', true], 's' => ', atm.captain, atm.personalRating AS rating, atm.seasonGames, atm.seasonWins'],
|
||||
'at' => [['atm'], 'j' => ['?_profiler_arena_team at ON at.id = atm.arenaTeamId', true], 's' => ', at.type'],
|
||||
'g' => ['j' => ['?_profiler_guild g ON g.id = p.guild', true], 's' => ', g.name AS guildname']
|
||||
);
|
||||
|
||||
public function __construct($conditions = [], $miscData = null)
|
||||
{
|
||||
parent::__construct($conditions, $miscData);
|
||||
|
||||
if ($this->error)
|
||||
return;
|
||||
|
||||
$realms = Profiler::getRealms();
|
||||
|
||||
// post processing
|
||||
$acvPoints = DB::Aowow()->selectCol('SELECT pc.id AS ARRAY_KEY, SUM(a.points) FROM ?_profiler_completion pc LEFT JOIN ?_achievement a ON a.id = pc.typeId WHERE pc.`type` = ?d AND pc.id IN (?a) GROUP BY pc.id', TYPE_ACHIEVEMENT, $this->getFoundIDs());
|
||||
|
||||
foreach ($this->iterate() as $id => &$curTpl)
|
||||
{
|
||||
if ($curTpl['realm'] && !isset($realms[$curTpl['realm']]))
|
||||
continue;
|
||||
|
||||
if (isset($realms[$curTpl['realm']]))
|
||||
{
|
||||
$curTpl['realmName'] = $realms[$curTpl['realm']]['name'];
|
||||
$curTpl['region'] = $realms[$curTpl['realm']]['region'];
|
||||
}
|
||||
|
||||
// battlegroup
|
||||
$curTpl['battlegroup'] = CFG_BATTLEGROUP;
|
||||
|
||||
$curTpl['achievementpoints'] = isset($acvPoints[$id]) ? $acvPoints[$id] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public function getProfileUrl()
|
||||
{
|
||||
$url = '?profile=';
|
||||
|
||||
if ($this->isCustom())
|
||||
return $url.$this->getField('id');
|
||||
|
||||
return $url.implode('.', array(
|
||||
Profiler::urlize($this->getField('region')),
|
||||
Profiler::urlize($this->getField('realmName')),
|
||||
urlencode($this->getField('name'))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -8,6 +8,7 @@ class QuestList extends BaseType
|
||||
{
|
||||
public static $type = TYPE_QUEST;
|
||||
public static $brickFile = 'quest';
|
||||
public static $dataTable = '?_quests';
|
||||
|
||||
public $requires = [];
|
||||
public $rewards = [];
|
||||
@@ -18,6 +19,7 @@ class QuestList extends BaseType
|
||||
'q' => [],
|
||||
'rsc' => ['j' => '?_spell rsc ON q.rewardSpellCast = rsc.id'], // limit rewardSpellCasts
|
||||
'qse' => ['j' => '?_quests_startend qse ON q.id = qse.questId', 's' => ', qse.method'], // groupConcat..?
|
||||
'e' => ['j' => ['?_events e ON e.id = `q`.eventId', true], 's' => ', e.holidayId']
|
||||
);
|
||||
|
||||
public function __construct($conditions = [], $miscData = null)
|
||||
@@ -33,7 +35,7 @@ class QuestList extends BaseType
|
||||
$_curTpl['cat1'] = $_curTpl['zoneOrSort']; // should probably be in a method...
|
||||
$_curTpl['cat2'] = 0;
|
||||
|
||||
foreach (Util::$questClasses as $k => $arr)
|
||||
foreach (Game::$questClasses as $k => $arr)
|
||||
{
|
||||
if (in_array($_curTpl['cat1'], $arr))
|
||||
{
|
||||
@@ -120,12 +122,18 @@ class QuestList extends BaseType
|
||||
return $this->curTpl['flags'] & QUEST_FLAG_REPEATABLE || $this->curTpl['specialFlags'] & QUEST_FLAG_SPECIAL_REPEATABLE;
|
||||
}
|
||||
|
||||
public function isDaily($strict = false)
|
||||
public function isDaily()
|
||||
{
|
||||
if ($strict)
|
||||
return $this->curTpl['flags'] & QUEST_FLAG_DAILY;
|
||||
else
|
||||
return $this->curTpl['flags'] & (QUEST_FLAG_DAILY | QUEST_FLAG_WEEKLY) || $this->curTpl['specialFlags'] & QUEST_FLAG_SPECIAL_MONTHLY;
|
||||
if ($this->curTpl['flags'] & QUEST_FLAG_DAILY)
|
||||
return 1;
|
||||
|
||||
if ($this->curTpl['flags'] & QUEST_FLAG_WEEKLY)
|
||||
return 2;
|
||||
|
||||
if ($this->curTpl['specialFlags'] & QUEST_FLAG_SPECIAL_MONTHLY)
|
||||
return 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// using reqPlayerKills and rewardHonor as a crutch .. has TC this even implemented..?
|
||||
@@ -164,7 +172,7 @@ class QuestList extends BaseType
|
||||
|
||||
foreach ($this->iterate() as $__)
|
||||
{
|
||||
if (!(Util::sideByRaceMask($this->curTpl['reqRaceMask']) & $side))
|
||||
if (!(Game::sideByRaceMask($this->curTpl['reqRaceMask']) & $side))
|
||||
continue;
|
||||
|
||||
list($series, $first) = DB::Aowow()->SelectRow(
|
||||
@@ -201,7 +209,7 @@ class QuestList extends BaseType
|
||||
'level' => $this->curTpl['level'],
|
||||
'reqlevel' => $this->curTpl['minLevel'],
|
||||
'name' => $this->getField('name', true),
|
||||
'side' => Util::sideByRaceMask($this->curTpl['reqRaceMask']),
|
||||
'side' => Game::sideByRaceMask($this->curTpl['reqRaceMask']),
|
||||
'wflags' => 0x0,
|
||||
'xp' => $this->curTpl['rewardXP']
|
||||
);
|
||||
@@ -241,6 +249,8 @@ class QuestList extends BaseType
|
||||
|
||||
// if ($this->isRepeatable()) // dafuque..? says repeatable and is used as 'disabled'..?
|
||||
// $data[$this->id]['wflags'] |= QUEST_CU_REPEATABLE;
|
||||
if ($this->curTpl['cuFlags'] & (CUSTOM_UNAVAILABLE | CUSTOM_DISABLED))
|
||||
$data[$this->id]['wflags'] |= QUEST_CU_REPEATABLE;
|
||||
|
||||
if ($this->curTpl['flags'] & QUEST_FLAG_DAILY)
|
||||
{
|
||||
@@ -399,10 +409,8 @@ class QuestList extends BaseType
|
||||
|
||||
// currencies
|
||||
if (!empty($this->rewards[$this->id][TYPE_CURRENCY]))
|
||||
{
|
||||
$_ = $this->rewards[$this->id][TYPE_CURRENCY];
|
||||
$data[TYPE_CURRENCY] = array_combine(array_keys($_), array_keys($_));
|
||||
}
|
||||
foreach ($this->rewards[$this->id][TYPE_CURRENCY] as $id => $__)
|
||||
$data[TYPE_CURRENCY][$id] = $id;
|
||||
}
|
||||
|
||||
if ($addMask & GLOBALINFO_SELF)
|
||||
@@ -422,189 +430,64 @@ class QuestListFilter extends Filter
|
||||
38 => [null, 1, 2, 3, 4, 5, 6, 7, 8, null, 10, 11, true, false],
|
||||
);
|
||||
protected $genericFilter = array(
|
||||
1 => [FILTER_CR_CALLBACK, 'cbReputation', '>', null], // increasesrepwith
|
||||
2 => [FILTER_CR_NUMERIC, 'rewardXP', NUM_CAST_INT ], // experiencegained
|
||||
3 => [FILTER_CR_NUMERIC, 'rewardOrReqMoney', NUM_CAST_INT ], // moneyrewarded
|
||||
4 => [FILTER_CR_CALLBACK, 'cbSpellRewards', null, null], // spellrewarded [yn]
|
||||
5 => [FILTER_CR_FLAG, 'flags', QUEST_FLAG_SHARABLE ], // sharable
|
||||
6 => [FILTER_CR_NUMERIC, 'timeLimit', NUM_CAST_INT ], // timer
|
||||
7 => [FILTER_CR_NYI_PH, null, 1 ], // firstquestseries
|
||||
9 => [FILTER_CR_CALLBACK, 'cbEarnReputation', null, null], // objectiveearnrepwith [enum]
|
||||
10 => [FILTER_CR_CALLBACK, 'cbReputation', '<', null], // decreasesrepwith
|
||||
11 => [FILTER_CR_NUMERIC, 'suggestedPlayers', NUM_CAST_INT ], // suggestedplayers
|
||||
15 => [FILTER_CR_NYI_PH, null, 1 ], // lastquestseries
|
||||
16 => [FILTER_CR_NYI_PH, null, 1 ], // partseries
|
||||
18 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
||||
19 => [FILTER_CR_CALLBACK, 'cbQuestRelation', 0x1, null], // startsfrom [enum]
|
||||
21 => [FILTER_CR_CALLBACK, 'cbQuestRelation', 0x2, null], // endsat [enum]
|
||||
22 => [FILTER_CR_CALLBACK, 'cbItemRewards', null, null], // itemrewards [op] [int]
|
||||
23 => [FILTER_CR_CALLBACK, 'cbItemChoices', null, null], // itemchoices [op] [int]
|
||||
24 => [FILTER_CR_CALLBACK, 'cbLacksStartEnd', null, null], // lacksstartend [yn]
|
||||
25 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||
27 => [FILTER_CR_FLAG, 'flags', QUEST_FLAG_DAILY ], // daily
|
||||
28 => [FILTER_CR_FLAG, 'flags', QUEST_FLAG_WEEKLY ], // weekly
|
||||
29 => [FILTER_CR_FLAG, 'flags', QUEST_FLAG_REPEATABLE ], // repeatable
|
||||
30 => [FILTER_CR_NUMERIC, 'id', null, true], // id
|
||||
5 => [FILTER_CR_FLAG, 'flags', QUEST_FLAG_SHARABLE ], // sharable
|
||||
11 => [FILTER_CR_NUMERIC, 'suggestedPlayers', ], // suggestedplayers
|
||||
6 => [FILTER_CR_NUMERIC, 'timeLimit', ], // timer
|
||||
42 => [FILTER_CR_STAFFFLAG, 'flags', ], // flags
|
||||
45 => [FILTER_CR_BOOLEAN, 'rewardTitleId', ], // titlerewarded
|
||||
2 => [FILTER_CR_NUMERIC, 'rewardXP', ], // experiencegained
|
||||
3 => [FILTER_CR_NUMERIC, 'rewardOrReqMoney', ], // moneyrewarded
|
||||
33 => [FILTER_CR_ENUM, 'holidayId', ], // relatedevent
|
||||
25 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||
18 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
||||
30 => [FILTER_CR_NUMERIC, 'id', NUM_CAST_INT, true], // id
|
||||
33 => [FILTER_CR_ENUM, 'e.holidayId' ], // relatedevent
|
||||
34 => [FILTER_CR_CALLBACK, 'cbAvailable', null, null], // availabletoplayers [yn]
|
||||
36 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
||||
37 => [FILTER_CR_CALLBACK, 'cbClassSpec', null, null], // classspecific [enum]
|
||||
37 => [FILTER_CR_CALLBACK, 'cbRaceSpec', null, null], // racespecific [enum]
|
||||
42 => [FILTER_CR_STAFFFLAG, 'flags' ], // flags
|
||||
43 => [FILTER_CR_CALLBACK, 'cbCurrencyReward', null, null], // currencyrewarded [enum]
|
||||
44 => [FILTER_CR_CALLBACK, 'cbLoremaster', null, null], // countsforloremaster_stc [yn]
|
||||
45 => [FILTER_CR_BOOLEAN, 'rewardTitleId' ] // titlerewarded
|
||||
);
|
||||
|
||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||
protected $inputFields = array(
|
||||
'cr' => [FILTER_V_RANGE, [1, 45], true ], // criteria ids
|
||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 99999]], true ], // criteria operators
|
||||
'crv' => [FILTER_V_REGEX, '/\D/', true ], // criteria values - only numerals
|
||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name / text - only printable chars, no delimiter
|
||||
'ex' => [FILTER_V_EQUAL, 'on', false], // also match subname
|
||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||
'minle' => [FILTER_V_RANGE, [1, 99], false], // min quest level
|
||||
'maxle' => [FILTER_V_RANGE, [1, 99], false], // max quest level
|
||||
'minrl' => [FILTER_V_RANGE, [1, 99], false], // min required level
|
||||
'maxrl' => [FILTER_V_RANGE, [1, 99], false], // max required level
|
||||
'si' => [FILTER_V_LIST, [-2, -1, 1, 2, 3], false], // siede
|
||||
'ty' => [FILTER_V_LIST, [0, 1, 21, 41, 62, [81, 85], 88, 89], true ] // type
|
||||
);
|
||||
|
||||
protected function createSQLForCriterium(&$cr)
|
||||
{
|
||||
if (in_array($cr[0], array_keys($this->genericFilter)))
|
||||
{
|
||||
if ($genCr = $this->genericCriterion($cr))
|
||||
return $genCr;
|
||||
|
||||
unset($cr);
|
||||
$this->error = true;
|
||||
return [1];
|
||||
}
|
||||
|
||||
switch ($cr[0])
|
||||
{
|
||||
case 1: // increasesrepwith
|
||||
if ($this->isSaneNumeric($cr[1]) && $cr[1] > 0)
|
||||
{
|
||||
return [
|
||||
'OR',
|
||||
['AND', ['rewardFactionId1', $cr[1]], ['rewardFactionValue1', 0, '>']],
|
||||
['AND', ['rewardFactionId2', $cr[1]], ['rewardFactionValue2', 0, '>']],
|
||||
['AND', ['rewardFactionId3', $cr[1]], ['rewardFactionValue3', 0, '>']],
|
||||
['AND', ['rewardFactionId4', $cr[1]], ['rewardFactionValue4', 0, '>']],
|
||||
['AND', ['rewardFactionId5', $cr[1]], ['rewardFactionValue5', 0, '>']]
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 10: // decreasesrepwith
|
||||
if ($this->isSaneNumeric($cr[1]) && $cr[1] > 0)
|
||||
{
|
||||
return [
|
||||
'OR',
|
||||
['AND', ['rewardFactionId1', $cr[1]], ['rewardFactionValue1', 0, '<']],
|
||||
['AND', ['rewardFactionId2', $cr[1]], ['rewardFactionValue2', 0, '<']],
|
||||
['AND', ['rewardFactionId3', $cr[1]], ['rewardFactionValue3', 0, '<']],
|
||||
['AND', ['rewardFactionId4', $cr[1]], ['rewardFactionValue4', 0, '<']],
|
||||
['AND', ['rewardFactionId5', $cr[1]], ['rewardFactionValue5', 0, '<']]
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 43: // currencyrewarded
|
||||
if ($this->isSaneNumeric($cr[1]) && $cr[1] > 0)
|
||||
{
|
||||
return [
|
||||
'OR',
|
||||
['rewardItemId1', $cr[1]], ['rewardItemId2', $cr[1]], ['rewardItemId3', $cr[1]], ['rewardItemId4', $cr[1]],
|
||||
['rewardChoiceItemId1', $cr[1]], ['rewardChoiceItemId2', $cr[1]], ['rewardChoiceItemId3', $cr[1]], ['rewardChoiceItemId4', $cr[1]], ['rewardChoiceItemId5', $cr[1]], ['rewardChoiceItemId6', $cr[1]]
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 34: // availabletoplayers
|
||||
if ($this->int2Bool($cr[1]))
|
||||
{
|
||||
if ($cr[1])
|
||||
return ['AND', [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0], [['flags', QUEST_FLAG_UNAVAILABLE, '&'], 0]];
|
||||
else
|
||||
return ['OR', ['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], ['flags', QUEST_FLAG_UNAVAILABLE, '&']];
|
||||
}
|
||||
break;
|
||||
case 23: // itemchoices [op] [int]
|
||||
if (!$this->isSaneNumeric($cr[2], false) || !$this->int2Op($cr[1]))
|
||||
break;
|
||||
|
||||
$this->extraOpts['q']['s'][] = ', (IF(rewardChoiceItemId1, 1, 0) + IF(rewardChoiceItemId2, 1, 0) + IF(rewardChoiceItemId3, 1, 0) + IF(rewardChoiceItemId4, 1, 0) + IF(rewardChoiceItemId5, 1, 0) + IF(rewardChoiceItemId6, 1, 0)) as numChoices';
|
||||
$this->extraOpts['q']['h'][] = 'numChoices '.$cr[1].' '.$cr[2];
|
||||
return [1];
|
||||
case 22: // itemrewards [op] [int]
|
||||
if (!$this->isSaneNumeric($cr[2], false) || !$this->int2Op($cr[1]))
|
||||
break;
|
||||
|
||||
$this->extraOpts['q']['s'][] = ', (IF(rewardItemId1, 1, 0) + IF(rewardItemId2, 1, 0) + IF(rewardItemId3, 1, 0) + IF(rewardItemId4, 1, 0)) as numRewards';
|
||||
$this->extraOpts['q']['h'][] = 'numRewards '.$cr[1].' '.$cr[2];
|
||||
return [1];
|
||||
case 44: // countsforloremaster_stc [bool]
|
||||
if ($this->int2Bool($cr[1]))
|
||||
{
|
||||
if ($cr[1])
|
||||
return ['AND', ['zoneOrSort', 0, '>'], [['flags', QUEST_FLAG_DAILY | QUEST_FLAG_WEEKLY | QUEST_FLAG_REPEATABLE , '&'], 0], [['specialFlags', QUEST_FLAG_SPECIAL_REPEATABLE | QUEST_FLAG_SPECIAL_MONTHLY , '&'], 0]];
|
||||
else
|
||||
return ['OR', ['zoneOrSort', 0, '<'], ['flags', QUEST_FLAG_DAILY | QUEST_FLAG_WEEKLY | QUEST_FLAG_REPEATABLE , '&'], ['specialFlags', QUEST_FLAG_SPECIAL_REPEATABLE | QUEST_FLAG_SPECIAL_MONTHLY , '&']];;
|
||||
}
|
||||
|
||||
break;
|
||||
case 4: // spellrewarded [bool]
|
||||
if ($this->int2Bool($cr[1]))
|
||||
{
|
||||
if ($cr[1])
|
||||
return ['OR', ['sourceSpellId', 0, '>'], ['rewardSpell', 0, '>'], ['rsc.effect1Id', SpellList::$effects['teach']], ['rsc.effect2Id', SpellList::$effects['teach']], ['rsc.effect3Id', SpellList::$effects['teach']]];
|
||||
else
|
||||
return ['AND', ['sourceSpellId', 0], ['rewardSpell', 0], ['rewardSpellCast', 0]];
|
||||
}
|
||||
break;
|
||||
case 9: // objectiveearnrepwith [enum]
|
||||
$_ = intVal($cr[1]);
|
||||
if ($_ > 0)
|
||||
return ['OR', ['reqFactionId1', $_], ['reqFactionId2', $_]];
|
||||
else if ($cr[1] == FILTER_ENUM_ANY) // any
|
||||
return ['OR', ['reqFactionId1', 0, '>'], ['reqFactionId2', 0, '>']];
|
||||
else if ($cr[1] == FILTER_ENUM_NONE) // none
|
||||
return ['AND', ['reqFactionId1', 0], ['reqFactionId2', 0]];
|
||||
|
||||
break;
|
||||
case 37: // classspecific [enum]
|
||||
$_ = isset($this->enums[$cr[0]][$cr[1]]) ? $this->enums[$cr[0]][$cr[1]] : null;
|
||||
if ($_ !== null)
|
||||
{
|
||||
if ($_ === true)
|
||||
return ['AND', ['reqClassMask', 0, '!'], [['reqClassMask', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL, '!']];
|
||||
else if ($_ === false)
|
||||
return ['OR', ['reqClassMask', 0], [['reqClassMask', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL]];
|
||||
else if (is_int($_))
|
||||
return ['AND', ['reqClassMask', (1 << ($_ - 1)), '&'], [['reqClassMask', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL, '!']];
|
||||
}
|
||||
break;
|
||||
case 38: // racespecific [enum]
|
||||
$_ = isset($this->enums[$cr[0]][$cr[1]]) ? $this->enums[$cr[0]][$cr[1]] : null;
|
||||
if ($_ !== null)
|
||||
{
|
||||
if ($_ === true)
|
||||
return ['AND', ['reqRaceMask', 0, '!'], [['reqRaceMask', RACE_MASK_ALL, '&'], RACE_MASK_ALL, '!'], [['reqRaceMask', RACE_MASK_ALLIANCE, '&'], RACE_MASK_ALLIANCE, '!'], [['reqRaceMask', RACE_MASK_HORDE, '&'], RACE_MASK_HORDE, '!']];
|
||||
else if ($_ === false)
|
||||
return ['OR', ['reqRaceMask', 0], ['reqRaceMask', RACE_MASK_ALL], ['reqRaceMask', RACE_MASK_ALLIANCE], ['reqRaceMask', RACE_MASK_HORDE]];
|
||||
else if (is_int($_))
|
||||
return ['AND', ['reqRaceMask', (1 << ($_ - 1)), '&'], [['reqRaceMask', RACE_MASK_ALLIANCE, '&'], RACE_MASK_ALLIANCE, '!'], [['reqRaceMask', RACE_MASK_HORDE, '&'], RACE_MASK_HORDE, '!']];
|
||||
}
|
||||
break;
|
||||
case 19: // startsfrom [enum]
|
||||
switch ($cr[1])
|
||||
{
|
||||
case 1: // npc
|
||||
return ['AND', ['qse.type', TYPE_NPC], ['qse.method', 0x1, '&']];
|
||||
case 2: // object
|
||||
return ['AND', ['qse.type', TYPE_OBJECT], ['qse.method', 0x1, '&']];
|
||||
case 3: // item
|
||||
return ['AND', ['qse.type', TYPE_ITEM], ['qse.method', 0x1, '&']];
|
||||
}
|
||||
break;
|
||||
case 21: // endsat [enum]
|
||||
switch ($cr[1])
|
||||
{
|
||||
case 1: // npc
|
||||
return ['AND', ['qse.type', TYPE_NPC], ['qse.method', 0x2, '&']];
|
||||
case 2: // object
|
||||
return ['AND', ['qse.type', TYPE_OBJECT], ['qse.method', 0x2, '&']];
|
||||
}
|
||||
break;
|
||||
case 24: // lacksstartend [bool]
|
||||
$missing = DB::Aowow()->selectCol('SELECT questId, max(method) a, min(method) b FROM ?_quests_startend GROUP BY questId HAVING (a | b) <> 3');
|
||||
if ($this->int2Bool($cr[1]))
|
||||
{
|
||||
if ($cr[1])
|
||||
return ['id', $missing];
|
||||
else
|
||||
return ['id', $missing, '!'];
|
||||
}
|
||||
break;
|
||||
case 7: // firstquestseries
|
||||
case 15: // lastquestseries
|
||||
case 16: // partseries
|
||||
/* todo */ return [1]; // self-joining eats substential amounts of time: should restructure that and also incorporate reqQ and openQ cases from infobox
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
unset($cr);
|
||||
$this->error = 1;
|
||||
$this->error = true;
|
||||
return [1];
|
||||
}
|
||||
|
||||
@@ -628,39 +511,19 @@ class QuestListFilter extends Filter
|
||||
|
||||
// level min
|
||||
if (isset($_v['minle']))
|
||||
{
|
||||
if (is_int($_v['minle']) && $_v['minle'] > 0)
|
||||
$parts[] = ['level', $_v['minle'], '>=']; // not considering quests that are always at player level (-1)
|
||||
else
|
||||
unset($_v['minle']);
|
||||
}
|
||||
$parts[] = ['level', $_v['minle'], '>=']; // not considering quests that are always at player level (-1)
|
||||
|
||||
// level max
|
||||
if (isset($_v['maxle']))
|
||||
{
|
||||
if (is_int($_v['maxle']) && $_v['maxle'] > 0)
|
||||
$parts[] = ['level', $_v['maxle'], '<='];
|
||||
else
|
||||
unset($_v['maxle']);
|
||||
}
|
||||
$parts[] = ['level', $_v['maxle'], '<='];
|
||||
|
||||
// reqLevel min
|
||||
if (isset($_v['minrl']))
|
||||
{
|
||||
if (is_int($_v['minrl']) && $_v['minrl'] > 0)
|
||||
$parts[] = ['minLevel', $_v['minrl'], '>='];// ignoring maxLevel
|
||||
else
|
||||
unset($_v['minrl']);
|
||||
}
|
||||
$parts[] = ['minLevel', $_v['minrl'], '>=']; // ignoring maxLevel
|
||||
|
||||
// reqLevel max
|
||||
if (isset($_v['maxrl']))
|
||||
{
|
||||
if (is_int($_v['maxrl']) && $_v['maxrl'] > 0)
|
||||
$parts[] = ['minLevel', $_v['maxrl'], '<='];// ignoring maxLevel
|
||||
else
|
||||
unset($_v['maxrl']);
|
||||
}
|
||||
$parts[] = ['minLevel', $_v['maxrl'], '<=']; // ignoring maxLevel
|
||||
|
||||
// side
|
||||
if (isset($_v['si']))
|
||||
@@ -685,23 +548,172 @@ class QuestListFilter extends Filter
|
||||
case -1:
|
||||
$parts[] = ['AND', $ex, ['reqRaceMask', RACE_MASK_ALLIANCE, '&']];
|
||||
break;
|
||||
default:
|
||||
unset($_v['si']);
|
||||
}
|
||||
}
|
||||
|
||||
// type [list]
|
||||
if (isset($_v['ty']))
|
||||
{
|
||||
$_ = (array)$_v['ty'];
|
||||
if (!array_diff($_, [0, 1, 21, 41, 62, 81, 82, 83, 84, 85, 88, 89]))
|
||||
$parts[] = ['type', $_];
|
||||
else
|
||||
unset($_v['ty']);
|
||||
}
|
||||
$parts[] = ['type', $_v['ty']];
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
protected function cbReputation($cr, $sign)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[1], NUM_REQ_INT) || $cr[1] <= 0)
|
||||
return false;
|
||||
|
||||
if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_factions WHERE id = ?d', $cr[1]))
|
||||
$this->formData['reputationCols'][] = [$cr[1], Util::localizedString($_, 'name')];
|
||||
|
||||
return [
|
||||
'OR',
|
||||
['AND', ['rewardFactionId1', $cr[1]], ['rewardFactionValue1', 0, $sign]],
|
||||
['AND', ['rewardFactionId2', $cr[1]], ['rewardFactionValue2', 0, $sign]],
|
||||
['AND', ['rewardFactionId3', $cr[1]], ['rewardFactionValue3', 0, $sign]],
|
||||
['AND', ['rewardFactionId4', $cr[1]], ['rewardFactionValue4', 0, $sign]],
|
||||
['AND', ['rewardFactionId5', $cr[1]], ['rewardFactionValue5', 0, $sign]]
|
||||
];
|
||||
}
|
||||
|
||||
protected function cbQuestRelation($cr, $flags)
|
||||
{
|
||||
switch ($cr[1])
|
||||
{
|
||||
case 1: // npc
|
||||
return ['AND', ['qse.type', TYPE_NPC], ['qse.method', $flags, '&']];
|
||||
case 2: // object
|
||||
return ['AND', ['qse.type', TYPE_OBJECT], ['qse.method', $flags, '&']];
|
||||
case 3: // item
|
||||
return ['AND', ['qse.type', TYPE_ITEM], ['qse.method', $flags, '&']];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbCurrencyReward($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[1], NUM_REQ_INT) || $cr[1] <= 0)
|
||||
return false;
|
||||
|
||||
return [
|
||||
'OR',
|
||||
['rewardItemId1', $cr[1]], ['rewardItemId2', $cr[1]], ['rewardItemId3', $cr[1]], ['rewardItemId4', $cr[1]],
|
||||
['rewardChoiceItemId1', $cr[1]], ['rewardChoiceItemId2', $cr[1]], ['rewardChoiceItemId3', $cr[1]], ['rewardChoiceItemId4', $cr[1]], ['rewardChoiceItemId5', $cr[1]], ['rewardChoiceItemId6', $cr[1]]
|
||||
];
|
||||
}
|
||||
|
||||
protected function cbAvailable($cr)
|
||||
{
|
||||
if (!$this->int2Bool($cr[1]))
|
||||
return false;
|
||||
|
||||
if ($cr[1])
|
||||
return [['cuFlags', CUSTOM_UNAVAILABLE | CUSTOM_DISABLED, '&'], 0];
|
||||
else
|
||||
return ['cuFlags', CUSTOM_UNAVAILABLE | CUSTOM_DISABLED, '&'];
|
||||
}
|
||||
|
||||
protected function cbItemChoices($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[2], NUM_CAST_INT) || !$this->int2Op($cr[1]))
|
||||
return false;
|
||||
|
||||
$this->extraOpts['q']['s'][] = ', (IF(rewardChoiceItemId1, 1, 0) + IF(rewardChoiceItemId2, 1, 0) + IF(rewardChoiceItemId3, 1, 0) + IF(rewardChoiceItemId4, 1, 0) + IF(rewardChoiceItemId5, 1, 0) + IF(rewardChoiceItemId6, 1, 0)) as numChoices';
|
||||
$this->extraOpts['q']['h'][] = 'numChoices '.$cr[1].' '.$cr[2];
|
||||
return [1];
|
||||
}
|
||||
|
||||
protected function cbItemRewards($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[2], NUM_CAST_INT) || !$this->int2Op($cr[1]))
|
||||
return false;
|
||||
|
||||
$this->extraOpts['q']['s'][] = ', (IF(rewardItemId1, 1, 0) + IF(rewardItemId2, 1, 0) + IF(rewardItemId3, 1, 0) + IF(rewardItemId4, 1, 0)) as numRewards';
|
||||
$this->extraOpts['q']['h'][] = 'numRewards '.$cr[1].' '.$cr[2];
|
||||
return [1];
|
||||
}
|
||||
|
||||
protected function cbLoremaster($cr)
|
||||
{
|
||||
if (!$this->int2Bool($cr[1]))
|
||||
return false;
|
||||
|
||||
if ($cr[1])
|
||||
return ['AND', ['zoneOrSort', 0, '>'], [['flags', QUEST_FLAG_DAILY | QUEST_FLAG_WEEKLY | QUEST_FLAG_REPEATABLE , '&'], 0], [['specialFlags', QUEST_FLAG_SPECIAL_REPEATABLE | QUEST_FLAG_SPECIAL_MONTHLY , '&'], 0]];
|
||||
else
|
||||
return ['OR', ['zoneOrSort', 0, '<'], ['flags', QUEST_FLAG_DAILY | QUEST_FLAG_WEEKLY | QUEST_FLAG_REPEATABLE , '&'], ['specialFlags', QUEST_FLAG_SPECIAL_REPEATABLE | QUEST_FLAG_SPECIAL_MONTHLY , '&']];;
|
||||
}
|
||||
|
||||
protected function cbSpellRewards($cr)
|
||||
{
|
||||
if (!$this->int2Bool($cr[1]))
|
||||
return false;
|
||||
|
||||
if ($cr[1])
|
||||
return ['OR', ['sourceSpellId', 0, '>'], ['rewardSpell', 0, '>'], ['rsc.effect1Id', SpellList::$effects['teach']], ['rsc.effect2Id', SpellList::$effects['teach']], ['rsc.effect3Id', SpellList::$effects['teach']]];
|
||||
else
|
||||
return ['AND', ['sourceSpellId', 0], ['rewardSpell', 0], ['rewardSpellCast', 0]];
|
||||
}
|
||||
|
||||
protected function cbEarnReputation($cr)
|
||||
{
|
||||
if (!Util::checkNumeric($cr[1], NUM_REQ_INT))
|
||||
return false;
|
||||
|
||||
if ($cr[1] > 0)
|
||||
return ['OR', ['reqFactionId1', $cr[1]], ['reqFactionId2', $cr[1]]];
|
||||
else if ($cr[1] == FILTER_ENUM_ANY) // any
|
||||
return ['OR', ['reqFactionId1', 0, '>'], ['reqFactionId2', 0, '>']];
|
||||
else if ($cr[1] == FILTER_ENUM_NONE) // none
|
||||
return ['AND', ['reqFactionId1', 0], ['reqFactionId2', 0]];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbClassSpec($cr)
|
||||
{
|
||||
if (!isset($this->enums[$cr[0]][$cr[1]]))
|
||||
return false;
|
||||
|
||||
$_ = $this->enums[$cr[0]][$cr[1]];
|
||||
if ($_ === true)
|
||||
return ['AND', ['reqClassMask', 0, '!'], [['reqClassMask', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL, '!']];
|
||||
else if ($_ === false)
|
||||
return ['OR', ['reqClassMask', 0], [['reqClassMask', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL]];
|
||||
else if (is_int($_))
|
||||
return ['AND', ['reqClassMask', (1 << ($_ - 1)), '&'], [['reqClassMask', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL, '!']];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbRaceSpec($cr)
|
||||
{
|
||||
if (!isset($this->enums[$cr[0]][$cr[1]]))
|
||||
return false;
|
||||
|
||||
$_ = $this->enums[$cr[0]][$cr[1]];
|
||||
if ($_ === true)
|
||||
return ['AND', ['reqRaceMask', 0, '!'], [['reqRaceMask', RACE_MASK_ALL, '&'], RACE_MASK_ALL, '!'], [['reqRaceMask', RACE_MASK_ALLIANCE, '&'], RACE_MASK_ALLIANCE, '!'], [['reqRaceMask', RACE_MASK_HORDE, '&'], RACE_MASK_HORDE, '!']];
|
||||
else if ($_ === false)
|
||||
return ['OR', ['reqRaceMask', 0], ['reqRaceMask', RACE_MASK_ALL], ['reqRaceMask', RACE_MASK_ALLIANCE], ['reqRaceMask', RACE_MASK_HORDE]];
|
||||
else if (is_int($_))
|
||||
return ['AND', ['reqRaceMask', (1 << ($_ - 1)), '&'], [['reqRaceMask', RACE_MASK_ALLIANCE, '&'], RACE_MASK_ALLIANCE, '!'], [['reqRaceMask', RACE_MASK_HORDE, '&'], RACE_MASK_HORDE, '!']];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function cbLacksStartEnd($cr)
|
||||
{
|
||||
if (!$this->int2Bool($cr[1]))
|
||||
return false;
|
||||
|
||||
$missing = DB::Aowow()->selectCol('SELECT questId, max(method) a, min(method) b FROM ?_quests_startend GROUP BY questId HAVING (a | b) <> 3');
|
||||
if ($cr[1])
|
||||
return ['id', $missing];
|
||||
else
|
||||
return ['id', $missing, '!'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,11 +8,12 @@ class SkillList extends BaseType
|
||||
{
|
||||
public static $type = TYPE_SKILL;
|
||||
public static $brickFile = 'skill';
|
||||
public static $dataTable = '?_skillline';
|
||||
|
||||
protected $queryBase = 'SELECT *, sl.id AS ARRAY_KEY FROM ?_skillline sl';
|
||||
protected $queryOpts = array(
|
||||
'sl' => [['si']],
|
||||
'si' => ['j' => '?_icons si ON si.id = sl.iconId', 's' => ', si.iconString'],
|
||||
'sl' => [['ic']],
|
||||
'ic' => ['j' => ['?_icons ic ON ic.id = sl.iconId', true], 's' => ', ic.name AS iconString'],
|
||||
);
|
||||
|
||||
public function __construct($conditions = [])
|
||||
@@ -31,6 +32,9 @@ class SkillList extends BaseType
|
||||
while (count($_) < 5)
|
||||
$_[] = 0;
|
||||
}
|
||||
|
||||
if (!$_curTpl['iconId'])
|
||||
$_curTpl['iconString'] = 'inv_misc_questionmark';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +57,7 @@ class SkillList extends BaseType
|
||||
'name' => Util::jsEscape($this->getField('name', true)),
|
||||
'profession' => $this->curTpl['professionMask'],
|
||||
'recipeSubclass' => $this->curTpl['recipeSubClass'],
|
||||
'specializations' => Util::toJSON($this->curTpl['specializations']),
|
||||
'specializations' => Util::toJSON($this->curTpl['specializations'], JSON_NUMERIC_CHECK),
|
||||
'icon' => Util::jsEscape($this->curTpl['iconString'])
|
||||
);
|
||||
}
|
||||
|
||||
136
includes/types/sound.class.php
Normal file
136
includes/types/sound.class.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class SoundList extends BaseType
|
||||
{
|
||||
use spawnHelper;
|
||||
|
||||
public static $type = TYPE_SOUND;
|
||||
public static $brickFile = 'sound';
|
||||
public static $dataTable = '?_sounds';
|
||||
public static $contribute = CONTRIBUTE_CO;
|
||||
|
||||
protected $queryBase = 'SELECT *, s.id AS ARRAY_KEY FROM ?_sounds s';
|
||||
|
||||
private $fileBuffer = [];
|
||||
private static $fileTypes = array(
|
||||
SOUND_TYPE_OGG => 'audio/ogg; codecs="vorbis"',
|
||||
SOUND_TYPE_MP3 => 'audio/mpeg'
|
||||
);
|
||||
|
||||
public function __construct($conditions = [])
|
||||
{
|
||||
parent::__construct($conditions);
|
||||
|
||||
// post processing
|
||||
foreach ($this->iterate() as $id => &$_curTpl)
|
||||
{
|
||||
$_curTpl['files'] = [];
|
||||
for ($i = 1; $i < 11; $i++)
|
||||
{
|
||||
if ($_curTpl['soundFile'.$i])
|
||||
{
|
||||
$this->fileBuffer[$_curTpl['soundFile'.$i]] = null;
|
||||
$_curTpl['files'][] = &$this->fileBuffer[$_curTpl['soundFile'.$i]];
|
||||
}
|
||||
|
||||
unset($_curTpl['soundFile'.$i]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->fileBuffer)
|
||||
{
|
||||
$files = DB::Aowow()->select('SELECT id AS ARRAY_KEY, `id`, `file` AS title, `type` FROM ?_sounds_files sf WHERE id IN (?a)', array_keys($this->fileBuffer));
|
||||
foreach ($files as $id => $data)
|
||||
{
|
||||
// skipp file extension
|
||||
$data['title'] = substr($data['title'], 0, -4);
|
||||
// enum to string
|
||||
$data['type'] = self::$fileTypes[$data['type']];
|
||||
// get real url
|
||||
$data['url'] = STATIC_URL . '/wowsounds/' . $data['id'];
|
||||
// v push v
|
||||
$this->fileBuffer[$id] = $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getName($id)
|
||||
{
|
||||
$this->getEntry($id);
|
||||
|
||||
return $this->getField('name');
|
||||
}
|
||||
|
||||
public function getListviewData()
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($this->iterate() as $__)
|
||||
{
|
||||
$data[$this->id] = array(
|
||||
'id' => $this->id,
|
||||
'type' => $this->getField('cat'),
|
||||
'name' => $this->getField('name'),
|
||||
'files' => array_values(array_filter($this->getField('files')))
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getJSGlobals($addMask = 0)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
foreach ($this->iterate() as $__)
|
||||
$data[self::$type][$this->id] = array(
|
||||
'name' => Util::jsEscape($this->getField('name', true)),
|
||||
'type' => $this->getField('cat'),
|
||||
'files' => array_values(array_filter($this->getField('files')))
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function renderTooltip() { }
|
||||
}
|
||||
|
||||
class SoundListFilter extends Filter
|
||||
{
|
||||
// we have no criteria for this one...
|
||||
protected function createSQLForCriterium(&$cr)
|
||||
{
|
||||
unset($cr);
|
||||
$this->error = true;
|
||||
return [1];
|
||||
}
|
||||
|
||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||
protected $inputFields = array(
|
||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name - only printable chars, no delimiter
|
||||
'ty' => [FILTER_V_LIST, [[1, 4], 6, 9, 10, 12, 13, 14, 16, 17, [19, 23], [25, 31], 50, 52, 53], true ] // type
|
||||
);
|
||||
|
||||
protected function createSQLForValues()
|
||||
{
|
||||
$parts = [];
|
||||
$_v = &$this->fiData['v'];
|
||||
|
||||
// name [str]
|
||||
if (isset($_v['na']))
|
||||
if ($_ = $this->modularizeString(['name']))
|
||||
$parts[] = $_;
|
||||
|
||||
// type [list]
|
||||
if (isset($_v['ty']))
|
||||
$parts[] = ['cat', $_v['ty']];
|
||||
|
||||
return $parts;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,16 +8,17 @@ class TitleList extends BaseType
|
||||
{
|
||||
use listviewHelper;
|
||||
|
||||
public static $type = TYPE_TITLE;
|
||||
public static $brickFile = 'title';
|
||||
public static $type = TYPE_TITLE;
|
||||
public static $brickFile = 'title';
|
||||
public static $dataTable = '?_titles';
|
||||
|
||||
public $sources = [];
|
||||
public $sources = [];
|
||||
|
||||
protected $queryBase = 'SELECT t.*, id AS ARRAY_KEY FROM ?_titles t';
|
||||
protected $queryOpts = array(
|
||||
't' => [['src']], // 11: TYPE_TITLE
|
||||
'src' => ['j' => ['?_source src ON type = 11 AND typeId = t.id', true], 's' => ', src13, moreType, moreTypeId']
|
||||
);
|
||||
protected $queryBase = 'SELECT t.*, id AS ARRAY_KEY FROM ?_titles t';
|
||||
protected $queryOpts = array(
|
||||
't' => [['src']], // 11: TYPE_TITLE
|
||||
'src' => ['j' => ['?_source src ON type = 11 AND typeId = t.id', true], 's' => ', src13, moreType, moreTypeId']
|
||||
);
|
||||
|
||||
public function __construct($conditions = [])
|
||||
{
|
||||
|
||||
@@ -6,16 +6,17 @@ if (!defined('AOWOW_REVISION'))
|
||||
|
||||
class UserList extends BaseType
|
||||
{
|
||||
public static $type = TYPE_USER;
|
||||
public static $brickFile = 'user';
|
||||
public static $type = TYPE_USER;
|
||||
public static $brickFile = 'user';
|
||||
public static $dataTable = ''; // doesn't have community content
|
||||
|
||||
public $sources = [];
|
||||
public $sources = [];
|
||||
|
||||
protected $queryBase = 'SELECT *, a.id AS ARRAY_KEY FROM ?_account a';
|
||||
protected $queryOpts = array(
|
||||
'a' => [['r']],
|
||||
'r' => ['j' => ['?_account_reputation r ON r.userId = a.id', true], 's' => ', IFNULL(SUM(r.amount), 0) AS reputation', 'g' => 'a.id']
|
||||
);
|
||||
protected $queryBase = 'SELECT *, a.id AS ARRAY_KEY FROM ?_account a';
|
||||
protected $queryOpts = array(
|
||||
'a' => [['r']],
|
||||
'r' => ['j' => ['?_account_reputation r ON r.userId = a.id', true], 's' => ', IFNULL(SUM(r.amount), 0) AS reputation', 'g' => 'a.id']
|
||||
);
|
||||
|
||||
public function getListviewData() { }
|
||||
|
||||
|
||||
@@ -6,14 +6,15 @@ if (!defined('AOWOW_REVISION'))
|
||||
|
||||
class WorldEventList extends BaseType
|
||||
{
|
||||
public static $type = TYPE_WORLDEVENT;
|
||||
public static $brickFile = 'event';
|
||||
public static $type = TYPE_WORLDEVENT;
|
||||
public static $brickFile = 'event';
|
||||
public static $dataTable = '?_events';
|
||||
|
||||
protected $queryBase = 'SELECT *, -e.id as id, -e.id AS ARRAY_KEY FROM ?_events e';
|
||||
protected $queryOpts = array(
|
||||
'e' => [['h']],
|
||||
'h' => ['j' => ['?_holidays h ON e.holidayId = h.id', true], 'o' => '-e.id ASC']
|
||||
);
|
||||
protected $queryBase = 'SELECT e.*, h.*, e.description AS nameINT, e.id AS id, e.id AS ARRAY_KEY FROM ?_events e';
|
||||
protected $queryOpts = array(
|
||||
'e' => [['h']],
|
||||
'h' => ['j' => ['?_holidays h ON e.holidayId = h.id', true], 'o' => '-e.id ASC']
|
||||
);
|
||||
|
||||
public function __construct($conditions = [])
|
||||
{
|
||||
@@ -40,22 +41,18 @@ class WorldEventList extends BaseType
|
||||
if ($this->curTpl['requires'])
|
||||
$this->curTpl['requires'] = explode(' ', $this->curTpl['requires']);
|
||||
|
||||
$this->curTpl['eventBak'] = -$this->curTpl['id'];
|
||||
|
||||
// change Ids if holiday is set
|
||||
if ($this->curTpl['holidayId'] > 0)
|
||||
{
|
||||
$this->curTpl['id'] = $this->curTpl['holidayId'];
|
||||
$this->curTpl['name'] = $this->getField('name', true);
|
||||
$replace[$this->id] = $this->curTpl;
|
||||
unset($this->curTpl['description']);
|
||||
}
|
||||
else // set a name if holiday is missing
|
||||
{
|
||||
// template
|
||||
$this->curTpl['name_loc0'] = $this->curTpl['description'];
|
||||
$this->curTpl['name_loc0'] = $this->curTpl['nameINT'];
|
||||
$this->curTpl['iconString'] = 'trade_engineering';
|
||||
$this->curTpl['name'] = '(SERVERSIDE) '.$this->getField('description', true);
|
||||
$this->curTpl['name'] = '(SERVERSIDE) '.$this->getField('nameINT', true);
|
||||
$replace[$this->id] = $this->curTpl;
|
||||
}
|
||||
}
|
||||
@@ -69,10 +66,21 @@ class WorldEventList extends BaseType
|
||||
|
||||
public static function getName($id)
|
||||
{
|
||||
if ($id > 0)
|
||||
$row = DB::Aowow()->SelectRow('SELECT * FROM ?_holidays WHERE Id = ?d', intVal($id));
|
||||
else
|
||||
$row = DB::Aowow()->SelectRow('SELECT description as name FROM ?_events WHERE Id = ?d', intVal(-$id));
|
||||
$row = DB::Aowow()->SelectRow('
|
||||
SELECT
|
||||
IFNULL(h.name_loc0, e.description) AS name_loc0,
|
||||
h.name_loc2,
|
||||
h.name_loc3,
|
||||
h.name_loc6,
|
||||
h.name_loc8
|
||||
FROM
|
||||
?_events e
|
||||
LEFT JOIN
|
||||
?_holidays h ON e.holidayId = h.id
|
||||
WHERE
|
||||
e.id = ?d',
|
||||
$id
|
||||
);
|
||||
|
||||
return Util::localizedString($row, 'name');
|
||||
}
|
||||
@@ -158,7 +166,31 @@ class WorldEventList extends BaseType
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function renderTooltip() { }
|
||||
public function renderTooltip()
|
||||
{
|
||||
if (!$this->curTpl)
|
||||
return null;
|
||||
|
||||
$x = '<table><tr><td>';
|
||||
|
||||
// head v that extra % is nesecary because we are using sprintf later on
|
||||
$x .= '<table width="100%%"><tr><td><b>'.Util::jsEscape($this->getField('name', true)).'</b></td><th><b class="q0">'.Lang::event('category', $this->getField('category')).'</b></th></tr></table>';
|
||||
|
||||
// use string-placeholder for dates
|
||||
// start
|
||||
$x .= Lang::event('start').Lang::main('colon').'%s<br>';
|
||||
// end
|
||||
$x .= Lang::event('end').Lang::main('colon').'%s';
|
||||
|
||||
$x .= '</td></tr></table>';
|
||||
|
||||
// desc
|
||||
if ($this->getField('holidayId'))
|
||||
if ($_ = $this->getField('description', true))
|
||||
$x .= '<table><tr><td><span class="q">'.Util::jsEscape($_).'</span></td></tr></table>';
|
||||
|
||||
return $x;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -8,10 +8,11 @@ class ZoneList extends BaseType
|
||||
{
|
||||
use listviewHelper;
|
||||
|
||||
public static $type = TYPE_ZONE;
|
||||
public static $brickFile = 'zone';
|
||||
public static $type = TYPE_ZONE;
|
||||
public static $brickFile = 'zone';
|
||||
public static $dataTable = '?_zones';
|
||||
|
||||
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_zones z';
|
||||
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_zones z';
|
||||
|
||||
public function __construct($conditions = [], $miscData = null)
|
||||
{
|
||||
|
||||
@@ -17,10 +17,12 @@ class User
|
||||
public static $dailyVotes = 0;
|
||||
public static $ip = null;
|
||||
|
||||
private static $reputation = 0;
|
||||
private static $dataKey = '';
|
||||
private static $expires = false;
|
||||
private static $passHash = '';
|
||||
private static $reputation = 0;
|
||||
private static $dataKey = '';
|
||||
private static $expires = false;
|
||||
private static $passHash = '';
|
||||
private static $excludeGroups = 1;
|
||||
private static $profiles = null;
|
||||
|
||||
public static function init()
|
||||
{
|
||||
@@ -39,7 +41,7 @@ class User
|
||||
// check IP bans
|
||||
if ($ipBan = DB::Aowow()->selectRow('SELECT count, unbanDate FROM ?_account_bannedips WHERE ip = ? AND type = 0', self::$ip))
|
||||
{
|
||||
if ($ipBan['count'] > CFG_FAILED_AUTH_COUNT && $ipBan['unbanDate'] > time())
|
||||
if ($ipBan['count'] > CFG_ACC_FAILED_AUTH_COUNT && $ipBan['unbanDate'] > time())
|
||||
return false;
|
||||
else if ($ipBan['unbanDate'] <= time())
|
||||
DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE ip = ?', self::$ip);
|
||||
@@ -54,7 +56,7 @@ class User
|
||||
return false;
|
||||
|
||||
$query = DB::Aowow()->SelectRow('
|
||||
SELECT a.id, a.passHash, a.displayName, a.locale, a.userGroups, a.userPerms, a.allowExpire, BIT_OR(ab.typeMask) AS bans, IFNULL(SUM(r.amount), 0) as reputation, a.avatar, a.dailyVotes
|
||||
SELECT a.id, a.passHash, a.displayName, a.locale, a.userGroups, a.userPerms, a.allowExpire, BIT_OR(ab.typeMask) AS bans, IFNULL(SUM(r.amount), 0) as reputation, a.avatar, a.dailyVotes, a.excludeGroups
|
||||
FROM ?_account a
|
||||
LEFT JOIN ?_account_banned ab ON a.id = ab.userId AND ab.end > UNIX_TIMESTAMP()
|
||||
LEFT JOIN ?_account_reputation r ON a.id = r.userId
|
||||
@@ -73,15 +75,26 @@ class User
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$id = intval($query['id']);
|
||||
self::$displayName = $query['displayName'];
|
||||
self::$passHash = $query['passHash'];
|
||||
self::$expires = (bool)$query['allowExpire'];
|
||||
self::$reputation = $query['reputation'];
|
||||
self::$banStatus = $query['bans'];
|
||||
self::$groups = $query['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($query['userGroups']);
|
||||
self::$perms = $query['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($query['userPerms']);
|
||||
self::$dailyVotes = $query['dailyVotes'];
|
||||
self::$id = intval($query['id']);
|
||||
self::$displayName = $query['displayName'];
|
||||
self::$passHash = $query['passHash'];
|
||||
self::$expires = (bool)$query['allowExpire'];
|
||||
self::$reputation = $query['reputation'];
|
||||
self::$banStatus = $query['bans'];
|
||||
self::$groups = $query['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($query['userGroups']);
|
||||
self::$perms = $query['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($query['userPerms']);
|
||||
self::$dailyVotes = $query['dailyVotes'];
|
||||
self::$excludeGroups = $query['excludeGroups'];
|
||||
|
||||
$conditions = array(
|
||||
[['cuFlags', PROFILER_CU_DELETED, '&'], 0],
|
||||
['OR', ['user', self::$id], ['ap.accountId', self::$id]]
|
||||
);
|
||||
|
||||
if (self::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
|
||||
array_shift($conditions);
|
||||
|
||||
self::$profiles = (new LocalProfileList($conditions));
|
||||
|
||||
if ($query['avatar'])
|
||||
self::$avatar = $query['avatar'];
|
||||
@@ -112,7 +125,7 @@ class User
|
||||
);
|
||||
|
||||
// gain rep for daily visit
|
||||
if (!(self::$banStatus & (ACC_BAN_TEMP | ACC_BAN_PERM)))
|
||||
if (!(self::$banStatus & (ACC_BAN_TEMP | ACC_BAN_PERM)) && !self::isInGroup(U_GROUP_PENDING))
|
||||
Util::gainSiteReputation(self::$id, SITEREP_ACTION_DAILYVISIT);
|
||||
|
||||
// increment consecutive visits (next day or first of new month and not more than 48h)
|
||||
@@ -140,11 +153,11 @@ class User
|
||||
$rawIp = explode(',', $rawIp)[0]; // [ip, proxy1, proxy2]
|
||||
|
||||
// check IPv4
|
||||
if ($ipAddr = filter_var($rawIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))
|
||||
if ($ipAddr = filter_var($rawIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
|
||||
break;
|
||||
|
||||
// check IPv6
|
||||
if ($ipAddr = filter_var($rawIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))
|
||||
if ($ipAddr = filter_var($rawIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -178,9 +191,18 @@ class User
|
||||
}
|
||||
}
|
||||
|
||||
// check
|
||||
if ($loc != LOCALE_EN && !(CFG_LOCALES & (1 << $loc)))
|
||||
$loc = LOCALE_EN;
|
||||
// check; pick first viable if failed
|
||||
if (CFG_LOCALES && !(CFG_LOCALES & (1 << $loc)))
|
||||
{
|
||||
foreach (Util::$localeStrings as $idx => $__)
|
||||
{
|
||||
if (CFG_LOCALES & (1 << $idx))
|
||||
{
|
||||
$loc = $idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set
|
||||
if (self::$id)
|
||||
@@ -213,7 +235,7 @@ class User
|
||||
$user = 0;
|
||||
$hash = '';
|
||||
|
||||
switch (CFG_AUTH_MODE)
|
||||
switch (CFG_ACC_AUTH_MODE)
|
||||
{
|
||||
case AUTH_MODE_SELF:
|
||||
{
|
||||
@@ -223,11 +245,11 @@ class User
|
||||
// handle login try limitation
|
||||
$ip = DB::Aowow()->selectRow('SELECT ip, count, unbanDate FROM ?_account_bannedips WHERE type = 0 AND ip = ?', self::$ip);
|
||||
if (!$ip || $ip['unbanDate'] < time()) // no entry exists or time expired; set count to 1
|
||||
DB::Aowow()->query('REPLACE INTO ?_account_bannedips (ip, type, count, unbanDate) VALUES (?, 0, 1, UNIX_TIMESTAMP() + ?d)', self::$ip, CFG_FAILED_AUTH_EXCLUSION);
|
||||
DB::Aowow()->query('REPLACE INTO ?_account_bannedips (ip, type, count, unbanDate) VALUES (?, 0, 1, UNIX_TIMESTAMP() + ?d)', self::$ip, CFG_ACC_FAILED_AUTH_BLOCK);
|
||||
else // entry already exists; increment count
|
||||
DB::Aowow()->query('UPDATE ?_account_bannedips SET count = count + 1, unbanDate = UNIX_TIMESTAMP() + ?d WHERE ip = ?', CFG_FAILED_AUTH_EXCLUSION, self::$ip);
|
||||
DB::Aowow()->query('UPDATE ?_account_bannedips SET count = count + 1, unbanDate = UNIX_TIMESTAMP() + ?d WHERE ip = ?', CFG_ACC_FAILED_AUTH_BLOCK, self::$ip);
|
||||
|
||||
if ($ip && $ip['count'] >= CFG_FAILED_AUTH_COUNT && $ip['unbanDate'] >= time())
|
||||
if ($ip && $ip['count'] >= CFG_ACC_FAILED_AUTH_COUNT && $ip['unbanDate'] >= time())
|
||||
return AUTH_IPBANNED;
|
||||
|
||||
$query = DB::Aowow()->SelectRow('
|
||||
@@ -245,9 +267,6 @@ class User
|
||||
if (!self::verifyCrypt($pass))
|
||||
return AUTH_WRONGPASS;
|
||||
|
||||
if ($query['status'] & ACC_STATUS_NEW)
|
||||
return AUTH_ACC_INACTIVE;
|
||||
|
||||
// successfull auth; clear bans for this IP
|
||||
DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE type = 0 AND ip = ?', self::$ip);
|
||||
|
||||
@@ -287,11 +306,13 @@ class User
|
||||
return AUTH_INTERNAL_ERR;
|
||||
|
||||
require 'config/extAuth.php';
|
||||
$result = extAuth($name, $pass, $extId);
|
||||
|
||||
$extGroup = -1;
|
||||
$result = extAuth($name, $pass, $extId, $extGroup);
|
||||
|
||||
if ($result == AUTH_OK && $extId)
|
||||
{
|
||||
if ($_ = self::checkOrCreateInDB($extId, $name))
|
||||
if ($_ = self::checkOrCreateInDB($extId, $name, $extGroup))
|
||||
$user = $_;
|
||||
else
|
||||
return AUTH_INTERNAL_ERR;
|
||||
@@ -314,18 +335,28 @@ class User
|
||||
}
|
||||
|
||||
// create a linked account for our settings if nessecary
|
||||
private static function checkOrCreateInDB($extId, $name)
|
||||
private static function checkOrCreateInDB($extId, $name, $userGroup = -1)
|
||||
{
|
||||
if ($_ = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE extId = ?d', $extId))
|
||||
return $_;
|
||||
if (!intVal($extId))
|
||||
return 0;
|
||||
|
||||
$newId = DB::Aowow()->query('INSERT IGNORE INTO ?_account (extId, user, displayName, joinDate, prevIP, prevLogin, locale, status) VALUES (?d, ?, ?, UNIX_TIMESTAMP(), ?, UNIX_TIMESTAMP(), ?d, ?d)',
|
||||
$userGroup = intVal($userGroup);
|
||||
|
||||
if ($_ = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE extId = ?d', $extId))
|
||||
{
|
||||
if ($userGroup >= U_GROUP_NONE)
|
||||
DB::Aowow()->query('UPDATE ?_account SET userGroups = ?d WHERE extId = ?d', $userGroup, $extId);
|
||||
return $_;
|
||||
}
|
||||
|
||||
$newId = DB::Aowow()->query('INSERT IGNORE INTO ?_account (extId, user, displayName, joinDate, prevIP, prevLogin, locale, status, userGroups) VALUES (?d, ?, ?, UNIX_TIMESTAMP(), ?, UNIX_TIMESTAMP(), ?d, ?d, ?d)',
|
||||
$extId,
|
||||
$name,
|
||||
Util::ucFirst($name),
|
||||
isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '',
|
||||
User::$localeId,
|
||||
ACC_STATUS_OK
|
||||
ACC_STATUS_OK,
|
||||
$userGroup >= U_GROUP_NONE ? $userGroup : U_GROUP_NONE
|
||||
);
|
||||
|
||||
if ($newId)
|
||||
@@ -352,7 +383,7 @@ class User
|
||||
public static function verifyCrypt($pass, $hash = '')
|
||||
{
|
||||
$_ = $hash ?: self::$passHash;
|
||||
return $_ == crypt($pass, $_);
|
||||
return $_ === crypt($pass, $_);
|
||||
}
|
||||
|
||||
// sha1 used by TC / MaNGOS
|
||||
@@ -363,16 +394,30 @@ class User
|
||||
|
||||
private static function verifySHA1($name, $pass)
|
||||
{
|
||||
return self::$passHash == self::hashSHA1($name, $pass);
|
||||
return strtoupper(self::$passHash) === strtoupper(self::hashSHA1($name, $pass));
|
||||
}
|
||||
|
||||
public static function isValidName($name, &$errCode = 0)
|
||||
{
|
||||
$errCode = 0;
|
||||
|
||||
if (strlen($name) < 4 || strlen($name) > 16)
|
||||
// different auth modes require different usernames
|
||||
$min = 0; // external case
|
||||
$max = 0;
|
||||
if (CFG_ACC_AUTH_MODE == AUTH_MODE_SELF)
|
||||
{
|
||||
$min = 4;
|
||||
$max = 16;
|
||||
}
|
||||
else if (CFG_ACC_AUTH_MODE == AUTH_MODE_REALM)
|
||||
{
|
||||
$min = 3;
|
||||
$max = 32;
|
||||
}
|
||||
|
||||
if (($min && mb_strlen($name) < $min) || ($max && mb_strlen($name) > $max))
|
||||
$errCode = 1;
|
||||
else if (preg_match('/[^\w\d]/i', $name))
|
||||
else if (preg_match('/[^\w\d\-]/i', $name))
|
||||
$errCode = 2;
|
||||
|
||||
return $errCode == 0;
|
||||
@@ -382,7 +427,8 @@ class User
|
||||
{
|
||||
$errCode = 0;
|
||||
|
||||
if (strlen($pass) < 6 || strlen($pass) > 16)
|
||||
// only enforce for own passwords
|
||||
if (mb_strlen($pass) < 6 && CFG_ACC_AUTH_MODE == AUTH_MODE_SELF)
|
||||
$errCode = 1;
|
||||
// else if (preg_match('/[^\w\d!"#\$%]/', $pass)) // such things exist..? :o
|
||||
// $errCode = 2;
|
||||
@@ -430,6 +476,14 @@ class User
|
||||
return self::$perms || self::$reputation >= CFG_REP_REQ_COMMENT;
|
||||
}
|
||||
|
||||
public static function canReply()
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_COMMENT | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return false;
|
||||
|
||||
return self::$perms || self::$reputation >= CFG_REP_REQ_REPLY;
|
||||
}
|
||||
|
||||
public static function canUpvote()
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_COMMENT | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
@@ -454,6 +508,22 @@ class User
|
||||
return self::$reputation >= CFG_REP_REQ_SUPERVOTE;
|
||||
}
|
||||
|
||||
public static function canUploadScreenshot()
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_SCREENSHOT | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function canSuggestVideo()
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_VIDEO | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function isPremium()
|
||||
{
|
||||
return self::isInGroup(U_GROUP_PREMIUM) || self::$reputation >= CFG_REP_REQ_PREMIUM;
|
||||
@@ -500,14 +570,19 @@ class User
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_TEMP | ACC_BAN_PERM))
|
||||
return $gUser;
|
||||
|
||||
$gUser['commentban'] = (bool)(self::$banStatus & ACC_BAN_COMMENT);
|
||||
$gUser['commentban'] = !self::canComment();
|
||||
$gUser['canUpvote'] = self::canUpvote();
|
||||
$gUser['canDownvote'] = self::canDownvote();
|
||||
$gUser['canPostReplies'] = self::canComment();
|
||||
$gUser['canPostReplies'] = self::canReply();
|
||||
$gUser['superCommentVotes'] = self::canSupervote();
|
||||
$gUser['downvoteRep'] = CFG_REP_REQ_DOWNVOTE;
|
||||
$gUser['upvoteRep'] = CFG_REP_REQ_UPVOTE;
|
||||
$gUser['characters'] = self::getCharacters();
|
||||
$gUser['excludegroups'] = self::$excludeGroups;
|
||||
$gUser['settings'] = (new StdClass); // profiler requires this to be set; has property premiumborder (NYI)
|
||||
|
||||
if ($_ = self::getProfilerExclusions())
|
||||
$gUser = array_merge($gUser, $_);
|
||||
|
||||
if ($_ = self::getProfiles())
|
||||
$gUser['profiles'] = $_;
|
||||
@@ -523,63 +598,45 @@ class User
|
||||
|
||||
public static function getWeightScales()
|
||||
{
|
||||
$data = [];
|
||||
$result = [];
|
||||
|
||||
$res = DB::Aowow()->select('SELECT * FROM ?_account_weightscales WHERE userId = ?d', self::$id);
|
||||
foreach ($res as $i)
|
||||
{
|
||||
$set = array (
|
||||
'name' => $i['name'],
|
||||
'id' => $i['id']
|
||||
);
|
||||
$res = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, name FROM ?_account_weightscales WHERE userId = ?d', self::$id);
|
||||
if (!$res)
|
||||
return $result;
|
||||
|
||||
$weights = explode(',', $i['weights']);
|
||||
foreach ($weights as $weight)
|
||||
{
|
||||
$w = explode(':', $weight);
|
||||
$weights = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, `field` AS ARRAY_KEY2, val FROM ?_account_weightscale_data WHERE id IN (?a)', array_keys($res));
|
||||
foreach ($weights as $id => $data)
|
||||
$result[] = array_merge(['name' => $res[$id], 'id' => $id], $data);
|
||||
|
||||
if ($w[1] === 'undefined')
|
||||
$w[1] = 0;
|
||||
return $result;
|
||||
}
|
||||
|
||||
$set[$w[0]] = $w[1];
|
||||
}
|
||||
public static function getProfilerExclusions()
|
||||
{
|
||||
$result = [];
|
||||
$modes = [1 => 'excludes', 2 => 'includes'];
|
||||
foreach ($modes as $mode => $field)
|
||||
if ($ex = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, typeId AS ARRAY_KEY2, typeId FROM ?_account_excludes WHERE mode = ?d AND userId = ?d', $mode, self::$id))
|
||||
foreach ($ex as $type => $ids)
|
||||
$result[$field][$type] = array_values($ids);
|
||||
|
||||
$data[] = $set;
|
||||
}
|
||||
|
||||
return $data;
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function getCharacters()
|
||||
{
|
||||
// existing chars on realm(s)
|
||||
$characters = array(
|
||||
// array(
|
||||
// 'id' => 22,
|
||||
// 'name' => 'Example Char',
|
||||
// 'realmname' => 'Example Realm',
|
||||
// 'region' => 'eu',
|
||||
// 'realm' => 'example-realm',
|
||||
// 'race' => 6,
|
||||
// 'classs' => 11,
|
||||
// 'level' => 80,
|
||||
// 'gender' => 1,
|
||||
// 'pinned' => 1
|
||||
// )
|
||||
);
|
||||
if (!self::$profiles)
|
||||
return [];
|
||||
|
||||
return $characters;
|
||||
return self::$profiles->getJSGlobals(PROFILEINFO_CHARACTER);
|
||||
}
|
||||
|
||||
public static function getProfiles()
|
||||
{
|
||||
// chars build in profiler
|
||||
$profiles = array(
|
||||
// array('id' => 21, 'name' => 'Example Profile 1', 'race' => 4, 'classs' => 5, 'level' => 72, 'gender' => 1, 'icon' => 'inv_axe_04'),
|
||||
// array('id' => 23, 'name' => 'Example Profile 2', 'race' => 11, 'classs' => 3, 'level' => 17, 'gender' => 0)
|
||||
);
|
||||
if (!self::$profiles)
|
||||
return [];
|
||||
|
||||
return $profiles;
|
||||
return self::$profiles->getJSGlobals(PROFILEINFO_PROFILE);
|
||||
}
|
||||
|
||||
public static function getCookies()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
70
index.php
70
index.php
@@ -22,19 +22,25 @@ switch ($pageCall)
|
||||
case 'account': // account management [nyi]
|
||||
case 'achievement':
|
||||
case 'achievements':
|
||||
// case 'arena-team':
|
||||
// case 'arena-teams':
|
||||
case 'arena-team':
|
||||
case 'arena-teams':
|
||||
case 'class':
|
||||
case 'classes':
|
||||
case 'currency':
|
||||
case 'currencies':
|
||||
case 'compare': // tool: item comparison
|
||||
case 'emote':
|
||||
case 'emotes':
|
||||
case 'enchantment':
|
||||
case 'enchantments':
|
||||
case 'event':
|
||||
case 'events':
|
||||
case 'faction':
|
||||
case 'factions':
|
||||
// case 'guild':
|
||||
// case 'guilds':
|
||||
case 'guild':
|
||||
case 'guilds':
|
||||
case 'icon':
|
||||
case 'icons':
|
||||
case 'item':
|
||||
case 'items':
|
||||
case 'itemset':
|
||||
@@ -60,8 +66,8 @@ switch ($pageCall)
|
||||
case 'search': // tool: searches
|
||||
case 'skill':
|
||||
case 'skills':
|
||||
// case 'sound': // db: sounds for zone, creature, spell, ...
|
||||
// case 'sounds':
|
||||
case 'sound':
|
||||
case 'sounds':
|
||||
case 'spell':
|
||||
case 'spells':
|
||||
case 'talent': // tool: talent calculator
|
||||
@@ -71,17 +77,40 @@ switch ($pageCall)
|
||||
case 'video':
|
||||
case 'zone':
|
||||
case 'zones':
|
||||
if (in_array($pageCall, ['admin', 'account', 'profile']))
|
||||
/* called by script */
|
||||
case 'data': // tool: dataset-loader
|
||||
case 'cookie': // lossless cookies and user settings
|
||||
case 'contactus':
|
||||
case 'comment':
|
||||
case 'filter': // pre-evaluate filter POST-data; sanitize and forward as GET-data
|
||||
case 'go-to-comment': // find page the comment is on and forward
|
||||
case 'locale': // subdomain-workaround, change the language
|
||||
$cleanName = str_replace(['-', '_'], '', ucFirst($altClass ?: $pageCall));
|
||||
try // can it be handled as ajax?
|
||||
{
|
||||
if (($_ = (new AjaxHandler($pageParam))->handle($pageCall)) !== null)
|
||||
$class = 'Ajax'.$cleanName;
|
||||
$ajax = new $class(explode('.', $pageParam));
|
||||
if ($ajax->handle($out))
|
||||
{
|
||||
header('Content-type: application/x-javascript; charset=utf-8');
|
||||
die((string)$_);
|
||||
Util::sendNoCacheHeader();
|
||||
|
||||
if ($ajax->doRedirect)
|
||||
header('Location: '.$out, true, 302);
|
||||
else
|
||||
{
|
||||
header('Content-type: '.$ajax->getContentType());
|
||||
die($out);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new Exception('not handled as ajax');
|
||||
}
|
||||
catch (Exception $e) // no, apparently not..
|
||||
{
|
||||
$class = $cleanName.'Page';
|
||||
(new $class($pageCall, $pageParam))->display();
|
||||
}
|
||||
|
||||
$_ = ($altClass ?: $pageCall).'Page';
|
||||
(new $_($pageCall, $pageParam))->display();
|
||||
break;
|
||||
/* other pages */
|
||||
case 'whats-new':
|
||||
@@ -91,6 +120,10 @@ switch ($pageCall)
|
||||
case 'help':
|
||||
case 'faq':
|
||||
case 'aboutus':
|
||||
case 'reputation':
|
||||
case 'privilege':
|
||||
case 'privileges':
|
||||
case 'top-users':
|
||||
(new MorePage($pageCall, $pageParam))->display();
|
||||
break;
|
||||
case 'latest-additions':
|
||||
@@ -104,19 +137,6 @@ switch ($pageCall)
|
||||
case 'random':
|
||||
(new UtilityPage($pageCall, $pageParam))->display();
|
||||
break;
|
||||
/* called by script */
|
||||
case 'data': // tool: dataset-loader
|
||||
case 'cookie': // lossless cookies and user settings
|
||||
case 'contactus':
|
||||
case 'comment':
|
||||
case 'go-to-comment': // find page the comment is on and forward
|
||||
case 'locale': // subdomain-workaround, change the language
|
||||
if (($_ = (new AjaxHandler($pageParam))->handle($pageCall)) !== null)
|
||||
{
|
||||
header('Content-type: application/x-javascript; charset=utf-8');
|
||||
die((string)$_);
|
||||
}
|
||||
break;
|
||||
default: // unk parameter given -> ErrorPage
|
||||
if (isset($_GET['power']))
|
||||
die('$WowheadPower.register(0, '.User::$localeId.', {})');
|
||||
|
||||
@@ -8,25 +8,34 @@ class Lang
|
||||
private static $user;
|
||||
private static $mail;
|
||||
private static $game;
|
||||
private static $maps;
|
||||
private static $profiler;
|
||||
private static $screenshot;
|
||||
private static $privileges;
|
||||
|
||||
// types
|
||||
private static $achievement;
|
||||
private static $chrClass;
|
||||
private static $currency;
|
||||
private static $event;
|
||||
private static $faction;
|
||||
private static $gameObject;
|
||||
private static $icon;
|
||||
private static $item;
|
||||
private static $itemset;
|
||||
private static $maps;
|
||||
private static $npc;
|
||||
private static $pet;
|
||||
private static $quest;
|
||||
private static $race;
|
||||
private static $skill;
|
||||
private static $sound;
|
||||
private static $spell;
|
||||
private static $title;
|
||||
private static $zone;
|
||||
|
||||
private static $emote;
|
||||
private static $enchantment;
|
||||
|
||||
public static function load($loc)
|
||||
{
|
||||
if (!file_exists('localization/locale_'.$loc.'.php'))
|
||||
@@ -37,33 +46,79 @@ class Lang
|
||||
foreach ($lang as $k => $v)
|
||||
self::$$k = $v;
|
||||
|
||||
// *cough* .. reuse-hack
|
||||
// *cough* .. reuse-hacks (because copy-pastaing text for 5 locales sucks)
|
||||
self::$item['cat'][2] = [self::$item['cat'][2], self::$spell['weaponSubClass']];
|
||||
self::$item['cat'][2][1][14] .= ' ('.self::$item['cat'][2][0].')';
|
||||
|
||||
// not localized .. for whatever reason
|
||||
self::$profiler['regions'] = array(
|
||||
'eu' => "Europe",
|
||||
'us' => "US & Oceanic"
|
||||
);
|
||||
|
||||
self::$main['moreTitles']['privilege'] = self::$privileges['_privileges'];
|
||||
}
|
||||
|
||||
// todo: make static props private and access through this
|
||||
public static function __callStatic($prop, $args)
|
||||
{
|
||||
if (!isset(self::$$prop))
|
||||
{
|
||||
Util::addNote(U_GROUP_STAFF, 'Lang::__callStatic() - tried to use undefined property Lang::$'.$prop);
|
||||
trigger_error('Lang - tried to use undefined property Lang::$'.$prop, E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
|
||||
$vspfArgs = [];
|
||||
|
||||
$var = self::$$prop;
|
||||
foreach ($args as $key)
|
||||
foreach ($args as $arg)
|
||||
{
|
||||
if (!isset($var[$key]))
|
||||
if (is_array($arg))
|
||||
{
|
||||
Util::addNote(U_GROUP_STAFF, 'Lang::__callStatic() - undefined key "'.$key.'" in property Lang::$'.$prop.'[\''.implode('\'][\'', $args).'\']');
|
||||
$vspfArgs = $arg;
|
||||
continue;
|
||||
}
|
||||
else if (!isset($var[$arg]))
|
||||
{
|
||||
trigger_error('Lang - undefined key "'.$arg.'" in property Lang::$'.$prop.'[\''.implode('\'][\'', $args).'\']', E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
|
||||
$var = $var[$key];
|
||||
$var = $var[$arg];
|
||||
}
|
||||
|
||||
return $var;
|
||||
// meh :x
|
||||
if ($var === null && $prop == 'spell' && count($args) == 1)
|
||||
{
|
||||
if ($args[0] == 'effects')
|
||||
$var = self::$$prop['unkEffect'];
|
||||
else if ($args[0] == 'auras')
|
||||
$var = self::$$prop['unkAura'];
|
||||
}
|
||||
|
||||
return self::vspf($var, $vspfArgs);
|
||||
}
|
||||
|
||||
public static function concat($args, $useAnd = true, $callback = null)
|
||||
{
|
||||
$b = '';
|
||||
$i = 0;
|
||||
$n = count($args);
|
||||
foreach ($args as $k => $arg)
|
||||
{
|
||||
if (is_callable($callback))
|
||||
$b .= $callback($arg, $k);
|
||||
else
|
||||
$b .= $arg;
|
||||
|
||||
if ($n > 1 && $i < ($n - 2))
|
||||
$b .= ', ';
|
||||
else if ($n > 1 && $i == $n - 2)
|
||||
$b .= Lang::main($useAnd ? 'and' : 'or');
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
return $b;
|
||||
}
|
||||
|
||||
public static function sort($prop, $group, $method = SORT_NATURAL)
|
||||
@@ -71,14 +126,14 @@ class Lang
|
||||
|
||||
if (!isset(self::$$prop))
|
||||
{
|
||||
Util::addNote(U_GROUP_STAFF, 'Lang::sort() - tried to use undefined property Lang::$'.$prop);
|
||||
trigger_error('Lang::sort - tried to use undefined property Lang::$'.$prop, E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
|
||||
$var = &self::$$prop;
|
||||
if (!isset($var[$group]))
|
||||
{
|
||||
Util::addNote(U_GROUP_STAFF, 'Lang::sort() - tried to use undefined property Lang::$'.$prop.'[\''.$group.'\']');
|
||||
trigger_error('Lang::sort - tried to use undefined property Lang::$'.$prop.'[\''.$group.'\']', E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -166,7 +221,7 @@ class Lang
|
||||
|
||||
public static function getReputationLevelForPoints($pts)
|
||||
{
|
||||
$_ = Util::getReputationLevelForPoints($pts);
|
||||
$_ = Game::getReputationLevelForPoints($pts);
|
||||
|
||||
return self::game('rep', $_);
|
||||
}
|
||||
@@ -205,12 +260,17 @@ class Lang
|
||||
if ($mask & (1 << $k) && $str)
|
||||
$tmp[] = $str;
|
||||
|
||||
return implode(', ', $tmp);
|
||||
if (!$tmp && $class == ITEM_CLASS_ARMOR)
|
||||
return self::spell('cat', -11, 8);
|
||||
else if (!$tmp && $class == ITEM_CLASS_WEAPON)
|
||||
return self::spell('cat', -11, 6);
|
||||
else
|
||||
return implode(', ', $tmp);
|
||||
}
|
||||
|
||||
public static function getStances($stanceMask)
|
||||
{
|
||||
$stanceMask &= 0xFC27909F; // clamp to available stances/forms..
|
||||
$stanceMask &= 0xFF37F6FF; // clamp to available stances/forms..
|
||||
|
||||
$tmp = [];
|
||||
$i = 1;
|
||||
@@ -320,6 +380,116 @@ class Lang
|
||||
|
||||
return implode(', ', $tmp);
|
||||
}
|
||||
|
||||
public static function nf($number, $decimals = 0, $no1k = false)
|
||||
{
|
||||
// [decimal, thousand]
|
||||
$seps = array(
|
||||
LOCALE_EN => [',', '.'],
|
||||
LOCALE_FR => [' ', ','],
|
||||
LOCALE_DE => ['.', ','],
|
||||
LOCALE_ES => ['.', ','],
|
||||
LOCALE_RU => [' ', ',']
|
||||
);
|
||||
|
||||
return number_format($number, $decimals, $seps[User::$localeId][1], $no1k ? '' : $seps[User::$localeId][0]);
|
||||
}
|
||||
|
||||
private static function vspf($var, $args)
|
||||
{
|
||||
if (is_array($var))
|
||||
{
|
||||
foreach ($var as &$v)
|
||||
$v == self::vspf($v, $args);
|
||||
|
||||
return $var;
|
||||
}
|
||||
|
||||
if ($args)
|
||||
$var = vsprintf($var, $args);
|
||||
|
||||
// line break
|
||||
// |n
|
||||
$var = str_replace('|n', '<br />', $var);
|
||||
|
||||
// color
|
||||
// |c<aarrggbb><word>|r
|
||||
$var = preg_replace('/\|cff([a-f0-9]{6})(.+?)\|r/i', '<span style="color: #$1;">$2</span>', $var);
|
||||
|
||||
// icon
|
||||
// |T<imgPath>:0:0:0:-1|t - not used, skip if found
|
||||
$var = preg_replace('/\|T[^\|]+\|t/', '', $var);
|
||||
|
||||
// hyperlink
|
||||
// |H<hyperlinkStruct>|h<name>|h - not used, truncate structure if found
|
||||
$var = preg_replace('/\|H[^\|]+\|h([^\|]+)\|h/', '$1', $var);
|
||||
|
||||
// french preposition : de
|
||||
// |2 <word>
|
||||
$var = preg_replace_callback('/\|2\s(\w)/i', function ($m) {
|
||||
if (in_array(strtolower($m[1]), ['a', 'e', 'h', 'i', 'o', 'u']))
|
||||
return "d'".$m[1];
|
||||
else
|
||||
return 'de '.$m[1];
|
||||
}, $var);
|
||||
|
||||
// russian word cunjugation thingy
|
||||
// |3-<number>(<word>)
|
||||
$var = preg_replace_callback('/\|3-(\d)\(([^\)]+)\)/i', function ($m) {
|
||||
switch ($m[0])
|
||||
{
|
||||
case 1: // seen cases
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
default: // passthrough .. unk case
|
||||
return $m[1];
|
||||
}
|
||||
|
||||
}, $var);
|
||||
|
||||
// numeric switch
|
||||
// <number> |4<singular>:<plural>[:<plural2>];
|
||||
$var = preg_replace_callback('/([\d\.\,]+)([^\d]*)\|4([^:]*):([^;]*);/i', function ($m) {
|
||||
$plurals = explode(':', $m[4]);
|
||||
$result = '';
|
||||
|
||||
if (count($plurals) == 2) // special case: ruRU
|
||||
{
|
||||
switch (substr($m[1], -1)) // check last digit of number
|
||||
{
|
||||
case 1:
|
||||
// but not 11 (teen number)
|
||||
if (!in_array($m[1], [11]))
|
||||
{
|
||||
$result = $m[3];
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
// but not 12, 13, 14 (teen number) [11 is passthrough]
|
||||
if (!in_array($m[1], [11, 12, 13, 14]))
|
||||
{
|
||||
$result = $plurals[0];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$result = $plurals[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
$result = ($m[1] == 1 ? $m[3] : $plurals[0]);
|
||||
|
||||
return $m[1].$m[2].$result;
|
||||
}, $var);
|
||||
|
||||
return $var;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -14,8 +14,7 @@ $lang = array(
|
||||
'timeUnits' => array(
|
||||
'sg' => ["año", "mes", "semana", "día", "hora", "minuto", "segundo", "milisegundo"],
|
||||
'pl' => ["años", "meses", "semanas", "dias", "horas", "minutos", "segundos", "milisegundos"],
|
||||
'ab' => ["año", "mes", "sem", "", "h", "min", "seg", "ms"],
|
||||
'ago' => 'hace %s'
|
||||
'ab' => ["año", "mes", "sem", "", "h", "min", "seg", "ms"]
|
||||
),
|
||||
'main' => array(
|
||||
'name' => "nombre",
|
||||
@@ -43,14 +42,18 @@ $lang = array(
|
||||
'cancel' => "Cancelar",
|
||||
'rewards' => "Recompensas",
|
||||
'gains' => "Ganancias",
|
||||
'login' => "[Login]",
|
||||
'login' => "Ingresar",
|
||||
'forum' => "Foro",
|
||||
'n_a' => "n/d",
|
||||
'siteRep' => "Reputación",
|
||||
'yourRepHistory'=> "Tu Historial de Reputación",
|
||||
'aboutUs' => "Sobre Aowow",
|
||||
'and' => " y ",
|
||||
'or' => " o ",
|
||||
'back' => "Arrière",
|
||||
'back' => "Atrás",
|
||||
'reputationTip' => "Puntos de reputación",
|
||||
'byUserTimeAgo' => 'Por <a href="'.HOST_URL.'/?user=%s">%1$s</a> hace %s',
|
||||
'help' => "Ayuda",
|
||||
|
||||
// filter
|
||||
'extSearch' => "Extender búsqueda",
|
||||
@@ -67,10 +70,10 @@ $lang = array(
|
||||
|
||||
// infobox
|
||||
'unavailable' => "No está disponible a los jugadores",
|
||||
'disabled' => "[Disabled]",
|
||||
'disabledHint' => "[Cannot be attained or completed]",
|
||||
'serverside' => "[Serverside]",
|
||||
'serversideHint'=> "[These informations are not in the Client and have been provided by sniffing and/or guessing.]",
|
||||
'disabled' => "Deshabilitado",
|
||||
'disabledHint' => "No puede ser conseguido o completado",
|
||||
'serverside' => "Parte del Servidor",
|
||||
'serversideHint'=> "Esta información no se encuentra en el Cliente y ha sido previsto mediante un analizador de paquetes (Sniffing) y/o suponiendo.",
|
||||
|
||||
// red buttons
|
||||
'links' => "Enlaces",
|
||||
@@ -107,22 +110,6 @@ $lang = array(
|
||||
'chooseClass' => "Escoge una clase",
|
||||
'chooseFamily' => "Escoge una familia de mascota",
|
||||
|
||||
// profiler
|
||||
'realm' => "Reino",
|
||||
'region' => "Región",
|
||||
'viewCharacter' => "View Character",
|
||||
'_cpHead' => "Perfiles de Personaje",
|
||||
'_cpHint' => "l <b>Gestor de perfiles</b> te permite editar tu personaje, encontrar mejoras de equipo, comprobar tu gearscore, ¡y más!",
|
||||
'_cpHelp' => "Para comenzar, sigue los pasos abajo indicados. Si quieres más información, revisa nuestra amplia <a href=\"?help=profiler\">página de ayuda</a>.",
|
||||
'_cpFooter' => "Si quieres una búsqueda más refinada, prueba con nuestras opciones de <a href=\"?profiles\">búsqueda avanzada</a>. También puedes crear un <a href=\"?profile&new\">perfil nuevo personalizado</a>.",
|
||||
|
||||
// help
|
||||
'help' => "Ayuda",
|
||||
'helpTopics' => array(
|
||||
"Los comentarios y tú", "Visualizador de modelos", "Capturas de pantalla: Sugerencias y trucos", "Medición de atributos",
|
||||
"Calculadora de talentos", "Comparación de objetos", "Perfiles", "Markup Guide"
|
||||
),
|
||||
|
||||
// search
|
||||
'search' => "Búsqueda",
|
||||
'searchButton' => "búsqueda",
|
||||
@@ -137,35 +124,74 @@ $lang = array(
|
||||
'dateFmtLong' => "d/m/Y \a \l\a\s H:i",
|
||||
|
||||
// error
|
||||
'intError' => "[An internal error occured.]",
|
||||
'intError2' => "[An internal error occured. (%s)]",
|
||||
'intError' => "Un error interno ha ocurrido.",
|
||||
'intError2' => "Un error interno ha ocurrido. (%s)",
|
||||
'genericError' => "Ha ocurrido un error; refresca la página e inténtalo de nuevo. Si el error persiste manda un correo a <a href='#contact'>feedback</a>", # LANG.genericerror
|
||||
'bannedRating' => "Has sido baneado y no podrás valorar comentarios.", # LANG.tooltip_banned_rating
|
||||
'tooManyVotes' => "Has alcanzado el límite diario de votos. Vuelve mañana.", # LANG.tooltip_too_many_votes
|
||||
|
||||
// screenshots
|
||||
'prepError' => "[An error occured preparing your screenshot]",
|
||||
'cropHint' => "[Crop the image by dragging the selection.<br>Please refer to <a href=\"?help=screenshots-tips-tricks\">Screenshots: Tips & Tricks</a> for an optimal layout.]",
|
||||
'caption' => "[Caption]",
|
||||
'originalSize' => "[Original size]",
|
||||
'targetSize' => "[Target size]",
|
||||
'minSize' => "[Minimum size]",
|
||||
'displayOn' => "[Displayed on: %s[br][%s=%d]]",
|
||||
'ssEdit' => "[Edit uploaded screenshot]",
|
||||
'ssUpload' => "[Screenshot Upload]",
|
||||
'ssSubmit' => "[Submit Screenshot]",
|
||||
'ssErrors' => array(
|
||||
'noUpload' => "[The file was not uploaded!]",
|
||||
'maxSize' => "[The file exceeds the maximum size of %s!]",
|
||||
'interrupted' => "[The upload process was interrupted!]",
|
||||
'noFile' => "[The file was not received!]",
|
||||
'noDest' => "[The page this screenshot should be displayed on, does not exist!]",
|
||||
'notAllowed' => "[You are not allowed to upload screenshots!]",
|
||||
'noImage' => "[The uploaded file is not an image file!]",
|
||||
'wrongFormat' => "[The image file must be a png or jpg!]",
|
||||
'load' => "[The image file could not be loaded!]",
|
||||
'tooSmall' => "[The image size is too small! (lower than %d x %d)]",
|
||||
'tooLarge' => "[The image size is too large! (greater than %d x %d)]"
|
||||
'moreTitles' => array(
|
||||
'reputation' => "Reputación de la web",
|
||||
'whats-new' => "What's New",
|
||||
'searchbox' => "Caja de búsqueda",
|
||||
'tooltips' => "Tooltips",
|
||||
'faq' => "Preguntas frecuentes",
|
||||
'aboutus' => "[What is AoWoW?]",
|
||||
'searchplugins' => "Extensiones de búsqueda",
|
||||
'privileges' => "Privilegios",
|
||||
'top-users' => "Usuarios más populares",
|
||||
'help' => array(
|
||||
'commenting-and-you' => "Los comentarios y tú", 'modelviewer' => "Visualizador de modelos", 'screenshots-tips-tricks' => "Capturas de pantalla: Sugerencias y trucos",
|
||||
'stat-weighting' => "Medición de atributos", 'talent-calculator' => "Calculadora de talentos", 'item-comparison' => "Comparación de objetos",
|
||||
'profiler' => "Perfiles", 'markup-guide' => "Margen de Guia"
|
||||
)
|
||||
)
|
||||
),
|
||||
'profiler' => array(
|
||||
'realm' => "Reino",
|
||||
'region' => "Región",
|
||||
'viewCharacter' => "View Character",
|
||||
'_cpHint' => "l <b>Gestor de perfiles</b> te permite editar tu personaje, encontrar mejoras de equipo, comprobar tu gearscore, ¡y más!",
|
||||
'_cpHelp' => "Para comenzar, sigue los pasos abajo indicados. Si quieres más información, revisa nuestra amplia <a href=\"?help=profiler\">página de ayuda</a>.",
|
||||
'_cpFooter' => "Si quieres una búsqueda más refinada, prueba con nuestras opciones de <a href=\"?profiles\">búsqueda avanzada</a>. También puedes crear un <a href=\"?profile&new\">perfil nuevo personalizado</a>.",
|
||||
'firstUseTitle' => "%s de %s",
|
||||
'complexFilter' => "[Complex filter selected! Search results are limited to cached Characters.]",
|
||||
|
||||
'resync' => "Resincronizar",
|
||||
'guildRoster' => "Lista de miembros de hermandad para <%s>",
|
||||
'arenaRoster' => "Personajes del Equipo de Arena para <%s>",
|
||||
'atCaptain' => "Capitán de equipo de arena",
|
||||
|
||||
'profiler' => "Gestor de Perfiles", // Perfiles de Personaje? (character profiler)
|
||||
'arenaTeams' => "Equipos de Arena",
|
||||
'guilds' => "Hermandades",
|
||||
|
||||
'notFound' => array(
|
||||
'guild' => "[This Guild doesn't exist or is not yet in the database.]",
|
||||
'arenateam' => "[This Arena Team doesn't exist or is not yet in the database.]",
|
||||
'profile' => "Este personaje no existe o no está aun en la base de datos.",
|
||||
),
|
||||
'dummyNPCs' => array(
|
||||
100001 => "Batalla de naves de guerra", 200001 => "Bestias de Rasganorte", 200002 => "Campeones de facciones", 200003 => "Gemelas Val'kyr"
|
||||
),
|
||||
),
|
||||
'screenshot' => array(
|
||||
'submission' => "Enviar una captura de pantalla",
|
||||
'selectAll' => "Seleccionar todos",
|
||||
'cropHint' => "Puede reducir su imagen e introducir una etiqueta.",
|
||||
'displayOn' => "Mostrado en:[br]%s - [%s=%d]",
|
||||
'caption' => "Anotación",
|
||||
'charLimit' => "Opcional, hasta 200 caracteres",
|
||||
'thanks' => array(
|
||||
'contrib' => "¡Muchísimas gracias por tu aportación!",
|
||||
'goBack' => '<a href="?%s=%d">aquí vuelve</a> a la página de la que viniste.',
|
||||
'note' => "Nota: Su captura de imagen tiene que ser aprobada antes de que pueda aparecer en el sitio. Esto puede tomar hasta 72 horas."
|
||||
),
|
||||
'error' => array(
|
||||
'unkFormat' => "Formato de imagen desconocido.",
|
||||
'tooSmall' => "Su captura de pantalla es muy pequeña. (< ".CFG_SCREENSHOT_MIN_SIZE."x".CFG_SCREENSHOT_MIN_SIZE.").",
|
||||
'selectSS' => "Por favor seleccione la captura de pantalla para subir.",
|
||||
'notAllowed' => "¡No estás permitido para subir capturas de pantalla!",
|
||||
)
|
||||
),
|
||||
'game' => array(
|
||||
@@ -178,8 +204,12 @@ $lang = array(
|
||||
'difficulty' => "Dificultad",
|
||||
'dispelType' => "Tipo de disipación",
|
||||
'duration' => "Duración",
|
||||
'gameObject' => "entidad",
|
||||
'gameObjects' => "Entidades",
|
||||
'emote' => "emoción",
|
||||
'emotes' => "Emociones",
|
||||
'enchantment' => "encantamiento",
|
||||
'enchantments' => "Encantamientos",
|
||||
'object' => "entidad",
|
||||
'objects' => "Entidades",
|
||||
'glyphType' => "Tipo de glifo",
|
||||
'race' => "raza",
|
||||
'races' => "Razas",
|
||||
@@ -191,6 +221,8 @@ $lang = array(
|
||||
'faction' => "facción",
|
||||
'factions' => "Facciones",
|
||||
'cooldown' => "%s de reutilización",
|
||||
'icon' => "icono",
|
||||
'icons' => "Iconos",
|
||||
'item' => "objeto",
|
||||
'items' => "Objetos",
|
||||
'itemset' => "conjunto de objetos",
|
||||
@@ -209,12 +241,13 @@ $lang = array(
|
||||
'requires' => "Requiere %s",
|
||||
'requires2' => "Requiere",
|
||||
'reqLevel' => "Necesitas ser de nivel %s",
|
||||
'reqLevelHlm' => "Necesitas ser de nivel %s",
|
||||
'reqSkillLevel' => "Requiere nivel de habilidad",
|
||||
'level' => "Nivel",
|
||||
'school' => "Escuela",
|
||||
'skill' => "habilidad",
|
||||
'skills' => "Habilidades",
|
||||
'sound' => "sonido",
|
||||
'sounds' => "Sonidos",
|
||||
'spell' => "hechizo",
|
||||
'spells' => "Hechizos",
|
||||
'type' => "Tipo",
|
||||
@@ -260,10 +293,10 @@ $lang = array(
|
||||
'rep' => ["Odiado", "Hostil", "Adverso", "Neutral", "Amistoso", "Honorable", "Reverenciado", "Exaltado"],
|
||||
'st' => array(
|
||||
"Defecto", "Forma felina", "Árbol de vida", "Forma de viaje", "Forma acuática", "Forma de oso",
|
||||
null, null, "Forma de oso temible", null, null, null,
|
||||
null, "Danza de las Sombras", null, null, "Lobo fantasmal", "Actitud de batalla",
|
||||
"Actitud defensiva", "Actitud rabiosa", null, null, "Metamorfosis", null,
|
||||
null, null, null, "Forma de vuelo presto", "Forma de las Sombras", "Forma de vuelo",
|
||||
"Ambiente", "Necrófago", "Forma de oso temible", "Steve's Ghoul", "Esqueleto Tharon'ja", "Luna Negra - Prueba de fuerza",
|
||||
"BLB Player", "Danza de las Sombras", "Criatura: oso", "Criatura: felino", "Lobo fantasmal", "Actitud de batalla",
|
||||
"Actitud defensiva", "Actitud rabiosa", "Test", "Zombi", "Metamorfosis", null,
|
||||
null, "No-muerto", "Furia", "Forma de vuelo presto", "Forma de las Sombras", "Forma de vuelo",
|
||||
"Sigilo", "Forma de lechúcico lunar", "Espíritu redentor"
|
||||
),
|
||||
'me' => array(
|
||||
@@ -288,11 +321,11 @@ $lang = array(
|
||||
45 => "Can del Núcleo", 46 => "Bestia espíritu"
|
||||
),
|
||||
'pvpRank' => array(
|
||||
null, "Private / Scout", "Corporal / Grunt",
|
||||
"Sergeant / Sergeant", "Master Sergeant / Senior Sergeant", "Sergeant Major / First Sergeant",
|
||||
"Knight / Stone Guard", "Knight-Lieutenant / Blood Guard", "Knight-Captain / Legionnare",
|
||||
"Knight-Champion / Centurion", "Lieutenant Commander / Champion", "Commander / Lieutenant General",
|
||||
"Marshal / General", "Field Marshal / Warlord", "Grand Marshal / High Warlord"
|
||||
null, "Soldado / Explorador", "Cabo / Bruto",
|
||||
"Sargento / Sargento", "Sargento maestro / Sargento jefe", "Sargento mayor / Sargento primero",
|
||||
"Caballero / Guardian de Piedra", "Teniente caballero / Guardia de sangre", "Capitán caballero / Legionario",
|
||||
"Campeón caballero / Centurion", "Teniente coronel / Campeón", "Comandante / Teniente general",
|
||||
"Mariscal / General", "Mariscal de campo / Señor de la Guerra", "Gran mariscal / Gran Señor de la Guerra"
|
||||
),
|
||||
),
|
||||
'account' => array(
|
||||
@@ -302,9 +335,8 @@ $lang = array(
|
||||
'groups' => array(
|
||||
-1 => "Ninguno", "Probador", "Administrador", "Editor", "Moderador", "Burócrata",
|
||||
"Desarrollador", "VIP", "Bloggor", "Premium", "Traductor", "Agente de ventas",
|
||||
"Gestor de Capturas de pantalla","Gestor de vídeos"
|
||||
"Gestor de Capturas de pantalla","Gestor de vídeos", "Partner de API", "Pendiente"
|
||||
),
|
||||
|
||||
// signIn
|
||||
'doSignIn' => "Iniciar sesión con tu cuenta de Aowow",
|
||||
'signIn' => "Iniciar sesión",
|
||||
@@ -319,48 +351,48 @@ $lang = array(
|
||||
// recovery
|
||||
'recoverUser' => "Pedir nombre de usuario",
|
||||
'recoverPass' => "Reiniciar contraseña: Paso %s de 2",
|
||||
'newPass' => "New Password",
|
||||
'newPass' => "Nueva Contraseña",
|
||||
|
||||
// creation
|
||||
'register' => "Inscripción: Paso %s de 2",
|
||||
'passConfirm' => "Confirmar contraseña",
|
||||
|
||||
// dashboard
|
||||
'ipAddress' => "IP-Adress",
|
||||
'lastIP' => "last used IP",
|
||||
'myAccount' => "My Account",
|
||||
'editAccount' => "Simply use the forms below to update your account information",
|
||||
'viewPubDesc' => 'View your Public Description in your <a href="?user=%s">Profile Page</a>',
|
||||
'ipAddress' => "Dirección IP",
|
||||
'lastIP' => "Última IP usada",
|
||||
'myAccount' => "Mi cuenta",
|
||||
'editAccount' => "Use el formulario siguienta para actualizar la información de la cuenta.",
|
||||
'viewPubDesc' => 'Mira tu descripción pública en tu <a href="?user=%s">Página de perfil</a>',
|
||||
|
||||
// bans
|
||||
'accBanned' => "This Account was closed",
|
||||
'bannedBy' => "Banned by",
|
||||
'ends' => "Ends on",
|
||||
'permanent' => "The ban is permanent",
|
||||
'reason' => "Reason",
|
||||
'noReason' => "No reason was given.",
|
||||
'accBanned' => "Esta cuenta fue cerrada.",
|
||||
'bannedBy' => "Suspendida por",
|
||||
'ends' => "Finaliza en",
|
||||
'permanent' => "La restricción es permanente",
|
||||
'reason' => "Razón",
|
||||
'noReason' => "Ningúna razón fue escrita.",
|
||||
|
||||
// form-text
|
||||
'emailInvalid' => "Esa dirección de correo electrónico no es válida.", // message_emailnotvalid
|
||||
'emailNotFound' => "The email address you entered is not associated with any account.<br><br>If you forgot the email you registered your account with email ".CFG_CONTACT_EMAIL." for assistance.",
|
||||
'createAccSent' => "An email was sent to <b>%s</b>. Simply follow the instructions to create your account.",
|
||||
'recovUserSent' => "An email was sent to <b>%s</b>. Simply follow the instructions to recover your username.",
|
||||
'recovPassSent' => "An email was sent to <b>%s</b>. Simply follow the instructions to reset your password.",
|
||||
'accActivated' => 'Your account has been activated.<br>Proceed to <a href="?account=signin&token=%s">sign in</a>',
|
||||
'userNotFound' => "The username you entered does not exists.",
|
||||
'wrongPass' => "That password is not vaild.",
|
||||
'accInactive' => "That account has not yet been confirmed active.",
|
||||
'loginExceeded' => "The maximum number of logins from this IP has been exceeded. Please try again in %s.",
|
||||
'signupExceeded'=> "The maximum number of signups from this IP has been exceeded. Please try again in %s.",
|
||||
'emailNotFound' => "El correo electrónico que ingresaste no está asociado con ninguna cuenta.<br><br>Si olvistaste el correo electronico con el que registraste la cuenta, escribe a ".CFG_CONTACT_EMAIL." para asistencia.",
|
||||
'createAccSent' => "Un correo fue enviado a <b>%s</b>. Siga las instrucciones para crear su cuenta.",
|
||||
'recovUserSent' => "Un correo fue enviado a <b>%s</b>. Siga las instrucciones para recuperar su nombre de usuario.",
|
||||
'recovPassSent' => "Un correo fue enviado a <b>%s</b>. Siga las instrucciones para reiniciar su contraseña.",
|
||||
'accActivated' => 'Su cuenta ha sido activada.<br>Ingrese a <a href="?account=signin&token=%s">para ingresar</a>',
|
||||
'userNotFound' => "El usuario que ha ingresado no existe",
|
||||
'wrongPass' => "La contraseña no es valida.",
|
||||
// 'accInactive' => "That account has not yet been confirmed active.",
|
||||
'loginExceeded' => "Ha excedido la cantidad de inicios de sesion con esta IP. Por favor intente en %s",
|
||||
'signupExceeded'=> "Ha excedido la cantidad de creaciones de cuentas con esta IP. Por favor intente en %s.",
|
||||
'errNameLength' => "Tu nombre de usuario tiene que tener por lo menos cuatro caracteres.", // message_usernamemin
|
||||
'errNameChars' => "Tu nombre de usuario solo puede contener números y letras.", // message_usernamenotvalid
|
||||
'errPassLength' => "Tu contraseña tiene que tener por lo menos seis caracteres.", // message_passwordmin
|
||||
'passMismatch' => "The passwords you entered do not match.",
|
||||
'nameInUse' => "That username is already taken.",
|
||||
'mailInUse' => "That email is already registered to an account.",
|
||||
'isRecovering' => "This account is already recovering. Follow the instructions in your email or wait %s for the token to expire.",
|
||||
'passMismatch' => "La contraseña que ingresó no concuerdan.",
|
||||
'nameInUse' => "El nombre de usuario ya se encuentra utilzado",
|
||||
'mailInUse' => "El correo electrónico ya se encuentra registrado a una cuenta",
|
||||
'isRecovering' => "Esta cuenta ya se encuentra en proceso de recuperación. Siga las intrucciones en su correo o espere %s para que el token expire ",
|
||||
'passCheckFail' => "Las contraseñas no son iguales.", // message_passwordsdonotmatch
|
||||
'newPassDiff' => "Su nueva contraseña tiene que ser diferente a Su contraseña anterior." // message_newpassdifferent
|
||||
'newPassDiff' => "Su nueva contraseña tiene que ser diferente a su contraseña anterior." // message_newpassdifferent
|
||||
),
|
||||
'user' => array(
|
||||
'notFound' => "¡No se encontró el usuario \"%s\"!",
|
||||
@@ -379,23 +411,43 @@ $lang = array(
|
||||
'posts' => "Mensajes en los foros"
|
||||
),
|
||||
'mail' => array(
|
||||
'tokenExpires' => "This token expires in %s.",
|
||||
'accConfirm' => ["Account Confirmation", "Welcome to ".CFG_NAME_SHORT."!\r\n\r\nClick the Link below to activate your account.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
|
||||
'recoverUser' => ["User Recovery", "Follow this link to log in.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
|
||||
'resetPass' => ["Password Reset", "Follow this link to reset your password.\r\n\r\n".HOST_URL."?account=forgotpassword&token=%s\r\n\r\nIf you did not request this mail simply ignore it."]
|
||||
'tokenExpires' => "Este token expira en %s",
|
||||
'accConfirm' => ["Confirmación de Cuenta", "Bienvenido a ".CFG_NAME_SHORT."!\r\n\r\nHaga click en el enlace siguiente para activar su cuenta.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nSi usted no solicitó este correo, por favor ignorelo."],
|
||||
'recoverUser' => ["Recuperacion de Usuario", "Siga a este enlace para ingresar.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nSi usted no solicitó este correo, por favor ignorelo."],
|
||||
'resetPass' => ["Reinicio de Contraseña", "Siga este enlace para reiniciar su contraseña.\r\n\r\n".HOST_URL."?account=forgotpassword&token=%s\r\n\r\nSi usted no solicitó este correo, por favor ignorelo."]
|
||||
),
|
||||
'emote' => array(
|
||||
'notFound' => "Este emoticón no existe",
|
||||
'self' => "Para Usted",
|
||||
'target' => "Para otros con un objetivo",
|
||||
'noTarget' => "Para otros sin un objetivo",
|
||||
'isAnimated' => "Usa una animación",
|
||||
'aliases' => "Aliases",
|
||||
'noText' => "Este emoticón no tiene texto",
|
||||
),
|
||||
'enchantment' => array(
|
||||
'details' => "Detalles",
|
||||
'activation' => "Activación",
|
||||
'notFound' => "Este encantamiento no existe.",
|
||||
'types' => array(
|
||||
1 => "Prob. Hechizo", 3 => "Equipar Hechizo", 7 => "Usar Hechizo", 8 => "Ranura prismática",
|
||||
5 => "Atributos", 2 => "Daño de arma", 6 => "DPS", 4 => "Defensa"
|
||||
)
|
||||
),
|
||||
'gameObject' => array(
|
||||
'notFound' => "Este entidad no existe.",
|
||||
'cat' => [0 => "Otros", 9 => "Libros", 3 => "Contenedores", -5 => "Cofres", 25 => "Bancos de peces", -3 => "Hierbas", -4 => "Venas de minerales", -2 => "Misiones", -6 => "Herramientas"],
|
||||
'type' => [ 9 => "Libro", 3 => "Contenedore", -5 => "Cofre", 25 => "", -3 => "Hierba", -4 => "Filóne de mineral", -2 => "Misión", -6 => ""],
|
||||
'unkPosition' => "No se conoce la ubicación de esta entidad.",
|
||||
'npcLootPH' => 'El <b>%s</b> contiene el botín de la pelea contra <a href="?npc=%d">%s</a>. Aparece al morir.',
|
||||
'key' => "Llave",
|
||||
'focus' => "[Spell Focus]",
|
||||
'focusDesc' => "[Spells requiring this Focus can be cast near this Object]",
|
||||
'focus' => "Foco del hechizo",
|
||||
'focusDesc' => "El hechizo que requiere este foco no puede ser lanzado cerca del objeto",
|
||||
'trap' => "Trampa",
|
||||
'triggeredBy' => "Accionado por",
|
||||
'capturePoint' => "Punto de captura",
|
||||
'restock' => "[Restocks every %s.]"
|
||||
'foundIn' => "Este entidad se puede encontrar en",
|
||||
'restock' => "Se renueva cada %s."
|
||||
),
|
||||
'npc' => array(
|
||||
'notFound' => "Este PNJ no existe.",
|
||||
@@ -404,10 +456,10 @@ $lang = array(
|
||||
'react' => "Reacción",
|
||||
'worth' => "Valor",
|
||||
'unkPosition' => "No se conoce la ubicación de este PNJ.",
|
||||
'difficultyPH' => "[Este PNJ es un marcador de posición para un modo diferente de]",
|
||||
'seat' => "[Seat]",
|
||||
'accessory' => "[Accessory]",
|
||||
'accessoryFor' => "[This creature is an accessory for vehicle]",
|
||||
'difficultyPH' => "Este PNJ es un marcador de posición para un modo diferente de",
|
||||
'seat' => "Asiento",
|
||||
'accessory' => "Accesorio",
|
||||
'accessoryFor' => "Esta criatura es una accesorio para vehículo",
|
||||
'quotes' => "Citas",
|
||||
'gainsDesc' => "Tras acabar con este PNJ ganarás",
|
||||
'repWith' => "reputación con",
|
||||
@@ -417,12 +469,13 @@ $lang = array(
|
||||
'melee' => "Cuerpo a cuerpo",
|
||||
'ranged' => "Ataque a distancia",
|
||||
'armor' => "Armadura",
|
||||
'foundIn' => "Este PNJ se puede encontrar en",
|
||||
'tameable' => "Domesticable (%s)",
|
||||
'waypoint' => "punto de recorrido",
|
||||
'wait' => "Tiempo de espera",
|
||||
'respawnIn' => "Reingreso en",
|
||||
'rank' => [0 => "Normal", 1 => "Élite", 4 => "Raro", 2 => "Élite raro", 3 => "Jefe"],
|
||||
'textRanges' => [null, "[sent to area]", "[sent to zone]", "[sent to map]", "[sent to world]"],
|
||||
'textRanges' => [null, "Mandar al área", "Mandar a zona", "Mandar al mapa", "Mandar al mundo"],
|
||||
'textTypes' => [null, "grita", "dice", "susurra"],
|
||||
'modes' => array(
|
||||
1 => ["Normal", "Heroico"],
|
||||
@@ -452,7 +505,7 @@ $lang = array(
|
||||
'titleReward' => 'Deberías obtener el título "<a href="?title=%d">%s</a>"',
|
||||
'slain' => "matado",
|
||||
'reqNumCrt' => "Requiere",
|
||||
'rfAvailable' => "Disponible en reino:",
|
||||
'rfAvailable' => "Disponible en reino: ",
|
||||
'_transfer' => 'Este logro será convertido a <a href="?achievement=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a> si lo transfieres a la <span class="icon-%s">%s</span>.',
|
||||
),
|
||||
'chrClass' => array(
|
||||
@@ -480,15 +533,29 @@ $lang = array(
|
||||
'Azeroth' => "Azeroth",
|
||||
'CosmicMap' => "Mapa cósmico",
|
||||
),
|
||||
'privileges' => array(
|
||||
'main' => "Aquí, en AoWoW, puedes conseguir <a href=\"?reputation\">reputación</a>. La forma principal de conseguirla es conseguir que tus comentarios sean votados de forma positiva.<br /><br />Así pues, la reputación es algo que mide, más o menos, cúanto has contribuido a la comunidad.<br /><br />Conforme consigues reputación, te ganas la confianza de la comunidad y tendrás privilegios adicionales. Puedes encontrar una lista completa debajo.",
|
||||
'privilege' => "Privilegio",
|
||||
'privileges' => "Privilegios",
|
||||
'requiredRep' => "Reputación requerida",
|
||||
'reqPoints' => "Este privilegio necesita <b>%s</b> puntos de reputación.",
|
||||
'_privileges' => array(
|
||||
null, "Escribir comentarios", "Escribir enlaces externos", null,
|
||||
"Sin CAPTCHAs", "Los votos de comentario valen más", null, null,
|
||||
null, "Más votos por día", "Dar una valoración positiva a comentarios", "Dar una valoración negativa a comentarios",
|
||||
"Escribir respuestas a comentarios", "Borde: Poco Común", "Borde: Raro", "Borde: Épica",
|
||||
"Borde: Legendaria", "AoWoW Premium"
|
||||
)
|
||||
),
|
||||
'zone' => array(
|
||||
'notFound' => "Esta zona no existe.",
|
||||
'attunement' => ["Requisito", "Requisito heroica"],
|
||||
'key' => ["Llave", "Llave heroica"],
|
||||
'location' => "Ubicación",
|
||||
'raidFaction' => "[Raid faction]",
|
||||
'raidFaction' => "Facción de la banda",
|
||||
'boss' => "Jefe Final",
|
||||
'reqLevels' => "Niveles requeridos: [tooltip=instancereqlevel_tip]%d[/tooltip], [tooltip=lfgreqlevel_tip]%d[/tooltip]",
|
||||
'zonePartOf' => "Cette zone fait partie de la zone [zone=%d].",
|
||||
'zonePartOf' => "Este campo es parte de la zona [zone=%d].",
|
||||
'autoRez' => "Resurrección automática",
|
||||
'city' => "Ciudad",
|
||||
'territory' => "Territorio",
|
||||
@@ -510,7 +577,7 @@ $lang = array(
|
||||
'requirements' => 'Requisitos',
|
||||
'reqMoney' => 'Dinero necesario',
|
||||
'money' => 'Dinero',
|
||||
'additionalReq' => "[Additional requirements to obtain this quest]",
|
||||
'additionalReq' => "Requerimientos adicionales para obtener esta misión",
|
||||
'reqRepWith' => 'Tu reputación con <a href="?faction=%d">%s</a> debe ser %s %s',
|
||||
'reqRepMin' => "de al menos",
|
||||
'reqRepMax' => "menor que",
|
||||
@@ -557,8 +624,9 @@ $lang = array(
|
||||
'receiveAlso' => "También recibirás",
|
||||
'spellCast' => "Te van a lanzar el siguiente hechizo",
|
||||
'spellLearn' => "Aprenderás",
|
||||
'bonusTalents' => "puntos de talento",
|
||||
'bonusTalents' => "%d |4punto:puntos; de talento",
|
||||
'spellDisplayed'=> ' (mostrando <a href="?spell=%d">%s</a>)',
|
||||
'attachment' => "Adjunto",
|
||||
'questInfo' => array(
|
||||
0 => "Normal", 1 => "Élite", 21 => "Vida", 41 => "JcJ", 62 => "Banda", 81 => "Mazmorra", 82 => "Evento del mundo",
|
||||
83 => "Legendaria", 84 => "Escolta", 85 => "Heroica", 88 => "Banda (10)", 89 => "Banda (25)"
|
||||
@@ -634,6 +702,9 @@ $lang = array(
|
||||
-2 => "Sin categoría"
|
||||
)
|
||||
),
|
||||
'icon' => array(
|
||||
'notFound' => "Este icono no existe."
|
||||
),
|
||||
'title' => array(
|
||||
'notFound' => "Este título no existe.",
|
||||
'_transfer' => 'Este título será convertido a <a href="?title=%d" class="q1">%s</a> si lo transfieres a la <span class="icon-%s">%s</span>.',
|
||||
@@ -655,19 +726,34 @@ $lang = array(
|
||||
1 => "Miscelánea", 2 => "Jugador contra Jugador", 4 => "Clásico", 21 => "Wrath of the Lich King", 22 => "Mazmorra y banda", 23 => "Burning Crusade", 41 => "Prueba", 3 => "No las uso"
|
||||
)
|
||||
),
|
||||
'sound' => array(
|
||||
'notFound' => "Este sonido no existe.",
|
||||
'foundIn' => "Este sonido se puede encontrar en",
|
||||
'goToPlaylist' => "Ir a mi lista de reproducción",
|
||||
'music' => "Música",
|
||||
'intro' => "Música de introducción",
|
||||
'ambience' => "Ambiente",
|
||||
'cat' => array(
|
||||
null, "Spells", "User Interface", "Footsteps", "Weapons Impacts", null, "Weapons Misses", null, null, "Pick Up/Put Down",
|
||||
"NPC Combat", null, "Errors", "Nature", "Objects", null, "Death", "NPC Greetings", null, "Armor",
|
||||
"Footstep Splash", "Water (Character)", "Water", "Tradeskills", "Misc Ambience", "Doodads", "Spell Fizzle", "NPC Loops", "Zone Music", "Emotes",
|
||||
"Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "Mi Lista de Reproducción"
|
||||
)
|
||||
),
|
||||
'pet' => array(
|
||||
'notFound' => "Esta familia de mascotas no existe.",
|
||||
'exotic' => "Exótica",
|
||||
'cat' => ["Ferocidad", "Tenacidad", "Astucia"]
|
||||
'cat' => ["Ferocidad", "Tenacidad", "Astucia"],
|
||||
'food' => ["Carne", "Pescado", "Queso", "Pan", "Hongo", "Fruta", "Carne cruda", "Pescado crudo"]
|
||||
),
|
||||
'faction' => array(
|
||||
'notFound' => "Esta facción no existe.",
|
||||
'spillover' => "[Reputation Spillover]",
|
||||
'spilloverDesc' => "[Gaining reputation with this faction also yields a proportional gain with the factions listed below.]",
|
||||
'spillover' => "Excedente de reputación",
|
||||
'spilloverDesc' => "Ganar reputación con esta facción tambien una proporción ganada con las facciones listadas a continuación.",
|
||||
'maxStanding' => "Posición máxima",
|
||||
'quartermaster' => "Intendente",
|
||||
'customRewRate' => "[Custom Reward Rate]",
|
||||
'_transfer' => '[The reputation with this faction will be converted to <a href="?faction=%d" class="q1">%s</a> if you transfer to <span class="icon-%s">%s</span>.]',
|
||||
'customRewRate' => "Radio de recompenza personalizado",
|
||||
'_transfer' => '[La reputación de esta facción sera convertida a <a href="?faction=%d" class="q1">%s</a> Si te transfieres a <span class="icon-%s">%s</span>.]',
|
||||
'cat' => array(
|
||||
1118 => ["Clásicas", 469 => "Alianza", 169 => "Cártel Bonvapor", 67 => "Horda", 891 => "Fuerzas de la Alianza", 892 => "Fuerzas de la Horda"],
|
||||
980 => ["The Burning Crusade", 936 => "Ciudad de Shattrath"],
|
||||
@@ -742,10 +828,12 @@ $lang = array(
|
||||
'pctCostOf' => "del %s base",
|
||||
'costPerSec' => ", mas %s por segundo",
|
||||
'costPerLevel' => ", mas %s por nivel",
|
||||
'_scaling' => "[Scaling]",
|
||||
'stackGroup' => "Grupo de aplilamiento",
|
||||
'linkedWith' => "Asociado con",
|
||||
'_scaling' => "Escala",
|
||||
'scaling' => array(
|
||||
'directSP' => "[+%.2f%% of spell power to direct component]", 'directAP' => "[+%.2f%% of attack power to direct component]",
|
||||
'dotSP' => "[+%.2f%% of spell power per tick]", 'dotAP' => "[+%.2f%% of attack power per tick]"
|
||||
'directSP' => "+%.2f%% del poder de hechizo al componente directo", 'directAP' => "+%.2f%% del poder de ataque al componente directo",
|
||||
'dotSP' => "+%.2f%% del poder de hechizo por tick", 'dotAP' => "+%.2f%% del poder de ataque por tick"
|
||||
),
|
||||
'powerRunes' => ["Escarcha", "Profano", "Sangre", "Muerte"],
|
||||
'powerTypes' => array(
|
||||
@@ -814,7 +902,8 @@ $lang = array(
|
||||
),
|
||||
'traitShort' => array(
|
||||
'atkpwr' => "PA", 'rgdatkpwr' => "PA", 'splpwr' => "PH", 'arcsplpwr' => "PArc", 'firsplpwr' => "PFue",
|
||||
'frosplpwr' => "PEsc", 'holsplpwr' => "PSag", 'natsplpwr' => "PNat", 'shasplpwr' => "PSom", 'splheal' => "Sana"
|
||||
'frosplpwr' => "PEsc", 'holsplpwr' => "PSag", 'natsplpwr' => "PNat", 'shasplpwr' => "PSom", 'splheal' => "Sana",
|
||||
'str' => "Fue", 'agi' => "Agi", 'sta' => "Agu", 'int' => "Int", 'spi' => "Esp"
|
||||
),
|
||||
'spellModOp' => array(
|
||||
"DAMAGE", "DURATION", "THREAT", "EFFECT1", "CHARGES",
|
||||
@@ -840,36 +929,127 @@ $lang = array(
|
||||
"Inscripción", "Abrir desde vehículo"
|
||||
),
|
||||
'stealthType' => ["GENERAL", "TRAP"],
|
||||
'invisibilityType' => ["GENERAL", 3 => "TRAP", 6 => "DRUNK"]
|
||||
'invisibilityType' => ["GENERAL", 3 => "TRAP", 6 => "DRUNK"],
|
||||
'unkEffect' => 'Unknown Effect',
|
||||
'effects' => array(
|
||||
/*0-5 */ 'None', 'Instakill', 'School Damage', 'Dummy', 'Portal Teleport', 'Teleport Units',
|
||||
/*6+ */ 'Apply Aura', 'Environmental Damage', 'Power Drain', 'Health Leech', 'Heal', 'Bind',
|
||||
/*12+ */ 'Portal', 'Ritual Base', 'Ritual Specialize', 'Ritual Activate Portal', 'Quest Complete', 'Weapon Damage NoSchool',
|
||||
/*18+ */ 'Resurrect', 'Add Extra Attacks', 'Dodge', 'Evade', 'Parry', 'Block',
|
||||
/*24+ */ 'Create Item', 'Can Use Weapon', 'Defense', 'Persistent Area Aura', 'Summon', 'Leap',
|
||||
/*30+ */ 'Energize', 'Weapon Damage Percent', 'Trigger Missile', 'Open Lock', 'Summon Change Item', 'Apply Area Aura Party',
|
||||
/*36+ */ 'Learn Spell', 'Spell Defense', 'Dispel', 'Language', 'Dual Wield', 'Jump',
|
||||
/*42+ */ 'Jump Dest', 'Teleport Units Face Caster','Skill Step', 'Add Honor', 'Spawn', 'Trade Skill',
|
||||
/*48+ */ 'Stealth', 'Detect', 'Trans Door', 'Force Critical Hit', 'Guarantee Hit', 'Enchant Item Permanent',
|
||||
/*54+ */ 'Enchant Item Temporary', 'Tame Creature', 'Summon Pet', 'Learn Pet Spell', 'Weapon Damage Flat', 'Create Random Item',
|
||||
/*60+ */ 'Proficiency', 'Send Event', 'Power Burn', 'Threat', 'Trigger Spell', 'Apply Area Aura Raid',
|
||||
/*66+ */ 'Create Mana Gem', 'Heal Max Health', 'Interrupt Cast', 'Distract', 'Pull', 'Pickpocket',
|
||||
/*72+ */ 'Add Farsight', 'Untrain Talents', 'Apply Glyph', 'Heal Mechanical', 'Summon Object Wild', 'Script Effect',
|
||||
/*78+ */ 'Attack', 'Sanctuary', 'Add Combo Points', 'Create House', 'Bind Sight', 'Duel',
|
||||
/*84+ */ 'Stuck', 'Summon Player', 'Activate Object', 'WMO Damage', 'WMO Repair', 'WMO Change',
|
||||
/*90+ */ 'Kill Credit', 'Threat All', 'Enchant Held Item', 'Force Deselect', 'Self Resurrect', 'Skinning',
|
||||
/*96+ */ 'Charge', 'Cast Button', 'Knock Back', 'Disenchant', 'Inebriate', 'Feed Pet',
|
||||
/*102+ */ 'Dismiss Pet', 'Reputation', 'Summon Object Slot1', 'Summon Object Slot2', 'Summon Object Slot3', 'Summon Object Slot4',
|
||||
/*108+ */ 'Dispel Mechanic', 'Summon Dead Pet', 'Destroy All Totems', 'Durability Damage', 'Summon Demon', 'Resurrect Flat',
|
||||
/*114+ */ 'Attack Me', 'Durability Damage Percent','Skin Player Corpse', 'Spirit Heal', 'Skill', 'Apply Area Aura Pet',
|
||||
/*120+ */ 'Teleport Graveyard', 'Weapon Damage Normalized', null, 'Send Taxi', 'Pull Towards', 'Modify Threat Percent',
|
||||
/*126+ */ 'Steal Beneficial Buff', 'Prospecting', 'Apply Area Aura Friend', 'Apply Area Aura Enemy', 'Redirect Threat', 'Play Sound',
|
||||
/*132+ */ 'Play Music', 'Unlearn Specialization', 'Kill Credit2', 'Call Pet', 'Heal Percent', 'Energize Percent',
|
||||
/*138+ */ 'Leap Back', 'Clear Quest', 'Force Cast', 'Force Cast With Value', 'Trigger Spell With Value', 'Apply Area Aura Owner',
|
||||
/*144+ */ 'Knock Back Dest', 'Pull Towards Dest', 'Activate Rune', 'Quest Fail', null, 'Charge Dest',
|
||||
/*150+ */ 'Quest Start', 'Trigger Spell 2', null, 'Create Tamed Pet', 'Discover Taxi', 'Dual Wield 2H Weapons',
|
||||
/*156+ */ 'Enchant Item Prismatic', 'Create Item 2', 'Milling', 'Allow Rename Pet', null, 'Talent Spec Count',
|
||||
/*162-164*/ 'Talent Spec Select', null, 'Remove Aura'
|
||||
),
|
||||
'unkAura' => 'Unknown Aura',
|
||||
'auras' => array(
|
||||
/*0- */ 'None', 'Bind Sight', 'Mod Possess', 'Periodic Damage', 'Dummy',
|
||||
/*5+ */ 'Mod Confuse', 'Mod Charm', 'Mod Fear', 'Periodic Heal', 'Mod Attack Speed',
|
||||
'Mod Threat', 'Taunt', 'Stun', 'Mod Damage Done Flat', 'Mod Damage Taken Flat',
|
||||
'Damage Shield', 'Mod Stealth', 'Mod Stealth Detection', 'Mod Invisibility', 'Mod Invisibility Detection',
|
||||
'Mod Health Percent', 'Mod Power Percent', 'Mod Resistance Flat', 'Periodic Trigger Spell', 'Periodic Energize',
|
||||
/*25+ */ 'Pacify', 'Root', 'Silence', 'Reflect Spells', 'Mod Stat Flat',
|
||||
'Mod Skill', 'Mod Increase Speed', 'Mod Increase Mounted Speed', 'Mod Decrease Speed', 'Mod Increase Health',
|
||||
'Mod Increase Power', 'Shapeshift', 'Spell Effect Immunity', 'Spell Aura Immunity', 'School Immunity',
|
||||
'Damage Immunity', 'Dispel Immunity', 'Proc Trigger Spell', 'Proc Trigger Damage', 'Track Creatures',
|
||||
'Track Resources', 'Mod Parry Skill', 'Mod Parry Percent', null, 'Mod Dodge Percent',
|
||||
/*50+ */ 'Mod Critical Healing Amount', 'Mod Block Percent', 'Mod Physical Crit Percent', 'Periodic Health Leech', 'Mod Hit Chance',
|
||||
'Mod Spell Hit Chance', 'Transform', 'Mod Spell Crit Chance', 'Mod Increase Swim Speed', 'Mod Damage Done Versus Creature',
|
||||
'Pacify Silence', 'Mod Scale', 'Periodic Health Funnel', 'Periodic Mana Funnel', 'Periodic Mana Leech',
|
||||
'Mod Casting Speed (not stacking)', 'Feign Death', 'Disarm', 'Stalked', 'School Absorb',
|
||||
'Extra Attacks', 'Mod Spell Crit Chance School', 'Mod Power Cost School Percent', 'Mod Power Cost School Flat', 'Reflect Spells School',
|
||||
/*75+ */ 'Language', 'Far Sight', 'Mechanic Immunity', 'Mounted', 'Mod Damage Done Percent',
|
||||
'Mod Stat Percent', 'Split Damage Percent', 'Water Breathing', 'Mod Base Resistance Flat', 'Mod Health Regeneration',
|
||||
'Mod Power Regeneration', 'Channel Death Item', 'Mod Damage Taken Percent', 'Mod Health Regeneration Percent', 'Periodic Damage Percent',
|
||||
'Mod Resist Chance', 'Mod Detect Range', 'Prevent Fleeing', 'Unattackable', 'Interrupt Regeneration',
|
||||
'Ghost', 'Spell Magnet', 'Mana Shield', 'Mod Skill Value', 'Mod Attack Power',
|
||||
/*100+ */ 'Auras Visible', 'Mod Resistance Percent', 'Mod Melee Attack Power Versus', 'Mod Total Threat', 'Water Walk',
|
||||
'Feather Fall', 'Hover', 'Add Flat Modifier', 'Add Percent Modifier', 'Add Target Trigger',
|
||||
'Mod Power Regeneration Percent', 'Add Caster Hit Trigger', 'Override Class Scripts', 'Mod Ranged Damage Taken Flat', 'Mod Ranged Damage Taken Percent',
|
||||
'Mod Healing', 'Mod Regeneration During Combat', 'Mod Mechanic Resistance', 'Mod Healing Taken Percent', 'Share Pet Tracking',
|
||||
'Untrackable', 'Empathy', 'Mod Offhand Damage Percent', 'Mod Target Resistance', 'Mod Ranged Attack Power',
|
||||
/*125+ */ 'Mod Melee Damage Taken Flat', 'Mod Melee Damage Taken Percent', 'Ranged Attack Power Attacker Bonus', 'Possess Pet', 'Mod Speed Always',
|
||||
'Mod Mounted Speed Always', 'Mod Ranged Attack Power Versus', 'Mod Increase Energy Percent', 'Mod Increase Health Percent', 'Mod Mana Regeneration Interrupt',
|
||||
'Mod Healing Done Flat', 'Mod Healing Done Percent', 'Mod Total Stat Percentage', 'Mod Melee Haste', 'Force Reaction',
|
||||
'Mod Ranged Haste', 'Mod Ranged Ammo Haste', 'Mod Base Resistance Percent', 'Mod Resistance Exclusive', 'Safe Fall',
|
||||
'Mod Pet Talent Points', 'Allow Tame Pet Type', 'Mechanic Immunity Mask', 'Retain Combo Points', 'Reduce Pushback',
|
||||
/*150+ */ 'Mod Shield Blockvalue Percent', 'Track Stealthed', 'Mod Detected Range', 'Split Damage Flat', 'Mod Stealth Level',
|
||||
'Mod Water Breathing', 'Mod Reputation Gain', 'Pet Damage Multi', 'Mod Shield Blockvalue', 'No PvP Credit',
|
||||
'Mod AoE Avoidance', 'Mod Health Regeneration In Combat', 'Power Burn Mana', 'Mod Crit Damage Bonus', null,
|
||||
'Melee Attack Power Attacker Bonus', 'Mod Attack Power Percent', 'Mod Ranged Attack Power Percent', 'Mod Damage Done Versus', 'Mod Crit Percent Versus',
|
||||
'Change Model', 'Mod Speed (not stacking)', 'Mod Mounted Speed (not stacking)', null, 'Mod Spell Damage Of Stat Percent',
|
||||
/*175+ */ 'Mod Spell Healing Of Stat Percent', 'Spirit Of Redemption', 'AoE Charm', 'Mod Debuff Resistance', 'Mod Attacker Spell Crit Chance',
|
||||
'Mod Spell Damage Versus', null, 'Mod Resistance Of Stat Percent', 'Mod Critical Threat', 'Mod Attacker Melee Hit Chance',
|
||||
'Mod Attacker Ranged Hit Chance', 'Mod Attacker Spell Hit Chance', 'Mod Attacker Melee Crit Chance', 'Mod Attacker Ranged Crit Chance', 'Mod Rating',
|
||||
'Mod Faction Reputation Gain', 'Use Normal Movement Speed', 'Mod Melee Ranged Haste', 'Mod Haste', 'Mod Target Absorb School',
|
||||
'Mod Target Ability Absorb School', 'Mod Cooldown', 'Mod Attacker Spell And Weapon Crit Chance', null, 'Mod Increases Spell Percent to Hit',
|
||||
/*200+ */ 'Mod XP Percent', 'Fly', 'Ignore Combat Result', 'Mod Attacker Melee Crit Damage', 'Mod Attacker Ranged Crit Damage',
|
||||
'Mod School Crit Damage Taken', 'Mod Increase Vehicle Flight Speed', 'Mod Increase Mounted Flight Speed', 'Mod Increase Flight Speed', 'Mod Mounted Flight Speed Always',
|
||||
'Mod Vehicle Speed Always', 'Mod Flight Speed (not stacking)', 'Mod Ranged Attack Power Of Stat Percent', 'Mod Rage from Damage Dealt', 'Tamed Pet Passive',
|
||||
'Arena Preparation', 'Haste Spells', 'Killing Spree', 'Haste Ranged', 'Mod Mana Regeneration from Stat',
|
||||
'Mod Rating from Stat', 'Ignore Threat', null, 'Raid Proc from Charge', null,
|
||||
/*225+ */ 'Raid Proc from Charge With Value', 'Periodic Dummy', 'Periodic Trigger Spell With Value', 'Detect Stealth', 'Mod AoE Damage Avoidance',
|
||||
'Mod Increase Health', 'Proc Trigger Spell With Value', 'Mod Mechanic Duration', 'Mod Display Model', 'Mod Mechanic Duration (not stacking)',
|
||||
'Mod Dispel Resist', 'Control Vehicle', 'Mod Spell Damage Of Attack Power', 'Mod Spell Healing Of Attack Power', 'Mod Scale 2',
|
||||
'Mod Expertise', 'Force Move Forward', 'Mod Spell Damage from Healing', 'Mod Faction', 'Comprehend Language',
|
||||
'Mod Aura Duration By Dispel', 'Mod Aura Duration By Dispel (not stacking)', 'Clone Caster', 'Mod Combat Result Chance', 'Convert Rune',
|
||||
/*250+ */ 'Mod Increase Health 2', 'Mod Enemy Dodge', 'Mod Speed Slow All', 'Mod Block Crit Chance', 'Mod Disarm Offhand',
|
||||
'Mod Mechanic Damage Taken Percent', 'No Reagent Use', 'Mod Target Resist By Spell Class', 'Mod Spell Visual', 'Mod HoT Percent',
|
||||
'Screen Effect', 'Phase', 'Ability Ignore Aurastate', 'Allow Only Ability', null,
|
||||
null, null, 'Mod Immune Aura Apply School', 'Mod Attack Power Of Stat Percent', 'Mod Ignore Target Resist',
|
||||
'Mod Ability Ignore Target Resist', 'Mod Damage Taken Percent From Caster', 'Ignore Melee Reset', 'X Ray', 'Ability Consume No Ammo',
|
||||
/*275+ */ 'Mod Ignore Shapeshift', 'Mod Mechanic Damage Done Percent', 'Mod Max Affected Targets', 'Mod Disarm Ranged', 'Initialize Images',
|
||||
'Mod Armor Penetration Percent', 'Mod Honor Gain Percent', 'Mod Base Health Percent', 'Mod Healing Received', 'Linked',
|
||||
'Mod Attack Power Of Armor', 'Ability Periodic Crit', 'Deflect Spells', 'Ignore Hit Direction', null,
|
||||
'Mod Crit Percent', 'Mod XP Quest Percent', 'Open Stable', 'Override Spells', 'Prevent Power Regeneration',
|
||||
null, 'Set Vehicle Id', 'Block Spell Family', 'Strangulate', null,
|
||||
/*300+ */ 'Share Damage Percent', 'School Heal Absorb', null, 'Mod Damage Done Versus Aurastate', 'Mod Fake Inebriate',
|
||||
'Mod Minimum Speed', null, 'Heal Absorb Test', 'Hunter Trap', null,
|
||||
'Mod Creature AoE Damage Avoidance', null, null, null, 'Prevent Ressurection',
|
||||
/* -316*/ 'Underwater Walking', 'Periodic Haste'
|
||||
)
|
||||
),
|
||||
'item' => array(
|
||||
'notFound' => "Este objeto no existe.",
|
||||
'armor' => "%s armadura",
|
||||
'block' => "%s bloqueo",
|
||||
'charges' => "cargas",
|
||||
'charges' => "%d |4carga:cargas;",
|
||||
'locked' => "Cerrado",
|
||||
'ratingString' => "%s @ L%s",
|
||||
'heroic' => "Heroico",
|
||||
'unique' => "Único",
|
||||
'uniqueEquipped'=> "Único-Equipado",
|
||||
'startQuest' => "Este objeto inicia una misión",
|
||||
'bagSlotString' => "%s de %d casillas",
|
||||
'dps' => "daño por segundo",
|
||||
'dps2' => "daño por segundo",
|
||||
'addsDps' => "Añade",
|
||||
'bagSlotString' => '%2$s de %1$d casillas',
|
||||
'fap' => "poder de ataque feral",
|
||||
'durability' => "Durabilidad",
|
||||
'durability' => "Durabilidad %d / %d",
|
||||
'realTime' => "tiempo real",
|
||||
'conjured' => "Objeto mágico",
|
||||
'damagePhys' => "%s Daño",
|
||||
'damageMagic' => "%s %s Daño",
|
||||
'speed' => "Velocidad",
|
||||
'sellPrice' => "Precio de venta",
|
||||
'itemLevel' => "Nivel de objeto",
|
||||
'itemLevel' => "Nivel de objeto %d",
|
||||
'randEnchant' => "<Encantamiento aleatorio>",
|
||||
'readClick' => "<Click derecho para leer>",
|
||||
'openClick' => "<Click derecho para abrir>",
|
||||
'set' => "Conjunto",
|
||||
'setBonus' => "(%d) Bonif.: %s",
|
||||
'setName' => "%s (%d/%d)",
|
||||
'partyLoot' => "Despojo de grupo",
|
||||
'smartLoot' => "Botín inteligente",
|
||||
'indestructible'=> "No puede ser destruido",
|
||||
@@ -902,6 +1082,18 @@ $lang = array(
|
||||
'buyout' => "Precio de venta en subasta",
|
||||
'each' => "cada uno",
|
||||
'tabOther' => "Otros",
|
||||
'reqMinLevel' => "Necesitas ser de nivel %d",
|
||||
'reqLevelRange' => "Requiere un nivel entre %d y %d (%s)",
|
||||
'unique' => ["Único", "Único (%d)", "Único: %s (%d)" ],
|
||||
'uniqueEquipped'=> ["Único-Equipado", null, "Único-Equipado: %s (%d)"],
|
||||
'speed' => "Veloc.",
|
||||
'dps' => "(%.1f daño por segundo)",
|
||||
'damage' => array( // *DAMAGE_TEMPLATE*
|
||||
// basic, basic /w school, add basic, add basic /w school
|
||||
"single" => ["%d Daño", "%d %s Daño", "+ %d daño", "+%d %s daños" ],
|
||||
"range" => ["%d - %d Daño", "%d - %d daño de %s", "+ %d: %d daño", "+%d - %d daño de %s" ],
|
||||
'ammo' => ["Añade %g daño por segundo", "Añade %g %s daño por segundo", "+ %g daño por segundo", "+ %g %s daño por segundo"]
|
||||
),
|
||||
'gems' => "Gemas",
|
||||
'socketBonus' => "Bono de ranura",
|
||||
'socket' => array(
|
||||
@@ -911,22 +1103,22 @@ $lang = array(
|
||||
"meta", "roja(s)", "amarilla(s)", "azul(es)"
|
||||
),
|
||||
'gemConditions' => array( // ENCHANT_CONDITION_*
|
||||
2 => ["menos de %d %s gema", "menos de %d %s gemas"],
|
||||
2 => "menos de %d |4gema:gemas; %s",
|
||||
3 => "más gemas %s que gemas %s",
|
||||
5 => ["al menos %d %s gema", "al menos %d %s gemas"]
|
||||
5 => "al menos %d |4gema:gemas; %s"
|
||||
),
|
||||
'reqRating' => array( // ITEM_REQ_ARENA_RATING*
|
||||
"Requiere un índice de arena personal y de equipo de %d",
|
||||
"Requiere un índice de arena personal y de equipo de %d<br>en la rama de 3c3 o de 5c5",
|
||||
"Requiere un índice de arena personal y de equipo de %d<br>en la rama de 5c5"
|
||||
"Requiere un índice de arena personal y de equipo de %d|nen la rama de 3c3 o de 5c5",
|
||||
"Requiere un índice de arena personal y de equipo de %d|nen la rama de 5c5"
|
||||
),
|
||||
'quality' => array(
|
||||
"Pobre", "Común", "Poco Común", "Raro",
|
||||
"Épica", "Legendaria", "Artefacto", "Reliquia"
|
||||
),
|
||||
'trigger' => array(
|
||||
"Uso: ", "Equipar: ", "Probabilidad al acertar: ", null, null,
|
||||
null, null
|
||||
"Uso: ", "Equipar: ", "Probabilidad al acertar: ", "", "",
|
||||
"", ""
|
||||
),
|
||||
'bonding' => array(
|
||||
"Se liga a la cuenta", "Se liga al recogerlo", "Se liga al equiparlo",
|
||||
@@ -1006,8 +1198,8 @@ $lang = array(
|
||||
13 => "Llaves",
|
||||
),
|
||||
'statType' => array(
|
||||
"Aumenta tu maná %d p.",
|
||||
"Aumenta tu salud %d p.",
|
||||
"Maná",
|
||||
"Salud",
|
||||
null,
|
||||
"agilidad",
|
||||
"fuerza",
|
||||
@@ -1034,16 +1226,16 @@ $lang = array(
|
||||
"Mejora tu índice de celeridad cuerpo a cuerpo %d p.",
|
||||
"Mejora tu índice de celeridad a distancia %d p.",
|
||||
"Mejora tu índice de celeridad con hechizos %d p.",
|
||||
"Aumenta tu índice de golpe %d p.",
|
||||
"Aumenta tu índice de golpe crítico %d p.",
|
||||
"Mejora tu índice de golpe %d p.",
|
||||
"Mejora tu índice de golpe crítico %d p.",
|
||||
"Mejora tu índice de evasión %d p.",
|
||||
"Mejora tu índice de evasión de golpes críticos %d p.",
|
||||
"Aumenta tu índice de temple %d p.",
|
||||
"Aumenta tu índice de celeridad %d p.",
|
||||
"Mejora tu índice de temple %d p.",
|
||||
"Mejora tu índice de celeridad %d p.",
|
||||
"Aumenta tu índice de pericia %d p.",
|
||||
"Aumenta el poder de ataque %d p.",
|
||||
"Aumenta el poder de ataque a distancia %d p.",
|
||||
"Aumenta en %d p. el poder de ataque bajo formas felinas, de oso, de oso temible y de lechúcico lunar.",
|
||||
"Aumenta el poder de ataque %d p. solo con las formas de gato, oso, oso temible y lechúcico lunar.",
|
||||
"Aumenta el daño infligido con hechizos y efectos mágicos hasta %d p.",
|
||||
"Aumenta la sanación hecha con hechizos y efectos mágicos hasta %d p.",
|
||||
"Restaura %d p. de maná cada 5 s.",
|
||||
|
||||
@@ -14,8 +14,7 @@ $lang = array(
|
||||
'timeUnits' => array(
|
||||
'sg' => ["année", "mois", "semaine", "jour", "heure", "minute", "seconde", "milliseconde"],
|
||||
'pl' => ["années", "mois", "semaines", "jours", "heures", "minutes", "secondes", "millisecondes"],
|
||||
'ab' => ["an", "mo", "sem", "jour", "h", "min", "s", "ms"],
|
||||
'ago' => 'il y a %s'
|
||||
'ab' => ["an", "mo", "sem", "jour", "h", "min", "s", "ms"]
|
||||
),
|
||||
'main' => array(
|
||||
'name' => "nom",
|
||||
@@ -47,10 +46,14 @@ $lang = array(
|
||||
'forum' => "Forum",
|
||||
'n_a' => "n/d",
|
||||
'siteRep' => "Réputation",
|
||||
'yourRepHistory'=> "Votre historique de réputation",
|
||||
'aboutUs' => "À propos de Aowow",
|
||||
'and' => " et ",
|
||||
'or' => " ou ",
|
||||
'back' => "Redro",
|
||||
'reputationTip' => "Points de réputation",
|
||||
'byUserTimeAgo' => 'Par <a href="'.HOST_URL.'/?user=%s">%1$s</a> il y a %s',
|
||||
'help' => "Aide",
|
||||
|
||||
// filter
|
||||
'extSearch' => "Recherche avancée",
|
||||
@@ -67,10 +70,10 @@ $lang = array(
|
||||
|
||||
// infobox
|
||||
'unavailable' => "Non disponible aux joueurs",
|
||||
'disabled' => "[Disabled]",
|
||||
'disabledHint' => "[Cannot be attained or completed]",
|
||||
'serverside' => "[Serverside]",
|
||||
'serversideHint'=> "[These informations are not in the Client and have been provided by sniffing and/or guessing.]",
|
||||
'disabled' => "Désactivé",
|
||||
'disabledHint' => "Ne peux pas être atteint ou complété",
|
||||
'serverside' => "Côté serveur",
|
||||
'serversideHint'=> "Ces informations ne sont pas contenues dans le client et ont été obtenues via sniff ou ont été devinées.",
|
||||
|
||||
// red buttons
|
||||
'links' => "Liens",
|
||||
@@ -107,22 +110,6 @@ $lang = array(
|
||||
'chooseClass' => "Choisissez une classe",
|
||||
'chooseFamily' => "Choisissez un familier",
|
||||
|
||||
// profiler
|
||||
'realm' => "Royaume",
|
||||
'region' => "Région",
|
||||
'viewCharacter' => "Voir Personnage",
|
||||
'_cpHead' => "Profiler de Personnage",
|
||||
'_cpHint' => "Le <b>Profiler de Personnage</b> vous permets de modifier votre personnage, trouver des améliorations d'équipement, vérifier votre score d'équipement et plus!",
|
||||
'_cpHelp' => "Pour débuter, suivez simplement les étapes ci-dessous. Si vous voulez plus d'information, lisez notre <a href=\"?help=profiler\">page d'aide</a> détaillée.",
|
||||
'_cpFooter' => "Si vous voulez une recherche plus raffinée, essayez nos options de <a href=\"?profiles\">recherche avancée</a>. Vous pouvez aussi créer un <a href=\"?profile&new\">nouveau profile personnalisé</a>.",
|
||||
|
||||
// help
|
||||
'help' => "Aide",
|
||||
'helpTopics' => array(
|
||||
"Le guide du commentaire", "Visionneuse 3D", "Captures d'écran : Trucs et astuces", "Échelles de valeurs",
|
||||
"Calculateur de talents", "Comparaison d'objets", "Profiler", "Markup Guide"
|
||||
),
|
||||
|
||||
// search
|
||||
'search' => "Recherche",
|
||||
'searchButton' => "Rechercher",
|
||||
@@ -143,29 +130,68 @@ $lang = array(
|
||||
'bannedRating' => "Vous avez été banni du score des commentaires.", # LANG.tooltip_banned_rating
|
||||
'tooManyVotes' => "Vous avez voté trop souvent aujourd'hui! Revenez demain.", # LANG.tooltip_too_many_votes
|
||||
|
||||
// screenshots
|
||||
'prepError' => "[An error occured preparing your screenshot]",
|
||||
'cropHint' => "[Crop the image by dragging the selection.<br>Please refer to <a href=\"?help=screenshots-tips-tricks\">Screenshots: Tips & Tricks</a> for an optimal layout.]",
|
||||
'moreTitles' => array(
|
||||
'reputation' => "Réputation du site",
|
||||
'whats-new' => "Quoi de neuf?",
|
||||
'searchbox' => "Boîte de recherche",
|
||||
'tooltips' => "Info-bulles",
|
||||
'faq' => "[Frequently Asked Questions]",
|
||||
'aboutus' => "[What is AoWoW?]",
|
||||
'searchplugins' => "Plug-ins de recherche",
|
||||
'privileges' => "Privilèges",
|
||||
'top-users' => "Meilleurs Utilisateurs",
|
||||
'help' => array(
|
||||
'commenting-and-you' => "Le guide du commentaire", 'modelviewer' => "Visionneuse 3D", 'screenshots-tips-tricks' => "Captures d'écran : Trucs et astuces",
|
||||
'stat-weighting' => "Échelles de valeurs", 'talent-calculator' => "Calculateur de talents", 'item-comparison' => "Comparaison d'objets",
|
||||
'profiler' => "Profiler", 'markup-guide' => "Markup Guide"
|
||||
)
|
||||
)
|
||||
),
|
||||
'profiler' => array(
|
||||
'realm' => "Royaume",
|
||||
'region' => "Région",
|
||||
'viewCharacter' => "Voir Personnage",
|
||||
'_cpHint' => "Le <b>Profiler de Personnage</b> vous permets de modifier votre personnage, trouver des améliorations d'équipement, vérifier votre score d'équipement et plus!",
|
||||
'_cpHelp' => "Pour débuter, suivez simplement les étapes ci-dessous. Si vous voulez plus d'information, lisez notre <a href=\"?help=profiler\">page d'aide</a> détaillée.",
|
||||
'_cpFooter' => "Si vous voulez une recherche plus raffinée, essayez nos options de <a href=\"?profiles\">recherche avancée</a>. Vous pouvez aussi créer un <a href=\"?profile&new\">nouveau profile personnalisé</a>.",
|
||||
'firstUseTitle' => "%s de %s",
|
||||
'complexFilter' => "[Complex filter selected! Search results are limited to cached Characters.]",
|
||||
|
||||
'resync' => "Resynchronisation",
|
||||
'guildRoster' => "Liste des membres pour la guilde de <%s>",
|
||||
'arenaRoster' => "[Arena Team Roster for <%s>]", // string probably lost
|
||||
'atCaptain' => "Capitaine d'équipe",
|
||||
|
||||
'profiler' => "Profiler de Personnage",
|
||||
'arenaTeams' => "Équipes d'Aréna",
|
||||
'guilds' => "Guildes",
|
||||
|
||||
'notFound' => array(
|
||||
'guild' => "[This Guild doesn't exist or is not yet in the database.]",
|
||||
'arenateam' => "[This Arena Team doesn't exist or is not yet in the database.]",
|
||||
'profile' => "[This character doesn't exist or is not yet in the database.]"
|
||||
),
|
||||
'dummyNPCs' => array(
|
||||
100001 => "Bataille des canonnières", 200001 => "Bêtes du Norfendre", 200002 => "Champions de faction", 200003 => "Les jumelles val'kyrs"
|
||||
),
|
||||
),
|
||||
'screenshot' => array(
|
||||
'submission' => "Envoi d'une capture d'écran",
|
||||
'selectAll' => "Sélectionner tout",
|
||||
'cropHint' => "Vous pouvez recadrer votre capture d'écran.",
|
||||
'displayOn' => "[Displayed on:[br]%s - [%s=%d]]",
|
||||
'caption' => "[Caption]",
|
||||
'originalSize' => "[Original size]",
|
||||
'targetSize' => "[Target size]",
|
||||
'minSize' => "[Minimum size]",
|
||||
'displayOn' => "[Displayed on: %s[br][%s=%d]]",
|
||||
'ssEdit' => "[Edit uploaded screenshot]",
|
||||
'ssUpload' => "[Screenshot Upload]",
|
||||
'ssSubmit' => "[Submit Screenshot]",
|
||||
'ssErrors' => array(
|
||||
'noUpload' => "[The file was not uploaded!]",
|
||||
'maxSize' => "[The file exceeds the maximum size of %s!]",
|
||||
'interrupted' => "[The upload process was interrupted!]",
|
||||
'noFile' => "[The file was not received!]",
|
||||
'noDest' => "[The page this screenshot should be displayed on, does not exist!]",
|
||||
'notAllowed' => "[You are not allowed to upload screenshots!]",
|
||||
'noImage' => "[The uploaded file is not an image file!]",
|
||||
'wrongFormat' => "[The image file must be a png or jpg!]",
|
||||
'load' => "[The image file could not be loaded!]",
|
||||
'tooSmall' => "[The image size is too small! (lower than %d x %d)]",
|
||||
'tooLarge' => "[The image size is too large! (greater than %d x %d)]"
|
||||
'charLimit' => "Optionnel, jusqu'à 200 caractères",
|
||||
'thanks' => array(
|
||||
'contrib' => "Merci beaucoup de votre contribution!",
|
||||
'goBack' => '<a href="?%s=%d">ici</a> pour retourner à la page d\'où vous venez.',
|
||||
'note' => "Note : Votre capture d'écran devra être approuvée avant d'apparaître sur le site. Cela peut prendre jusqu'à 72 heures."
|
||||
),
|
||||
'error' => array(
|
||||
'unkFormat' => "Format d'image inconnu.",
|
||||
'tooSmall' => "Votre capture est bien trop petite. (< ".CFG_SCREENSHOT_MIN_SIZE."x".CFG_SCREENSHOT_MIN_SIZE.").",
|
||||
'selectSS' => "Veuillez sélectionner la capture d'écran à envoyer.",
|
||||
'notAllowed' => "Vous n'êtes pas autorisés à exporter des captures d'écran.",
|
||||
)
|
||||
),
|
||||
'game' => array(
|
||||
@@ -178,8 +204,12 @@ $lang = array(
|
||||
'difficulty' => "Difficulté",
|
||||
'dispelType' => "Type de dissipation",
|
||||
'duration' => "Durée",
|
||||
'gameObject' => "entité",
|
||||
'gameObjects' => "Entités",
|
||||
'emote' => "emote",
|
||||
'emotes' => "Emotes",
|
||||
'enchantment' => "enchantement",
|
||||
'enchantments' => "Enchantements",
|
||||
'object' => "entité",
|
||||
'objects' => "Entités",
|
||||
'glyphType' => "Type de glyphe",
|
||||
'race' => "race",
|
||||
'races' => "Races",
|
||||
@@ -191,6 +221,8 @@ $lang = array(
|
||||
'faction' => "faction",
|
||||
'factions' => "Factions",
|
||||
'cooldown' => "%s de recharge",
|
||||
'icon' => "icône",
|
||||
'icons' => "Icônes",
|
||||
'item' => "objet",
|
||||
'items' => "Objets",
|
||||
'itemset' => "ensemble d'objets",
|
||||
@@ -209,12 +241,13 @@ $lang = array(
|
||||
'requires' => "%s requis",
|
||||
'requires2' => "Requiert",
|
||||
'reqLevel' => "Niveau %s requis",
|
||||
'reqLevelHlm' => "Requiert Niveau %s",
|
||||
'reqSkillLevel' => "Niveau de compétence requis",
|
||||
'level' => "Niveau",
|
||||
'school' => "École",
|
||||
'skill' => "compétence",
|
||||
'skills' => "Compétences",
|
||||
'sound' => "son",
|
||||
'sounds' => "Sons",
|
||||
'spell' => "sort",
|
||||
'spells' => "Sorts",
|
||||
'type' => "Type",
|
||||
@@ -260,10 +293,10 @@ $lang = array(
|
||||
'rep' => ["Détesté", "Hostile", "Inamical", "Neutre", "Amical", "Honoré", "Révéré", "Exalté"],
|
||||
'st' => array(
|
||||
"Défaut", "Forme de félin", "Arbre de vie", "Forme de voyage", "Forme aquatique", "Forme d'ours",
|
||||
null, null, "Forme d'ours redoutable", null, null, null,
|
||||
null, "Danse de l'ombre", null, null, "Loup fantôme", "Posture de combat",
|
||||
"Posture défensive", "Posture berserker", null, null, "Métamorphe", null,
|
||||
null, null, null, "Forme de vol rapide", "Forme d'Ombre", "Forme de vol",
|
||||
"Ambiant", "Goule", "Forme d'ours redoutable", "Goule de Steve", "Squelette de Tharon'ja", "Sombrelune - épreuve de force",
|
||||
"Joueur BLB", "Danse de l'ombre", "Créature - Ours", "Créature - Félin", "Loup fantôme", "Posture de combat",
|
||||
"Posture défensive", "Posture berserker", "Test", "Zombie", "Métamorphe", null,
|
||||
null, "Mort-vivant", "Frénésie", "Forme de vol rapide", "Forme d'Ombre", "Forme de vol",
|
||||
"Camouflage", "Forme de sélénien", "Esprit de rédemption"
|
||||
),
|
||||
'me' => array(
|
||||
@@ -302,7 +335,7 @@ $lang = array(
|
||||
'groups' => array(
|
||||
-1 => "None", "Testeur", "Administrateur", "Éditeur", "Modérateur", "Bureaucrate",
|
||||
"Développeur", "VIP", "Bloggeur", "Premium", "Traducteur", "Agent de ventes",
|
||||
"Gestionnaire de capture d'écran","Gestionnaire de vidéos"
|
||||
"Gestionnaire de capture d'écran","Gestionnaire de vidéos", "Partenaire API", "En attente"
|
||||
),
|
||||
// signIn
|
||||
'doSignIn' => "Connexion à votre compte Aowow",
|
||||
@@ -318,51 +351,51 @@ $lang = array(
|
||||
// recovery
|
||||
'recoverUser' => "Demande de nom d'utilisateur",
|
||||
'recoverPass' => "Changement de mot de passe : Étape %s de 2",
|
||||
'newPass' => "New Password",
|
||||
'newPass' => "Nouveau mot de passe",
|
||||
|
||||
// creation
|
||||
'register' => "Enregistrement : Étape %s de 2",
|
||||
'passConfirm' => "Confirmez",
|
||||
|
||||
// dashboard
|
||||
'ipAddress' => "IP-Adress",
|
||||
'lastIP' => "last used IP",
|
||||
'myAccount' => "My Account",
|
||||
'editAccount' => "Simply use the forms below to update your account information",
|
||||
'viewPubDesc' => 'View your Public Description in your <a href="?user=%s">Profile Page</a>',
|
||||
'ipAddress' => "Addresse IP",
|
||||
'lastIP' => "Dernière IP utilisée",
|
||||
'myAccount' => "Mon compte",
|
||||
'editAccount' => "Utilisez les formulaires ci-dessous pour mettre à jour vos informations.",
|
||||
'viewPubDesc' => 'Voyez vos informations publiques dans votre <a href="?user=%s">Profile Page</a>',
|
||||
|
||||
// bans
|
||||
'accBanned' => "This Account was closed",
|
||||
'bannedBy' => "Banned by",
|
||||
'ends' => "Ends on",
|
||||
'permanent' => "The ban is permanent",
|
||||
'reason' => "Reason",
|
||||
'noReason' => "No reason was given.",
|
||||
'accBanned' => "Ce compte a été fermé.",
|
||||
'bannedBy' => "Banni par",
|
||||
'ends' => "Termine le",
|
||||
'permanent' => "Ce bannissement est permanent",
|
||||
'reason' => "Raison",
|
||||
'noReason' => "Aucune raison donnée.",
|
||||
|
||||
// form-text
|
||||
'emailInvalid' => "Cette adresse courriel est invalide.", // message_emailnotvalid
|
||||
'emailNotFound' => "The email address you entered is not associated with any account.<br><br>If you forgot the email you registered your account with email ".CFG_CONTACT_EMAIL." for assistance.",
|
||||
'createAccSent' => "An email was sent to <b>%s</b>. Simply follow the instructions to create your account.",
|
||||
'recovUserSent' => "An email was sent to <b>%s</b>. Simply follow the instructions to recover your username.",
|
||||
'recovPassSent' => "An email was sent to <b>%s</b>. Simply follow the instructions to reset your password.",
|
||||
'accActivated' => 'Your account has been activated.<br>Proceed to <a href="?account=signin&token=%s">sign in</a>',
|
||||
'userNotFound' => "The username you entered does not exists.",
|
||||
'wrongPass' => "That password is not vaild.",
|
||||
'accInactive' => "That account has not yet been confirmed active.",
|
||||
'loginExceeded' => "The maximum number of logins from this IP has been exceeded. Please try again in %s.",
|
||||
'signupExceeded'=> "The maximum number of signups from this IP has been exceeded. Please try again in %s.",
|
||||
'emailNotFound' => "L'address email que vous avez entrée n'est pas associée à un compte.<br><br>Si vous avez oublié l'address email avec laquelle vous avez enregistré votre compte".CFG_CONTACT_EMAIL." pour obtenir de l'aide.",
|
||||
'createAccSent' => "Un email a été envoyé à <b>%s</b>. Suivez les instructions pour créer votre compte.",
|
||||
'recovUserSent' => "Un email a été envoyé à <b>%s</b>. Suivez les instructions pour récupérer votre nom d'utilisateur.",
|
||||
'recovPassSent' => "Un email a été envoyé à <b>%s</b>. Suivez les instructions pour réinitialiser votre mot de passe.",
|
||||
'accActivated' => 'Votre compte a été activé.<br>Vous pouvez maintenant <a href="?account=signin&token=%s">vous connecter</a>',
|
||||
'userNotFound' => "Le nom d'utilisateur que vous avez saisi n'éxiste pas.",
|
||||
'wrongPass' => "Ce mot de passe est invalide.",
|
||||
// 'accInactive' => "Ce compte n'a pas encore été activé.",
|
||||
'loginExceeded' => "Le nombre maximum de connections depuis cette IP a été dépassé. Essayez de nouevau dans %s.",
|
||||
'signupExceeded'=> "Le nombre maximum d'inscriptions depuis cette IP a été dépassé. Essayez de nouveau dans %s.",
|
||||
'errNameLength' => "Votre nom d'utilisateur doit faire au moins 4 caractères de long.", // message_usernamemin
|
||||
'errNameChars' => "Votre nom d'utilisateur doit contenir seulement des lettres et des chiffres.", // message_usernamenotvalid
|
||||
'errPassLength' => "Votre mot de passe doit faire au moins 6 caractères de long.", // message_passwordmin
|
||||
'passMismatch' => "The passwords you entered do not match.",
|
||||
'nameInUse' => "That username is already taken.",
|
||||
'mailInUse' => "That email is already registered to an account.",
|
||||
'isRecovering' => "This account is already recovering. Follow the instructions in your email or wait %s for the token to expire.",
|
||||
'passMismatch' => "Les mots de passe que vous avez saisis ne correspondent pas.",
|
||||
'nameInUse' => "Ce nom d'utilisateur est déjà utilisé.",
|
||||
'mailInUse' => "Cette addresse email est déjà liée à un compte.",
|
||||
'isRecovering' => "Ce compte est déjà en train d'être récupéré. Suivez les instruction dans l'email reçu ou attendez %s pour que le token expire.",
|
||||
'passCheckFail' => "Les mots de passe ne correspondent pas.", // message_passwordsdonotmatch
|
||||
'newPassDiff' => "Votre nouveau mot de passe doit être différent de l'ancien." // message_newpassdifferent
|
||||
),
|
||||
'user' => array(
|
||||
'notFound' => "Utilisateur \"%s\" non trouvé !",
|
||||
'notFound' => "Utilisateur \"%s\" non trouvé!",
|
||||
'removed' => "(Supprimé)",
|
||||
'joinDate' => "Inscription",
|
||||
'lastLogin' => "Dernière visite",
|
||||
@@ -379,22 +412,42 @@ $lang = array(
|
||||
),
|
||||
'mail' => array(
|
||||
'tokenExpires' => "This token expires in %s.",
|
||||
'accConfirm' => ["Account Confirmation", "Welcome to ".CFG_NAME_SHORT."!\r\n\r\nClick the Link below to activate your account.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
|
||||
'recoverUser' => ["User Recovery", "Follow this link to log in.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
|
||||
'resetPass' => ["Password Reset", "Follow this link to reset your password.\r\n\r\n".HOST_URL."?account=forgotpassword&token=%s\r\n\r\nIf you did not request this mail simply ignore it."]
|
||||
'accConfirm' => ["Activation de compte", "Bienvenue sur ".CFG_NAME_SHORT."!\r\n\r\nCliquez sur le lien ci-dessous pour activer votre compte.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nSi vous n'avez pas demandé cet email, ignorez le."],
|
||||
'recoverUser' => ["Récupération d'utilisateur", "Suivez ce lien pour vous connecter.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nSi vous n'avez pas demandé cet email, ignorez le."],
|
||||
'resetPass' => ["Réinitialisation du mot de passe", "Suivez ce lien pour réinitialiser votre mot de passe.\r\n\r\n".HOST_URL."?account=forgotpassword&token=%s\r\n\r\nSi vous n'avez pas fait de demande de réinitialisation, ignorez cet email."]
|
||||
),
|
||||
'emote' => array(
|
||||
'notFound' => "[This Emote doesn't exist.]",
|
||||
'self' => "Vers vous-même",
|
||||
'target' => "Vers les autres avec une cible",
|
||||
'noTarget' => "Vers les autres sans cible",
|
||||
'isAnimated' => "Utilise une animation",
|
||||
'aliases' => "Alias",
|
||||
'noText' => "Cette émote n'a pas de texte.",
|
||||
),
|
||||
'enchantment' => array(
|
||||
'details' => "En détail",
|
||||
'activation' => "Activation",
|
||||
'notFound' => "Cet enchantement n'existe pas.",
|
||||
'types' => array(
|
||||
1 => "Sort proc", 3 => "Sort équipé", 7 => "Sort utilisé", 8 => "Châsse prismatique",
|
||||
5 => "Statistiques", 2 => "Dégâts d'arme", 6 => "DPS", 4 => "Défense"
|
||||
)
|
||||
),
|
||||
'gameObject' => array(
|
||||
'notFound' => "Cette entité n'existe pas.",
|
||||
'cat' => [0 => "Autre", 9 => "Livres", 3 => "Conteneurs", -5 => "Coffres", 25 => "Bancs de poissons", -3 => "Herbes", -4 => "Filons de minerai", -2 => "Quêtes", -6 => "Outils"],
|
||||
'type' => [ 9 => "Livre", 3 => "Conteneur", -5 => "Coffre", 25 => "", -3 => "Herbe", -4 => "Filon de minerai", -2 => "Quête", -6 => ""],
|
||||
'unkPosition' => "L'emplacement de cette entité est inconnu.",
|
||||
'npcLootPH' => 'Le <b>%s</b> contient les récompenses du combat contre <a href="?npc=%d">%s</a>. Il apparaît après sa mort.',
|
||||
'key' => "Clé",
|
||||
'focus' => "[Spell Focus]",
|
||||
'focusDesc' => "[Spells requiring this Focus can be cast near this Object]",
|
||||
'focus' => "Focus de sort",
|
||||
'focusDesc' => "Les sorts nécessitant ce focus peuvent être lancés près de cet entité.",
|
||||
'trap' => "Piège",
|
||||
'triggeredBy' => "Déclenché par",
|
||||
'capturePoint' => "Point de capture",
|
||||
'restock' => "[Restocks every %s.]"
|
||||
'foundIn' => "Cette entité se trouve dans",
|
||||
'restock' => "Se remplit toutes les %s.]"
|
||||
),
|
||||
'npc' => array(
|
||||
'notFound' => "Ce PNJ n'existe pas.",
|
||||
@@ -403,10 +456,10 @@ $lang = array(
|
||||
'react' => "Réaction",
|
||||
'worth' => "Vaut",
|
||||
'unkPosition' => "L'emplacement de ce PNJ est inconnu.",
|
||||
'difficultyPH' => "[Ce PNJ est un espace réservé pour un autre mode de]",
|
||||
'seat' => "[Seat]",
|
||||
'accessory' => "[Accessory]",
|
||||
'accessoryFor' => "[This creature is an accessory for vehicle]",
|
||||
'difficultyPH' => "Ce PNJ est un espace réservé pour un autre mode de difficulté.",
|
||||
'seat' => "Siège",
|
||||
'accessory' => "Passager",
|
||||
'accessoryFor' => "Ce PNJ est un passager pour un véhicule.",
|
||||
'quotes' => "Citations",
|
||||
'gainsDesc' => "Après avoir tué ce PNJ vous allez obtenir",
|
||||
'repWith' => "points de réputation avec",
|
||||
@@ -416,6 +469,7 @@ $lang = array(
|
||||
'melee' => "de mêlée",
|
||||
'ranged' => "à distance",
|
||||
'armor' => "Armure",
|
||||
'foundIn' => "Ce PNJ se trouve dans",
|
||||
'tameable' => "Domptable (%s)",
|
||||
'waypoint' => "Point de route",
|
||||
'wait' => "Période d'attente",
|
||||
@@ -479,6 +533,20 @@ $lang = array(
|
||||
'Azeroth' => "Azeroth",
|
||||
'CosmicMap' => "Carte cosmique",
|
||||
),
|
||||
'privileges' => array(
|
||||
'main' => "Sur AoWoW, vous pouvez accumuler de la <a href=\"?reputation\">réputation</a>. Le principal moyen d'en accumuler est d'avoir un score élevé pour vos commentaires.<br><br>Ainsi, la réputation est une vision sommaire de vos contributions à la communauté.<br><br>En amassant de la réputation, vous gagnez le respect de la communauté et vous obtiendrez certains privilèges. Vous pouvez en trouver la liste complète ci-dessous.",
|
||||
'privilege' => "Privilège",
|
||||
'privileges' => "Privilèges",
|
||||
'requiredRep' => "Réputation Requise",
|
||||
'reqPoints' => "Ce privilège requiert <b>%s</b> points de réputation.",
|
||||
'_privileges' => array(
|
||||
null, "Poster des commentaires", "Poster des liens externes", null,
|
||||
"Pas de CAPTCHA", "Les votes des commentaires ont plus de valeur",null, null,
|
||||
null, "Plus de votes par jour", "Emettre des votes positifs pour les commentaires", "Donner des votes négatifs aux commentaires",
|
||||
"Envoyer des réponses aux commentaires","Bordure : Bonne", "Bordure : Rare", "Bordure : Épique",
|
||||
"Bordure : Légendaire", "AoWoW Premium"
|
||||
)
|
||||
),
|
||||
'zone' => array(
|
||||
'notFound' => "Cette zone n'existe pas.",
|
||||
'attunement' => ["Accès", "Accès Héroïque"],
|
||||
@@ -489,7 +557,7 @@ $lang = array(
|
||||
'reqLevels' => "Niveaux requis : [tooltip=instancereqlevel_tip]%d[/tooltip], [tooltip=lfgreqlevel_tip]%d[/tooltip]",
|
||||
'zonePartOf' => "Cette zone fait partie de la zone [zone=%d].",
|
||||
'autoRez' => "Résurrection automatique",
|
||||
'city' => "Город",
|
||||
'city' => "Ville",
|
||||
'territory' => "Territoire",
|
||||
'instanceType' => "Type d'instance",
|
||||
'hcAvailable' => "Mode héroïque disponible (%d)",
|
||||
@@ -556,8 +624,9 @@ $lang = array(
|
||||
'receiveAlso' => "Vous recevrez également",
|
||||
'spellCast' => "Vous allez être la cible du sort suivant",
|
||||
'spellLearn' => "Vous apprendrez",
|
||||
'bonusTalents' => "points de talent",
|
||||
'bonusTalents' => "%d |4point:points; de talent",
|
||||
'spellDisplayed'=> ' (<a href="?spell=%d">%s</a> affichés)',
|
||||
'attachment' => "[Attachment]",
|
||||
'questInfo' => array(
|
||||
0 => "Standard", 1 => "Groupe", 21 => "Vie", 41 => "JcJ", 62 => "Raid", 81 => "Donjon", 82 => "Évènement mondial",
|
||||
83 => "Légendaire", 84 => "Escorte", 85 => "Héroïque", 88 => "Raid (10)", 89 => "Raid (25)"
|
||||
@@ -628,10 +697,14 @@ $lang = array(
|
||||
),
|
||||
7 => array( "Divers",
|
||||
-365 => "Guerre d'Ahn'Qiraj", -1010 => "Chercheur de donjons", -1 => "Épique", -344 => "Légendaire", -367 => "Réputation",
|
||||
-368 => "Invasion du fléau", -241 => "Tournoi"),
|
||||
-368 => "Invasion du fléau", -241 => "Tournoi"
|
||||
),
|
||||
-2 => "Non classés"
|
||||
)
|
||||
),
|
||||
'icon' => array(
|
||||
'notFound' => "Cette icône n'existe pas."
|
||||
),
|
||||
'title' => array(
|
||||
'notFound' => "Ce titre n'existe pas.",
|
||||
'_transfer' => 'Ce titre sera converti en <a href="?title=%d" class="q1">%s</a> si vous transférez en <span class="icon-%s">%s</span>.',
|
||||
@@ -653,19 +726,34 @@ $lang = array(
|
||||
1 => "Divers", 2 => "JcJ", 4 => "Classique", 21 => "Wrath of the Lich King", 22 => "Raid", 23 => "Burning Crusade", 41 => "Test", 3 => "Inutilisées"
|
||||
)
|
||||
),
|
||||
'sound' => array(
|
||||
'notFound' => "Ce son n'existe pas.",
|
||||
'foundIn' => "Ce son se trouve dans",
|
||||
'goToPlaylist' => "Aller à votre playlist",
|
||||
'music' => "Musique",
|
||||
'intro' => "Musique d'introduction",
|
||||
'ambience' => "Ambiance",
|
||||
'cat' => array(
|
||||
null, "Spells", "User Interface", "Footsteps", "Weapons Impacts", null, "Weapons Misses", null, null, "Pick Up/Put Down",
|
||||
"NPC Combat", null, "Errors", "Nature", "Objects", null, "Death", "NPC Greetings", null, "Armor",
|
||||
"Footstep Splash", "Water (Character)", "Water", "Tradeskills", "Misc Ambience", "Doodads", "Spell Fizzle", "NPC Loops", "Zone Music", "Emotes",
|
||||
"Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "Ma playlist"
|
||||
)
|
||||
),
|
||||
'pet' => array(
|
||||
'notFound' => "Cette famille de familiers n'existe pas.",
|
||||
'exotic' => "Exotique",
|
||||
'cat' => ["Férocité", "Tenacité", "Ruse"]
|
||||
'cat' => ["Férocité", "Tenacité", "Ruse"],
|
||||
'food' => ["Viande", "Poisson", "Fromage", "Pain", "Champignon", "Fruit", "Viande crue", "Poisson cru"]
|
||||
),
|
||||
'faction' => array(
|
||||
'notFound' => "Cette faction n'existe pas.",
|
||||
'spillover' => "[Reputation Spillover]",
|
||||
'spilloverDesc' => "[Gaining reputation with this faction also yields a proportional gain with the factions listed below.]",
|
||||
'spillover' => "Partage de réputations",
|
||||
'spilloverDesc' => "Gagner de la réputation avec cette faction fourni une réputation proportionnelle avec les factions ci-dessous.",
|
||||
'maxStanding' => "Niveau maximum",
|
||||
'quartermaster' => "Intendant",
|
||||
'customRewRate' => "[Custom Reward Rate]",
|
||||
'_transfer' => '[The reputation with this faction will be converted to <a href="?faction=%d" class="q1">%s</a> if you transfer to <span class="icon-%s">%s</span>.]',
|
||||
'customRewRate' => "Taux de récompense personnalisé",
|
||||
'_transfer' => 'La réputation de cette faction sera convertie en <a href="?faction=%d" class="q1">%s</a> si vous transférez vers <span class="icon-%s">%s</span>.]',
|
||||
'cat' => array(
|
||||
1118 => ["Classique", 469 => "Alliance", 169 => "Cartel Gentepression", 67 => "Horde", 891 => "Forces de l'Alliance", 892 => "Forces de la Horde"],
|
||||
980 => ["The Burning Crusade", 936 => "Shattrath"],
|
||||
@@ -740,10 +828,12 @@ $lang = array(
|
||||
'pctCostOf' => "de la %s de base",
|
||||
'costPerSec' => ", plus %s par seconde",
|
||||
'costPerLevel' => ", plus %s par niveau",
|
||||
'stackGroup' => "[Stack Group]",
|
||||
'linkedWith' => "[Linked with]",
|
||||
'_scaling' => "[Scaling]",
|
||||
'scaling' => array(
|
||||
'directSP' => "[+%.2f%% of spell power to direct component]", 'directAP' => "[+%.2f%% of attack power to direct component]",
|
||||
'dotSP' => "[+%.2f%% of spell power per tick]", 'dotAP' => "[+%.2f%% of attack power per tick]"
|
||||
'directSP' => "+%.2f%% de la puissance des sorts directe", 'directAP' => "+%.2f%% de la puissance d'attaque directe",
|
||||
'dotSP' => "+%.2f%% de la puissance des sorts par tick", 'dotAP' => "+%.2f%% de la puissance d'attaque par tick"
|
||||
),
|
||||
'powerRunes' => ["Givre", "Impie", "Sang", "Mort"],
|
||||
'powerTypes' => array(
|
||||
@@ -812,7 +902,8 @@ $lang = array(
|
||||
),
|
||||
'traitShort' => array(
|
||||
'atkpwr' => "PA", 'rgdatkpwr' => "PAD", 'splpwr' => "PS", 'arcsplpwr' => "PArc", 'firsplpwr' => "PFeu",
|
||||
'frosplpwr' => "PGiv", 'holsplpwr' => "PSac", 'natsplpwr' => "PNat", 'shasplpwr' => "POmb", 'splheal' => "Soins"
|
||||
'frosplpwr' => "PGiv", 'holsplpwr' => "PSac", 'natsplpwr' => "PNat", 'shasplpwr' => "POmb", 'splheal' => "Soins",
|
||||
'str' => "For", 'agi' => "Agi", 'sta' => "End", 'int' => "Int", 'spi' => "Esp"
|
||||
),
|
||||
'spellModOp' => array(
|
||||
"DAMAGE", "DURATION", "THREAT", "EFFECT1", "CHARGES",
|
||||
@@ -838,36 +929,127 @@ $lang = array(
|
||||
"Calligraphie", "Ouverture à partir d'un véhicule",
|
||||
),
|
||||
'stealthType' => ["GENERAL", "TRAP"],
|
||||
'invisibilityType' => ["GENERAL", 3 => "TRAP", 6 => "DRUNK"]
|
||||
'invisibilityType' => ["GENERAL", 3 => "TRAP", 6 => "DRUNK"],
|
||||
'unkEffect' => 'Unknown Effect',
|
||||
'effects' => array(
|
||||
/*0-5 */ 'None', 'Instakill', 'School Damage', 'Dummy', 'Portal Teleport', 'Teleport Units',
|
||||
/*6+ */ 'Apply Aura', 'Environmental Damage', 'Power Drain', 'Health Leech', 'Heal', 'Bind',
|
||||
/*12+ */ 'Portal', 'Ritual Base', 'Ritual Specialize', 'Ritual Activate Portal', 'Quest Complete', 'Weapon Damage NoSchool',
|
||||
/*18+ */ 'Resurrect', 'Add Extra Attacks', 'Dodge', 'Evade', 'Parry', 'Block',
|
||||
/*24+ */ 'Create Item', 'Can Use Weapon', 'Defense', 'Persistent Area Aura', 'Summon', 'Leap',
|
||||
/*30+ */ 'Energize', 'Weapon Damage Percent', 'Trigger Missile', 'Open Lock', 'Summon Change Item', 'Apply Area Aura Party',
|
||||
/*36+ */ 'Learn Spell', 'Spell Defense', 'Dispel', 'Language', 'Dual Wield', 'Jump',
|
||||
/*42+ */ 'Jump Dest', 'Teleport Units Face Caster','Skill Step', 'Add Honor', 'Spawn', 'Trade Skill',
|
||||
/*48+ */ 'Stealth', 'Detect', 'Trans Door', 'Force Critical Hit', 'Guarantee Hit', 'Enchant Item Permanent',
|
||||
/*54+ */ 'Enchant Item Temporary', 'Tame Creature', 'Summon Pet', 'Learn Pet Spell', 'Weapon Damage Flat', 'Create Random Item',
|
||||
/*60+ */ 'Proficiency', 'Send Event', 'Power Burn', 'Threat', 'Trigger Spell', 'Apply Area Aura Raid',
|
||||
/*66+ */ 'Create Mana Gem', 'Heal Max Health', 'Interrupt Cast', 'Distract', 'Pull', 'Pickpocket',
|
||||
/*72+ */ 'Add Farsight', 'Untrain Talents', 'Apply Glyph', 'Heal Mechanical', 'Summon Object Wild', 'Script Effect',
|
||||
/*78+ */ 'Attack', 'Sanctuary', 'Add Combo Points', 'Create House', 'Bind Sight', 'Duel',
|
||||
/*84+ */ 'Stuck', 'Summon Player', 'Activate Object', 'WMO Damage', 'WMO Repair', 'WMO Change',
|
||||
/*90+ */ 'Kill Credit', 'Threat All', 'Enchant Held Item', 'Force Deselect', 'Self Resurrect', 'Skinning',
|
||||
/*96+ */ 'Charge', 'Cast Button', 'Knock Back', 'Disenchant', 'Inebriate', 'Feed Pet',
|
||||
/*102+ */ 'Dismiss Pet', 'Reputation', 'Summon Object Slot1', 'Summon Object Slot2', 'Summon Object Slot3', 'Summon Object Slot4',
|
||||
/*108+ */ 'Dispel Mechanic', 'Summon Dead Pet', 'Destroy All Totems', 'Durability Damage', 'Summon Demon', 'Resurrect Flat',
|
||||
/*114+ */ 'Attack Me', 'Durability Damage Percent','Skin Player Corpse', 'Spirit Heal', 'Skill', 'Apply Area Aura Pet',
|
||||
/*120+ */ 'Teleport Graveyard', 'Weapon Damage Normalized', null, 'Send Taxi', 'Pull Towards', 'Modify Threat Percent',
|
||||
/*126+ */ 'Steal Beneficial Buff', 'Prospecting', 'Apply Area Aura Friend', 'Apply Area Aura Enemy', 'Redirect Threat', 'Play Sound',
|
||||
/*132+ */ 'Play Music', 'Unlearn Specialization', 'Kill Credit2', 'Call Pet', 'Heal Percent', 'Energize Percent',
|
||||
/*138+ */ 'Leap Back', 'Clear Quest', 'Force Cast', 'Force Cast With Value', 'Trigger Spell With Value', 'Apply Area Aura Owner',
|
||||
/*144+ */ 'Knock Back Dest', 'Pull Towards Dest', 'Activate Rune', 'Quest Fail', null, 'Charge Dest',
|
||||
/*150+ */ 'Quest Start', 'Trigger Spell 2', null, 'Create Tamed Pet', 'Discover Taxi', 'Dual Wield 2H Weapons',
|
||||
/*156+ */ 'Enchant Item Prismatic', 'Create Item 2', 'Milling', 'Allow Rename Pet', null, 'Talent Spec Count',
|
||||
/*162-164*/ 'Talent Spec Select', null, 'Remove Aura'
|
||||
),
|
||||
'unkAura' => 'Unknown Aura',
|
||||
'auras' => array(
|
||||
/*0- */ 'None', 'Bind Sight', 'Mod Possess', 'Periodic Damage', 'Dummy',
|
||||
/*5+ */ 'Mod Confuse', 'Mod Charm', 'Mod Fear', 'Periodic Heal', 'Mod Attack Speed',
|
||||
'Mod Threat', 'Taunt', 'Stun', 'Mod Damage Done Flat', 'Mod Damage Taken Flat',
|
||||
'Damage Shield', 'Mod Stealth', 'Mod Stealth Detection', 'Mod Invisibility', 'Mod Invisibility Detection',
|
||||
'Mod Health Percent', 'Mod Power Percent', 'Mod Resistance Flat', 'Periodic Trigger Spell', 'Periodic Energize',
|
||||
/*25+ */ 'Pacify', 'Root', 'Silence', 'Reflect Spells', 'Mod Stat Flat',
|
||||
'Mod Skill', 'Mod Increase Speed', 'Mod Increase Mounted Speed', 'Mod Decrease Speed', 'Mod Increase Health',
|
||||
'Mod Increase Power', 'Shapeshift', 'Spell Effect Immunity', 'Spell Aura Immunity', 'School Immunity',
|
||||
'Damage Immunity', 'Dispel Immunity', 'Proc Trigger Spell', 'Proc Trigger Damage', 'Track Creatures',
|
||||
'Track Resources', 'Mod Parry Skill', 'Mod Parry Percent', null, 'Mod Dodge Percent',
|
||||
/*50+ */ 'Mod Critical Healing Amount', 'Mod Block Percent', 'Mod Physical Crit Percent', 'Periodic Health Leech', 'Mod Hit Chance',
|
||||
'Mod Spell Hit Chance', 'Transform', 'Mod Spell Crit Chance', 'Mod Increase Swim Speed', 'Mod Damage Done Versus Creature',
|
||||
'Pacify Silence', 'Mod Scale', 'Periodic Health Funnel', 'Periodic Mana Funnel', 'Periodic Mana Leech',
|
||||
'Mod Casting Speed (not stacking)', 'Feign Death', 'Disarm', 'Stalked', 'School Absorb',
|
||||
'Extra Attacks', 'Mod Spell Crit Chance School', 'Mod Power Cost School Percent', 'Mod Power Cost School Flat', 'Reflect Spells School',
|
||||
/*75+ */ 'Language', 'Far Sight', 'Mechanic Immunity', 'Mounted', 'Mod Damage Done Percent',
|
||||
'Mod Stat Percent', 'Split Damage Percent', 'Water Breathing', 'Mod Base Resistance Flat', 'Mod Health Regeneration',
|
||||
'Mod Power Regeneration', 'Channel Death Item', 'Mod Damage Taken Percent', 'Mod Health Regeneration Percent', 'Periodic Damage Percent',
|
||||
'Mod Resist Chance', 'Mod Detect Range', 'Prevent Fleeing', 'Unattackable', 'Interrupt Regeneration',
|
||||
'Ghost', 'Spell Magnet', 'Mana Shield', 'Mod Skill Value', 'Mod Attack Power',
|
||||
/*100+ */ 'Auras Visible', 'Mod Resistance Percent', 'Mod Melee Attack Power Versus', 'Mod Total Threat', 'Water Walk',
|
||||
'Feather Fall', 'Hover', 'Add Flat Modifier', 'Add Percent Modifier', 'Add Target Trigger',
|
||||
'Mod Power Regeneration Percent', 'Add Caster Hit Trigger', 'Override Class Scripts', 'Mod Ranged Damage Taken Flat', 'Mod Ranged Damage Taken Percent',
|
||||
'Mod Healing', 'Mod Regeneration During Combat', 'Mod Mechanic Resistance', 'Mod Healing Taken Percent', 'Share Pet Tracking',
|
||||
'Untrackable', 'Empathy', 'Mod Offhand Damage Percent', 'Mod Target Resistance', 'Mod Ranged Attack Power',
|
||||
/*125+ */ 'Mod Melee Damage Taken Flat', 'Mod Melee Damage Taken Percent', 'Ranged Attack Power Attacker Bonus', 'Possess Pet', 'Mod Speed Always',
|
||||
'Mod Mounted Speed Always', 'Mod Ranged Attack Power Versus', 'Mod Increase Energy Percent', 'Mod Increase Health Percent', 'Mod Mana Regeneration Interrupt',
|
||||
'Mod Healing Done Flat', 'Mod Healing Done Percent', 'Mod Total Stat Percentage', 'Mod Melee Haste', 'Force Reaction',
|
||||
'Mod Ranged Haste', 'Mod Ranged Ammo Haste', 'Mod Base Resistance Percent', 'Mod Resistance Exclusive', 'Safe Fall',
|
||||
'Mod Pet Talent Points', 'Allow Tame Pet Type', 'Mechanic Immunity Mask', 'Retain Combo Points', 'Reduce Pushback',
|
||||
/*150+ */ 'Mod Shield Blockvalue Percent', 'Track Stealthed', 'Mod Detected Range', 'Split Damage Flat', 'Mod Stealth Level',
|
||||
'Mod Water Breathing', 'Mod Reputation Gain', 'Pet Damage Multi', 'Mod Shield Blockvalue', 'No PvP Credit',
|
||||
'Mod AoE Avoidance', 'Mod Health Regeneration In Combat', 'Power Burn Mana', 'Mod Crit Damage Bonus', null,
|
||||
'Melee Attack Power Attacker Bonus', 'Mod Attack Power Percent', 'Mod Ranged Attack Power Percent', 'Mod Damage Done Versus', 'Mod Crit Percent Versus',
|
||||
'Change Model', 'Mod Speed (not stacking)', 'Mod Mounted Speed (not stacking)', null, 'Mod Spell Damage Of Stat Percent',
|
||||
/*175+ */ 'Mod Spell Healing Of Stat Percent', 'Spirit Of Redemption', 'AoE Charm', 'Mod Debuff Resistance', 'Mod Attacker Spell Crit Chance',
|
||||
'Mod Spell Damage Versus', null, 'Mod Resistance Of Stat Percent', 'Mod Critical Threat', 'Mod Attacker Melee Hit Chance',
|
||||
'Mod Attacker Ranged Hit Chance', 'Mod Attacker Spell Hit Chance', 'Mod Attacker Melee Crit Chance', 'Mod Attacker Ranged Crit Chance', 'Mod Rating',
|
||||
'Mod Faction Reputation Gain', 'Use Normal Movement Speed', 'Mod Melee Ranged Haste', 'Mod Haste', 'Mod Target Absorb School',
|
||||
'Mod Target Ability Absorb School', 'Mod Cooldown', 'Mod Attacker Spell And Weapon Crit Chance', null, 'Mod Increases Spell Percent to Hit',
|
||||
/*200+ */ 'Mod XP Percent', 'Fly', 'Ignore Combat Result', 'Mod Attacker Melee Crit Damage', 'Mod Attacker Ranged Crit Damage',
|
||||
'Mod School Crit Damage Taken', 'Mod Increase Vehicle Flight Speed', 'Mod Increase Mounted Flight Speed', 'Mod Increase Flight Speed', 'Mod Mounted Flight Speed Always',
|
||||
'Mod Vehicle Speed Always', 'Mod Flight Speed (not stacking)', 'Mod Ranged Attack Power Of Stat Percent', 'Mod Rage from Damage Dealt', 'Tamed Pet Passive',
|
||||
'Arena Preparation', 'Haste Spells', 'Killing Spree', 'Haste Ranged', 'Mod Mana Regeneration from Stat',
|
||||
'Mod Rating from Stat', 'Ignore Threat', null, 'Raid Proc from Charge', null,
|
||||
/*225+ */ 'Raid Proc from Charge With Value', 'Periodic Dummy', 'Periodic Trigger Spell With Value', 'Detect Stealth', 'Mod AoE Damage Avoidance',
|
||||
'Mod Increase Health', 'Proc Trigger Spell With Value', 'Mod Mechanic Duration', 'Mod Display Model', 'Mod Mechanic Duration (not stacking)',
|
||||
'Mod Dispel Resist', 'Control Vehicle', 'Mod Spell Damage Of Attack Power', 'Mod Spell Healing Of Attack Power', 'Mod Scale 2',
|
||||
'Mod Expertise', 'Force Move Forward', 'Mod Spell Damage from Healing', 'Mod Faction', 'Comprehend Language',
|
||||
'Mod Aura Duration By Dispel', 'Mod Aura Duration By Dispel (not stacking)', 'Clone Caster', 'Mod Combat Result Chance', 'Convert Rune',
|
||||
/*250+ */ 'Mod Increase Health 2', 'Mod Enemy Dodge', 'Mod Speed Slow All', 'Mod Block Crit Chance', 'Mod Disarm Offhand',
|
||||
'Mod Mechanic Damage Taken Percent', 'No Reagent Use', 'Mod Target Resist By Spell Class', 'Mod Spell Visual', 'Mod HoT Percent',
|
||||
'Screen Effect', 'Phase', 'Ability Ignore Aurastate', 'Allow Only Ability', null,
|
||||
null, null, 'Mod Immune Aura Apply School', 'Mod Attack Power Of Stat Percent', 'Mod Ignore Target Resist',
|
||||
'Mod Ability Ignore Target Resist', 'Mod Damage Taken Percent From Caster', 'Ignore Melee Reset', 'X Ray', 'Ability Consume No Ammo',
|
||||
/*275+ */ 'Mod Ignore Shapeshift', 'Mod Mechanic Damage Done Percent', 'Mod Max Affected Targets', 'Mod Disarm Ranged', 'Initialize Images',
|
||||
'Mod Armor Penetration Percent', 'Mod Honor Gain Percent', 'Mod Base Health Percent', 'Mod Healing Received', 'Linked',
|
||||
'Mod Attack Power Of Armor', 'Ability Periodic Crit', 'Deflect Spells', 'Ignore Hit Direction', null,
|
||||
'Mod Crit Percent', 'Mod XP Quest Percent', 'Open Stable', 'Override Spells', 'Prevent Power Regeneration',
|
||||
null, 'Set Vehicle Id', 'Block Spell Family', 'Strangulate', null,
|
||||
/*300+ */ 'Share Damage Percent', 'School Heal Absorb', null, 'Mod Damage Done Versus Aurastate', 'Mod Fake Inebriate',
|
||||
'Mod Minimum Speed', null, 'Heal Absorb Test', 'Hunter Trap', null,
|
||||
'Mod Creature AoE Damage Avoidance', null, null, null, 'Prevent Ressurection',
|
||||
/* -316*/ 'Underwater Walking', 'Periodic Haste'
|
||||
)
|
||||
),
|
||||
'item' => array(
|
||||
'notFound' => "Cet objet n'existe pas.",
|
||||
'armor' => "Armure : %s",
|
||||
'block' => "Bloquer : %s",
|
||||
'charges' => "Charges",
|
||||
'charges' => "%d |4charge:charges;",
|
||||
'locked' => "Verrouillé",
|
||||
'ratingString' => "%s @ L%s",
|
||||
'heroic' => "Héroïque",
|
||||
'unique' => "Unique",
|
||||
'uniqueEquipped'=> "Unique - Equipé",
|
||||
'startQuest' => "Cet objet permet de lancer une quête",
|
||||
'bagSlotString' => "%s %d emplacements",
|
||||
'dps' => "dégâts par seconde",
|
||||
'dps2' => "dégâts par seconde",
|
||||
'addsDps' => "Ajoute",
|
||||
'bagSlotString' => '%2$s %1$d |4emplacement:emplacements;',
|
||||
'fap' => "puissance d'attaque en combat farouche",
|
||||
'durability' => "Durabilité",
|
||||
'durability' => "Durabilité %d / %d",
|
||||
'realTime' => "temps réel",
|
||||
'conjured' => "Objet invoqué",
|
||||
'damagePhys' => "Dégâts : %s",
|
||||
'damageMagic' => "%s points de dégâts (%s)",
|
||||
'speed' => "Vitesse",
|
||||
'sellPrice' => "Prix de Vente",
|
||||
'itemLevel' => "Niveau d'objet",
|
||||
'itemLevel' => "Niveau d'objet %d",
|
||||
'randEnchant' => "<Enchantement aléatoire>",
|
||||
'readClick' => "<Clique Droit pour Lire>",
|
||||
'openClick' => "<Clic Droit pour Ouvrir>",
|
||||
'set' => "Set",
|
||||
'setBonus' => "(%d) Ensemble : %s",
|
||||
'setName' => "%s (%d/%d)",
|
||||
'partyLoot' => "Butin de groupe",
|
||||
'smartLoot' => "Butin intelligent",
|
||||
'indestructible'=> "Ne peut être détruit",
|
||||
@@ -891,7 +1073,7 @@ $lang = array(
|
||||
'cost' => "Coût",
|
||||
'content' => "Contenu",
|
||||
'_transfer' => 'Cet objet sera converti en <a href="?item=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a> si vous transférez en <span class="icon-%s">%s</span>.',
|
||||
'_unavailable' => "Este objeto no está disponible para los jugadores.",
|
||||
'_unavailable' => "Cet objet n'est pas disponible pour les joueurs.",
|
||||
'_rndEnchants' => "Enchantements aléatoires",
|
||||
'_chance' => "(%s%% de chance)",
|
||||
'slot' => "Emplacement",
|
||||
@@ -900,6 +1082,18 @@ $lang = array(
|
||||
'buyout' => "Vente immédiate",
|
||||
'each' => "chacun",
|
||||
'tabOther' => "Autre",
|
||||
'reqMinLevel' => "Niveau %d requis",
|
||||
'reqLevelRange' => "Niveau %d à %d (%s) requis",
|
||||
'unique' => ["Unique", "Unique (%d)", "Unique: %s (%d)" ], // ITEM_UNIQUE, ITEM_UNIQUE_MULTIPLE, ITEM_LIMIT_CATEGORY
|
||||
'uniqueEquipped'=> ["Unique - Equipé", null, "Unique - Equipé: %s (%d)"], // ITEM_UNIQUE_EQUIPPABLE, null, ITEM_LIMIT_CATEGORY_MULTIPLE
|
||||
'speed' => "Vitesse",
|
||||
'dps' => "(%.1f dégâts par seconde)",
|
||||
'damage' => array( // *DAMAGE_TEMPLATE*
|
||||
// basic, basic /w school, add basic, add basic /w school
|
||||
'single' => ["%d Dégâts", "%d points de dégâts (%s)", "+ %d points de dégâts", "+ %d points de dégâts (%s)" ],
|
||||
'range' => ["Dégâts : %d - %d", "%d - %d points de dégâts (%s)", "+ %d - %d points de dégâts", "+%d - %d points de dégâts (%s)" ],
|
||||
'ammo' => ["Ajoute %g dégâts par seconde", "Ajoute %g points de dégâts (%s) par seconde", "+ %g points de dégâts par seconde", "+ %g points de dégâts (%s) par seconde" ]
|
||||
),
|
||||
'gems' => "Gemmes",
|
||||
'socketBonus' => "Bonus de châsse",
|
||||
'socket' => array(
|
||||
@@ -909,22 +1103,22 @@ $lang = array(
|
||||
"Méta", "rouge(s)", "jaune(s)", "bleue(s)"
|
||||
),
|
||||
'gemConditions' => array( // ENCHANT_CONDITION_*
|
||||
2 => ["moins de %d gemme %s", "moins de %d gemmes %s"],
|
||||
3 => "plus de gemmes %s que de %s", // plus de gemmes %s que |2 %s
|
||||
5 => ["au moins %d gemme %s", "au moins %d gemmes %s"]
|
||||
2 => "moins de %d |4gemme:gemmes; %s",
|
||||
3 => "plus de gemmes %s que |2 %s",
|
||||
5 => "au moins %d |4gemme:gemmes; %s"
|
||||
),
|
||||
'reqRating' => array( // ITEM_REQ_ARENA_RATING*
|
||||
"Nécessite une cote d'arène personnelle et en équipe de %d",
|
||||
"Nécessite une cote d'arène personnelle et en équipe de %d<br>en arène de 3c3 ou 5c5.",
|
||||
"Nécessite une cote d'arène personnelle et en équipe de %d<br>en arène de 5c5."
|
||||
"Nécessite une cote d'arène personnelle et en équipe de %d|nen arène de 3c3 ou 5c5.",
|
||||
"Nécessite une cote d'arène personnelle et en équipe de %d|nen arène de 5c5."
|
||||
),
|
||||
'quality' => array(
|
||||
"Médiocre", "Classique", "Bonne", "Rare",
|
||||
"Épique", "Légendaire", "Artefact", "Héritage"
|
||||
),
|
||||
'trigger' => array(
|
||||
"Utilise : ", "Équipé : ", "Chances quand vous touchez : ", null, null,
|
||||
null, null
|
||||
"Utilise : ", "Équipé : ", "Chances quand vous touchez : ", "", "",
|
||||
"", ""
|
||||
),
|
||||
'bonding' => array(
|
||||
"Lié au compte", "Lié quand ramassé", "Lié quand équipé",
|
||||
@@ -1004,8 +1198,8 @@ $lang = array(
|
||||
13 => "Clés",
|
||||
),
|
||||
'statType' => array(
|
||||
"Augmente vos points de mana de %d.",
|
||||
"Augmente vos points de vie de %d.",
|
||||
"Mana",
|
||||
"Vie",
|
||||
null,
|
||||
"Agilité",
|
||||
"Force",
|
||||
|
||||
@@ -14,8 +14,7 @@ $lang = array(
|
||||
'timeUnits' => array(
|
||||
'sg' => ["год", "месяц", "неделя", "день", "час", "минута", "секунда", "миллисекунда"],
|
||||
'pl' => ["годы", "месяцы", "недели", "дн.", "часы", "мин", "секунды", "миллисекундах"],
|
||||
'ab' => ["г.", "мес.", "нед.", "дн", "ч.", "мин", "сек.", "мс"],
|
||||
'ago' => '%s назад'
|
||||
'ab' => ["г.", "мес.", "нед.", "дн", "ч.", "мин", "сек.", "мс"]
|
||||
),
|
||||
'main' => array(
|
||||
'name' => "название",
|
||||
@@ -47,10 +46,14 @@ $lang = array(
|
||||
'forum' => "Форум",
|
||||
'n_a' => "нет",
|
||||
'siteRep' => "Репутация",
|
||||
'yourRepHistory'=> "История вашей репутации",
|
||||
'aboutUs' => "О Aowow",
|
||||
'and' => " и ",
|
||||
'or' => " или ",
|
||||
'back' => "Назад",
|
||||
'reputationTip' => "Очки репутации",
|
||||
'byUserTimeAgo' => 'От <a href="'.HOST_URL.'/?user=%s">%1s</a> %s назад',
|
||||
'help' => "Справка",
|
||||
|
||||
// filter
|
||||
'extSearch' => "Расширенный поиск",
|
||||
@@ -107,22 +110,6 @@ $lang = array(
|
||||
'chooseClass' => "Выберите класс",
|
||||
'chooseFamily' => "Выберите семейство питомцев",
|
||||
|
||||
// profiler
|
||||
'realm' => "Игровой мир",
|
||||
'region' => "Регион",
|
||||
'viewCharacter' => "Открыть персонажа",
|
||||
'_cpHead' => "Профили персонажей",
|
||||
'_cpHint' => "<b>Профили персонажей</b> позволяет вам редактировать своего персонажа, находить улучшения предметов и многое другое!",
|
||||
'_cpHelp' => "Чтобы начать использовать профили персонажей, следуйте инструкциям ниже. Если вам потребуется помощь, вы можете обратиться к <a href=\"?help=profiler\">справке</a>.",
|
||||
'_cpFooter' => "Если вам нужен более точный поиск, вы можете использовать <a href=\"?profiles\">дополнительные опции</a>. Также, вы можете создать <a href=\"?profile&new\">новый собственный профиль</a>.",
|
||||
|
||||
// help
|
||||
'help' => "Справка",
|
||||
'helpTopics' => array(
|
||||
"Комментарии и Вы", "3D просмотр", "Скриншоты: Секреты мастерства", "Значимость характеристик",
|
||||
"Расчёт талантов", "Сравнение предметов", "Профили персонажей", "Markup Guide"
|
||||
),
|
||||
|
||||
// search
|
||||
'search' => "Поиск",
|
||||
'searchButton' => "Поиск",
|
||||
@@ -143,29 +130,68 @@ $lang = array(
|
||||
'bannedRating' => "Вам была заблокирована возможность оценивать комментарии.", # LANG.tooltip_banned_rating
|
||||
'tooManyVotes' => "Вы сегодня проголосовали слишком много раз! Вы сможете продолжить завтра.", # LANG.tooltip_too_many_votes
|
||||
|
||||
// screenshots
|
||||
'prepError' => "[An error occured preparing your screenshot]",
|
||||
'cropHint' => "[Crop the image by dragging the selection.<br>Please refer to <a href=\"?help=screenshots-tips-tricks\">Screenshots: Tips & Tricks</a> for an optimal layout.]",
|
||||
'moreTitles' => array(
|
||||
'reputation' => "Репутация на сайте",
|
||||
'whats-new' => "Новости",
|
||||
'searchbox' => "Окно поиска",
|
||||
'tooltips' => "Всплывающие подсказки",
|
||||
'faq' => "[Frequently Asked Questions]",
|
||||
'aboutus' => "[What is AoWoW?]",
|
||||
'searchplugins' => "Дополнения для браузеров",
|
||||
'privileges' => "Привилегии",
|
||||
'top-users' => "Лучшие пользователи",
|
||||
'help' => array(
|
||||
'commenting-and-you' => "Комментарии и Вы", 'modelviewer' => "3D просмотр", 'screenshots-tips-tricks' => "Скриншоты: Секреты мастерства",
|
||||
'stat-weighting' => "Значимость характеристик", 'talent-calculator' => "Расчёт талантов", 'item-comparison' => "Сравнение предметов",
|
||||
'profiler' => "Профили персонажей", 'markup-guide' => "Markup Guide"
|
||||
)
|
||||
)
|
||||
),
|
||||
'profiler' => array(
|
||||
'realm' => "Игровой мир",
|
||||
'region' => "Регион",
|
||||
'viewCharacter' => "Открыть персонажа",
|
||||
'_cpHint' => "<b>Профили персонажей</b> позволяет вам редактировать своего персонажа, находить улучшения предметов и многое другое!",
|
||||
'_cpHelp' => "Чтобы начать использовать профили персонажей, следуйте инструкциям ниже. Если вам потребуется помощь, вы можете обратиться к <a href=\"?help=profiler\">справке</a>.",
|
||||
'_cpFooter' => "Если вам нужен более точный поиск, вы можете использовать <a href=\"?profiles\">дополнительные опции</a>. Также, вы можете создать <a href=\"?profile&new\">новый собственный профиль</a>.",
|
||||
'firstUseTitle' => "%s", // yes, thats correct. No nonsense, just the name
|
||||
'complexFilter' => "[Complex filter selected! Search results are limited to cached Characters.]",
|
||||
|
||||
'resync' => "Ресинхронизация",
|
||||
'guildRoster' => "Список членов гильдии <%s>",
|
||||
'arenaRoster' => "[Arena Team Roster for <%s>]", // string probably lost
|
||||
'atCaptain' => "Капитан команды арены",
|
||||
|
||||
'profiler' => "Профили персонажей",
|
||||
'arenaTeams' => "Команды арен",
|
||||
'guilds' => "Гильдии",
|
||||
|
||||
'notFound' => array(
|
||||
'profile' => "Этот персонаж не существует, либо еще не добавлен в базу данных.",
|
||||
'arenateam' => "[This Arena Team doesn't exist or is not yet in the database.]",
|
||||
'guild' => "Такая гильдия не существует, или еще не добавлена в базу данных."
|
||||
),
|
||||
'dummyNPCs' => array(
|
||||
100001 => "Бой на Кораблях", 200001 => "Звери Нордскола", 200002 => "Чемпионы фракций", 200003 => "Валь'киры-близнецы"
|
||||
),
|
||||
),
|
||||
'screenshot' => array(
|
||||
'submission' => "Добавление изображения",
|
||||
'selectAll' => "Выбрать всё",
|
||||
'cropHint' => "Вы можете произвести кадрирование изображения и указать заголовок.",
|
||||
'displayOn' => "[Displayed on:[br]%s - [%s=%d]]",
|
||||
'caption' => "[Caption]",
|
||||
'originalSize' => "[Original size]",
|
||||
'targetSize' => "[Target size]",
|
||||
'minSize' => "[Minimum size]",
|
||||
'displayOn' => "[Displayed on: %s[br][%s=%d]]",
|
||||
'ssEdit' => "[Edit uploaded screenshot]",
|
||||
'ssUpload' => "[Screenshot Upload]",
|
||||
'ssSubmit' => "[Submit Screenshot]",
|
||||
'ssErrors' => array(
|
||||
'noUpload' => "[The file was not uploaded!]",
|
||||
'maxSize' => "[The file exceeds the maximum size of %s!]",
|
||||
'interrupted' => "[The upload process was interrupted!]",
|
||||
'noFile' => "[The file was not received!]",
|
||||
'noDest' => "[The page this screenshot should be displayed on, does not exist!]",
|
||||
'charLimit' => "Не обязательно, вплоть до 200 знаков",
|
||||
'thanks' => array(
|
||||
'contrib' => "Спасибо за ваш вклад!",
|
||||
'goBack' => '<a href="?%s=%d">здесь</a> чтобы перейти к предыдущей странице.',
|
||||
'note' => "Примечание: Перед появлением на сайте, ваше изображение должно быть одобрено. Это может занять до 72 часов."
|
||||
),
|
||||
'error' => array(
|
||||
'unkFormat' => "неизвестный формат изображения.",
|
||||
'tooSmall' => "Изображение слишком маленькое. (< ".CFG_SCREENSHOT_MIN_SIZE."x".CFG_SCREENSHOT_MIN_SIZE.").",
|
||||
'selectSS' => "Выберите изображение для загрузки.",
|
||||
'notAllowed' => "[You are not allowed to upload screenshots!]",
|
||||
'noImage' => "[The uploaded file is not an image file!]",
|
||||
'wrongFormat' => "[The image file must be a png or jpg!]",
|
||||
'load' => "[The image file could not be loaded!]",
|
||||
'tooSmall' => "[The image size is too small! (lower than %d x %d)]",
|
||||
'tooLarge' => "[The image size is too large! (greater than %d x %d)]"
|
||||
)
|
||||
),
|
||||
'game' => array(
|
||||
@@ -178,8 +204,12 @@ $lang = array(
|
||||
'difficulty' => "Сложность",
|
||||
'dispelType' => "Тип рассеивания",
|
||||
'duration' => "Длительность",
|
||||
'gameObject' => "объект",
|
||||
'gameObjects' => "Объекты",
|
||||
'emote' => "Эмоция",
|
||||
'emotes' => "Эмоции",
|
||||
'enchantment' => "улучшение",
|
||||
'enchantments' => "Улучшения",
|
||||
'object' => "объект",
|
||||
'objects' => "Объекты",
|
||||
'glyphType' => "Тип символа",
|
||||
'race' => "раса",
|
||||
'races' => "Расы",
|
||||
@@ -191,6 +221,8 @@ $lang = array(
|
||||
'faction' => "фракция",
|
||||
'factions' => "Фракции",
|
||||
'cooldown' => "Восстановление: %s",
|
||||
'icon' => "иконка",
|
||||
'icons' => "Иконки",
|
||||
'item' => "предмет",
|
||||
'items' => "Предметы",
|
||||
'itemset' => "комплект",
|
||||
@@ -209,12 +241,13 @@ $lang = array(
|
||||
'requires' => "Требует %s",
|
||||
'requires2' => "Требуется:",
|
||||
'reqLevel' => "Требуется уровень: %s",
|
||||
'reqLevelHlm' => "Требуется уровень: %s",
|
||||
'reqSkillLevel' => "Требуется уровень навыка",
|
||||
'level' => "Уровень",
|
||||
'school' => "Школа",
|
||||
'skill' => "Уровень навыка",
|
||||
'skills' => "Умения",
|
||||
'sound' => "Звук",
|
||||
'sounds' => "Звуки",
|
||||
'spell' => "заклинание",
|
||||
'spells' => "Заклинания",
|
||||
'type' => "Тип",
|
||||
@@ -260,10 +293,10 @@ $lang = array(
|
||||
'rep' => array("Ненависть", "Враждебность", "Неприязнь", "Равнодушие", "Дружелюбие", "Уважение", "Почтение", "Превознесение"),
|
||||
'st' => array(
|
||||
"По-умолчанию", "Облик кошки", "TОблик Древа жизни", "Походный облик", "Водный облик", "Облик медведя",
|
||||
null, null, "Облик лютого медведя", null, null, null,
|
||||
null, "Танец теней", null, null, "Призрачный волк", "Боевая стойка",
|
||||
"Оборонительная стойка", "Стойка берсерка", null, null, "Метаморфоза", null,
|
||||
null, null, null, "Облик стремительной птицы", "Облик Тьмы", "Облик птицы",
|
||||
"Фауна", "Вурдалак", "Облик лютого медведя", "Вурдалак Стива", "Скелет Тарон'джа", "Ярмарка Новолуния - испытание силы",
|
||||
"BLB Player", "Танец теней", "Существо: медведь", "Существо: кошка", "Призрачный волк", "Боевая стойка",
|
||||
"Оборонительная стойка", "Стойка берсерка", "Тест", "Зомби", "Метаморфоза", null,
|
||||
null, "Нежить", "Бешенство", "Облик стремительной птицы", "Облик Тьмы", "Облик птицы",
|
||||
"Незаметность", "Облик лунного совуха", "Дух воздаяния"
|
||||
),
|
||||
'me' => array(
|
||||
@@ -302,7 +335,7 @@ $lang = array(
|
||||
'groups' => array(
|
||||
-1 => "Нет", "Тестер", "Администратор", "Редактор", "Модератор", "Бюрократ",
|
||||
"Разработчик", "VIP", "Блогер", "Учетная запись Премиум", "Переводчик", "Агент по продажам",
|
||||
"Менеджер изображений", "Менеджер видео"
|
||||
"Менеджер изображений", "Менеджер видео", "API партнер", "Ожидающее"
|
||||
),
|
||||
// signIn
|
||||
'doSignIn' => "Войти в вашу учетную запись Aowow",
|
||||
@@ -348,7 +381,7 @@ $lang = array(
|
||||
'accActivated' => 'Your account has been activated.<br>Proceed to <a href="?account=signin&token=%s">sign in</a>',
|
||||
'userNotFound' => "The username you entered does not exists.",
|
||||
'wrongPass' => "That password is not vaild.",
|
||||
'accInactive' => "That account has not yet been confirmed active.",
|
||||
// 'accInactive' => "That account has not yet been confirmed active.",
|
||||
'loginExceeded' => "The maximum number of logins from this IP has been exceeded. Please try again in %s.",
|
||||
'signupExceeded'=> "The maximum number of signups from this IP has been exceeded. Please try again in %s.",
|
||||
'errNameLength' => "Имя пользователя не должно быть короче 4 символов.", // message_usernamemin
|
||||
@@ -383,17 +416,37 @@ $lang = array(
|
||||
'recoverUser' => ["User Recovery", "Follow this link to log in.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nIf you did not request this mail simply ignore it."],
|
||||
'resetPass' => ["Password Reset", "Follow this link to reset your password.\r\n\r\n".HOST_URL."?account=forgotpassword&token=%s\r\n\r\nIf you did not request this mail simply ignore it."]
|
||||
),
|
||||
'emote' => array(
|
||||
'notFound' => "[This Emote doesn't exist.]",
|
||||
'self' => "[To Yourself]",
|
||||
'target' => "[To others with a target]",
|
||||
'noTarget' => "[To others without a target]",
|
||||
'isAnimated' => "[Uses an animation]",
|
||||
'aliases' => "[Aliases]",
|
||||
'noText' => "[This Emote has no text.]",
|
||||
),
|
||||
'enchantment' => array(
|
||||
'details' => "Подробности",
|
||||
'activation' => "Активации",
|
||||
'notFound' => "Такой улучшение не существует.",
|
||||
'types' => array(
|
||||
1 => "[Proc Spell]", 3 => "[Equip Spell]", 7 => "[Use Spell]", 8 => "Бесцветное гнездо",
|
||||
5 => "Характеристики", 2 => "Урон оружия", 6 => "УВС", 4 => "Защита"
|
||||
)
|
||||
),
|
||||
'gameObject' => array(
|
||||
'notFound' => "Такой объект не существует.",
|
||||
'cat' => [0 => "Другое", 9 => "Книги", 3 => "Контейнеры", -5 => "Сундуки", 25 => "Рыболовные лунки",-3 => "Травы", -4 => "Полезные ископаемые", -2 => "Задания", -6 => "Инструменты"],
|
||||
'type' => [ 9 => "Книга", 3 => "Контейнер", -5 => "Сундук", 25 => "", -3 => "Растение", -4 => "Полезное ископаемое", -2 => "Задание", -6 => ""],
|
||||
'unkPosition' => "Местонахождение этого объекта неизвестно.",
|
||||
'npcLootPH' => '[The <b>%s</b> contains the loot from the fight against <a href="?npc=%d">%s</a>. It spawns after his death.]',
|
||||
'key' => "Ключ",
|
||||
'focus' => "[Spell Focus]",
|
||||
'focusDesc' => "[Spells requiring this Focus can be cast near this Object]",
|
||||
'trap' => "Ловушки",
|
||||
'triggeredBy' => "Срабатывает от",
|
||||
'capturePoint' => "Точка захвата",
|
||||
'foundIn' => "Этот НИП может быть найден в следующих зонах:",
|
||||
'restock' => "[Restocks every %s.]"
|
||||
),
|
||||
'npc' => array(
|
||||
@@ -416,6 +469,7 @@ $lang = array(
|
||||
'melee' => "Ближнего боя",
|
||||
'ranged' => "Дальнего боя",
|
||||
'armor' => "Броня",
|
||||
'foundIn' => "Этот объект может быть найден в следующих зонах:",
|
||||
'tameable' => "Можно приручить (%s)",
|
||||
'waypoint' => "Путевой точки",
|
||||
'wait' => "Период ожидания",
|
||||
@@ -451,7 +505,7 @@ $lang = array(
|
||||
'titleReward' => 'Наградное звание: "<a href="?title=%d">%s</a>"',
|
||||
'slain' => "убито",
|
||||
'reqNumCrt' => "Требуется",
|
||||
'rfAvailable' => "[Available on realm]:",
|
||||
'rfAvailable' => "[Available on realm]: ",
|
||||
'_transfer' => 'Этот предмет превратится в <a href="?achievement=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a>, если вы перейдете за <span class="icon-%s">%s</span>.',
|
||||
),
|
||||
'chrClass' => array(
|
||||
@@ -479,6 +533,20 @@ $lang = array(
|
||||
'Azeroth' => "Азерот",
|
||||
'CosmicMap' => "Звёздная карта",
|
||||
),
|
||||
'privileges' => array(
|
||||
'main' => "Здесь на AoWoW вы можете зарабатывать <a href=\"?reputation\">репутацию</a>. Основной источник получения репутации — увеличение рейтинга ваших комментариев другими пользователями.<br><br>Репутация примерно измеряет количество вашего вклада в сообщество.<br><br>По мере того, как вы зарабатываете репутацию, вы получаете доверие сообщества и особые привилегии. Полный список привилегий расположен ниже.",
|
||||
'privilege' => "Привилегия",
|
||||
'privileges' => "Привилегии",
|
||||
'requiredRep' => "Необходима репутация",
|
||||
'reqPoints' => "Для этой привилегии требуется <b>%s</b> очков репутации.",
|
||||
'_privileges' => array(
|
||||
null, "Оставлять комментарии", "Оставлять внешние ссылки", null,
|
||||
"Нет CAPTCHA", "Более сильные голоса", null, null,
|
||||
null, "Больше голосов в день", "Голосовать за комментарии", "Голосовать против комментариев",
|
||||
"Отвечать на комментарии", "Граница: Необычный", "Граница: Редкий", "Граница: Эпический",
|
||||
"Граница: Легендарный", "AoWoW Premium"
|
||||
)
|
||||
),
|
||||
'zone' => array(
|
||||
'notFound' => "Такая местность не существует.",
|
||||
'attunement' => ["[Attunement]", "[Heroic attunement]"],
|
||||
@@ -556,8 +624,9 @@ $lang = array(
|
||||
'receiveAlso' => "Вы также получите",
|
||||
'spellCast' => "Следующее заклинание будет наложено на вас",
|
||||
'spellLearn' => "Вы изучите",
|
||||
'bonusTalents' => "очков талантов",
|
||||
'bonusTalents' => "%d |4очко талантов:очка талантов:очков талантов;",
|
||||
'spellDisplayed'=> ' (показано: <a href="?spell=%d">%s</a>)',
|
||||
'attachment' => "[Attachment]",
|
||||
'questInfo' => array(
|
||||
0 => "Обычный", 1 => "Группа", 21 => "Жизнь", 41 => "PvP", 62 => "Рейд", 81 => "Подземелье", 82 => "Игровое событие",
|
||||
83 => "Легенда", 84 => "Сопровождение", 85 => "Героическое", 88 => "Рейд (10)", 89 => "Рейд (25)"
|
||||
@@ -633,6 +702,9 @@ $lang = array(
|
||||
-2 => "Разное"
|
||||
)
|
||||
),
|
||||
'icon' => array(
|
||||
'notFound' => "Этой иконки не существует"
|
||||
),
|
||||
'title' => array(
|
||||
'notFound' => "Такое звание не существует.",
|
||||
'_transfer' => 'Этот предмет превратится в <a href="?title=%d" class="q1">%s</a>, если вы перейдете за <span class="icon-%s">%s</span>.',
|
||||
@@ -654,10 +726,25 @@ $lang = array(
|
||||
1 => "Разное", 2 => "PvP", 4 => "World of Warcraft", 21 => "Wrath of the Lich King", 22 => "Подземелья и рейды", 23 => "Burning Crusade", 41 => "Test", 3 => "Неактивно"
|
||||
)
|
||||
),
|
||||
'sound' => array(
|
||||
'notFound' => "Этот звук не существует.",
|
||||
'foundIn' => "Этот Звук может быть найден в следующих зонах:",
|
||||
'goToPlaylist' => "Перейти к плейлисту",
|
||||
'music' => "Музыка",
|
||||
'intro' => "Начальная музыка",
|
||||
'ambience' => "Атмосфера",
|
||||
'cat' => array(
|
||||
null, "Spells", "User Interface", "Footsteps", "Weapons Impacts", null, "Weapons Misses", null, null, "Pick Up/Put Down",
|
||||
"NPC Combat", null, "Errors", "Nature", "Objects", null, "Death", "NPC Greetings", null, "Armor",
|
||||
"Footstep Splash", "Water (Character)", "Water", "Tradeskills", "Misc Ambience", "Doodads", "Spell Fizzle", "NPC Loops", "Zone Music", "Emotes",
|
||||
"Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "Мой плейлист"
|
||||
)
|
||||
),
|
||||
'pet' => array(
|
||||
'notFound' => "Такой породы питомцев не существует.",
|
||||
'exotic' => "Экзотический",
|
||||
'cat' => ["Свирепость", "Упорство", "Хитрость"]
|
||||
'cat' => ["Свирепость", "Упорство", "Хитрость"],
|
||||
'food' => ["Мясо", "Рыба", "Сыр", "Хлеб", "Грибы", "Фрукты", "Сырое мясо", "Сырая рыба"]
|
||||
),
|
||||
'faction' => array(
|
||||
'notFound' => "Такая фракция не существует.",
|
||||
@@ -721,7 +808,6 @@ $lang = array(
|
||||
'_collapseAll' => "Свернуть все",
|
||||
'_expandAll' => "Развернуть все",
|
||||
'_transfer' => 'Этот предмет превратится в <a href="?spell=%d" class="q%d icontiny tinyspecial" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/%s.gif)">%s</a>, если вы перейдете за <span class="icon-%s">%s</span>.',
|
||||
|
||||
'discovered' => "Изучается путём освоения местности",
|
||||
'ppm' => "Срабатывает %s раз в минуту",
|
||||
'procChance' => "Шанс срабатывания",
|
||||
@@ -742,6 +828,8 @@ $lang = array(
|
||||
'pctCostOf' => "от базовой %s",
|
||||
'costPerSec' => ", плюс %s в секунду",
|
||||
'costPerLevel' => ", плюс %s за уровень",
|
||||
'stackGroup' => "[Stack Group]",
|
||||
'linkedWith' => "[Linked with]",
|
||||
'_scaling' => "[Scaling]",
|
||||
'scaling' => array(
|
||||
'directSP' => "[+%.2f%% of spell power to direct component]", 'directAP' => "[+%.2f%% of attack power to direct component]",
|
||||
@@ -814,7 +902,8 @@ $lang = array(
|
||||
),
|
||||
'traitShort' => array(
|
||||
'atkpwr' => "СА", 'rgdatkpwr' => "Сил", 'splpwr' => "СЗ", 'arcsplpwr' => "Урон", 'firsplpwr' => "Урон",
|
||||
'frosplpwr' => "Урон", 'holsplpwr' => "Урон", 'natsplpwr' => "Урон", 'shasplpwr' => "Урон", 'splheal' => "Исцеление"
|
||||
'frosplpwr' => "Урон", 'holsplpwr' => "Урон", 'natsplpwr' => "Урон", 'shasplpwr' => "Урон", 'splheal' => "Исцеление",
|
||||
'str' => "Сила", 'agi' => "Ловк", 'sta' => "Выно", 'int' => "Инт", 'spi' => "Дух"
|
||||
),
|
||||
'spellModOp' => array(
|
||||
"DAMAGE", "DURATION", "THREAT", "EFFECT1", "CHARGES",
|
||||
@@ -840,36 +929,127 @@ $lang = array(
|
||||
"Начертание", "Открыть на ходу"
|
||||
),
|
||||
'stealthType' => ["GENERAL", "TRAP"],
|
||||
'invisibilityType' => ["GENERAL", 3 => "TRAP", 6 => "DRUNK"]
|
||||
'invisibilityType' => ["GENERAL", 3 => "TRAP", 6 => "DRUNK"],
|
||||
'unkEffect' => 'Unknown Effect',
|
||||
'effects' => array(
|
||||
/*0-5 */ 'None', 'Instakill', 'School Damage', 'Dummy', 'Portal Teleport', 'Teleport Units',
|
||||
/*6+ */ 'Apply Aura', 'Environmental Damage', 'Power Drain', 'Health Leech', 'Heal', 'Bind',
|
||||
/*12+ */ 'Portal', 'Ritual Base', 'Ritual Specialize', 'Ritual Activate Portal', 'Quest Complete', 'Weapon Damage NoSchool',
|
||||
/*18+ */ 'Resurrect', 'Add Extra Attacks', 'Dodge', 'Evade', 'Parry', 'Block',
|
||||
/*24+ */ 'Create Item', 'Can Use Weapon', 'Defense', 'Persistent Area Aura', 'Summon', 'Leap',
|
||||
/*30+ */ 'Energize', 'Weapon Damage Percent', 'Trigger Missile', 'Open Lock', 'Summon Change Item', 'Apply Area Aura Party',
|
||||
/*36+ */ 'Learn Spell', 'Spell Defense', 'Dispel', 'Language', 'Dual Wield', 'Jump',
|
||||
/*42+ */ 'Jump Dest', 'Teleport Units Face Caster','Skill Step', 'Add Honor', 'Spawn', 'Trade Skill',
|
||||
/*48+ */ 'Stealth', 'Detect', 'Trans Door', 'Force Critical Hit', 'Guarantee Hit', 'Enchant Item Permanent',
|
||||
/*54+ */ 'Enchant Item Temporary', 'Tame Creature', 'Summon Pet', 'Learn Pet Spell', 'Weapon Damage Flat', 'Create Random Item',
|
||||
/*60+ */ 'Proficiency', 'Send Event', 'Power Burn', 'Threat', 'Trigger Spell', 'Apply Area Aura Raid',
|
||||
/*66+ */ 'Create Mana Gem', 'Heal Max Health', 'Interrupt Cast', 'Distract', 'Pull', 'Pickpocket',
|
||||
/*72+ */ 'Add Farsight', 'Untrain Talents', 'Apply Glyph', 'Heal Mechanical', 'Summon Object Wild', 'Script Effect',
|
||||
/*78+ */ 'Attack', 'Sanctuary', 'Add Combo Points', 'Create House', 'Bind Sight', 'Duel',
|
||||
/*84+ */ 'Stuck', 'Summon Player', 'Activate Object', 'WMO Damage', 'WMO Repair', 'WMO Change',
|
||||
/*90+ */ 'Kill Credit', 'Threat All', 'Enchant Held Item', 'Force Deselect', 'Self Resurrect', 'Skinning',
|
||||
/*96+ */ 'Charge', 'Cast Button', 'Knock Back', 'Disenchant', 'Inebriate', 'Feed Pet',
|
||||
/*102+ */ 'Dismiss Pet', 'Reputation', 'Summon Object Slot1', 'Summon Object Slot2', 'Summon Object Slot3', 'Summon Object Slot4',
|
||||
/*108+ */ 'Dispel Mechanic', 'Summon Dead Pet', 'Destroy All Totems', 'Durability Damage', 'Summon Demon', 'Resurrect Flat',
|
||||
/*114+ */ 'Attack Me', 'Durability Damage Percent','Skin Player Corpse', 'Spirit Heal', 'Skill', 'Apply Area Aura Pet',
|
||||
/*120+ */ 'Teleport Graveyard', 'Weapon Damage Normalized', null, 'Send Taxi', 'Pull Towards', 'Modify Threat Percent',
|
||||
/*126+ */ 'Steal Beneficial Buff', 'Prospecting', 'Apply Area Aura Friend', 'Apply Area Aura Enemy', 'Redirect Threat', 'Play Sound',
|
||||
/*132+ */ 'Play Music', 'Unlearn Specialization', 'Kill Credit2', 'Call Pet', 'Heal Percent', 'Energize Percent',
|
||||
/*138+ */ 'Leap Back', 'Clear Quest', 'Force Cast', 'Force Cast With Value', 'Trigger Spell With Value', 'Apply Area Aura Owner',
|
||||
/*144+ */ 'Knock Back Dest', 'Pull Towards Dest', 'Activate Rune', 'Quest Fail', null, 'Charge Dest',
|
||||
/*150+ */ 'Quest Start', 'Trigger Spell 2', null, 'Create Tamed Pet', 'Discover Taxi', 'Dual Wield 2H Weapons',
|
||||
/*156+ */ 'Enchant Item Prismatic', 'Create Item 2', 'Milling', 'Allow Rename Pet', null, 'Talent Spec Count',
|
||||
/*162-164*/ 'Talent Spec Select', null, 'Remove Aura'
|
||||
),
|
||||
'unkAura' => 'Unknown Aura',
|
||||
'auras' => array(
|
||||
/*0- */ 'None', 'Bind Sight', 'Mod Possess', 'Periodic Damage', 'Dummy',
|
||||
/*5+ */ 'Mod Confuse', 'Mod Charm', 'Mod Fear', 'Periodic Heal', 'Mod Attack Speed',
|
||||
'Mod Threat', 'Taunt', 'Stun', 'Mod Damage Done Flat', 'Mod Damage Taken Flat',
|
||||
'Damage Shield', 'Mod Stealth', 'Mod Stealth Detection', 'Mod Invisibility', 'Mod Invisibility Detection',
|
||||
'Mod Health Percent', 'Mod Power Percent', 'Mod Resistance Flat', 'Periodic Trigger Spell', 'Periodic Energize',
|
||||
/*25+ */ 'Pacify', 'Root', 'Silence', 'Reflect Spells', 'Mod Stat Flat',
|
||||
'Mod Skill', 'Mod Increase Speed', 'Mod Increase Mounted Speed', 'Mod Decrease Speed', 'Mod Increase Health',
|
||||
'Mod Increase Power', 'Shapeshift', 'Spell Effect Immunity', 'Spell Aura Immunity', 'School Immunity',
|
||||
'Damage Immunity', 'Dispel Immunity', 'Proc Trigger Spell', 'Proc Trigger Damage', 'Track Creatures',
|
||||
'Track Resources', 'Mod Parry Skill', 'Mod Parry Percent', null, 'Mod Dodge Percent',
|
||||
/*50+ */ 'Mod Critical Healing Amount', 'Mod Block Percent', 'Mod Physical Crit Percent', 'Periodic Health Leech', 'Mod Hit Chance',
|
||||
'Mod Spell Hit Chance', 'Transform', 'Mod Spell Crit Chance', 'Mod Increase Swim Speed', 'Mod Damage Done Versus Creature',
|
||||
'Pacify Silence', 'Mod Scale', 'Periodic Health Funnel', 'Periodic Mana Funnel', 'Periodic Mana Leech',
|
||||
'Mod Casting Speed (not stacking)', 'Feign Death', 'Disarm', 'Stalked', 'School Absorb',
|
||||
'Extra Attacks', 'Mod Spell Crit Chance School', 'Mod Power Cost School Percent', 'Mod Power Cost School Flat', 'Reflect Spells School',
|
||||
/*75+ */ 'Language', 'Far Sight', 'Mechanic Immunity', 'Mounted', 'Mod Damage Done Percent',
|
||||
'Mod Stat Percent', 'Split Damage Percent', 'Water Breathing', 'Mod Base Resistance Flat', 'Mod Health Regeneration',
|
||||
'Mod Power Regeneration', 'Channel Death Item', 'Mod Damage Taken Percent', 'Mod Health Regeneration Percent', 'Periodic Damage Percent',
|
||||
'Mod Resist Chance', 'Mod Detect Range', 'Prevent Fleeing', 'Unattackable', 'Interrupt Regeneration',
|
||||
'Ghost', 'Spell Magnet', 'Mana Shield', 'Mod Skill Value', 'Mod Attack Power',
|
||||
/*100+ */ 'Auras Visible', 'Mod Resistance Percent', 'Mod Melee Attack Power Versus', 'Mod Total Threat', 'Water Walk',
|
||||
'Feather Fall', 'Hover', 'Add Flat Modifier', 'Add Percent Modifier', 'Add Target Trigger',
|
||||
'Mod Power Regeneration Percent', 'Add Caster Hit Trigger', 'Override Class Scripts', 'Mod Ranged Damage Taken Flat', 'Mod Ranged Damage Taken Percent',
|
||||
'Mod Healing', 'Mod Regeneration During Combat', 'Mod Mechanic Resistance', 'Mod Healing Taken Percent', 'Share Pet Tracking',
|
||||
'Untrackable', 'Empathy', 'Mod Offhand Damage Percent', 'Mod Target Resistance', 'Mod Ranged Attack Power',
|
||||
/*125+ */ 'Mod Melee Damage Taken Flat', 'Mod Melee Damage Taken Percent', 'Ranged Attack Power Attacker Bonus', 'Possess Pet', 'Mod Speed Always',
|
||||
'Mod Mounted Speed Always', 'Mod Ranged Attack Power Versus', 'Mod Increase Energy Percent', 'Mod Increase Health Percent', 'Mod Mana Regeneration Interrupt',
|
||||
'Mod Healing Done Flat', 'Mod Healing Done Percent', 'Mod Total Stat Percentage', 'Mod Melee Haste', 'Force Reaction',
|
||||
'Mod Ranged Haste', 'Mod Ranged Ammo Haste', 'Mod Base Resistance Percent', 'Mod Resistance Exclusive', 'Safe Fall',
|
||||
'Mod Pet Talent Points', 'Allow Tame Pet Type', 'Mechanic Immunity Mask', 'Retain Combo Points', 'Reduce Pushback',
|
||||
/*150+ */ 'Mod Shield Blockvalue Percent', 'Track Stealthed', 'Mod Detected Range', 'Split Damage Flat', 'Mod Stealth Level',
|
||||
'Mod Water Breathing', 'Mod Reputation Gain', 'Pet Damage Multi', 'Mod Shield Blockvalue', 'No PvP Credit',
|
||||
'Mod AoE Avoidance', 'Mod Health Regeneration In Combat', 'Power Burn Mana', 'Mod Crit Damage Bonus', null,
|
||||
'Melee Attack Power Attacker Bonus', 'Mod Attack Power Percent', 'Mod Ranged Attack Power Percent', 'Mod Damage Done Versus', 'Mod Crit Percent Versus',
|
||||
'Change Model', 'Mod Speed (not stacking)', 'Mod Mounted Speed (not stacking)', null, 'Mod Spell Damage Of Stat Percent',
|
||||
/*175+ */ 'Mod Spell Healing Of Stat Percent', 'Spirit Of Redemption', 'AoE Charm', 'Mod Debuff Resistance', 'Mod Attacker Spell Crit Chance',
|
||||
'Mod Spell Damage Versus', null, 'Mod Resistance Of Stat Percent', 'Mod Critical Threat', 'Mod Attacker Melee Hit Chance',
|
||||
'Mod Attacker Ranged Hit Chance', 'Mod Attacker Spell Hit Chance', 'Mod Attacker Melee Crit Chance', 'Mod Attacker Ranged Crit Chance', 'Mod Rating',
|
||||
'Mod Faction Reputation Gain', 'Use Normal Movement Speed', 'Mod Melee Ranged Haste', 'Mod Haste', 'Mod Target Absorb School',
|
||||
'Mod Target Ability Absorb School', 'Mod Cooldown', 'Mod Attacker Spell And Weapon Crit Chance', null, 'Mod Increases Spell Percent to Hit',
|
||||
/*200+ */ 'Mod XP Percent', 'Fly', 'Ignore Combat Result', 'Mod Attacker Melee Crit Damage', 'Mod Attacker Ranged Crit Damage',
|
||||
'Mod School Crit Damage Taken', 'Mod Increase Vehicle Flight Speed', 'Mod Increase Mounted Flight Speed', 'Mod Increase Flight Speed', 'Mod Mounted Flight Speed Always',
|
||||
'Mod Vehicle Speed Always', 'Mod Flight Speed (not stacking)', 'Mod Ranged Attack Power Of Stat Percent', 'Mod Rage from Damage Dealt', 'Tamed Pet Passive',
|
||||
'Arena Preparation', 'Haste Spells', 'Killing Spree', 'Haste Ranged', 'Mod Mana Regeneration from Stat',
|
||||
'Mod Rating from Stat', 'Ignore Threat', null, 'Raid Proc from Charge', null,
|
||||
/*225+ */ 'Raid Proc from Charge With Value', 'Periodic Dummy', 'Periodic Trigger Spell With Value', 'Detect Stealth', 'Mod AoE Damage Avoidance',
|
||||
'Mod Increase Health', 'Proc Trigger Spell With Value', 'Mod Mechanic Duration', 'Mod Display Model', 'Mod Mechanic Duration (not stacking)',
|
||||
'Mod Dispel Resist', 'Control Vehicle', 'Mod Spell Damage Of Attack Power', 'Mod Spell Healing Of Attack Power', 'Mod Scale 2',
|
||||
'Mod Expertise', 'Force Move Forward', 'Mod Spell Damage from Healing', 'Mod Faction', 'Comprehend Language',
|
||||
'Mod Aura Duration By Dispel', 'Mod Aura Duration By Dispel (not stacking)', 'Clone Caster', 'Mod Combat Result Chance', 'Convert Rune',
|
||||
/*250+ */ 'Mod Increase Health 2', 'Mod Enemy Dodge', 'Mod Speed Slow All', 'Mod Block Crit Chance', 'Mod Disarm Offhand',
|
||||
'Mod Mechanic Damage Taken Percent', 'No Reagent Use', 'Mod Target Resist By Spell Class', 'Mod Spell Visual', 'Mod HoT Percent',
|
||||
'Screen Effect', 'Phase', 'Ability Ignore Aurastate', 'Allow Only Ability', null,
|
||||
null, null, 'Mod Immune Aura Apply School', 'Mod Attack Power Of Stat Percent', 'Mod Ignore Target Resist',
|
||||
'Mod Ability Ignore Target Resist', 'Mod Damage Taken Percent From Caster', 'Ignore Melee Reset', 'X Ray', 'Ability Consume No Ammo',
|
||||
/*275+ */ 'Mod Ignore Shapeshift', 'Mod Mechanic Damage Done Percent', 'Mod Max Affected Targets', 'Mod Disarm Ranged', 'Initialize Images',
|
||||
'Mod Armor Penetration Percent', 'Mod Honor Gain Percent', 'Mod Base Health Percent', 'Mod Healing Received', 'Linked',
|
||||
'Mod Attack Power Of Armor', 'Ability Periodic Crit', 'Deflect Spells', 'Ignore Hit Direction', null,
|
||||
'Mod Crit Percent', 'Mod XP Quest Percent', 'Open Stable', 'Override Spells', 'Prevent Power Regeneration',
|
||||
null, 'Set Vehicle Id', 'Block Spell Family', 'Strangulate', null,
|
||||
/*300+ */ 'Share Damage Percent', 'School Heal Absorb', null, 'Mod Damage Done Versus Aurastate', 'Mod Fake Inebriate',
|
||||
'Mod Minimum Speed', null, 'Heal Absorb Test', 'Hunter Trap', null,
|
||||
'Mod Creature AoE Damage Avoidance', null, null, null, 'Prevent Ressurection',
|
||||
/* -316*/ 'Underwater Walking', 'Periodic Haste'
|
||||
)
|
||||
),
|
||||
'item' => array(
|
||||
'notFound' => "Такой предмет не существует.",
|
||||
'armor' => "Броня: %s",
|
||||
'block' => "Блок: %s",
|
||||
'charges' => "зарядов",
|
||||
'locked' => "Заперт",
|
||||
'charges' => "%d |4заряд:заряда:зарядов;",
|
||||
'locked' => "Заперто",
|
||||
'ratingString' => "%s @ L%s",
|
||||
'heroic' => "Героический",
|
||||
'unique' => "Уникальный",
|
||||
'uniqueEquipped'=> "Не более 1 в вооружении",
|
||||
'startQuest' => "Этот предмет позволяет получить задание.",
|
||||
'bagSlotString' => "%s (ячеек: %d)",
|
||||
'dps' => "ед. урона в секунду",
|
||||
'dps2' => "урон в секунду",
|
||||
'addsDps' => "Добавляет",
|
||||
'bagSlotString' => '%2$s (%1$d |4ячейка:ячейки:ячеек;)',
|
||||
'fap' => "Сила атаки зверя",
|
||||
'durability' => "Прочность:",
|
||||
'durability' => "Прочность: %d / %d",
|
||||
'realTime' => "реальное время",
|
||||
'conjured' => "Сотворенный предмет",
|
||||
'damagePhys' => "Урон: %s",
|
||||
'damageMagic' => "Урон: %s (%s)",
|
||||
'speed' => "Скорость",
|
||||
'sellPrice' => "Цена продажи",
|
||||
'itemLevel' => "Уровень предмета:",
|
||||
'itemLevel' => "Уровень предмета: %d",
|
||||
'randEnchant' => "<Случайное зачарование>",
|
||||
'readClick' => "<Щелкните правой кнопкой мыши, чтобы прочитать.>",
|
||||
'openClick' => "<Щелкните правой кнопкой мыши, чтобы открыть.>",
|
||||
'set' => "Набор",
|
||||
'setBonus' => "Комплект (%d |4предмет:предмета:предметов;): %s",
|
||||
'setName' => "%s (%d/%d)",
|
||||
'partyLoot' => "Добыча группы",
|
||||
'smartLoot' => "Умное распределение добычи",
|
||||
'indestructible'=> "Невозможно выбросить",
|
||||
@@ -902,6 +1082,18 @@ $lang = array(
|
||||
'buyout' => "Цена выкупа",
|
||||
'each' => "каждый",
|
||||
'tabOther' => "Другое",
|
||||
'reqMinLevel' => "Требуется уровень: %d",
|
||||
'reqLevelRange' => "Требуемый уровень: %d – %d (%d)",
|
||||
'unique' => ["Уникальный", "Уникальный (%d)", "Уникальный: %s (%d)" ],
|
||||
'uniqueEquipped'=> ["Уникальный использующийся", null, "Уникальный использующийся предмет: %s (%d)"],
|
||||
'speed' => "Скорость",
|
||||
'dps' => "(%.1f ед. урона в секунду)",
|
||||
'damage' => array( // *DAMAGE_TEMPLATE*
|
||||
// basic, basic /w school, add basic, add basic /w school
|
||||
'single' => ["Урон: %d", "%d ед. |3-6(%s)", "+ %d ед. урона", "+%d ед. урона (%s)" ],
|
||||
'range' => ["Урон: %d - %d", "%d - %d ед. |3-6(%s)", "+ %d - %d ед. урона", "+%d - %d ед. урона (%s)" ],
|
||||
'ammo' => ["Добавляет %g ед. урона в секунду", "Добавляет %g ед. урона (%s) в секунду", "+ ед. урона в секунду от боеприпасов (%g)", "+ %g %s ед. урона в секунду" ]
|
||||
),
|
||||
'gems' => "Самоцветы",
|
||||
'socketBonus' => "При соответствии цвета",
|
||||
'socket' => array(
|
||||
@@ -911,14 +1103,14 @@ $lang = array(
|
||||
"Особый", "Красный", "Желтый", "Синий"
|
||||
),
|
||||
'gemConditions' => array( // ENCHANT_CONDITION_* so whats that pipe-code..?
|
||||
2 => ["меньше, чем %d камень %s цвета", "меньше, чем %d камня %s цвета"], // меньше, чем %d |4камень:камня:камней; |3-1(%s) цвета
|
||||
3 => "больше %s, чем %s камней", // больше |3-7(%s), чем |3-7(%s) камней
|
||||
5 => ["хотя бы %d камень %s цвета", "хотя бы %d камня %s цвета"] // хотя бы %d |4камень:камня:камней; |3-1(%s) цвета; same here
|
||||
2 => "меньше, чем %d |4камень:камня:камней; |3-1(%s) цвета",
|
||||
3 => "больше |3-7(%s), чем |3-7(%s) камней",
|
||||
5 => "хотя бы %d |4камень:камня:камней; |3-1(%s) цвета"
|
||||
),
|
||||
'reqRating' => array( // ITEM_REQ_ARENA_RATING*
|
||||
"Требуется личный и командный рейтинг на арене не ниже %d",
|
||||
"Требуется личный рейтинг и рейтинг команды Арены %d<br>в команде 3 на 3 или 5 на 5",
|
||||
"Требуется личный рейтинг и рейтинг команды Арены %d<br>в команде 5 на 5"
|
||||
"Требуется личный рейтинг и рейтинг команды Арены %d|nв команде 3 на 3 или 5 на 5",
|
||||
"Требуется личный рейтинг и рейтинг команды Арены %d|nв команде 5 на 5"
|
||||
),
|
||||
'quality' => array(
|
||||
"Низкий", "Обычный", "Необычный", "Редкий",
|
||||
@@ -926,7 +1118,7 @@ $lang = array(
|
||||
),
|
||||
'trigger' => array(
|
||||
"Использование: ", "Если на персонаже: ", "Возможный эффект при попадании: ",
|
||||
null, null, null, null
|
||||
"", "", "", ""
|
||||
),
|
||||
'bonding' => array(
|
||||
"Привязано к учетной записи", "Персональный при поднятии", "Становится персональным при надевании",
|
||||
@@ -1005,8 +1197,8 @@ $lang = array(
|
||||
13 => "Ключи",
|
||||
),
|
||||
'statType' => array(
|
||||
"Увеличение запаса маны на %d ед.",
|
||||
"Увеличение максимального запаса здоровья на %d ед.",
|
||||
"к мане",
|
||||
"к здоровью",
|
||||
null,
|
||||
"к ловкости",
|
||||
"к силе",
|
||||
|
||||
@@ -73,8 +73,13 @@ class AccountPage extends GenericPage
|
||||
switch ($this->category[0])
|
||||
{
|
||||
case 'forgotpassword':
|
||||
if (CFG_AUTH_MODE != AUTH_MODE_SELF) // only recover own accounts
|
||||
$this->error();
|
||||
if (CFG_ACC_AUTH_MODE != AUTH_MODE_SELF)
|
||||
{
|
||||
if (CFG_ACC_EXT_RECOVER_URL)
|
||||
header('Location: '.CFG_ACC_EXT_RECOVER_URL, true, 302);
|
||||
else
|
||||
$this->error();
|
||||
}
|
||||
|
||||
$this->tpl = 'acc-recover';
|
||||
$this->resetPass = false;
|
||||
@@ -85,8 +90,13 @@ class AccountPage extends GenericPage
|
||||
$this->head = sprintf(Lang::account('recoverPass'), $nStep);
|
||||
break;
|
||||
case 'forgotusername':
|
||||
if (CFG_AUTH_MODE != AUTH_MODE_SELF) // only recover own accounts
|
||||
$this->error();
|
||||
if (CFG_ACC_AUTH_MODE != AUTH_MODE_SELF)
|
||||
{
|
||||
if (CFG_ACC_EXT_RECOVER_URL)
|
||||
header('Location: '.CFG_ACC_EXT_RECOVER_URL, true, 302);
|
||||
else
|
||||
$this->error();
|
||||
}
|
||||
|
||||
$this->tpl = 'acc-recover';
|
||||
$this->resetPass = false;
|
||||
@@ -123,9 +133,17 @@ class AccountPage extends GenericPage
|
||||
|
||||
break;
|
||||
case 'signup':
|
||||
if (!CFG_ALLOW_REGISTER || CFG_AUTH_MODE != AUTH_MODE_SELF)
|
||||
if (!CFG_ACC_ALLOW_REGISTER)
|
||||
$this->error();
|
||||
|
||||
if (CFG_ACC_AUTH_MODE != AUTH_MODE_SELF)
|
||||
{
|
||||
if (CFG_ACC_EXT_CREATE_URL)
|
||||
header('Location: '.CFG_ACC_EXT_CREATE_URL, true, 302);
|
||||
else
|
||||
$this->error();
|
||||
}
|
||||
|
||||
$this->tpl = 'acc-signUp';
|
||||
$nStep = 1;
|
||||
if ($this->_post['username'] || $this->_post['password'] || $this->_post['c_password'] || $this->_post['email'])
|
||||
@@ -141,10 +159,8 @@ class AccountPage extends GenericPage
|
||||
else if (!empty($_GET['token']) && ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE status = ?d AND token = ?', ACC_STATUS_NEW, $_GET['token'])))
|
||||
{
|
||||
$nStep = 2;
|
||||
DB::Aowow()->query('UPDATE ?_account SET status = ?d WHERE token = ?', ACC_STATUS_OK, $_GET['token']);
|
||||
DB::Aowow()->query('REPLACE INTO ?_account_bannedips (ip, type, count, unbanDate) VALUES (?, 1, ?d + 1, UNIX_TIMESTAMP() + ?d)', User::$ip, CFG_FAILED_AUTH_COUNT, CFG_FAILED_AUTH_EXCLUSION);
|
||||
|
||||
Util::gainSiteReputation($newId, SITEREP_ACTION_REGISTER);
|
||||
DB::Aowow()->query('UPDATE ?_account SET status = ?d, statusTimer = 0, token = 0, userGroups = ?d WHERE token = ?', ACC_STATUS_OK, U_GROUP_NONE, $_GET['token']);
|
||||
DB::Aowow()->query('REPLACE INTO ?_account_bannedips (ip, type, count, unbanDate) VALUES (?, 1, ?d + 1, UNIX_TIMESTAMP() + ?d)', User::$ip, CFG_ACC_FAILED_AUTH_COUNT, CFG_ACC_FAILED_AUTH_BLOCK);
|
||||
|
||||
$this->text = sprintf(Lang::account('accActivated'), $_GET['token']);
|
||||
}
|
||||
@@ -218,7 +234,6 @@ class AccountPage extends GenericPage
|
||||
/* Listview */
|
||||
/************/
|
||||
|
||||
$this->lvTabs = [];
|
||||
$this->forceTabs = true;
|
||||
|
||||
// Reputation changelog (params only for comment-events)
|
||||
@@ -227,11 +242,7 @@ class AccountPage extends GenericPage
|
||||
foreach ($repData as &$r)
|
||||
$r['when'] = date(Util::$dateFormatInternal, $r['when']);
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'reputationhistory',
|
||||
'data' => $repData,
|
||||
'params' => []
|
||||
);
|
||||
$this->lvTabs[] = ['reputationhistory', ['data' => $repData]];
|
||||
}
|
||||
|
||||
// comments
|
||||
@@ -241,14 +252,11 @@ class AccountPage extends GenericPage
|
||||
// _totalCount: 377,
|
||||
// note: $WH.sprintf(LANG.lvnote_usercomments, 377),
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'commentpreview',
|
||||
'data' => $_,
|
||||
'params' => array(
|
||||
'hiddenCols' => "$['author']",
|
||||
'onBeforeCreate' => '$Listview.funcBox.beforeUserComments'
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['commentpreview', array(
|
||||
'data' => $_,
|
||||
'hiddenCols' => ['author'],
|
||||
'onBeforeCreate' => '$Listview.funcBox.beforeUserComments'
|
||||
)];
|
||||
}
|
||||
|
||||
// replies
|
||||
@@ -259,13 +267,10 @@ class AccountPage extends GenericPage
|
||||
// _totalCount: 377,
|
||||
// note: $WH.sprintf(LANG.lvnote_usercomments, 377),
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'replypreview',
|
||||
'data' => $_,
|
||||
'params' => array(
|
||||
'hiddenCols' => "$['author']"
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['replypreview', array(
|
||||
'data' => $_,
|
||||
'hiddenCols' => ['author']
|
||||
)];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -346,9 +351,10 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
return Lang::main('intError');
|
||||
|
||||
// reset account status, update expiration
|
||||
DB::Aowow()->query('UPDATE ?_account SET prevIP = IF(curIp = ?, prevIP, curIP), curIP = IF(curIp = ?, curIP, ?), allowExpire = ?d, status = 0, statusTimer = 0, token = "" WHERE user = ?',
|
||||
DB::Aowow()->query('UPDATE ?_account SET prevIP = IF(curIp = ?, prevIP, curIP), curIP = IF(curIp = ?, curIP, ?), allowExpire = ?d, status = IF(status = ?d, status, 0), statusTimer = IF(status = ?d, statusTimer, 0), token = IF(status = ?d, token, "") WHERE user = ?',
|
||||
User::$ip, User::$ip, User::$ip,
|
||||
$this->_post['remember_me'] != 'yes',
|
||||
ACC_STATUS_NEW, ACC_STATUS_NEW, ACC_STATUS_NEW,
|
||||
$this->_post['username']
|
||||
);
|
||||
|
||||
@@ -366,12 +372,9 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
case AUTH_WRONGPASS:
|
||||
User::destroy();
|
||||
return Lang::account('wrongPass');
|
||||
case AUTH_ACC_INACTIVE:
|
||||
User::destroy();
|
||||
return Lang::account('accInactive');
|
||||
case AUTH_IPBANNED:
|
||||
User::destroy();
|
||||
return sprintf(Lang::account('loginExceeded'), Util::formatTime(CFG_FAILED_AUTH_EXCLUSION * 1000));
|
||||
return sprintf(Lang::account('loginExceeded'), Util::formatTime(CFG_ACC_FAILED_AUTH_BLOCK * 1000));
|
||||
case AUTH_INTERNAL_ERR:
|
||||
User::destroy();
|
||||
return Lang::main('intError');
|
||||
@@ -403,10 +406,10 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
|
||||
// limit account creation
|
||||
$ip = DB::Aowow()->selectRow('SELECT ip, count, unbanDate FROM ?_account_bannedips WHERE type = 1 AND ip = ?', User::$ip);
|
||||
if ($ip && $ip['count'] >= CFG_FAILED_AUTH_COUNT && $ip['unbanDate'] >= time())
|
||||
if ($ip && $ip['count'] >= CFG_ACC_FAILED_AUTH_COUNT && $ip['unbanDate'] >= time())
|
||||
{
|
||||
DB::Aowow()->query('UPDATE ?_account_bannedips SET count = count + 1, unbanDate = UNIX_TIMESTAMP() + ?d WHERE ip = ? AND type = 1', CFG_FAILED_AUTH_EXCLUSION, User::$ip);
|
||||
return sprintf(Lang::account('signupExceeded'), Util::formatTime(CFG_FAILED_AUTH_EXCLUSION * 1000));
|
||||
DB::Aowow()->query('UPDATE ?_account_bannedips SET count = count + 1, unbanDate = UNIX_TIMESTAMP() + ?d WHERE ip = ? AND type = 1', CFG_ACC_FAILED_AUTH_BLOCK, User::$ip);
|
||||
return sprintf(Lang::account('signupExceeded'), Util::formatTime(CFG_ACC_FAILED_AUTH_BLOCK * 1000));
|
||||
}
|
||||
|
||||
// username taken
|
||||
@@ -415,7 +418,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
|
||||
// create..
|
||||
$token = Util::createHash();
|
||||
$id = DB::Aowow()->query('REPLACE INTO ?_account (user, passHash, displayName, email, joindate, curIP, allowExpire, locale, status, statusTimer, token) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(), ?, ?d, ?d, ?d, UNIX_TIMESTAMP() + ?d, ?)',
|
||||
$ok = DB::Aowow()->query('REPLACE INTO ?_account (user, passHash, displayName, email, joindate, curIP, allowExpire, locale, userGroups, status, statusTimer, token) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(), ?, ?d, ?d, ?d, ?d, UNIX_TIMESTAMP() + ?d, ?)',
|
||||
$this->_post['username'],
|
||||
User::hashCrypt($this->_post['password']),
|
||||
Util::ucFirst($this->_post['username']),
|
||||
@@ -423,19 +426,23 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
User::$ip,
|
||||
$this->_post['remember_me'] != 'yes',
|
||||
User::$localeId,
|
||||
U_GROUP_PENDING,
|
||||
ACC_STATUS_NEW,
|
||||
CFG_ACCOUNT_CREATE_SAVE_DECAY,
|
||||
CFG_ACC_CREATE_SAVE_DECAY,
|
||||
$token
|
||||
);
|
||||
if (!$id) // something went wrong
|
||||
if (!$ok)
|
||||
return Lang::main('intError');
|
||||
else if ($_ = $this->sendMail(Lang::mail('accConfirm', 0), sprintf(Lang::mail('accConfirm', 1), $token), CFG_ACCOUNT_CREATE_SAVE_DECAY))
|
||||
else if ($_ = $this->sendMail(Lang::mail('accConfirm', 0), sprintf(Lang::mail('accConfirm', 1), $token), CFG_ACC_CREATE_SAVE_DECAY))
|
||||
{
|
||||
if ($id = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE token = ?', $token))
|
||||
Util::gainSiteReputation($id, SITEREP_ACTION_REGISTER);
|
||||
|
||||
// success:: update ip-bans
|
||||
if (!$ip || $ip['unbanDate'] < time())
|
||||
DB::Aowow()->query('REPLACE INTO ?_account_bannedips (ip, type, count, unbanDate) VALUES (?, 1, 1, UNIX_TIMESTAMP() + ?d)', User::$ip, CFG_FAILED_AUTH_EXCLUSION);
|
||||
DB::Aowow()->query('REPLACE INTO ?_account_bannedips (ip, type, count, unbanDate) VALUES (?, 1, 1, UNIX_TIMESTAMP() + ?d)', User::$ip, CFG_ACC_FAILED_AUTH_BLOCK);
|
||||
else
|
||||
DB::Aowow()->query('UPDATE ?_account_bannedips SET count = count + 1, unbanDate = UNIX_TIMESTAMP() + ?d WHERE ip = ? AND type = 1', CFG_FAILED_AUTH_EXCLUSION, User::$ip);
|
||||
DB::Aowow()->query('UPDATE ?_account_bannedips SET count = count + 1, unbanDate = UNIX_TIMESTAMP() + ?d WHERE ip = ? AND type = 1', CFG_ACC_FAILED_AUTH_BLOCK, User::$ip);
|
||||
|
||||
return $_;
|
||||
}
|
||||
@@ -443,11 +450,11 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
|
||||
private function doRecoverPass()
|
||||
{
|
||||
if ($_ = $this->initRecovery(ACC_STATUS_RECOVER_PASS, CFG_ACCOUNT_RECOVERY_DECAY, $token))
|
||||
if ($_ = $this->initRecovery(ACC_STATUS_RECOVER_PASS, CFG_ACC_RECOVERY_DECAY, $token))
|
||||
return $_;
|
||||
|
||||
// send recovery mail
|
||||
return $this->sendMail(Lang::mail('resetPass', 0), sprintf(Lang::mail('resetPass', 1), $token), CFG_ACCOUNT_RECOVERY_DECAY);
|
||||
return $this->sendMail(Lang::mail('resetPass', 0), sprintf(Lang::mail('resetPass', 1), $token), CFG_ACC_RECOVERY_DECAY);
|
||||
}
|
||||
|
||||
private function doResetPass()
|
||||
@@ -475,11 +482,11 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
||||
|
||||
private function doRecoverUser()
|
||||
{
|
||||
if ($_ = $this->initRecovery(ACC_STATUS_RECOVER_USER, CFG_ACCOUNT_RECOVERY_DECAY, $token))
|
||||
if ($_ = $this->initRecovery(ACC_STATUS_RECOVER_USER, CFG_ACC_RECOVERY_DECAY, $token))
|
||||
return $_;
|
||||
|
||||
// send recovery mail
|
||||
return $this->sendMail(Lang::mail('recoverUser', 0), sprintf(Lang::mail('recoverUser', 1), $token), CFG_ACCOUNT_RECOVERY_DECAY);
|
||||
return $this->sendMail(Lang::mail('recoverUser', 0), sprintf(Lang::mail('recoverUser', 1), $token), CFG_ACC_RECOVERY_DECAY);
|
||||
}
|
||||
|
||||
private function initRecovery($type, $delay, &$token)
|
||||
|
||||
@@ -103,14 +103,9 @@ class AchievementPage extends GenericPage
|
||||
if ($this->subject->getField('flags') & 0x100 && DB::isConnectable(DB_AUTH))
|
||||
{
|
||||
$avlb = [];
|
||||
foreach (DB::Auth()->selectCol('SELECT id AS ARRAY_KEY, name FROM realmlist WHERE allowedSecurityLevel = 0 AND gamebuild = ?d', WOW_VERSION) AS $rId => $name)
|
||||
{
|
||||
if (!DB::isConnectable(DB_CHARACTERS . $rId))
|
||||
continue;
|
||||
|
||||
foreach (Profiler::getRealms() AS $rId => $rData)
|
||||
if (!DB::Characters($rId)->selectCell('SELECT 1 FROM character_achievement WHERE achievement = ?d LIMIT 1', $this->typeId))
|
||||
$avlb[] = $name;
|
||||
}
|
||||
$avlb[] = Util::ucWords($rData['name']);
|
||||
|
||||
if ($avlb)
|
||||
$infobox[] = Lang::achievement('rfAvailable').implode(', ', $avlb);
|
||||
@@ -151,8 +146,14 @@ class AchievementPage extends GenericPage
|
||||
$this->series = $series ? [[$series, null]] : null;
|
||||
$this->description = $this->subject->getField('description', true);
|
||||
$this->redButtons = array(
|
||||
BUTTON_LINKS => ['color' => 'ffffff00', 'linkId' => Util::$typeStrings[TYPE_ACHIEVEMENT].':'.$this->typeId.':"..UnitGUID("player")..":0:0:0:0:0:0:0:0'],
|
||||
BUTTON_WOWHEAD => !($this->subject->getField('cuFlags') & CUSTOM_SERVERSIDE)
|
||||
BUTTON_WOWHEAD => !($this->subject->getField('cuFlags') & CUSTOM_SERVERSIDE),
|
||||
BUTTON_LINKS => array(
|
||||
'linkColor' => 'ffffff00',
|
||||
'linkId' => Util::$typeStrings[TYPE_ACHIEVEMENT].':'.$this->typeId.':"..UnitGUID("player")..":0:0:0:0:0:0:0:0',
|
||||
'linkName' => $this->name,
|
||||
'type' => $this->type,
|
||||
'typeId' => $this->typeId
|
||||
)
|
||||
);
|
||||
$this->criteria = array(
|
||||
'reqQty' => $this->subject->getField('reqCriteriaCount'),
|
||||
@@ -224,15 +225,12 @@ class AchievementPage extends GenericPage
|
||||
['id', $this->typeId, '!']
|
||||
);
|
||||
$saList = new AchievementList($conditions);
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'achievement',
|
||||
'data' => $saList->getListviewData(),
|
||||
'params' => array(
|
||||
'id' => 'see-also',
|
||||
'name' => '$LANG.tab_seealso',
|
||||
'visibleCols' => "$['category']"
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['achievement', array(
|
||||
'data' => array_values($saList->getListviewData()),
|
||||
'id' => 'see-also',
|
||||
'name' => '$LANG.tab_seealso',
|
||||
'visibleCols' => ['category']
|
||||
)];
|
||||
$this->extendGlobalData($saList->getJSGlobals());
|
||||
|
||||
// tab: criteria of
|
||||
@@ -243,15 +241,12 @@ class AchievementPage extends GenericPage
|
||||
if (!empty($refs))
|
||||
{
|
||||
$coList = new AchievementList(array(['id', $refs]));
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'achievement',
|
||||
'data' => $coList->getListviewData(),
|
||||
'params' => array(
|
||||
'id' => 'criteria-of',
|
||||
'name' => '$LANG.tab_criteriaof',
|
||||
'visibleCols' => "$['category']"
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['achievement', array(
|
||||
'data' => array_values($coList->getListviewData()),
|
||||
'id' => 'criteria-of',
|
||||
'name' => '$LANG.tab_criteriaof',
|
||||
'visibleCols' => ['category']
|
||||
)];
|
||||
$this->extendGlobalData($coList->getJSGlobals());
|
||||
}
|
||||
|
||||
@@ -261,6 +256,12 @@ class AchievementPage extends GenericPage
|
||||
|
||||
$iconId = 1;
|
||||
$rightCol = [];
|
||||
$scripts = [];
|
||||
|
||||
// serverside extra-Data
|
||||
$crtIds = array_column($this->subject->getCriteria(), 'id');
|
||||
Util::checkNumeric($crtIds);
|
||||
$crtExtraData = DB::World()->select('SELECT criteria_id AS ARRAY_KEY, type AS ARRAY_KEY2, value1, value2, ScriptName FROM achievement_criteria_data WHERE criteria_id IN (?a)', $crtIds);
|
||||
|
||||
foreach ($this->subject->getCriteria() as $i => $crt)
|
||||
{
|
||||
@@ -418,11 +419,84 @@ class AchievementPage extends GenericPage
|
||||
'text' => $crtName,
|
||||
);
|
||||
break;
|
||||
// link to emote
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
|
||||
$tmp['link'] = array(
|
||||
'href' => '?emote='.$obj,
|
||||
'text' => $crtName,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
// Add a gold coin icon if required
|
||||
$tmp['extraText'] = $displayMoney ? Util::formatMoney($qty) : $crtName;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($crtExtraData[$crt['id']]))
|
||||
{
|
||||
$tmp['extraData'] = [];
|
||||
foreach ($crtExtraData[$crt['id']] as $xType => $xData)
|
||||
{
|
||||
// just pick stuff, that can actually be linked
|
||||
switch ($xType)
|
||||
{
|
||||
case 1: // TYPE_T_CREATURE
|
||||
$tmp['extraData'][] = ['?npc='.$xData['value1'], CreatureList::getName($xData['value1'])];
|
||||
break;
|
||||
case 2: // TYPE_T_PLAYER_CLASS_RACE
|
||||
case 21: // TYPE_S_PLAYER_CLASS_RACE
|
||||
if ($xData['value1'])
|
||||
$tmp['extraData'][] = ['?class='.$xData['value1'], (new CharClassList(array(['id', $xData['value1']])))->getField('name', true)];
|
||||
|
||||
if ($xData['value2'])
|
||||
$tmp['extraData'][] = ['?race='.$xData['value2'], (new CharRaceList(array(['id', $xData['value2']])))->getField('name', true)];
|
||||
|
||||
break;
|
||||
// case 3: // TYPE_T_PLAYER_LESS_HEALTH
|
||||
// case 4: // TYPE_T_PLAYER_DEAD
|
||||
case 5: // TYPE_S_AURA
|
||||
case 7: // TYPE_T_AURA
|
||||
$tmp['extraData'][] = ['?spell='.$xData['value1'], SpellList::getName($xData['value1'])];
|
||||
break;
|
||||
case 6: // TYPE_S_AREA
|
||||
$tmp['extraData'][] = ['?zone='.$xData['value1'], ZoneList::getName($xData['value1'])];
|
||||
break;
|
||||
// case 8: // TYPE_VALUE
|
||||
// case 9: // TYPE_T_LEVEL
|
||||
// case 10: // TYPE_T_GENDER
|
||||
case 11: // TYPE_SCRIPT
|
||||
if ($xData['ScriptName'])
|
||||
$scripts[] = $xData['ScriptName'];
|
||||
|
||||
break;
|
||||
// case 12: // TYPE_MAP_DIFFICULTY
|
||||
// case 13: // TYPE_MAP_PLAYER_COUNT
|
||||
// case 14: // TYPE_T_TEAM
|
||||
// case 15: // TYPE_S_DRUNK
|
||||
case 16: // TYPE_HOLIDAY
|
||||
if ($we = new WorldEventList(array(['holidayId', $xData['value1']])))
|
||||
$tmp['extraData'][] = ['?event='.$we->id, $we->getField('name', true)];
|
||||
|
||||
break;
|
||||
// case 17: // TYPE_BG_LOSS_TEAM_SCORE
|
||||
// case 18: // TYPE_INSTANCE_SCRIPT
|
||||
// case 19: // TYPE_S_EQUIPED_ITEM
|
||||
case 20: // TYPE_MAP_ID
|
||||
if ($z = new ZoneList(array(['mapIdBak', $xData['value1']])))
|
||||
$tmp['extraData'][] = ['?zone='.$z->id, $z->getField('name', true)];
|
||||
|
||||
break;
|
||||
// case 22: // TYPE_NTH_BIRTHDAY
|
||||
case 23: // TYPE_S_KNOWN_TITLE
|
||||
$tmp['extraData'][] = ['?title='.$xData['value1'], trim(str_replace('%s', '', (new TitleList(array(['id', $xData['value1']])))->getField('male', true)))];
|
||||
break;
|
||||
}
|
||||
|
||||
// moar stuffz
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// If the right column
|
||||
if ($i % 2)
|
||||
$this->criteria['data'][] = $tmp;
|
||||
@@ -433,6 +507,13 @@ class AchievementPage extends GenericPage
|
||||
// If you found the second column - merge data from it to the end of the main body
|
||||
if ($rightCol)
|
||||
$this->criteria['data'] = array_merge($this->criteria['data'], $rightCol);
|
||||
|
||||
// criteria have scripts
|
||||
if (User::isInGroup(U_GROUP_EMPLOYEE) && $scripts)
|
||||
{
|
||||
$s = '[li]Script'.Lang::main('colon').'[ul][li]'.implode('[/li][li]', array_unique($scripts)).'[/li][/ul][/li]';
|
||||
$this->infobox = substr_replace($this->infobox, $s, -5, 0);
|
||||
}
|
||||
}
|
||||
|
||||
protected function generateTooltip($asError = false)
|
||||
@@ -442,7 +523,7 @@ class AchievementPage extends GenericPage
|
||||
|
||||
$x = '$WowheadPower.registerAchievement('.$this->typeId.', '.User::$localeId.",{\n";
|
||||
$x .= "\tname_".User::$localeString.": '".Util::jsEscape($this->subject->getField('name', true))."',\n";
|
||||
$x .= "\ticon: '".urlencode($this->subject->getField('iconString'))."',\n";
|
||||
$x .= "\ticon: '".rawurlencode($this->subject->getField('iconString', true, true))."',\n";
|
||||
$x .= "\ttooltip_".User::$localeString.": '".$this->subject->renderTooltip()."'\n";
|
||||
$x .= "});";
|
||||
|
||||
@@ -464,10 +545,10 @@ class AchievementPage extends GenericPage
|
||||
die($tt);
|
||||
}
|
||||
|
||||
public function notFound()
|
||||
public function notFound($title = '', $msg = '')
|
||||
{
|
||||
if ($this->mode != CACHE_TYPE_TOOLTIP)
|
||||
return parent::notFound(Lang::game('achievement'), Lang::achievement('notFound'));
|
||||
return parent::notFound($title ?: Lang::game('achievement'), $msg ?: Lang::achievement('notFound'));
|
||||
|
||||
header('Content-type: application/x-javascript; charset=utf-8');
|
||||
echo $this->generateTooltip(true);
|
||||
|
||||
@@ -42,8 +42,8 @@ class AchievementsPage extends GenericPage
|
||||
|
||||
public function __construct($pageCall, $pageParam)
|
||||
{
|
||||
$this->filterObj = new AchievementListFilter();
|
||||
$this->getCategoryFromUrl($pageParam);
|
||||
$this->filterObj = new AchievementListFilter(false, $this->category);
|
||||
|
||||
parent::__construct($pageCall, $pageParam);
|
||||
|
||||
@@ -63,9 +63,12 @@ class AchievementsPage extends GenericPage
|
||||
$conditions[] = ['category', (int)end($this->category)];
|
||||
|
||||
// recreate form selection
|
||||
$this->filter = $this->filterObj->getForm('form');
|
||||
$this->filter = $this->filterObj->getForm();
|
||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
|
||||
$this->filter['fi'] = $this->filterObj->getForm();
|
||||
$this->filter['initData'] = ['init' => 'achievements'];
|
||||
|
||||
if ($x = $this->filterObj->getSetCriteria())
|
||||
$this->filter['initData']['sc'] = $x;
|
||||
|
||||
if ($fiCnd = $this->filterObj->getConditions())
|
||||
$conditions[] = $fiCnd;
|
||||
@@ -88,37 +91,33 @@ class AchievementsPage extends GenericPage
|
||||
$acvList = new AchievementList($conditions);
|
||||
}
|
||||
|
||||
$params = $data = [];
|
||||
$tabData = [];
|
||||
if (!$acvList->error)
|
||||
{
|
||||
$data = $acvList->getListviewData();
|
||||
$tabData['data'] = array_values($acvList->getListviewData());
|
||||
|
||||
// fill g_items, g_titles, g_achievements
|
||||
$this->extendGlobalData($acvList->getJSGlobals());
|
||||
|
||||
// if we are have different cats display field
|
||||
if ($acvList->hasDiffFields(['category']))
|
||||
$params['visibleCols'] = "$['category']";
|
||||
$tabData['visibleCols'] = ['category'];
|
||||
|
||||
if (!empty($this->filter['fi']['extraCols']))
|
||||
$params['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
|
||||
$tabData['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
|
||||
|
||||
// create note if search limit was exceeded
|
||||
if ($acvList->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
{
|
||||
$params['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_achievementsfound', $acvList->getMatches(), CFG_SQL_LIMIT_DEFAULT);
|
||||
$params['_truncated'] = 1;
|
||||
$tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_achievementsfound', $acvList->getMatches(), CFG_SQL_LIMIT_DEFAULT);
|
||||
$tabData['_truncated'] = 1;
|
||||
}
|
||||
|
||||
if ($this->filterObj->error)
|
||||
$params['_errors'] = '$1';
|
||||
$tabData['_errors'] = 1;
|
||||
}
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'achievement',
|
||||
'data' => $data,
|
||||
'params' => $params
|
||||
);
|
||||
$this->lvTabs[] = ['achievement', $tabData];
|
||||
|
||||
// sort for dropdown-menus in filter
|
||||
Lang::sort('game', 'si');
|
||||
|
||||
407
pages/admin.php
407
pages/admin.php
@@ -20,7 +20,7 @@ class AdminPage extends GenericPage
|
||||
switch ($pageParam)
|
||||
{
|
||||
case 'screenshots':
|
||||
$this->reqUGroup = U_GROUP_STAFF | U_GROUP_SCREENSHOT;
|
||||
$this->reqUGroup = U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SCREENSHOT;
|
||||
$this->generator = 'handleScreenshots';
|
||||
$this->tpl = 'admin/screenshots';
|
||||
|
||||
@@ -38,11 +38,19 @@ class AdminPage extends GenericPage
|
||||
case 'siteconfig':
|
||||
$this->reqUGroup = U_GROUP_ADMIN | U_GROUP_DEV;
|
||||
$this->generator = 'handleConfig';
|
||||
$this->tpl = 'list-page-generic';
|
||||
$this->tpl = 'admin/siteconfig';
|
||||
|
||||
array_push($this->path, 2, 18);
|
||||
$this->name = 'Site Configuration';
|
||||
break;
|
||||
case 'weight-presets':
|
||||
$this->reqUGroup = U_GROUP_ADMIN | U_GROUP_DEV | U_GROUP_BUREAU;
|
||||
$this->generator = 'handleWeightPresets';
|
||||
$this->tpl = 'admin/weight-presets';
|
||||
|
||||
array_push($this->path, 2, 16);
|
||||
$this->name = 'Weight Presets';
|
||||
break;
|
||||
default: // error out through unset template
|
||||
}
|
||||
|
||||
@@ -60,321 +68,51 @@ class AdminPage extends GenericPage
|
||||
private function handleConfig()
|
||||
{
|
||||
$this->addCSS(array(
|
||||
['string' => '.grid input[type=\'text\'] { width:250px; }'],
|
||||
['string' => '.grid input[type=\'text\'], .grid input[type=\'number\'] { width:250px; text-align:left; }'],
|
||||
['string' => '.grid input[type=\'button\'] { width:65px; padding:2px; }'],
|
||||
['string' => '.disabled { opacity:0.4 !important; }'],
|
||||
['string' => '.grid a.tip { margin:0px 5px; opacity:0.8; }'],
|
||||
['string' => '.grid a.tip:hover { opacity:1; }'],
|
||||
['string' => '.status { position:absolute; right:5px; }'],
|
||||
['string' => '.grid tr { height:30px; }'],
|
||||
['string' => '.grid .disabled { opacity:0.4 !important; }'],
|
||||
['string' => '.grid .status { position:absolute; right:5px; }'],
|
||||
));
|
||||
|
||||
// well .. fuck!
|
||||
ob_start();
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
function createStatusIcon(errTxt)
|
||||
{
|
||||
function fadeout()
|
||||
{
|
||||
$(this).animate({ opacity: '0.0' }, 250, null, function() {
|
||||
$WH.de(this);
|
||||
$WH.Tooltip.hide()
|
||||
});
|
||||
}
|
||||
|
||||
var a = $WH.ce('a');
|
||||
a.style.opacity = 0;
|
||||
a.className = errTxt ? 'icon-report' : 'icon-tick';
|
||||
g_addTooltip(a, errTxt || 'success', 'q');
|
||||
a.onclick = fadeout.bind(a);
|
||||
setTimeout(function () { $(a).animate({ opacity: '1.0' }, 250); }, 50);
|
||||
setTimeout(fadeout.bind(a), 10000);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
function cfg_add(el)
|
||||
{
|
||||
_self = el.parentNode.parentNode;
|
||||
|
||||
var tr = $WH.ce('tr');
|
||||
|
||||
tr.style.position = 'relative';
|
||||
|
||||
var td = $WH.ce('td'),
|
||||
key = $WH.ce('input');
|
||||
|
||||
key.type = 'text';
|
||||
key.name = 'key';
|
||||
$WH.ae(td, key);
|
||||
$WH.ae(tr, td);
|
||||
|
||||
var td = $WH.ce('td'),
|
||||
val = $WH.ce('input');
|
||||
|
||||
val.type = 'text';
|
||||
val.name = 'value';
|
||||
$WH.ae(td, val);
|
||||
$WH.ae(tr, td);
|
||||
|
||||
var td = $WH.ce('td'),
|
||||
aCancel = $WH.ce('a'),
|
||||
aSubmit = $WH.ce('a'),
|
||||
status = $WH.ce('span');
|
||||
|
||||
aSubmit.className = 'icon-save tip';
|
||||
g_addTooltip(aSubmit, 'Submit Setting', 'q');
|
||||
|
||||
aCancel.className = 'icon-delete tip';
|
||||
g_addTooltip(aCancel, 'Cancel', 'q');
|
||||
|
||||
aSubmit.onclick = cfg_new.bind(aSubmit, key, val);
|
||||
aCancel.onclick = function () {
|
||||
$WH.Tooltip.hide();
|
||||
$WH.de(this.parentNode.parentNode);
|
||||
};
|
||||
|
||||
status.className = 'status';
|
||||
|
||||
$WH.ae(td, aSubmit);
|
||||
$WH.ae(td, $WH.ct('|'));
|
||||
$WH.ae(td, aCancel);
|
||||
$WH.ae(td, status);
|
||||
$WH.ae(tr, td);
|
||||
|
||||
_self.parentNode.insertBefore(tr, _self);
|
||||
key.focus();
|
||||
}
|
||||
|
||||
function cfg_new(elKey, elVal)
|
||||
{
|
||||
var
|
||||
_td = this.parentNode,
|
||||
_row = this.parentNode.parentNode,
|
||||
_status = $(_td).find('.status')[0];
|
||||
|
||||
// already performing action
|
||||
if (_status.lastChild && _status.lastChild.tagName == 'IMG')
|
||||
return;
|
||||
else if (_status.lastChild && _status.lastChild.tagName == 'A')
|
||||
$WH.ee(_status);
|
||||
|
||||
if (!elKey.value || !elVal.value)
|
||||
{
|
||||
$WH.ae(_status, createStatusIcon('key or value are empty'));
|
||||
return;
|
||||
}
|
||||
|
||||
var
|
||||
key = elKey.value.toLowerCase().trim(),
|
||||
value = elVal.value.trim();
|
||||
|
||||
$(_status).append(CreateAjaxLoader());
|
||||
|
||||
new Ajax('?admin=siteconfig&action=add&id=' + key + '&val=' + value, {
|
||||
method: 'get',
|
||||
onSuccess: function(xhr) {
|
||||
$WH.ee(_status);
|
||||
|
||||
if (!xhr.responseText) {
|
||||
$WH.ee(_row);
|
||||
$(_row).append($('<td>' + key + '</td>')).append($('<td><input id="' + key + '" type="text" name="' + key + '" value="' + value + '" /></td>'));
|
||||
|
||||
var
|
||||
td = $WH.ce('td'),
|
||||
a = $WH.ce('a'),
|
||||
sp = $WH.ce('span');
|
||||
|
||||
g_addTooltip(a, 'Save Changes', 'q');
|
||||
a.onclick = cfg_submit.bind(a, key);
|
||||
a.className = 'icon-save tip';
|
||||
$WH.ae(td, a);
|
||||
|
||||
a = $WH.ce('a');
|
||||
a.className = 'icon-refresh tip disabled';
|
||||
$WH.ae(td, $WH.ct('|'));
|
||||
$WH.ae(td, a);
|
||||
|
||||
a = $WH.ce('a');
|
||||
g_addTooltip(a, 'Remove Setting', 'q');
|
||||
a.onclick = cfg_remove.bind(a, key);
|
||||
a.className = 'icon-delete tip';
|
||||
$WH.ae(td, $WH.ct('|'));
|
||||
$WH.ae(td, a);
|
||||
|
||||
sp.className = 'status';
|
||||
$WH.ae(sp, createStatusIcon());
|
||||
$WH.ae(td, sp);
|
||||
$WH.ae(_row, td);
|
||||
}
|
||||
else {
|
||||
$WH.ae(_status, createStatusIcon(xhr.responseText));
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function cfg_submit(id)
|
||||
{
|
||||
var
|
||||
node = $WH.ge(id),
|
||||
_td = this.parentNode,
|
||||
_status = $(_td).find('.status')[0];
|
||||
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
var value = 0;
|
||||
|
||||
// already performing action
|
||||
if (_status.lastChild && _status.lastChild.tagName == 'IMG')
|
||||
return;
|
||||
else if (_status.lastChild && _status.lastChild.tagName == 'A')
|
||||
$WH.ee(_status);
|
||||
|
||||
if (node.tagName == 'DIV')
|
||||
{
|
||||
// bitmask
|
||||
$(node).find('input[type="checkbox"]').each(function(idx, opt) {
|
||||
if (opt.checked)
|
||||
value |= (1 << opt.value);
|
||||
});
|
||||
|
||||
// boolean
|
||||
$(node).find('input[type="radio"]').each(function(idx, opt) {
|
||||
if (opt.checked)
|
||||
value = opt.value;
|
||||
});
|
||||
}
|
||||
else if (node.tagName == 'SELECT') // opt-list
|
||||
{
|
||||
$(node).find('option').each(function(idx, opt) {
|
||||
if (opt.selected)
|
||||
value = opt.value;
|
||||
});
|
||||
}
|
||||
else if (node.tagName == 'INPUT') // string or numeric
|
||||
{
|
||||
if (node.value.search(/[^\d\s\/\*\-\+\.]/i) == -1)
|
||||
node.value = eval(node.value);
|
||||
|
||||
value = node.value;
|
||||
}
|
||||
|
||||
value = value.toString().trim();
|
||||
|
||||
if (!value.length)
|
||||
{
|
||||
$WH.ae(_status, createStatusIcon('value is empty'));
|
||||
return;
|
||||
}
|
||||
|
||||
$(_status).append(CreateAjaxLoader());
|
||||
|
||||
new Ajax('?admin=siteconfig&action=update&id=' + id + '&val=' + value, {
|
||||
method: 'get',
|
||||
onSuccess: function(xhr) {
|
||||
$WH.ee(_status);
|
||||
$WH.ae(_status, createStatusIcon(xhr.responseText));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function cfg_default(id, val)
|
||||
{
|
||||
var node = $WH.ge(id);
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
if (node.tagName == 'DIV')
|
||||
{
|
||||
// bitmask
|
||||
$(node).find('input[type="checkbox"]').each(function(idx, opt) { opt.checked = !!(val & (1 << opt.value)); });
|
||||
|
||||
// boolean
|
||||
$(node).find('input[type="radio"]').each(function(idx, opt) { opt.checked = !!opt.value == !!val; });
|
||||
}
|
||||
else if (node.tagName == 'SELECT') // opt-list
|
||||
$(node).find('option').each(function(idx, opt) { opt.selected = opt.value == val; });
|
||||
else if (node.tagName == 'INPUT') // string or numeric
|
||||
node.value = val;
|
||||
}
|
||||
|
||||
function cfg_remove(id)
|
||||
{
|
||||
var
|
||||
_td = this.parentNode,
|
||||
_status = $(_td).find('.status')[0];
|
||||
|
||||
// already performing action
|
||||
if (_status.lastChild && _status.lastChild.tagName == 'IMG')
|
||||
return;
|
||||
else if (_status.lastChild && _status.lastChild.tagName == 'A')
|
||||
$WH.ee(_status);
|
||||
|
||||
if (!confirm('Confirm remove'))
|
||||
return;
|
||||
|
||||
$(_status).append(CreateAjaxLoader());
|
||||
|
||||
new Ajax('?admin=siteconfig&action=remove&id=' + id, {
|
||||
method: 'get',
|
||||
onSuccess: function(xhr) {
|
||||
if (!xhr.responseText)
|
||||
$WH.de(_td.parentNode);
|
||||
else {
|
||||
$WH.ee(_status);
|
||||
$WH.ae(_status, createStatusIcon(xhr.responseText));
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
$this->extraHTML = ob_get_contents();
|
||||
ob_end_clean();
|
||||
// eof (end of fuckup)
|
||||
|
||||
$head = '<table class="grid"><tr><th><b>Key</b></th><th><b>Value</b></th><th style="width:150px;"><b>Options</b></th></tr>';
|
||||
|
||||
// for aowow
|
||||
if ($rows = DB::Aowow()->select('SELECT * FROM ?_config WHERE (flags & ?d) = 0 ORDER BY `key` ASC', CON_FLAG_PHP))
|
||||
$mainTab = [];
|
||||
$miscTab = [];
|
||||
foreach (Util::$configCats as $idx => $catName)
|
||||
{
|
||||
$buff = $head;
|
||||
foreach ($rows as $r)
|
||||
$buff .= $this->configAddRow($r);
|
||||
if ($rows = DB::Aowow()->select('SELECT * FROM ?_config WHERE cat = ?d ORDER BY `flags` DESC, `key` ASC', $idx))
|
||||
{
|
||||
$buff = $head;
|
||||
foreach ($rows as $r)
|
||||
$buff .= $this->configAddRow($r);
|
||||
|
||||
$buff .= '</table>';
|
||||
if (!$idx) //cat: misc
|
||||
$buff .= '<tr><td colspan="3"><a class="icon-add" onclick="cfg_add(this)">new configuration</a></td></tr>';
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => null,
|
||||
'data' => $buff,
|
||||
'params' => array(
|
||||
'name' => 'Aowow',
|
||||
'id' => 'aowow'
|
||||
)
|
||||
);
|
||||
$buff .= '</table>';
|
||||
|
||||
if ($idx)
|
||||
$mainTab[$catName] = $buff;
|
||||
else
|
||||
$miscTab[$catName] = $buff;
|
||||
}
|
||||
}
|
||||
|
||||
// for php
|
||||
$rows = DB::Aowow()->select('SELECT * FROM ?_config WHERE flags & ?d ORDER BY `key` ASC', CON_FLAG_PHP);
|
||||
$buff = $head;
|
||||
foreach ($rows as $r)
|
||||
$buff .= $this->configAddRow($r);
|
||||
foreach ($mainTab as $n => $t)
|
||||
$this->lvTabs[] = [null, array(
|
||||
'data' => $t,
|
||||
'name' => $n,
|
||||
'id' => Profiler::urlize($n)
|
||||
)];
|
||||
|
||||
$buff .= '<tr><td colspan="3"><a class="icon-add" onclick="cfg_add(this)">new configuration</a></td></tr>';
|
||||
$buff .= '</table>';
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => null,
|
||||
'data' => $buff,
|
||||
'params' => array(
|
||||
'name' => 'PHP',
|
||||
'id' => 'php'
|
||||
)
|
||||
);
|
||||
foreach ($miscTab as $n => $t)
|
||||
$this->lvTabs[] = [null, array(
|
||||
'data' => $t,
|
||||
'name' => $n,
|
||||
'id' => Profiler::urlize($n)
|
||||
)];
|
||||
}
|
||||
|
||||
private function handlePhpInfo()
|
||||
@@ -423,26 +161,20 @@ class AdminPage extends GenericPage
|
||||
else
|
||||
$name .= $p[0];
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => null,
|
||||
'data' => $body,
|
||||
'params' => array(
|
||||
'id' => strtolower(strtr($name, [' ' => ''])),
|
||||
'name' => $name
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = [null, array(
|
||||
'data' => $body,
|
||||
'id' => strtolower(strtr($name, [' ' => ''])),
|
||||
'name' => $name
|
||||
)];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->lvTabs[] = array(
|
||||
'file' => null,
|
||||
'data' => $buff,
|
||||
'params' => array(
|
||||
'id' => strtolower($names[$i]),
|
||||
'name' => $names[$i]
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = [null, array(
|
||||
'data' => $buff,
|
||||
'id' => strtolower($names[$i]),
|
||||
'name' => $names[$i]
|
||||
)];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -468,7 +200,7 @@ class AdminPage extends GenericPage
|
||||
else if (!empty($_GET['user']))
|
||||
{
|
||||
$name = urldecode($_GET['user']);
|
||||
if (strlen($name) > 3)
|
||||
if (mb_strlen($name) >= 3)
|
||||
{
|
||||
if ($uId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE displayName = ?', ucFirst($name)))
|
||||
{
|
||||
@@ -486,11 +218,38 @@ class AdminPage extends GenericPage
|
||||
$this->ssNFound = $nMatches; // ssm_numPagesFound
|
||||
}
|
||||
|
||||
private function handleWeightPresets()
|
||||
{
|
||||
$this->addCSS(['string' => '.wt-edit {display:inline-block; vertical-align:top; width:350px;}']);
|
||||
$this->addJS('filters.js');
|
||||
|
||||
$head = $body = '';
|
||||
|
||||
$scales = DB::Aowow()->select('SELECT class AS ARRAY_KEY, id AS ARRAY_KEY2, name, icon FROM ?_account_weightscales WHERE userId = 0');
|
||||
$weights = DB::Aowow()->selectCol('SELECT awd.id AS ARRAY_KEY, awd.field AS ARRAY_KEY2, awd.val FROM ?_account_weightscale_data awd JOIN ?_account_weightscales ad ON awd.id = ad.id WHERE ad.userId = 0');
|
||||
foreach ($scales as $cl => $data)
|
||||
{
|
||||
$ul = '';
|
||||
foreach ($data as $id => $s)
|
||||
{
|
||||
$weights[$id]['__icon'] = $s['icon'];
|
||||
$ul .= '[url=# onclick="loadScale.bind(this, '.$id.')();"]'.$s['name'].'[/url][br]';
|
||||
}
|
||||
|
||||
$head .= '[td=header]'.Lang::game('cl', $cl).'[/td]';
|
||||
$body .= '[td valign=top]'.$ul.'[/td]';
|
||||
}
|
||||
|
||||
$this->extraText = '[table class=grid][tr]'.$head.'[/tr][tr]'.$body.'[/tr][/table]';
|
||||
|
||||
$this->extraHTML = '<script type="text/javascript">var wt_presets = '.Util::toJSON($weights).";</script>\n\n";
|
||||
}
|
||||
|
||||
private function configAddRow($r)
|
||||
{
|
||||
$buff = '<tr>';
|
||||
$info = explode(' - ', $r['comment']);
|
||||
$key = $r['flags'] & CON_FLAG_PHP ? strtolower($r['key']) : 'CFG_'.strtoupper($r['key']);
|
||||
$key = $r['flags'] & CON_FLAG_PHP ? strtolower($r['key']) : strtoupper($r['key']);
|
||||
|
||||
// name
|
||||
if (!empty($info[1]))
|
||||
@@ -522,7 +281,7 @@ class AdminPage extends GenericPage
|
||||
$buff .= '</div></td>';
|
||||
}
|
||||
else
|
||||
$buff .= '<td><input id="'.$key.'" type="text" name="'.$key.'" value="'.$r['value'].'" /></td>';
|
||||
$buff .= '<td><input id="'.$key.'" type="'.($r['flags'] & CON_FLAG_TYPE_STRING ? 'text" placeholder="<empty>' : 'number'.($r['flags'] & CON_FLAG_TYPE_FLOAT ? '" step="any' : '')).'" name="'.$key.'" value="'.$r['value'].'" /></td>';
|
||||
|
||||
// actions
|
||||
$buff .= '<td style="position:relative;">';
|
||||
|
||||
139
pages/arenateam.php
Normal file
139
pages/arenateam.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// menuId 5: Profiler g_initPath()
|
||||
// tabId 1: Tools g_initHeader()
|
||||
class ArenaTeamPage extends GenericPage
|
||||
{
|
||||
use TrProfiler;
|
||||
|
||||
protected $lvTabs = [];
|
||||
|
||||
protected $tabId = 1;
|
||||
protected $path = [1, 5, 3];
|
||||
protected $tpl = 'roster';
|
||||
protected $js = ['profile_all.js', 'profile.js'];
|
||||
protected $css = [['path' => 'Profiler.css']];
|
||||
|
||||
public function __construct($pageCall, $pageParam)
|
||||
{
|
||||
$params = array_map('urldecode', explode('.', $pageParam));
|
||||
if ($params[0])
|
||||
$params[0] = Profiler::urlize($params[0]);
|
||||
if (isset($params[1]))
|
||||
$params[1] = Profiler::urlize($params[1]);
|
||||
|
||||
parent::__construct($pageCall, $pageParam);
|
||||
|
||||
if (count($params) == 1 && intval($params[0]))
|
||||
{
|
||||
$this->subject = new LocalArenaTeamList(array(['at.id', intval($params[0])]));
|
||||
if ($this->subject->error)
|
||||
$this->notFound();
|
||||
|
||||
header('Location: '.$this->subject->getProfileUrl(), true, 302);
|
||||
}
|
||||
else if (count($params) == 3)
|
||||
{
|
||||
$this->getSubjectFromUrl($pageParam);
|
||||
if (!$this->subjectName)
|
||||
$this->notFound();
|
||||
|
||||
// 3 possibilities
|
||||
// 1) already synced to aowow
|
||||
if ($subject = DB::Aowow()->selectRow('SELECT id, realmGUID, cuFlags FROM ?_profiler_arena_team WHERE realm = ?d AND nameUrl = ?', $this->realmId, Profiler::urlize($this->subjectName)))
|
||||
{
|
||||
if ($subject['cuFlags'] & PROFILER_CU_NEEDS_RESYNC)
|
||||
{
|
||||
$this->handleIncompleteData($subject['realmGUID']);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->subjectGUID = $subject['id'];
|
||||
$this->subject = new LocalArenaTeamList(array(['id', $subject['id']]));
|
||||
if ($this->subject->error)
|
||||
$this->notFound();
|
||||
|
||||
$this->profile = $params;
|
||||
$this->name = sprintf(Lang::profiler('arenaRoster'), $this->subject->getField('name'));
|
||||
}
|
||||
// 2) not yet synced but exists on realm (wont work if we get passed an urlized name, but there is nothing we can do about it)
|
||||
else if ($team = DB::Characters($this->realmId)->selectRow('SELECT at.arenaTeamId AS realmGUID, at.name, at.type FROM arena_team at WHERE at.name = ?', Util::ucFirst($this->subjectName)))
|
||||
{
|
||||
$team['realm'] = $this->realmId;
|
||||
$team['cuFlags'] = PROFILER_CU_NEEDS_RESYNC;
|
||||
|
||||
// create entry from realm with basic info
|
||||
DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_arena_team (?#) VALUES (?a)', array_keys($team), array_values($team));
|
||||
|
||||
$this->handleIncompleteData($team['realmGUID']);
|
||||
}
|
||||
// 3) does not exist at all
|
||||
else
|
||||
$this->notFound();
|
||||
}
|
||||
else
|
||||
$this->notFound();
|
||||
}
|
||||
|
||||
protected function generateTitle()
|
||||
{
|
||||
$team = !empty($this->subject) ? $this->subject->getField('name') : $this->subjectName;
|
||||
$team .= ' ('.$this->realm.' - '.Lang::profiler('regions', $this->region).')';
|
||||
|
||||
array_unshift($this->title, $team, Util::ucFirst(Lang::profiler('profiler')));
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
if ($this->doResync)
|
||||
return;
|
||||
|
||||
$this->addJS('?data=realms.weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
||||
|
||||
$this->redButtons[BUTTON_RESYNC] = [$this->subjectGUID, 'arena-team'];
|
||||
|
||||
/****************/
|
||||
/* Main Content */
|
||||
/****************/
|
||||
|
||||
|
||||
// statistic calculations here
|
||||
|
||||
|
||||
/**************/
|
||||
/* Extra Tabs */
|
||||
/**************/
|
||||
|
||||
// tab: members
|
||||
$member = new LocalProfileList(array(['atm.arenaTeamId', $this->subjectGUID]));
|
||||
if (!$member->error)
|
||||
{
|
||||
$this->lvTabs[] = ['profile', array(
|
||||
'data' => array_values($member->getListviewData(PROFILEINFO_CHARACTER | PROFILEINFO_ARENA)),
|
||||
'sort' => [-15],
|
||||
'visibleCols' => ['race', 'classs', 'level', 'talents', 'gearscore', 'rating', 'wins', 'losses'],
|
||||
'hiddenCols' => ['guild', 'location']
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
public function notFound($title = '', $msg = '')
|
||||
{
|
||||
return parent::notFound($title ?: Util::ucFirst(Lang::profiler('profiler')), $msg ?: Lang::profiler('notFound', 'arenateam'));
|
||||
}
|
||||
|
||||
private function handleIncompleteData($teamGuid)
|
||||
{
|
||||
//display empty page and queue status
|
||||
$newId = Profiler::scheduleResync(TYPE_ARENA_TEAM, $this->realmId, $teamGuid);
|
||||
|
||||
$this->doResync = ['arena-team', $newId];
|
||||
$this->initialSync();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
116
pages/arenateams.php
Normal file
116
pages/arenateams.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// menuId 5: Profiler g_initPath()
|
||||
// tabId 1: Tools g_initHeader()
|
||||
class ArenaTeamsPage extends GenericPage
|
||||
{
|
||||
use TrProfiler;
|
||||
|
||||
protected $tabId = 1;
|
||||
protected $path = [1, 5, 3];
|
||||
protected $tpl = 'arena-teams';
|
||||
protected $js = ['filters.js', 'profile_all.js', 'profile.js'];
|
||||
|
||||
public function __construct($pageCall, $pageParam)
|
||||
{
|
||||
$this->getSubjectFromUrl($pageParam);
|
||||
|
||||
$this->filterObj = new ArenaTeamListFilter();
|
||||
|
||||
foreach (Profiler::getRealms() as $idx => $r)
|
||||
{
|
||||
if ($this->region && $r['region'] != $this->region)
|
||||
continue;
|
||||
|
||||
if ($this->realm && $r['name'] != $this->realm)
|
||||
continue;
|
||||
|
||||
$this->sumSubjects += DB::Characters($idx)->selectCell('SELECT count(*) FROM arena_team');
|
||||
}
|
||||
|
||||
parent::__construct($pageCall, $pageParam);
|
||||
|
||||
$this->name = Lang::profiler('arenaTeams');
|
||||
$this->subCat = $pageParam ? '='.$pageParam : '';
|
||||
}
|
||||
|
||||
protected function generateTitle()
|
||||
{
|
||||
if ($this->realm)
|
||||
array_unshift($this->title, $this->realm,/* CFG_BATTLEGROUP,*/ Lang::profiler('regions', $this->region), Lang::profiler('arenaTeams'));
|
||||
else if ($this->region)
|
||||
array_unshift($this->title, Lang::profiler('regions', $this->region), Lang::profiler('arenaTeams'));
|
||||
else
|
||||
array_unshift($this->title, Lang::profiler('arenaTeams'));
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
$this->addJS('?data=realms&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
||||
|
||||
$conditions = [];
|
||||
if (!User::isInGroup(U_GROUP_EMPLOYEE))
|
||||
$conditions[] = ['at.rating', 1000, '>'];
|
||||
|
||||
if ($_ = $this->filterObj->getConditions())
|
||||
$conditions[] = $_;
|
||||
|
||||
// recreate form selection
|
||||
$this->filter = $this->filterObj->getForm();
|
||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
|
||||
$this->filter['initData'] = ['type' => 'arenateams'];
|
||||
|
||||
$tabData = array(
|
||||
'id' => 'arena-teams',
|
||||
'hideCount' => 1,
|
||||
'sort' => [-16],
|
||||
'extraCols' => ['$Listview.extraCols.members'],
|
||||
'visibleCols' => ['rank', 'wins', 'losses', 'rating'],
|
||||
'hiddenCols' => ['arenateam', 'guild'],
|
||||
);
|
||||
|
||||
if (empty($this->filter['sz']))
|
||||
$tabData['visibleCols'][] = 'size';
|
||||
|
||||
$miscParams = [];
|
||||
if ($this->realm)
|
||||
$miscParams['sv'] = $this->realm;
|
||||
if ($this->region)
|
||||
$miscParams['rg'] = $this->region;
|
||||
|
||||
$teams = new RemoteArenaTeamList($conditions, $miscParams);
|
||||
if (!$teams->error)
|
||||
{
|
||||
$teams->initializeLocalEntries();
|
||||
|
||||
$dFields = $teams->hasDiffFields(['faction', 'type']);
|
||||
if (!($dFields & 0x1))
|
||||
$tabData['hiddenCols'][] = 'faction';
|
||||
|
||||
$tabData['data'] = array_values($teams->getListviewData());
|
||||
|
||||
// create note if search limit was exceeded
|
||||
if ($this->filter['query'] && $teams->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
{
|
||||
$tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_arenateamsfound2', $this->sumSubjects, $teams->getMatches());
|
||||
$tabData['_truncated'] = 1;
|
||||
}
|
||||
else if ($teams->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
$tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_arenateamsfound', $this->sumSubjects, 0);
|
||||
|
||||
if ($this->filterObj->error)
|
||||
$tabData['_errors'] = 1;
|
||||
}
|
||||
|
||||
$this->lvTabs[] = ['profile', $tabData, 'membersCol'];
|
||||
|
||||
Lang::sort('game', 'cl');
|
||||
Lang::sort('game', 'ra');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
107
pages/class.php
107
pages/class.php
@@ -96,7 +96,7 @@ class ClassPage extends GenericPage
|
||||
$this->expansion = Util::$expansionString[$this->subject->getField('expansion')];
|
||||
$this->headIcons = ['class_'.strtolower($this->subject->getField('fileString'))];
|
||||
$this->redButtons = array(
|
||||
BUTTON_LINKS => ['color' => '', 'linkId' => ''],
|
||||
BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId],
|
||||
BUTTON_WOWHEAD => true,
|
||||
BUTTON_TALENT => ['href' => '?talent#'.Util::$tcEncoding[$tcClassId[$this->typeId] * 3], 'pet' => false],
|
||||
BUTTON_FORUM => false // todo (low): CFG_BOARD_URL + X
|
||||
@@ -126,27 +126,25 @@ class ClassPage extends GenericPage
|
||||
'OR',
|
||||
['s.cuFlags', SPELL_CU_LAST_RANK, '&'],
|
||||
['s.rankNo', 0]
|
||||
]
|
||||
],
|
||||
CFG_SQL_LIMIT_NONE
|
||||
);
|
||||
|
||||
$genSpells = new SpellList($conditions);
|
||||
if (!$genSpells->error)
|
||||
{
|
||||
$this->extendGlobalData($genSpells->getJSGlobals(GLOBALINFO_SELF));
|
||||
$this->extendGlobalData($genSpells->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'spell',
|
||||
'data' => $genSpells->getListviewData(),
|
||||
'params' => array(
|
||||
'id' => 'spells',
|
||||
'name' => '$LANG.tab_spells',
|
||||
'visibleCols' => "$['level', 'schools', 'type', 'classes']",
|
||||
'hiddenCols' => "$['reagents', 'skill']",
|
||||
'sort' => "$['-level', 'type', 'name']",
|
||||
'computeDataFunc' => '$Listview.funcBox.initSpellFilter',
|
||||
'onAfterCreate' => '$Listview.funcBox.addSpellIndicator'
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['spell', array(
|
||||
'data' => array_values($genSpells->getListviewData()),
|
||||
'id' => 'spells',
|
||||
'name' => '$LANG.tab_spells',
|
||||
'visibleCols' => ['level', 'schools', 'type', 'classes'],
|
||||
'hiddenCols' => ['reagents', 'skill'],
|
||||
'sort' => ['-level', 'type', 'name'],
|
||||
'computeDataFunc' => '$Listview.funcBox.initSpellFilter',
|
||||
'onAfterCreate' => '$Listview.funcBox.addSpellIndicator'
|
||||
)];
|
||||
}
|
||||
|
||||
// Tab: Items (grouped)
|
||||
@@ -155,7 +153,7 @@ class ClassPage extends GenericPage
|
||||
['requiredClass', $_mask, '&'],
|
||||
[['requiredClass', CLASS_MASK_ALL, '&'], CLASS_MASK_ALL, '!'],
|
||||
['itemset', 0], // hmm, do or dont..?
|
||||
0
|
||||
CFG_SQL_LIMIT_NONE
|
||||
);
|
||||
|
||||
$items = new ItemList($conditions);
|
||||
@@ -163,23 +161,21 @@ class ClassPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($items->getJSGlobals());
|
||||
|
||||
if (!$items->hasDiffFields(['requiredRace']))
|
||||
$hidden = "$['side']";
|
||||
$hiddenCols = null;
|
||||
if ($items->hasDiffFields(['requiredRace']))
|
||||
$hiddenCols = ['side'];
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'item',
|
||||
'data' => $items->getListviewData(),
|
||||
'params' => array(
|
||||
'id' => 'items',
|
||||
'name' => '$LANG.tab_items',
|
||||
'visibleCols' => "$['dps', 'armor', 'slot']",
|
||||
'hiddenCols' => isset($hidden) ? $hidden : null,
|
||||
'computeDataFunc' => '$Listview.funcBox.initSubclassFilter',
|
||||
'onAfterCreate' => '$Listview.funcBox.addSubclassIndicator',
|
||||
'note' => sprintf(Util::$filterResultString, '?items&filter=cr=152;crs='.$this->typeId.';crv=0'),
|
||||
'_truncated' => 1
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['item', array(
|
||||
'data' => array_values($items->getListviewData()),
|
||||
'id' => 'items',
|
||||
'name' => '$LANG.tab_items',
|
||||
'visibleCols' => ['dps', 'armor', 'slot'],
|
||||
'hiddenCols' => $hiddenCols,
|
||||
'computeDataFunc' => '$Listview.funcBox.initSubclassFilter',
|
||||
'onAfterCreate' => '$Listview.funcBox.addSubclassIndicator',
|
||||
'note' => sprintf(Util::$filterResultString, '?items&filter=cr=152;crs='.$this->typeId.';crv=0'),
|
||||
'_truncated' => 1
|
||||
)];
|
||||
}
|
||||
|
||||
// Tab: Quests
|
||||
@@ -193,11 +189,10 @@ class ClassPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($quests->getJSGlobals());
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'quest',
|
||||
'data' => $quests->getListviewData(),
|
||||
'params' => ['sort' => "$['reqlevel', 'name']"]
|
||||
);
|
||||
$this->lvTabs[] = ['quest', array(
|
||||
'data' => array_values($quests->getListviewData()),
|
||||
'sort' => ['reqlevel', 'name']
|
||||
)];
|
||||
}
|
||||
|
||||
// Tab: Itemsets
|
||||
@@ -206,15 +201,12 @@ class ClassPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($sets->getJSGlobals(GLOBALINFO_SELF));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'itemset',
|
||||
'data' => $sets->getListviewData(),
|
||||
'params' => array(
|
||||
'note' => sprintf(Util::$filterResultString, '?itemsets&filter=cl='.$this->typeId),
|
||||
'hiddenCols' => "$['classes']",
|
||||
'sort' => "$['-level', 'name']"
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['itemset', array(
|
||||
'data' => array_values($sets->getListviewData()),
|
||||
'note' => sprintf(Util::$filterResultString, '?itemsets&filter=cl='.$this->typeId),
|
||||
'hiddenCols' => ['classes'],
|
||||
'sort' => ['-level', 'name']
|
||||
)];
|
||||
}
|
||||
|
||||
// Tab: Trainer
|
||||
@@ -227,26 +219,17 @@ class ClassPage extends GenericPage
|
||||
$trainer = new CreatureList($conditions);
|
||||
if (!$trainer->error)
|
||||
{
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'creature',
|
||||
'data' => $trainer->getListviewData(),
|
||||
'params' => array(
|
||||
'id' => 'trainers',
|
||||
'name' => '$LANG.tab_trainers'
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['creature', array(
|
||||
'data' => array_values($trainer->getListviewData()),
|
||||
'id' => 'trainers',
|
||||
'name' => '$LANG.tab_trainers'
|
||||
)];
|
||||
}
|
||||
|
||||
// Tab: Races
|
||||
$races = new CharRaceList(array(['classMask', $_mask, '&']));
|
||||
if (!$races->error)
|
||||
{
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'race',
|
||||
'data' => $races->getListviewData(),
|
||||
'params' => []
|
||||
);
|
||||
}
|
||||
$this->lvTabs[] = ['race', ['data' => array_values($races->getListviewData())]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,13 +27,7 @@ class ClassesPage extends GenericPage
|
||||
{
|
||||
$classes = new CharClassList();
|
||||
if (!$classes->error)
|
||||
{
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'class',
|
||||
'data' => $classes->getListviewData(),
|
||||
'params' => []
|
||||
);
|
||||
}
|
||||
$this->lvTabs[] = ['class', ['data' => array_values($classes->getListviewData())]];
|
||||
}
|
||||
|
||||
protected function generateTitle()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('invalid access');
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// tabId 1: Tools g_initHeader()
|
||||
@@ -43,6 +43,12 @@ class ComparePage extends GenericPage
|
||||
// add conditional js
|
||||
$this->addJS('?data=weight-presets.gems.enchants.itemsets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
||||
|
||||
$this->summary = array(
|
||||
'template' => 'compare',
|
||||
'id' => 'compare',
|
||||
'parent' => 'compare-generic'
|
||||
);
|
||||
|
||||
if (!$this->compareString)
|
||||
return;
|
||||
|
||||
@@ -64,7 +70,8 @@ class ComparePage extends GenericPage
|
||||
|
||||
$outSet[] = $outString;
|
||||
}
|
||||
$this->summary = $outSet;
|
||||
|
||||
$this->summary['groups'] = $outSet;
|
||||
|
||||
$iList = new ItemList(array(['i.id', $items]));
|
||||
$data = $iList->getListviewData(ITEMINFO_SUBITEMS | ITEMINFO_JSON);
|
||||
@@ -74,12 +81,15 @@ class ComparePage extends GenericPage
|
||||
if (empty($data[$itemId]))
|
||||
continue;
|
||||
|
||||
$this->cmpItems[] = [
|
||||
$itemId,
|
||||
$iList->getField('name', true),
|
||||
$iList->getField('quality'),
|
||||
$iList->getField('iconString'),
|
||||
$data[$itemId]
|
||||
if (!empty($data[$itemId]['subitems']))
|
||||
foreach ($data[$itemId]['subitems'] as &$si)
|
||||
$si['enchantment'] = implode(', ', $si['enchantment']);
|
||||
|
||||
$this->cmpItems[$itemId] = [
|
||||
'name_'.User::$localeString => $iList->getField('name', true),
|
||||
'quality' => $iList->getField('quality'),
|
||||
'icon' => $iList->getField('iconString'),
|
||||
'jsonequip' => $data[$itemId]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,11 +37,7 @@ class CurrenciesPage extends GenericPage
|
||||
$conditions[] = ['category', (int)$this->category[0]];
|
||||
|
||||
$money = new CurrencyList($conditions);
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'currency',
|
||||
'data' => $money->getListviewData(),
|
||||
'params' => []
|
||||
);
|
||||
$this->lvTabs[] = ['currency', ['data' => array_values($money->getListviewData())]];
|
||||
}
|
||||
|
||||
protected function generateTitle()
|
||||
|
||||
@@ -21,11 +21,15 @@ class CurrencyPage extends GenericPage
|
||||
{
|
||||
parent::__construct($pageCall, $id);
|
||||
|
||||
// temp locale
|
||||
if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain']))
|
||||
Util::powerUseLocale($_GET['domain']);
|
||||
|
||||
$this->typeId = intVal($id);
|
||||
|
||||
$this->subject = new CurrencyList(array(['id', $this->typeId]));
|
||||
if ($this->subject->error)
|
||||
$this->notFound(Lang::game('currency'), Lang::currency('notFound'));
|
||||
$this->notFound();
|
||||
|
||||
$this->name = $this->subject->getField('name', true);
|
||||
}
|
||||
@@ -50,12 +54,10 @@ class CurrencyPage extends GenericPage
|
||||
/* Infobox */
|
||||
/**********/
|
||||
|
||||
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
|
||||
$infobox = Lang::getInfoBoxForFlags(intval($this->subject->getField('cuFlags')));
|
||||
|
||||
if ($this->typeId == 103) // Arena Points
|
||||
$infobox[] = Lang::currency('cap').Lang::main('colon').'10\'000';
|
||||
else if ($this->typeId == 104) // Honor
|
||||
$infobox[] = Lang::currency('cap').Lang::main('colon').'75\'000';
|
||||
if ($_ = $this->subject->getField('cap'))
|
||||
$infobox[] = Lang::currency('cap').Lang::main('colon').Lang::nf($_);
|
||||
|
||||
/****************/
|
||||
/* Main Content */
|
||||
@@ -69,6 +71,9 @@ class CurrencyPage extends GenericPage
|
||||
BUTTON_LINKS => true
|
||||
);
|
||||
|
||||
if ($_ = $this->subject->getField('description', true))
|
||||
$this->extraText = $_;
|
||||
|
||||
/**************/
|
||||
/* Extra Tabs */
|
||||
/**************/
|
||||
@@ -82,20 +87,8 @@ class CurrencyPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($lootTabs->jsGlobals);
|
||||
|
||||
foreach ($lootTabs->iterate() as $tab)
|
||||
{
|
||||
$this->lvTabs[] = array(
|
||||
'file' => $tab[0],
|
||||
'data' => $tab[1],
|
||||
'params' => [
|
||||
'name' => $tab[2],
|
||||
'id' => $tab[3],
|
||||
'extraCols' => $tab[4] ? '$['.implode(', ', array_unique($tab[4])).']' : null,
|
||||
'hiddenCols' => $tab[5] ? '$['.implode(', ', array_unique($tab[5])).']' : null,
|
||||
'visibleCols' => $tab[6] ? '$'. Util::toJSON( array_unique($tab[6])) : null
|
||||
]
|
||||
);
|
||||
}
|
||||
foreach ($lootTabs->iterate() as list($file, $tabData))
|
||||
$this->lvTabs[] = [$file, $tabData];
|
||||
}
|
||||
|
||||
// tab: sold by
|
||||
@@ -109,7 +102,7 @@ class CurrencyPage extends GenericPage
|
||||
if (!$soldBy->error)
|
||||
{
|
||||
$sbData = $soldBy->getListviewData();
|
||||
$extraCols = ['Listview.extraCols.stock', "Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", 'Listview.extraCols.cost'];
|
||||
$extraCols = ['$Listview.extraCols.stock', "\$Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", '$Listview.extraCols.cost'];
|
||||
$holidays = [];
|
||||
|
||||
foreach ($sbData as $k => &$row)
|
||||
@@ -130,7 +123,7 @@ class CurrencyPage extends GenericPage
|
||||
if ($vendors[$k]['event'])
|
||||
{
|
||||
if (count($extraCols) == 3) // not already pushed
|
||||
$extraCols[] = 'Listview.extraCols.condition';
|
||||
$extraCols[] = '$Listview.extraCols.condition';
|
||||
|
||||
$this->extendGlobalIds(TYPE_WORLDEVENT, $vendors[$k]['event']);
|
||||
$row['condition'][0][$this->typeId][] = [[CND_ACTIVE_EVENT, $vendors[$k]['event']]];
|
||||
@@ -145,16 +138,13 @@ class CurrencyPage extends GenericPage
|
||||
);
|
||||
}
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'creature',
|
||||
'data' => $sbData,
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_soldby',
|
||||
'id' => 'sold-by-npc',
|
||||
'extraCols' => '$['.implode(', ', $extraCols).']',
|
||||
'hiddenCols' => "$['level', 'type']"
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['creature', array(
|
||||
'data' => array_values($sbData),
|
||||
'name' => '$LANG.tab_soldby',
|
||||
'id' => 'sold-by-npc',
|
||||
'extraCols' => $extraCols,
|
||||
'hiddenCols' => ['level', 'type']
|
||||
)];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,18 +157,16 @@ class CurrencyPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($createdBy->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
|
||||
|
||||
if ($createdBy->hasSetFields(['reagent1']))
|
||||
$visCols = ['reagents'];
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'spell',
|
||||
'data' => $createdBy->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_createdby',
|
||||
'id' => 'created-by',
|
||||
'visibleCols' => isset($visCols) ? '$'.Util::toJSON($visCols) : null
|
||||
]
|
||||
$tabData = array(
|
||||
'data' => array_values($createdBy->getListviewData()),
|
||||
'name' => '$LANG.tab_createdby',
|
||||
'id' => 'created-by',
|
||||
);
|
||||
|
||||
if ($createdBy->hasSetFields(['reagent1']))
|
||||
$tabData['visibleCols'] = ['reagents'];
|
||||
|
||||
$this->lvTabs[] = ['spell', $tabData];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,24 +194,61 @@ class CurrencyPage extends GenericPage
|
||||
$boughtBy = new ItemList(array(['id', $boughtBy]));
|
||||
if (!$boughtBy->error)
|
||||
{
|
||||
if ($boughtBy->getMatches() <= CFG_SQL_LIMIT_DEFAULT)
|
||||
$n = null;
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'item',
|
||||
'data' => $boughtBy->getListviewData(ITEMINFO_VENDOR, [TYPE_CURRENCY => $this->typeId]),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_currencyfor',
|
||||
'id' => 'currency-for',
|
||||
'extraCols' => "$[Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')]",
|
||||
'note' => $n ? sprintf(Util::$filterResultString, $n) : null
|
||||
]
|
||||
$tabData = array(
|
||||
'data' => array_values($boughtBy->getListviewData(ITEMINFO_VENDOR, [TYPE_CURRENCY => $this->typeId])),
|
||||
'name' => '$LANG.tab_currencyfor',
|
||||
'id' => 'currency-for',
|
||||
'extraCols' => ["\$Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')"],
|
||||
);
|
||||
|
||||
if ($boughtBy->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
$tabData['note'] = sprintf(Util::$filterResultString, $n);
|
||||
|
||||
$this->lvTabs[] = ['item', $tabData];
|
||||
|
||||
$this->extendGlobalData($boughtBy->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function generateTooltip($asError = false)
|
||||
{
|
||||
if ($asError)
|
||||
return '$WowheadPower.registerCurrency('.$this->typeId.', '.User::$localeId.', {});';
|
||||
|
||||
$x = '$WowheadPower.registerCurrency('.$this->typeId.', '.User::$localeId.", {\n";
|
||||
$x .= "\tname_".User::$localeString.": '".Util::jsEscape($this->subject->getField('name', true))."',\n";
|
||||
$x .= "\ticon: '".rawurlencode($this->subject->getField('iconString', true, true))."',\n";
|
||||
$x .= "\ttooltip_".User::$localeString.": '".$this->subject->renderTooltip()."'\n";
|
||||
$x .= "});";
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
public function display($override = '')
|
||||
{
|
||||
if ($this->mode != CACHE_TYPE_TOOLTIP)
|
||||
return parent::display($override);
|
||||
|
||||
if (!$this->loadCache($tt))
|
||||
{
|
||||
$tt = $this->generateTooltip();
|
||||
$this->saveCache($tt);
|
||||
}
|
||||
|
||||
header('Content-type: application/x-javascript; charset=utf-8');
|
||||
die($tt);
|
||||
}
|
||||
|
||||
public function notFound($title = '', $msg = '')
|
||||
{
|
||||
if ($this->mode != CACHE_TYPE_TOOLTIP)
|
||||
return parent::notFound($title ?: Lang::game('currency'), $msg ?: Lang::currency('notFound'));
|
||||
|
||||
header('Content-type: application/x-javascript; charset=utf-8');
|
||||
echo $this->generateTooltip(true);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
128
pages/emote.php
Normal file
128
pages/emote.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// menuId 100: Emotes g_initPath()
|
||||
// tabid 0: Database g_initHeader()
|
||||
class EmotePage extends GenericPage
|
||||
{
|
||||
use DetailPage;
|
||||
|
||||
protected $type = TYPE_EMOTE;
|
||||
protected $typeId = 0;
|
||||
protected $tpl = 'detail-page-generic';
|
||||
protected $path = [0, 100];
|
||||
protected $tabId = 0;
|
||||
protected $mode = CACHE_TYPE_PAGE;
|
||||
|
||||
public function __construct($pageCall, $id)
|
||||
{
|
||||
parent::__construct($pageCall, $id);
|
||||
|
||||
$this->typeId = intVal($id);
|
||||
|
||||
$this->subject = new EmoteList(array(['id', $this->typeId]));
|
||||
if ($this->subject->error)
|
||||
$this->notFound(Util::ucFirst(Lang::game('emote')), Lang::emote('notFound'));
|
||||
|
||||
$this->name = Util::ucFirst($this->subject->getField('cmd'));
|
||||
}
|
||||
|
||||
protected function generatePath() { }
|
||||
|
||||
protected function generateTitle()
|
||||
{
|
||||
array_unshift($this->title, $this->name, Util::ucFirst(Lang::game('emote')));
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
/***********/
|
||||
/* Infobox */
|
||||
/***********/
|
||||
|
||||
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
|
||||
|
||||
// has Animation
|
||||
if ($this->subject->getField('isAnimated'))
|
||||
$infobox[] = Lang::emote('isAnimated');
|
||||
|
||||
/****************/
|
||||
/* Main Content */
|
||||
/****************/
|
||||
|
||||
$text = '';
|
||||
if ($aliasses = DB::Aowow()->selectCol('SELECT command FROM ?_emotes_aliasses WHERE id = ?d AND locales & ?d', $this->typeId, 1 << User::$localeId))
|
||||
{
|
||||
$text .= '[h3]'.Lang::emote('aliases').'[/h3][ul]';
|
||||
foreach ($aliasses as $a)
|
||||
$text .= '[li]/'.$a.'[/li]';
|
||||
|
||||
$text .= '[/ul][br][br]';
|
||||
}
|
||||
|
||||
$texts = [];
|
||||
if ($_ = $this->subject->getField('self', true))
|
||||
$texts[Lang::emote('self')] = $_;
|
||||
|
||||
if ($_ = $this->subject->getField('target', true))
|
||||
$texts[Lang::emote('target')] = $_;
|
||||
|
||||
if ($_ = $this->subject->getField('noTarget', true))
|
||||
$texts[Lang::emote('noTarget')] = $_;
|
||||
|
||||
if (!$texts)
|
||||
$text .= '[div][i class=q0]'.Lang::emote('noText').'[/i][/div]';
|
||||
else
|
||||
foreach ($texts as $h => $t)
|
||||
$text .= '[pad][b]'.$h.'[/b][ul][li][span class=s4]'.preg_replace('/%\d?\$?s/', '<'.Util::ucFirst(Lang::main('name')).'>', $t).'[/span][/li][/ul]';
|
||||
|
||||
$this->extraText = $text;
|
||||
$this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
|
||||
$this->redButtons = array(
|
||||
BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId],
|
||||
BUTTON_WOWHEAD => false
|
||||
);
|
||||
|
||||
/**************/
|
||||
/* Extra Tabs */
|
||||
/**************/
|
||||
|
||||
// tab: achievement
|
||||
$condition = array(
|
||||
['ac.type', ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE],
|
||||
['ac.value1', $this->typeId],
|
||||
);
|
||||
$acv = new AchievementList($condition);
|
||||
|
||||
$this->lvTabs[] = ['achievement', ['data' => array_values($acv->getListviewData())]];
|
||||
|
||||
$this->extendGlobalData($acv->getJsGlobals());
|
||||
|
||||
// tab: sound
|
||||
if ($em = DB::Aowow()->select('SELECT soundId AS ARRAY_KEY, BIT_OR(1 << (raceId - 1)) AS raceMask, BIT_OR(1 << (gender - 1)) AS gender FROM aowow_emotes_sounds WHERE emoteId = ?d GROUP BY soundId', $this->typeId))
|
||||
{
|
||||
$sounds = new SoundList(array(['id', array_keys($em)]));
|
||||
if (!$sounds->error)
|
||||
{
|
||||
$this->extendGlobalData($sounds->getJSGlobals(GLOBALINFO_SELF));
|
||||
$data = $sounds->getListviewData();
|
||||
foreach($data as $id => &$d)
|
||||
{
|
||||
$d['races'] = $em[$id]['raceMask'];
|
||||
$d['gender'] = $em[$id]['gender'];
|
||||
}
|
||||
|
||||
$this->lvTabs[] = ['sound', array(
|
||||
'data' => array_values($data),
|
||||
// gender races
|
||||
'extraCols' => ['$Listview.templates.title.columns[1]', '$Listview.templates.classs.columns[1]']
|
||||
)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
44
pages/emotes.php
Normal file
44
pages/emotes.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// menuId 100: Emotes g_initPath()
|
||||
// tabid 0: Database g_initHeader()
|
||||
class EmotesPage extends GenericPage
|
||||
{
|
||||
use ListPage;
|
||||
|
||||
protected $type = TYPE_EMOTE;
|
||||
protected $tpl = 'list-page-generic';
|
||||
protected $path = [0, 100];
|
||||
protected $tabId = 0;
|
||||
protected $mode = CACHE_TYPE_PAGE;
|
||||
|
||||
public function __construct($pageCall, $pageParam)
|
||||
{
|
||||
parent::__construct($pageCall, $pageParam);
|
||||
|
||||
$this->name = Util::ucFirst(Lang::game('emotes'));
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
$tabData = array(
|
||||
'data' => array_values((new EmoteList())->getListviewData()),
|
||||
'name' => Util::ucFirst(Lang::game('emotes'))
|
||||
);
|
||||
|
||||
$this->lvTabs[] = ['emote', $tabData, 'emote'];
|
||||
}
|
||||
|
||||
protected function generateTitle()
|
||||
{
|
||||
array_unshift($this->title, $this->name);
|
||||
}
|
||||
|
||||
protected function generatePath() { }
|
||||
}
|
||||
|
||||
?>
|
||||
324
pages/enchantment.php
Normal file
324
pages/enchantment.php
Normal file
@@ -0,0 +1,324 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// menuId 101: Enchantment g_initPath()
|
||||
// tabId 0: Database g_initHeader()
|
||||
class EnchantmentPage extends GenericPage
|
||||
{
|
||||
use DetailPage;
|
||||
|
||||
protected $type = TYPE_ENCHANTMENT;
|
||||
protected $typeId = 0;
|
||||
protected $tpl = 'enchantment';
|
||||
protected $path = [0, 101];
|
||||
protected $tabId = 0;
|
||||
protected $mode = CACHE_TYPE_PAGE;
|
||||
|
||||
public function __construct($pageCall, $id)
|
||||
{
|
||||
parent::__construct($pageCall, $id);
|
||||
|
||||
$this->typeId = intVal($id);
|
||||
|
||||
$this->subject = new EnchantmentList(array(['id', $this->typeId]));
|
||||
if ($this->subject->error)
|
||||
$this->notFound(Util::ucFirst(Lang::game('enchantment')), Lang::enchantment('notFound'));
|
||||
|
||||
$this->extendGlobalData($this->subject->getJSGlobals());
|
||||
|
||||
$this->name = Util::ucFirst($this->subject->getField('name', true));
|
||||
}
|
||||
|
||||
private function getDistinctType()
|
||||
{
|
||||
$type = 0;
|
||||
for ($i = 1; $i < 4; $i++)
|
||||
{
|
||||
if ($_ = $this->subject->getField('type'.$i))
|
||||
{
|
||||
if ($type) // already set
|
||||
return 0;
|
||||
else
|
||||
$type = $_;
|
||||
}
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
/***********/
|
||||
/* Infobox */
|
||||
/***********/
|
||||
|
||||
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
|
||||
|
||||
// reqLevel
|
||||
if ($_ = $this->subject->getField('requiredLevel'))
|
||||
$infobox[] = sprintf(Lang::game('reqLevel'), $_);
|
||||
|
||||
// reqskill
|
||||
if ($_ = $this->subject->getField('skillLine'))
|
||||
{
|
||||
$this->extendGlobalIds(TYPE_SKILL, $_);
|
||||
|
||||
$foo = sprintf(Lang::game('requires'), ' [skill='.$_.']');
|
||||
if ($_ = $this->subject->getField('skillLevel'))
|
||||
$foo .= ' ('.$_.')';
|
||||
|
||||
$infobox[] = $foo;
|
||||
}
|
||||
|
||||
|
||||
/****************/
|
||||
/* Main Content */
|
||||
/****************/
|
||||
|
||||
|
||||
$this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
|
||||
$this->redButtons = array(
|
||||
BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId],
|
||||
BUTTON_WOWHEAD => false
|
||||
);
|
||||
|
||||
$this->effects = [];
|
||||
// 3 effects
|
||||
for ($i = 1; $i < 4; $i++)
|
||||
{
|
||||
$_ty = $this->subject->getField('type'.$i);
|
||||
$_qty = $this->subject->getField('amount'.$i);
|
||||
$_obj = $this->subject->getField('object'.$i);
|
||||
|
||||
switch ($_ty)
|
||||
{
|
||||
case 1:
|
||||
case 3:
|
||||
case 7:
|
||||
$sArr = $this->subject->getField('spells')[$i];
|
||||
$spl = $this->subject->getRelSpell($sArr[0]);
|
||||
$this->effects[$i]['name'] = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, 'Type: '.$_ty, Lang::item('trigger', $sArr[1])) : Lang::item('trigger', $sArr[1]);
|
||||
$this->effects[$i]['proc'] = $sArr[3];
|
||||
$this->effects[$i]['value'] = $_qty ?: null;
|
||||
$this->effects[$i]['icon'] = array(
|
||||
'name' => !$spl ? Util::ucFirst(Lang::game('spell')).' #'.$sArr[0] : Util::localizedString($spl, 'name'),
|
||||
'id' => $sArr[0],
|
||||
'count' => $sArr[2]
|
||||
);
|
||||
break;
|
||||
case 5:
|
||||
if ($_obj < 2) // [mana, health] are on [0, 1] respectively and are expected on [1, 2] ..
|
||||
$_obj++; // 0 is weaponDmg .. ehh .. i messed up somewhere
|
||||
|
||||
$this->effects[$i]['tip'] = [$_obj, Game::$itemMods[$_obj]];
|
||||
// DO NOT BREAK!
|
||||
case 2:
|
||||
case 6:
|
||||
case 8:
|
||||
case 4:
|
||||
$this->effects[$i]['name'] = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, 'Type: '.$_ty, Lang::enchantment('types', $_ty)) : Lang::enchantment('types', $_ty);
|
||||
$this->effects[$i]['value'] = $_qty;
|
||||
if ($_ty == 4)
|
||||
$this->effects[$i]['name'] .= Lang::main('colon').'('.(User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, 'Object: '.$_obj, Lang::getMagicSchools(1 << $_obj)) : Lang::getMagicSchools(1 << $_obj)).')';
|
||||
}
|
||||
}
|
||||
|
||||
// activation conditions
|
||||
if ($_ = $this->subject->getField('conditionId'))
|
||||
{
|
||||
$x = '';
|
||||
|
||||
if ($gemCnd = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantmentcondition WHERE id = ?d', $_))
|
||||
{
|
||||
for ($i = 1; $i < 6; $i++)
|
||||
{
|
||||
if (!$gemCnd['color'.$i])
|
||||
continue;
|
||||
|
||||
$fiColors = function ($idx)
|
||||
{
|
||||
$foo = '';
|
||||
switch ($idx)
|
||||
{
|
||||
case 2: $foo = '0:3:5'; break; // red
|
||||
case 3: $foo = '2:4:5'; break; // yellow
|
||||
case 4: $foo = '1:3:4'; break; // blue
|
||||
}
|
||||
|
||||
return $foo;
|
||||
};
|
||||
|
||||
$bLink = $gemCnd['color'.$i] ? '<a class="tip" href="?items=3&filter=ty='.$fiColors($gemCnd['color'.$i]).'">'.Lang::item('gemColors', $gemCnd['color'.$i] - 1).'</a>' : '';
|
||||
$cLink = $gemCnd['cmpColor'.$i] ? '<a class="tip" href="?items=3&filter=ty='.$fiColors($gemCnd['cmpColor'.$i]).'">'.Lang::item('gemColors', $gemCnd['cmpColor'.$i] - 1).'</a>' : '';
|
||||
|
||||
switch ($gemCnd['comparator'.$i])
|
||||
{
|
||||
case 2: // requires less <color> than (<value> || <comparecolor>) gems
|
||||
case 5: // requires at least <color> than (<value> || <comparecolor>) gems
|
||||
$sp = (int)$gemCnd['value'.$i] > 1;
|
||||
$x .= '<span class="q0">'.Lang::achievement('reqNumCrt').' '.Lang::item('gemConditions', $gemCnd['comparator'.$i], [$gemCnd['value'.$i], $bLink]).'</span><br />';
|
||||
break;
|
||||
case 3: // requires more <color> than (<value> || <comparecolor>) gems
|
||||
$link = '<a href="?items=3&filter=ty='.$fiColors($gemCnd['cmpColor'.$i]).'">'.Lang::item('gemColors', $gemCnd['cmpColor'.$i] - 1).'</a>';
|
||||
$x .= '<span class="q0">'.Lang::achievement('reqNumCrt').' '.Lang::item('gemConditions', $gemCnd['comparator'.$i], [$bLink, $cLink]).'</span><br />';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->activateCondition = $x;
|
||||
}
|
||||
|
||||
/**************/
|
||||
/* Extra Tabs */
|
||||
/**************/
|
||||
|
||||
// used by gem
|
||||
$gemList = new ItemList(array(['gemEnchantmentId', $this->typeId]));
|
||||
if (!$gemList->error)
|
||||
{
|
||||
$this->lvTabs[] = ['item', array(
|
||||
'data' => array_values($gemList->getListviewData()),
|
||||
'name' => '$LANG.tab_usedby + \' \' + LANG.gems',
|
||||
'id' => 'used-by-gem',
|
||||
)];
|
||||
|
||||
$this->extendGlobalData($gemList->getJsGlobals());
|
||||
}
|
||||
|
||||
// used by socket bonus
|
||||
$socketsList = new ItemList(array(['socketBonus', $this->typeId]));
|
||||
if (!$socketsList->error)
|
||||
{
|
||||
$this->lvTabs[] = ['item', array(
|
||||
'data' => array_values($socketsList->getListviewData()),
|
||||
'name' => '$LANG.tab_usedby + \' \' + \''.Lang::item('socketBonus').'\'',
|
||||
'id' => 'used-by-socketbonus',
|
||||
)];
|
||||
|
||||
$this->extendGlobalData($socketsList->getJsGlobals());
|
||||
}
|
||||
|
||||
// used by spell
|
||||
// used by useItem
|
||||
$cnd = array(
|
||||
'OR',
|
||||
['AND', ['effect1Id', [53, 54, 156, 92]], ['effect1MiscValue', $this->typeId]],
|
||||
['AND', ['effect2Id', [53, 54, 156, 92]], ['effect2MiscValue', $this->typeId]],
|
||||
['AND', ['effect3Id', [53, 54, 156, 92]], ['effect3MiscValue', $this->typeId]],
|
||||
);
|
||||
$spellList = new SpellList($cnd);
|
||||
if (!$spellList->error)
|
||||
{
|
||||
$spellData = $spellList->getListviewData();
|
||||
$this->extendGlobalData($spellList->getJsGlobals());
|
||||
|
||||
$spellIds = $spellList->getFoundIDs();
|
||||
$conditions = array(
|
||||
'OR', // [use, useUndelayed]
|
||||
['AND', ['spellTrigger1', [0, 5]], ['spellId1', $spellIds]],
|
||||
['AND', ['spellTrigger2', [0, 5]], ['spellId2', $spellIds]],
|
||||
['AND', ['spellTrigger3', [0, 5]], ['spellId3', $spellIds]],
|
||||
['AND', ['spellTrigger4', [0, 5]], ['spellId4', $spellIds]],
|
||||
['AND', ['spellTrigger5', [0, 5]], ['spellId5', $spellIds]]
|
||||
);
|
||||
|
||||
$ubItems = new ItemList($conditions);
|
||||
if (!$ubItems->error)
|
||||
{
|
||||
$this->lvTabs[] = ['item', array(
|
||||
'data' => array_values($ubItems->getListviewData()),
|
||||
'name' => '$LANG.tab_usedby + \' \' + LANG.types[3][0]',
|
||||
'id' => 'used-by-item',
|
||||
)];
|
||||
|
||||
$this->extendGlobalData($ubItems->getJSGlobals(GLOBALINFO_SELF));
|
||||
}
|
||||
|
||||
// remove found spells if they are used by an item
|
||||
if (!$ubItems->error)
|
||||
{
|
||||
foreach ($spellList->iterate() as $sId => $__)
|
||||
{
|
||||
// if Perm. Enchantment has a createItem its a Scroll of Enchantment (display both)
|
||||
for ($i = 1; $i < 4; $i++)
|
||||
if ($spellList->getField('effect'.$i.'Id') == 53 && $spellList->getField('effect'.$i.'CreateItemId'))
|
||||
continue 2;
|
||||
|
||||
foreach ($ubItems->iterate() as $__)
|
||||
{
|
||||
for ($i = 1; $i < 6; $i++)
|
||||
{
|
||||
if ($ubItems->getField('spellId'.$i) == $sId)
|
||||
{
|
||||
unset($spellData[$sId]);
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->lvTabs[] = ['spell', array(
|
||||
'data' => array_values($spellData),
|
||||
'name' => '$LANG.tab_usedby + \' \' + LANG.types[6][0]',
|
||||
'id' => 'used-by-spell',
|
||||
)];
|
||||
}
|
||||
|
||||
// used by randomAttrItem
|
||||
$ire = DB::Aowow()->select(
|
||||
'SELECT *, ABS(id) AS ARRAY_KEY FROM ?_itemrandomenchant WHERE enchantId1 = ?d OR enchantId2 = ?d OR enchantId3 = ?d OR enchantId4 = ?d OR enchantId5 = ?d',
|
||||
$this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId
|
||||
);
|
||||
if ($ire)
|
||||
{
|
||||
if ($iet = DB::World()->select('SELECT entry AS ARRAY_KEY, ench, chance FROM item_enchantment_template WHERE ench IN (?a)', array_keys($ire)))
|
||||
{
|
||||
$randIds = []; // transform back to signed format
|
||||
foreach ($iet as $tplId => $data)
|
||||
$randIds[$ire[$data['ench']]['id'] > 0 ? $tplId : -$tplId] = $ire[$data['ench']]['id'];
|
||||
|
||||
$randItems = new ItemList(array(CFG_SQL_LIMIT_NONE, ['randomEnchant', array_keys($randIds)]));
|
||||
if (!$randItems->error)
|
||||
{
|
||||
$data = $randItems->getListviewData();
|
||||
foreach ($randItems->iterate() as $iId => $__)
|
||||
{
|
||||
$re = $randItems->getField('randomEnchant');
|
||||
|
||||
$data[$iId]['percent'] = $iet[abs($re)]['chance'];
|
||||
$data[$iId]['count'] = 1; // expected by js or the pct-col becomes unsortable
|
||||
$data[$iId]['rel'] = 'rand='.$ire[$iet[abs($re)]['ench']]['id'];
|
||||
$data[$iId]['name'] .= ' '.Util::localizedString($ire[$iet[abs($re)]['ench']], 'name');
|
||||
}
|
||||
|
||||
$this->lvTabs[] = ['item', array(
|
||||
'data' => array_values($data),
|
||||
'id' => 'used-by-rand',
|
||||
'name' => '$LANG.tab_usedby + \' \' + \''.Lang::item('_rndEnchants').'\'',
|
||||
'extraCols' => ['$Listview.extraCols.percent']
|
||||
)];
|
||||
|
||||
$this->extendGlobalData($randItems->getJSGlobals(GLOBALINFO_SELF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function generateTitle()
|
||||
{
|
||||
array_unshift($this->title, $this->name, Util::ucFirst(Lang::game('enchantment')));
|
||||
}
|
||||
|
||||
protected function generatePath()
|
||||
{
|
||||
if ($_ = $this->getDistinctType())
|
||||
$this->path[] = $_;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
108
pages/enchantments.php
Normal file
108
pages/enchantments.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// menuId 101: Enchantment g_initPath()
|
||||
// tabId 0: Database g_initHeader()
|
||||
class EnchantmentsPage extends GenericPage
|
||||
{
|
||||
use ListPage;
|
||||
|
||||
protected $type = TYPE_ENCHANTMENT;
|
||||
protected $tpl = 'enchantments';
|
||||
protected $path = [0, 101];
|
||||
protected $tabId = 0;
|
||||
protected $mode = CACHE_TYPE_PAGE;
|
||||
protected $js = ['filters.js'];
|
||||
|
||||
public function __construct($pageCall, $pageParam)
|
||||
{
|
||||
$this->getCategoryFromUrl($pageParam);;
|
||||
$this->filterObj = new EnchantmentListFilter(false, ['parentCats' => $this->category]);
|
||||
|
||||
parent::__construct($pageCall, $pageParam);
|
||||
|
||||
$this->name = Util::ucFirst(Lang::game('enchantments'));
|
||||
$this->subCat = $pageParam !== null ? '='.$pageParam : '';
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
$tabData = array(
|
||||
'data' => [],
|
||||
'name' => Util::ucFirst(Lang::game('enchantments'))
|
||||
);
|
||||
|
||||
$conditions = [];
|
||||
|
||||
if (!User::isInGroup(U_GROUP_EMPLOYEE))
|
||||
$conditions[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0];
|
||||
|
||||
if ($_ = $this->filterObj->getConditions())
|
||||
$conditions[] = $_;
|
||||
|
||||
$ench = new EnchantmentList($conditions);
|
||||
|
||||
$tabData['data'] = array_values($ench->getListviewData());
|
||||
$this->extendGlobalData($ench->getJSGlobals());
|
||||
|
||||
// recreate form selection
|
||||
$this->filter = $this->filterObj->getForm();
|
||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL;
|
||||
$this->filter['initData'] = ['init' => 'enchantments'];
|
||||
|
||||
if ($x = $this->filterObj->getSetCriteria())
|
||||
$this->filter['initData']['sc'] = $x;
|
||||
|
||||
$xCols = $this->filterObj->getExtraCols();
|
||||
foreach (Util::$itemFilter as $fiId => $str)
|
||||
if (array_column($tabData['data'], $str))
|
||||
$xCols[] = $fiId;
|
||||
|
||||
if (array_column($tabData['data'], 'dmg'))
|
||||
$xCols[] = 34;
|
||||
|
||||
if ($xCols)
|
||||
$this->filter['initData']['ec'] = array_values(array_unique($xCols));
|
||||
|
||||
if ($xCols)
|
||||
$tabData['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
|
||||
|
||||
if ($ench->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
{
|
||||
$tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_enchantmentsfound', $ench->getMatches(), CFG_SQL_LIMIT_DEFAULT);
|
||||
$tabData['_truncated'] = 1;
|
||||
}
|
||||
|
||||
if (array_filter(array_column($tabData['data'], 'spells')))
|
||||
$tabData['visibleCols'] = ['trigger'];
|
||||
|
||||
if (!$ench->hasSetFields(['skillLine']))
|
||||
$tabData['hiddenCols'] = ['skill'];
|
||||
|
||||
if ($this->filterObj->error)
|
||||
$tabData['_errors'] = '$1';
|
||||
|
||||
$this->lvTabs[] = ['enchantment', $tabData, 'enchantment'];
|
||||
}
|
||||
|
||||
protected function generateTitle()
|
||||
{
|
||||
$form = $this->filterObj->getForm('form');
|
||||
if (!empty($form['ty']) && intVal($form['ty']) && $form['ty'] > 0 && $form['ty'] < 9)
|
||||
array_unshift($this->title, Lang::enchantment('types', $form['ty']));
|
||||
|
||||
array_unshift($this->title, $this->name);
|
||||
}
|
||||
|
||||
protected function generatePath()
|
||||
{
|
||||
$form = $this->filterObj->getForm('form');
|
||||
if (isset($form['ty']) && !is_array($form['ty']))
|
||||
$this->path[] = $form['ty'];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
270
pages/event.php
270
pages/event.php
@@ -4,8 +4,8 @@ if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// menuId 11: Object g_initPath()
|
||||
// tabId 0: Database g_initHeader()
|
||||
// menuId 11: Worldevent g_initPath()
|
||||
// tabId 0: Database g_initHeader()
|
||||
class EventPage extends GenericPage
|
||||
{
|
||||
use DetailPage;
|
||||
@@ -24,22 +24,25 @@ class EventPage extends GenericPage
|
||||
{
|
||||
parent::__construct($pageCall, $id);
|
||||
|
||||
// temp locale
|
||||
if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain']))
|
||||
Util::powerUseLocale($_GET['domain']);
|
||||
|
||||
$this->typeId = intVal($id);
|
||||
|
||||
$conditions = $this->typeId < 0 ? [['id', -$this->typeId]] : [['holidayId', $this->typeId]];
|
||||
|
||||
$this->subject = new WorldEventList($conditions);
|
||||
$this->subject = new WorldEventList(array(['id', $this->typeId]));
|
||||
if ($this->subject->error)
|
||||
$this->notFound(Lang::game('event'), Lang::event('notFound'));
|
||||
$this->notFound();
|
||||
|
||||
$this->hId = $this->subject->getField('holidayId');
|
||||
$this->eId = $this->subject->getField('eventBak');
|
||||
|
||||
// redirect if associated with a holiday
|
||||
if ($this->hId && $this->typeId != $this->hId)
|
||||
header('Location: '.HOST_URL.'?event='.$this->hId, true, 302);
|
||||
|
||||
$this->name = $this->subject->getField('name', true);
|
||||
$this->hId = $this->subject->getField('holidayId');
|
||||
$this->eId = $this->typeId;
|
||||
$this->name = $this->subject->getField('name', true);
|
||||
$this->dates = array(
|
||||
'firstDate' => $this->subject->getField('startTime'),
|
||||
'lastDate' => $this->subject->getField('endTime'),
|
||||
'length' => $this->subject->getField('length'),
|
||||
'rec' => $this->subject->getField('occurence')
|
||||
);
|
||||
}
|
||||
|
||||
protected function generatePath()
|
||||
@@ -84,16 +87,14 @@ class EventPage extends GenericPage
|
||||
/* Main Content */
|
||||
/****************/
|
||||
|
||||
// no entry in ?_articles? use default HolidayDescription
|
||||
if ($this->hId && empty($this->article))
|
||||
$this->article = ['text' => Util::jsEscape($this->subject->getField('description', true)), 'params' => []];
|
||||
|
||||
$this->headIcons = [$this->subject->getField('iconString')];
|
||||
$this->redButtons = array(
|
||||
BUTTON_WOWHEAD => $this->typeId > 0,
|
||||
BUTTON_LINKS => true
|
||||
);
|
||||
$this->dates = array(
|
||||
'firstDate' => $this->subject->getField('startTime'),
|
||||
'lastDate' => $this->subject->getField('endTime'),
|
||||
'length' => $this->subject->getField('length'),
|
||||
'rec' => $this->subject->getField('occurence')
|
||||
BUTTON_WOWHEAD => $this->hId > 0,
|
||||
BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId]
|
||||
);
|
||||
|
||||
/**************/
|
||||
@@ -112,11 +113,12 @@ class EventPage extends GenericPage
|
||||
foreach ($data as &$d)
|
||||
$d['method'] = $npcIds[$d['id']];
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => CreatureList::$brickFile,
|
||||
'data' => $data,
|
||||
'params' => ['note' => $hasFilter ? sprintf(Util::$filterResultString, '?npcs&filter=cr=38;crs='.$this->hId.';crv=0') : null]
|
||||
);
|
||||
$tabData = ['data' => array_values($data)];
|
||||
|
||||
if ($hasFilter)
|
||||
$tabData['note'] = sprintf(Util::$filterResultString, '?npcs&filter=cr=38;crs='.$this->hId.';crv=0');
|
||||
|
||||
$this->lvTabs[] = ['creature', $tabData];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,11 +132,12 @@ class EventPage extends GenericPage
|
||||
foreach ($data as &$d)
|
||||
$d['method'] = $objectIds[$d['id']];
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => GameObjectList::$brickFile,
|
||||
'data' => $data,
|
||||
'params' => ['note' => $hasFilter ? sprintf(Util::$filterResultString, '?objects&filter=cr=16;crs='.$this->hId.';crv=0') : null]
|
||||
);
|
||||
$tabData = ['data' => array_values($data)];
|
||||
|
||||
if ($hasFilter)
|
||||
$tabData['note'] = sprintf(Util::$filterResultString, '?objects&filter=cr=16;crs='.$this->hId.';crv=0');
|
||||
|
||||
$this->lvTabs[] = ['object', $tabData];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,14 +150,15 @@ class EventPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($acvs->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => AchievementList::$brickFile,
|
||||
'data' => $acvs->getListviewData(),
|
||||
'params' => array(
|
||||
'note' => $hasFilter ? sprintf(Util::$filterResultString, '?achievements&filter=cr=11;crs='.$this->hId.';crv=0') : null,
|
||||
'visibleCols' => "$['category']"
|
||||
)
|
||||
$tabData = array(
|
||||
'data' => array_values($acvs->getListviewData()),
|
||||
'visibleCols' => ['category']
|
||||
);
|
||||
|
||||
if ($hasFilter)
|
||||
$tabData['note'] = sprintf(Util::$filterResultString, '?achievements&filter=cr=11;crs='.$this->hId.';crv=0');
|
||||
|
||||
$this->lvTabs[] = ['achievement', $tabData];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,20 +167,21 @@ class EventPage extends GenericPage
|
||||
{
|
||||
$itemCnd = array(
|
||||
'OR',
|
||||
['holidayId', $this->hId], // direct requirement on item
|
||||
['eventId', $this->eId], // direct requirement on item
|
||||
);
|
||||
|
||||
// tab: quests (by table, go & creature)
|
||||
$quests = new QuestList(array(['holidayId', $this->hId]));
|
||||
$quests = new QuestList(array(['eventId', $this->eId]));
|
||||
if (!$quests->error)
|
||||
{
|
||||
$this->extendGlobalData($quests->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => QuestList::$brickFile,
|
||||
'data' => $quests->getListviewData(),
|
||||
'params' => ['note' => $hasFilter ? sprintf(Util::$filterResultString, '?quests&filter=cr=33;crs='.$this->hId.';crv=0') : null]
|
||||
);
|
||||
$tabData = ['data'=> array_values($quests->getListviewData())];
|
||||
|
||||
if ($hasFilter)
|
||||
$tabData['note'] = sprintf(Util::$filterResultString, '?quests&filter=cr=33;crs='.$this->hId.';crv=0');
|
||||
|
||||
$this->lvTabs[] = ['quest', $tabData];
|
||||
|
||||
$questItems = [];
|
||||
foreach (array_column($quests->rewards, TYPE_ITEM) as $arr)
|
||||
@@ -208,23 +213,24 @@ class EventPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($eventItems->getJSGlobals(GLOBALINFO_SELF));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => ItemList::$brickFile,
|
||||
'data' => $eventItems->getListviewData(),
|
||||
'params' => ['note' => $hasFilter ? sprintf(Util::$filterResultString, '?items&filter=cr=160;crs='.$this->hId.';crv=0') : null]
|
||||
);
|
||||
$tabData = ['data'=> array_values($eventItems->getListviewData())];
|
||||
|
||||
if ($hasFilter)
|
||||
$tabData['note'] = sprintf(Util::$filterResultString, '?items&filter=cr=160;crs='.$this->hId.';crv=0');
|
||||
|
||||
$this->lvTabs[] = ['item', $tabData];
|
||||
}
|
||||
}
|
||||
|
||||
// tab: see also (event conditions)
|
||||
if ($rel = DB::World()->selectCol('SELECT IF(eventEntry = prerequisite_event, NULL, IF(eventEntry = ?d, -prerequisite_event, eventEntry)) FROM game_event_prerequisite WHERE prerequisite_event = ?d OR eventEntry = ?d', $this->eId, $this->eId, $this->eId))
|
||||
if ($rel = DB::World()->selectCol('SELECT IF(eventEntry = prerequisite_event, NULL, IF(eventEntry = ?d, prerequisite_event, -eventEntry)) FROM game_event_prerequisite WHERE prerequisite_event = ?d OR eventEntry = ?d', $this->eId, $this->eId, $this->eId))
|
||||
{
|
||||
$list = [];
|
||||
array_walk($rel, function($v, $k) use (&$list) {
|
||||
if ($v > 0)
|
||||
$list[] = $v;
|
||||
else if ($v === null)
|
||||
Util::addNote(U_GROUP_EMPLOYEE, 'game_event_prerequisite: this event has itself as prerequisite');
|
||||
trigger_error('game_event_prerequisite: this event has itself as prerequisite', E_USER_WARNING);
|
||||
});
|
||||
|
||||
if ($list)
|
||||
@@ -233,82 +239,136 @@ class EventPage extends GenericPage
|
||||
$this->extendGlobalData($relEvents->getJSGlobals());
|
||||
$relData = $relEvents->getListviewData();
|
||||
foreach ($relEvents->getFoundIDs() as $id)
|
||||
$relData[$id]['condition'][0][$this->typeId][] = [[-CND_ACTIVE_EVENT, -$this->eId]];
|
||||
$relData[$id]['condition'][0][$this->typeId][] = [[-CND_ACTIVE_EVENT, $this->eId]];
|
||||
|
||||
$this->extendGlobalData($this->subject->getJSGlobals());
|
||||
foreach ($rel as $r)
|
||||
{
|
||||
if ($r >= 0)
|
||||
if ($r <= 0)
|
||||
continue;
|
||||
|
||||
$this->extendGlobalIds(TYPE_WORLDEVENT, $r);
|
||||
|
||||
$d = $this->subject->getListviewData();
|
||||
$d[-$this->eId]['condition'][0][$this->typeId][] = [[-CND_ACTIVE_EVENT, $r]];
|
||||
$d[$this->eId]['condition'][0][$this->typeId][] = [[-CND_ACTIVE_EVENT, $r]];
|
||||
|
||||
$relData = array_merge($relData, $d);
|
||||
}
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => WorldEventList::$brickFile,
|
||||
'data' => $relData,
|
||||
'params' => array(
|
||||
'id' => 'see-also',
|
||||
'name' => '$LANG.tab_seealso',
|
||||
'hiddenCols' => "$['date']",
|
||||
'extraCols' => '$[Listview.extraCols.condition]'
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['event', array(
|
||||
'data' => array_values($relData),
|
||||
'id' => 'see-also',
|
||||
'name' => '$LANG.tab_seealso',
|
||||
'hiddenCols' => ['date'],
|
||||
'extraCols' => ['$Listview.extraCols.condition']
|
||||
)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function postCache()
|
||||
{
|
||||
/********************/
|
||||
/* finalize infobox */
|
||||
/********************/
|
||||
|
||||
// update dates to now()
|
||||
$updated = WorldEventList::updateDates($this->dates);
|
||||
|
||||
// start
|
||||
if ($updated['start'])
|
||||
array_push($this->infobox, Lang::event('start').Lang::main('colon').date(Lang::main('dateFmtLong'), $updated['start']));
|
||||
|
||||
// end
|
||||
if ($updated['end'])
|
||||
array_push($this->infobox, Lang::event('end').Lang::main('colon').date(Lang::main('dateFmtLong'), $updated['end']));
|
||||
|
||||
// occurence
|
||||
if ($updated['rec'] > 0)
|
||||
array_push($this->infobox, Lang::event('interval').Lang::main('colon').Util::formatTime($updated['rec'] * 1000));
|
||||
|
||||
// in progress
|
||||
if ($updated['start'] < time() && $updated['end'] > time())
|
||||
array_push($this->infobox, '[span class=q2]'.Lang::event('inProgress').'[/span]');
|
||||
|
||||
$this->infobox = '[ul][li]'.implode('[/li][li]', $this->infobox).'[/li][/ul]';
|
||||
|
||||
/***************************/
|
||||
/* finalize related events */
|
||||
/***************************/
|
||||
|
||||
foreach ($this->lvTabs as &$view)
|
||||
if ($this->mode == CACHE_TYPE_TOOLTIP)
|
||||
{
|
||||
if ($view['file'] != WorldEventList::$brickFile)
|
||||
continue;
|
||||
|
||||
foreach ($view['data'] as &$data)
|
||||
{
|
||||
$updated = WorldEventList::updateDates($data['_date']);
|
||||
unset($data['_date']);
|
||||
$data['startDate'] = $updated['start'] ? date(Util::$dateFormatInternal, $updated['start']) : false;
|
||||
$data['endDate'] = $updated['end'] ? date(Util::$dateFormatInternal, $updated['end']) : false;
|
||||
$data['rec'] = $updated['rec'];
|
||||
}
|
||||
|
||||
return array(
|
||||
date(Lang::main('dateFmtLong'), $updated['start']),
|
||||
date(Lang::main('dateFmtLong'), $updated['end'])
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($this->hId)
|
||||
Util::$wowheadLink = 'http://'.Util::$subDomains[User::$localeId].'.wowhead.com/event='.$this->hId;
|
||||
|
||||
/********************/
|
||||
/* finalize infobox */
|
||||
/********************/
|
||||
|
||||
// start
|
||||
if ($updated['start'])
|
||||
array_push($this->infobox, Lang::event('start').Lang::main('colon').date(Lang::main('dateFmtLong'), $updated['start']));
|
||||
|
||||
// end
|
||||
if ($updated['end'])
|
||||
array_push($this->infobox, Lang::event('end').Lang::main('colon').date(Lang::main('dateFmtLong'), $updated['end']));
|
||||
|
||||
// occurence
|
||||
if ($updated['rec'] > 0)
|
||||
array_push($this->infobox, Lang::event('interval').Lang::main('colon').Util::formatTime($updated['rec'] * 1000));
|
||||
|
||||
// in progress
|
||||
if ($updated['start'] < time() && $updated['end'] > time())
|
||||
array_push($this->infobox, '[span class=q2]'.Lang::event('inProgress').'[/span]');
|
||||
|
||||
$this->infobox = '[ul][li]'.implode('[/li][li]', $this->infobox).'[/li][/ul]';
|
||||
|
||||
/***************************/
|
||||
/* finalize related events */
|
||||
/***************************/
|
||||
|
||||
foreach ($this->lvTabs as &$view)
|
||||
{
|
||||
if ($view[0] != WorldEventList::$brickFile)
|
||||
continue;
|
||||
|
||||
foreach ($view[1]['data'] as &$data)
|
||||
{
|
||||
$updated = WorldEventList::updateDates($data['_date']);
|
||||
unset($data['_date']);
|
||||
$data['startDate'] = $updated['start'] ? date(Util::$dateFormatInternal, $updated['start']) : false;
|
||||
$data['endDate'] = $updated['end'] ? date(Util::$dateFormatInternal, $updated['end']) : false;
|
||||
$data['rec'] = $updated['rec'];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function generateTooltip($asError = false)
|
||||
{
|
||||
if ($asError)
|
||||
return '$WowheadPower.registerHoliday('.$this->typeId.', '.User::$localeId.', {});';
|
||||
|
||||
$x = '$WowheadPower.registerHoliday('.$this->typeId.', '.User::$localeId.", {\n";
|
||||
$x .= "\tname_".User::$localeString.": '".Util::jsEscape($this->subject->getField('name', true))."',\n";
|
||||
|
||||
if ($this->subject->getField('iconString') != 'trade_engineering')
|
||||
$x .= "\ticon: '".rawurlencode($this->subject->getField('iconString', true, true))."',\n";
|
||||
|
||||
$x .= "\ttooltip_".User::$localeString.": '".$this->subject->renderTooltip()."'\n";
|
||||
$x .= "});";
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
public function display($override = '')
|
||||
{
|
||||
if ($this->mode != CACHE_TYPE_TOOLTIP)
|
||||
return parent::display($override);
|
||||
|
||||
if (!$this->loadCache($tt))
|
||||
{
|
||||
$tt = $this->generateTooltip();
|
||||
$this->saveCache($tt);
|
||||
}
|
||||
|
||||
list($start, $end) = $this->postCache();
|
||||
|
||||
header('Content-type: application/x-javascript; charset=utf-8');
|
||||
die(sprintf($tt, $start, $end));
|
||||
}
|
||||
|
||||
public function notFound($title = '', $msg = '')
|
||||
{
|
||||
if ($this->mode != CACHE_TYPE_TOOLTIP)
|
||||
return parent::notFound($title ?: Lang::game('event'), $msg ?: Lang::event('notFound'));
|
||||
|
||||
header('Content-type: application/x-javascript; charset=utf-8');
|
||||
echo $this->generateTooltip(true);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,19 +52,16 @@ class EventsPage extends GenericPage
|
||||
if ($d = $events->getField('requires'))
|
||||
$this->deps[$events->id] = $d;
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'event',
|
||||
'data' => $events->getListviewData(),
|
||||
'params' => []
|
||||
);
|
||||
$data = array_values($events->getListviewData());
|
||||
|
||||
if ($_ = array_filter($events->getListviewData(), function($x) {return $x['id'] > 0;}))
|
||||
$this->lvTabs[] = ['event', ['data' => $data]];
|
||||
|
||||
if ($_ = array_values(array_filter($data, function($x) {return $x['category'] > 0;})))
|
||||
{
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'calendar',
|
||||
'data' => $_,
|
||||
'params' => ['hideCount' => 1]
|
||||
);
|
||||
$this->lvTabs[] = ['calendar', array(
|
||||
'data' => $_,
|
||||
'hideCount' => 1
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +83,7 @@ class EventsPage extends GenericPage
|
||||
// recalculate dates with now()
|
||||
foreach ($this->lvTabs as &$views)
|
||||
{
|
||||
foreach ($views['data'] as &$data)
|
||||
foreach ($views[1]['data'] as &$data)
|
||||
{
|
||||
// is a followUp-event
|
||||
if (!empty($this->deps[$data['id']]))
|
||||
|
||||
@@ -88,7 +88,7 @@ class FactionPage extends GenericPage
|
||||
$this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
|
||||
$this->redButtons = array(
|
||||
BUTTON_WOWHEAD => true,
|
||||
BUTTON_LINKS => true
|
||||
BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId]
|
||||
);
|
||||
|
||||
// Spillover Effects
|
||||
@@ -134,12 +134,15 @@ class FactionPage extends GenericPage
|
||||
|
||||
switch ($k)
|
||||
{
|
||||
case 'quest_rate': $buff .= '[tr][td]'.Lang::game('quests') .Lang::main('colon').'[/td]'; break;
|
||||
case 'quest_daily_rate': $buff .= '[tr][td]'.Lang::game('quests').' ('.Lang::quest('daily').')' .Lang::main('colon').'[/td]'; break;
|
||||
case 'quest_weekly_rate': $buff .= '[tr][td]'.Lang::game('quests').' ('.Lang::quest('weekly').')' .Lang::main('colon').'[/td]'; break;
|
||||
case 'quest_monthly_rate': $buff .= '[tr][td]'.Lang::game('quests').' ('.Lang::quest('monthly').')'.Lang::main('colon').'[/td]'; break;
|
||||
case 'creature_rate': $buff .= '[tr][td]'.Lang::game('npcs') .Lang::main('colon').'[/td]'; break;
|
||||
case 'spell_rate': $buff .= '[tr][td]'.Lang::game('spells') .Lang::main('colon').'[/td]'; break;
|
||||
case 'quest_rate': $buff .= '[tr][td]'.Lang::game('quests') .Lang::main('colon').'[/td]'; break;
|
||||
case 'quest_daily_rate': $buff .= '[tr][td]'.Lang::game('quests').' ('.Lang::quest('daily').')' .Lang::main('colon').'[/td]'; break;
|
||||
case 'quest_weekly_rate': $buff .= '[tr][td]'.Lang::game('quests').' ('.Lang::quest('weekly').')' .Lang::main('colon').'[/td]'; break;
|
||||
case 'quest_monthly_rate': $buff .= '[tr][td]'.Lang::game('quests').' ('.Lang::quest('monthly').')' .Lang::main('colon').'[/td]'; break;
|
||||
case 'quest_repeatable_rate': $buff .= '[tr][td]'.Lang::game('quests').' ('.Lang::quest('repeatable').')'.Lang::main('colon').'[/td]'; break;
|
||||
case 'creature_rate': $buff .= '[tr][td]'.Lang::game('npcs') .Lang::main('colon').'[/td]'; break;
|
||||
case 'spell_rate': $buff .= '[tr][td]'.Lang::game('spells') .Lang::main('colon').'[/td]'; break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
$buff .= '[td width=35px align=right][span class=q'.($v < 1 ? '10]' : '2]+').intVal(($v - 1) * 100).'%[/span][/td][/tr]';
|
||||
@@ -175,49 +178,49 @@ class FactionPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($items->getJSGlobals(GLOBALINFO_SELF));
|
||||
|
||||
$tab = array(
|
||||
'file' => 'item',
|
||||
'data' => $items->getListviewData(),
|
||||
'showRep' => true,
|
||||
'params' => array(
|
||||
'extraCols' => '$_',
|
||||
'sort' => "$['standing', 'name']"
|
||||
)
|
||||
$tabData = array(
|
||||
'data' => array_values($items->getListviewData()),
|
||||
'extraCols' => '$_',
|
||||
'sort' => ['standing', 'name']
|
||||
);
|
||||
|
||||
if ($items->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
$tab['params']['note'] = sprintf(Util::$filterResultString, '?items&filter=cr=17;crs='.$this->typeId.';crv=0');
|
||||
$tabData['note'] = sprintf(Util::$filterResultString, '?items&filter=cr=17;crs='.$this->typeId.';crv=0');
|
||||
|
||||
$this->lvTabs[] = $tab;
|
||||
$this->lvTabs[] = ['item', $tabData, 'itemStandingCol'];
|
||||
}
|
||||
|
||||
// tab: creatures with onKill reputation
|
||||
if ($this->subject->getField('reputationIndex') != -1) // only if you can actually gain reputation by kills
|
||||
{
|
||||
// inherit siblings/children from $spillover
|
||||
$cIds = DB::World()->selectCol('SELECT DISTINCT creature_id FROM creature_onkill_reputation WHERE
|
||||
(RewOnKillRepValue1 > 0 AND (RewOnKillRepFaction1 = ?d{ OR (RewOnKillRepFaction1 IN (?a) AND IsTeamAward1 <> 0)})) OR
|
||||
(RewOnKillRepValue2 > 0 AND (RewOnKillRepFaction2 = ?d{ OR (RewOnKillRepFaction2 IN (?a) AND IsTeamAward2 <> 0)}))',
|
||||
$cRep = DB::World()->selectCol('SELECT DISTINCT creature_id AS ARRAY_KEY, qty FROM (
|
||||
SELECT creature_id, RewOnKillRepValue1 as qty FROM creature_onkill_reputation WHERE RewOnKillRepValue1 > 0 AND (RewOnKillRepFaction1 = ?d{ OR (RewOnKillRepFaction1 IN (?a) AND IsTeamAward1 <> 0)}) UNION
|
||||
SELECT creature_id, RewOnKillRepValue2 as qty FROM creature_onkill_reputation WHERE RewOnKillRepValue2 > 0 AND (RewOnKillRepFaction2 = ?d{ OR (RewOnKillRepFaction2 IN (?a) AND IsTeamAward2 <> 0)})
|
||||
) x',
|
||||
$this->typeId, $spillover->getFoundIDs() ?: DBSIMPLE_SKIP,
|
||||
$this->typeId, $spillover->getFoundIDs() ?: DBSIMPLE_SKIP
|
||||
);
|
||||
|
||||
if ($cIds)
|
||||
if ($cRep)
|
||||
{
|
||||
$killCreatures = new CreatureList(array(['id', $cIds]));
|
||||
$killCreatures = new CreatureList(array(['id', array_keys($cRep)]));
|
||||
if (!$killCreatures->error)
|
||||
{
|
||||
$tab = array(
|
||||
'file' => 'creature',
|
||||
'data' => $killCreatures->getListviewData(),
|
||||
'showRep' => true,
|
||||
'params' => []
|
||||
$data = $killCreatures->getListviewData();
|
||||
foreach ($data as $id => &$d)
|
||||
$d['reputation'] = $cRep[$id];
|
||||
|
||||
$tabData = array(
|
||||
'data' => array_values($data),
|
||||
'extraCols' => '$_',
|
||||
'sort' => ['-reputation', 'name']
|
||||
);
|
||||
|
||||
if ($killCreatures->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
$tab['params']['note'] = sprintf(Util::$filterResultString, '?npcs&filter=cr=42;crs='.$this->typeId.';crv=0');
|
||||
$tabData['note'] = sprintf(Util::$filterResultString, '?npcs&filter=cr=42;crs='.$this->typeId.';crv=0');
|
||||
|
||||
$this->lvTabs[] = $tab;
|
||||
$this->lvTabs[] = ['creature', $tabData, 'npcRepCol'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,20 +231,16 @@ class FactionPage extends GenericPage
|
||||
$members = new CreatureList(array(['faction', $_]));
|
||||
if (!$members->error)
|
||||
{
|
||||
$tab = array(
|
||||
'file' => 'creature',
|
||||
'data' => $members->getListviewData(),
|
||||
'showRep' => true,
|
||||
'params' => array(
|
||||
'id' => 'member',
|
||||
'name' => '$LANG.tab_members'
|
||||
)
|
||||
$tabData = array(
|
||||
'data' => array_values($members->getListviewData()),
|
||||
'id' => 'member',
|
||||
'name' => '$LANG.tab_members'
|
||||
);
|
||||
|
||||
if ($members->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
$tab['params']['note'] = sprintf(Util::$filterResultString, '?npcs&filter=cr=3;crs='.$this->typeId.';crv=0');
|
||||
$tabData['note'] = sprintf(Util::$filterResultString, '?npcs&filter=cr=3;crs='.$this->typeId.';crv=0');
|
||||
|
||||
$this->lvTabs[] = $tab;
|
||||
$this->lvTabs[] = ['creature', $tabData];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,13 +249,7 @@ class FactionPage extends GenericPage
|
||||
{
|
||||
$objects = new GameObjectList(array(['faction', $_]));
|
||||
if (!$objects->error)
|
||||
{
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'object',
|
||||
'data' => $objects->getListviewData(),
|
||||
'params' => []
|
||||
);
|
||||
}
|
||||
$this->lvTabs[] = ['object', ['data' => array_values($objects->getListviewData())]];
|
||||
}
|
||||
|
||||
// tab: quests
|
||||
@@ -273,17 +266,15 @@ class FactionPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($quests->getJSGlobals(GLOBALINFO_ANY));
|
||||
|
||||
$tab = array(
|
||||
'file' => 'quest',
|
||||
'data' => $quests->getListviewData($this->typeId),
|
||||
'showRep' => true,
|
||||
'params' => ['extraCols' => '$_']
|
||||
$tabData = array(
|
||||
'data' => array_values($quests->getListviewData($this->typeId)),
|
||||
'extraCols' => '$_'
|
||||
);
|
||||
|
||||
if ($quests->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
$tab['params']['note'] = sprintf(Util::$filterResultString, '?quests&filter=cr=1;crs='.$this->typeId.';crv=0');
|
||||
$tabData['note'] = sprintf(Util::$filterResultString, '?quests&filter=cr=1;crs='.$this->typeId.';crv=0');
|
||||
|
||||
$this->lvTabs[] = $tab;
|
||||
$this->lvTabs[] = ['quest', $tabData, 'questRepCol'];
|
||||
}
|
||||
|
||||
// tab: achievements
|
||||
@@ -296,15 +287,12 @@ class FactionPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($acvs->getJSGlobals(GLOBALINFO_ANY));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'achievement',
|
||||
'data' => $acvs->getListviewData(),
|
||||
'params' => array(
|
||||
'id' => 'criteria-of',
|
||||
'name' => '$LANG.tab_criteriaof',
|
||||
'visibleCols' => "$['category']"
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['achievement', array(
|
||||
'data' => array_values($acvs->getListviewData()),
|
||||
'id' => 'criteria-of',
|
||||
'name' => '$LANG.tab_criteriaof',
|
||||
'visibleCols' => ['category']
|
||||
)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,13 +53,9 @@ class FactionsPage extends GenericPage
|
||||
$data = [];
|
||||
$factions = new FactionList($conditions);
|
||||
if (!$factions->error)
|
||||
$data = $factions->getListviewData();
|
||||
$data = array_values($factions->getListviewData());
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'faction',
|
||||
'data' => $data,
|
||||
'params' => []
|
||||
);
|
||||
$this->lvTabs[] = ['faction', ['data' => $data]];
|
||||
}
|
||||
|
||||
protected function generateTitle()
|
||||
|
||||
@@ -10,7 +10,13 @@ trait DetailPage
|
||||
protected $category = null; // not used on detail pages
|
||||
protected $lvTabs = []; // most pages have this
|
||||
|
||||
private $subject = null; // so it will not get cached
|
||||
protected $ssError = null;
|
||||
protected $coError = null;
|
||||
protected $viError = null;
|
||||
|
||||
protected $subject = null; // so it will not get cached
|
||||
|
||||
protected $contribute = CONTRIBUTE_ANY;
|
||||
|
||||
protected function generateCacheKey($withStaff = true)
|
||||
{
|
||||
@@ -25,6 +31,20 @@ trait DetailPage
|
||||
|
||||
return implode('_', $key);
|
||||
}
|
||||
|
||||
protected function applyCCErrors()
|
||||
{
|
||||
if (!empty($_SESSION['error']['co']))
|
||||
$this->coError = $_SESSION['error']['co'];
|
||||
|
||||
if (!empty($_SESSION['error']['ss']))
|
||||
$this->ssError = $_SESSION['error']['ss'];
|
||||
|
||||
if (!empty($_SESSION['error']['vi']))
|
||||
$this->viError = $_SESSION['error']['vi'];
|
||||
|
||||
unset($_SESSION['error']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +73,88 @@ trait ListPage
|
||||
}
|
||||
}
|
||||
|
||||
trait TrProfiler
|
||||
{
|
||||
protected $region = '';
|
||||
protected $realm = '';
|
||||
protected $realmId = 0;
|
||||
protected $battlegroup = ''; // not implemented, since no pserver supports it
|
||||
protected $subjectName = '';
|
||||
protected $subjectGUID = 0;
|
||||
protected $sumSubjects = 0;
|
||||
|
||||
protected $doResync = null;
|
||||
|
||||
protected function getSubjectFromUrl($str)
|
||||
{
|
||||
if (!$str)
|
||||
return;
|
||||
|
||||
// cat[0] is always region
|
||||
// cat[1] is realm or bGroup (must be realm if cat[2] is set)
|
||||
// cat[2] is arena-team, guild or player
|
||||
$cat = explode('.', $str, 3);
|
||||
|
||||
$cat = array_map('urldecode', $cat);
|
||||
|
||||
if (count($cat) > 3)
|
||||
return;
|
||||
|
||||
if ($cat[0] !== 'eu' && $cat[0] !== 'us')
|
||||
return;
|
||||
|
||||
$this->region = $cat[0];
|
||||
|
||||
// if ($cat[1] == Profiler::urlize(CFG_BATTLEGROUP))
|
||||
// $this->battlegroup = CFG_BATTLEGROUP;
|
||||
if (isset($cat[1]))
|
||||
{
|
||||
foreach (Profiler::getRealms() as $rId => $r)
|
||||
{
|
||||
if (Profiler::urlize($r['name']) == $cat[1])
|
||||
{
|
||||
$this->realm = $r['name'];
|
||||
$this->realmId = $rId;
|
||||
if (isset($cat[2]) && mb_strlen($cat[2]) >= 3)
|
||||
$this->subjectName = $cat[2]; // cannot reconstruct original name from urlized form; match against special name field
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function initialSync()
|
||||
{
|
||||
$this->prepareContent();
|
||||
|
||||
$this->notFound = array(
|
||||
'title' => sprintf(Lang::profiler('firstUseTitle'), $this->subjectName, $this->realm),
|
||||
'msg' => ''
|
||||
);
|
||||
$this->hasComContent = false;
|
||||
Util::arraySumByKey($this->mysql, DB::Aowow()->getStatistics(), DB::World()->getStatistics());
|
||||
|
||||
if (isset($this->tabId))
|
||||
$this->pageTemplate['activeTab'] = $this->tabId;
|
||||
|
||||
$this->display('text-page-generic');
|
||||
exit();
|
||||
}
|
||||
|
||||
protected function generatePath()
|
||||
{
|
||||
if ($this->region)
|
||||
{
|
||||
$this->path[] = $this->region;
|
||||
|
||||
if ($this->realm)
|
||||
$this->path[] = Profiler::urlize($this->realm);
|
||||
// else
|
||||
// $this->path[] = Profiler::urlize(CFG_BATTLEGROUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GenericPage
|
||||
{
|
||||
@@ -84,10 +186,53 @@ class GenericPage
|
||||
private $memcached = null;
|
||||
private $mysql = ['time' => 0, 'count' => 0];
|
||||
|
||||
public function __construct($pageCall/*, $pageParam */)
|
||||
private $headerLogo = '';
|
||||
private $fullParams = '';
|
||||
|
||||
private $lvTemplates = array(
|
||||
'achievement' => ['template' => 'achievement', 'id' => 'achievements', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_achievements' ],
|
||||
'calendar' => ['template' => 'holidaycal', 'id' => 'calendar', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_calendar' ],
|
||||
'class' => ['template' => 'classs', 'id' => 'classes', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_classes' ],
|
||||
'commentpreview' => ['template' => 'commentpreview', 'id' => 'comments', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_comments' ],
|
||||
'creature' => ['template' => 'npc', 'id' => 'npcs', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_npcs' ],
|
||||
'currency' => ['template' => 'currency', 'id' => 'currencies', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_currencies' ],
|
||||
'emote' => ['template' => 'emote', 'id' => 'emotes', 'parent' => 'lv-generic', 'data' => [] ],
|
||||
'enchantment' => ['template' => 'enchantment', 'id' => 'enchantments', 'parent' => 'lv-generic', 'data' => [] ],
|
||||
'event' => ['template' => 'holiday', 'id' => 'holidays', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_holidays' ],
|
||||
'faction' => ['template' => 'faction', 'id' => 'factions', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_factions' ],
|
||||
'genericmodel' => ['template' => 'genericmodel', 'id' => 'same-model-as', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_samemodelas' ],
|
||||
'icongallery' => ['template' => 'icongallery', 'id' => 'icons', 'parent' => 'lv-generic', 'data' => [] ],
|
||||
'item' => ['template' => 'item', 'id' => 'items', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_items' ],
|
||||
'itemset' => ['template' => 'itemset', 'id' => 'itemsets', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_itemsets' ],
|
||||
'model' => ['template' => 'model', 'id' => 'gallery', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_gallery' ],
|
||||
'object' => ['template' => 'object', 'id' => 'objects', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_objects' ],
|
||||
'pet' => ['template' => 'pet', 'id' => 'hunter-pets', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_pets' ],
|
||||
'profile' => ['template' => 'profile', 'id' => 'profiles', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_profiles' ],
|
||||
'quest' => ['template' => 'quest', 'id' => 'quests', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_quests' ],
|
||||
'race' => ['template' => 'race', 'id' => 'races', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_races' ],
|
||||
'replypreview' => ['template' => 'replypreview', 'id' => 'comment-replies', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_commentreplies'],
|
||||
'reputationhistory' => ['template' => 'reputationhistory', 'id' => 'reputation', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_reputation' ],
|
||||
'screenshot' => ['template' => 'screenshot', 'id' => 'screenshots', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_screenshots' ],
|
||||
'skill' => ['template' => 'skill', 'id' => 'skills', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_skills' ],
|
||||
'sound' => ['template' => 'sound', 'id' => 'sounds', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.types[19][2]' ],
|
||||
'spell' => ['template' => 'spell', 'id' => 'spells', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_spells' ],
|
||||
'title' => ['template' => 'title', 'id' => 'titles', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_titles' ],
|
||||
'topusers' => ['template' => 'topusers', 'id' => 'topusers', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.topusers' ],
|
||||
'video' => ['template' => 'video', 'id' => 'videos', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_videos' ],
|
||||
'zone' => ['template' => 'zone', 'id' => 'zones', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_zones' ]
|
||||
);
|
||||
|
||||
public function __construct($pageCall, $pageParam = null)
|
||||
{
|
||||
$this->time = microtime(true);
|
||||
|
||||
$this->fullParams = $pageCall;
|
||||
if ($pageParam)
|
||||
$this->fullParams .= '='.$pageParam;
|
||||
|
||||
if (CFG_CACHE_DIR && Util::writeDir(CFG_CACHE_DIR))
|
||||
$this->cacheDir = mb_substr(CFG_CACHE_DIR, -1) != '/' ? CFG_CACHE_DIR.'/' : CFG_CACHE_DIR;
|
||||
|
||||
// force page refresh
|
||||
if (isset($_GET['refresh']) && User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV))
|
||||
{
|
||||
@@ -106,6 +251,10 @@ class GenericPage
|
||||
$this->mode = CACHE_TYPE_XML;
|
||||
else
|
||||
{
|
||||
// get alt header logo
|
||||
if ($ahl = DB::Aowow()->selectCell('SELECT altHeaderLogo FROM ?_home_featuredbox WHERE ?d BETWEEN startDate AND endDate ORDER BY id DESC', time()))
|
||||
$this->headerLogo = Util::defStatic($ahl);
|
||||
|
||||
$this->gUser = User::getUserGlobals();
|
||||
$this->pageTemplate['pageName'] = strtolower($pageCall);
|
||||
|
||||
@@ -130,6 +279,10 @@ class GenericPage
|
||||
$this->maintenance();
|
||||
else if (CFG_MAINTENANCE && User::isInGroup(U_GROUP_EMPLOYEE))
|
||||
Util::addNote(U_GROUP_EMPLOYEE, 'Maintenance mode enabled!');
|
||||
|
||||
// get errors from previous page from session and apply to template
|
||||
if (method_exists($this, 'applyCCErrors'))
|
||||
$this->applyCCErrors();
|
||||
}
|
||||
|
||||
/**********/
|
||||
@@ -152,23 +305,26 @@ class GenericPage
|
||||
if (!isset($this->category) || empty($this->validCats))
|
||||
return true;
|
||||
|
||||
switch (count($this->category))
|
||||
$c = $this->category; // shorthand
|
||||
|
||||
switch (count($c))
|
||||
{
|
||||
case 0: // no params works always
|
||||
return true;
|
||||
case 1: // null is valid || value in a 1-dim-array || key for a n-dim-array
|
||||
return $this->category[0] === null || in_array($this->category[0], $this->validCats) || !empty($this->validCats[$this->category[0]]);
|
||||
case 1: // null is valid || value in a 1-dim-array || (key for a n-dim-array && ( has more subcats || no further subCats ))
|
||||
$filtered = array_filter($this->validCats, function ($x) { return is_int($x); });
|
||||
return $c[0] === null || in_array($c[0], $filtered) || (!empty($this->validCats[$c[0]]) && (is_array($this->validCats[$c[0]]) || $this->validCats[$c[0]] === true));
|
||||
case 2: // first param has to be a key. otherwise invalid
|
||||
if (!isset($this->validCats[$this->category[0]]))
|
||||
if (!isset($this->validCats[$c[0]]))
|
||||
return false;
|
||||
|
||||
// check if the sub-array is n-imensional
|
||||
if (count($this->validCats[$this->category[0]]) == count($this->validCats[$this->category[0]], COUNT_RECURSIVE))
|
||||
return in_array($this->category[1], $this->validCats[$this->category[0]]); // second param is value in second level array
|
||||
if (is_array($this->validCats[$c[0]]) && count($this->validCats[$c[0]]) == count($this->validCats[$c[0]], COUNT_RECURSIVE))
|
||||
return in_array($c[1], $this->validCats[$c[0]]); // second param is value in second level array
|
||||
else
|
||||
return isset($this->validCats[$this->category[0]][$this->category[1]]); // check if params is key of another array
|
||||
return isset($this->validCats[$c[0]][$c[1]]); // check if params is key of another array
|
||||
case 3: // 3 params MUST point to a specific value
|
||||
return isset($this->validCats[$this->category[0]][$this->category[1]]) && in_array($this->category[2], $this->validCats[$this->category[0]][$this->category[1]]);
|
||||
return isset($this->validCats[$c[0]][$c[1]]) && in_array($c[2], $this->validCats[$c[0]][$c[1]]);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -178,15 +334,15 @@ class GenericPage
|
||||
/* Prepare Page */
|
||||
/****************/
|
||||
|
||||
private function prepareContent() // get from cache ?: run generators
|
||||
protected function prepareContent() // get from cache ?: run generators
|
||||
{
|
||||
if (!$this->loadCache())
|
||||
{
|
||||
$this->addArticle();
|
||||
|
||||
$this->generateContent();
|
||||
$this->generatePath();
|
||||
$this->generateTitle();
|
||||
$this->generateContent();
|
||||
|
||||
$this->applyGlobals();
|
||||
|
||||
@@ -194,11 +350,20 @@ class GenericPage
|
||||
}
|
||||
|
||||
if (isset($this->type) && isset($this->typeId))
|
||||
{
|
||||
$this->gPageInfo = array( // varies slightly for special pages like maps, user-dashboard or profiler
|
||||
'type' => $this->type,
|
||||
'typeId' => $this->typeId,
|
||||
'name' => $this->name
|
||||
);
|
||||
}
|
||||
else if (!empty($this->articleUrl))
|
||||
{
|
||||
$this->gPageInfo = array(
|
||||
'articleUrl' => $this->fullParams, // is actually be the url-param
|
||||
'editAccess' => isset($this->editAccess) ? $this->editAccess : (U_GROUP_ADMIN | U_GROUP_EDITOR | U_GROUP_BUREAU)
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($this->path))
|
||||
$this->pageTemplate['breadcrumb'] = $this->path;
|
||||
@@ -209,6 +374,13 @@ class GenericPage
|
||||
if (method_exists($this, 'postCache')) // e.g. update dates for events and such
|
||||
$this->postCache();
|
||||
|
||||
// determine contribute tabs
|
||||
if (isset($this->subject))
|
||||
{
|
||||
$x = get_class($this->subject);
|
||||
$this->contribute = $x::$contribute;
|
||||
}
|
||||
|
||||
if (!empty($this->hasComContent)) // get comments, screenshots, videos
|
||||
{
|
||||
$this->community = CommunityContent::getAll($this->type, $this->typeId, $jsGlobals);
|
||||
@@ -254,38 +426,57 @@ class GenericPage
|
||||
|
||||
private function addArticle() // get article & static infobox (run before processing jsGlobals)
|
||||
{
|
||||
if (empty($this->type) || !isset($this->typeId))
|
||||
return;
|
||||
|
||||
$article = DB::Aowow()->selectRow(
|
||||
'SELECT article, quickInfo, locale FROM ?_articles WHERE type = ?d AND typeId = ?d AND locale = ?d UNION ALL '.
|
||||
'SELECT article, quickInfo, locale FROM ?_articles WHERE type = ?d AND typeId = ?d AND locale = 0 ORDER BY locale DESC LIMIT 1',
|
||||
$this->type, $this->typeId, User::$localeId,
|
||||
$this->type, $this->typeId
|
||||
);
|
||||
$article = [];
|
||||
if (!empty($this->type) && isset($this->typeId))
|
||||
{
|
||||
$article = DB::Aowow()->selectRow('SELECT article, quickInfo, locale, editAccess FROM ?_articles WHERE type = ?d AND typeId = ?d AND locale = ?d UNION ALL SELECT article, quickInfo, locale, editAccess FROM ?_articles WHERE type = ?d AND typeId = ?d AND locale = 0 ORDER BY locale DESC LIMIT 1',
|
||||
$this->type, $this->typeId, User::$localeId, $this->type, $this->typeId
|
||||
);
|
||||
}
|
||||
else if (!empty($this->articleUrl))
|
||||
{
|
||||
$article = DB::Aowow()->selectRow('SELECT article, quickInfo, locale, editAccess FROM ?_articles WHERE url = ? AND locale = ?d UNION ALL SELECT article, quickInfo, locale, editAccess FROM ?_articles WHERE url = ? AND locale = 0 ORDER BY locale DESC LIMIT 1',
|
||||
$this->articleUrl, User::$localeId, $this->articleUrl
|
||||
);
|
||||
}
|
||||
|
||||
if ($article)
|
||||
{
|
||||
foreach ($article as $text)
|
||||
(new Markup($text))->parseGlobalsFromText($this->jsgBuffer);
|
||||
|
||||
$replace = array(
|
||||
'<script' => '<scr"+"ipt',
|
||||
'script>' => 'scr"+"ipt>',
|
||||
'HOST_URL' => HOST_URL,
|
||||
'STATIC_URL' => STATIC_URL
|
||||
);
|
||||
if ($article['article'])
|
||||
(new Markup($article['article']))->parseGlobalsFromText($this->jsgBuffer);
|
||||
if ($article['quickInfo'])
|
||||
(new Markup($article['quickInfo']))->parseGlobalsFromText($this->jsgBuffer);
|
||||
|
||||
$this->article = array(
|
||||
'text' => strtr($article['article'], $replace),
|
||||
'text' => Util::jsEscape(Util::defStatic($article['article'])),
|
||||
'params' => []
|
||||
);
|
||||
|
||||
if (!empty($this->type) && isset($this->typeId))
|
||||
$this->article['params']['dbpage'] = true;
|
||||
|
||||
// convert U_GROUP_* to MARKUP.CLASS_* (as seen in js-object Markup)
|
||||
if($article['editAccess'] & (U_GROUP_ADMIN | U_GROUP_VIP | U_GROUP_DEV))
|
||||
$this->article['params']['allow'] = '$Markup.CLASS_ADMIN';
|
||||
else if($article['editAccess'] & U_GROUP_STAFF)
|
||||
$this->article['params']['allow'] = '$Markup.CLASS_STAFF';
|
||||
else if($article['editAccess'] & U_GROUP_PREMIUM)
|
||||
$this->article['params']['allow'] = '$Markup.CLASS_PREMIUM';
|
||||
else if($article['editAccess'] & U_GROUP_PENDING)
|
||||
$this->article['params']['allow'] = '$Markup.CLASS_PENDING';
|
||||
else
|
||||
$this->article['params']['allow'] = '$Markup.CLASS_USER';
|
||||
|
||||
$this->editAccess = $article['editAccess'];
|
||||
|
||||
if (empty($this->infobox) && !empty($article['quickInfo']))
|
||||
$this->infobox = $article['quickInfo'];
|
||||
|
||||
if ($article['locale'] != User::$localeId)
|
||||
$this->article['params'] = ['prepend' => Util::jsEscape('<div class="notice-box"><span class="icon-bubble">'.Lang::main('englishOnly').'</span></div>')];
|
||||
$this->article['params']['prepend'] = '<div class="notice-box"><span class="icon-bubble">'.Lang::main('englishOnly').'</span></div>';
|
||||
|
||||
if (method_exists($this, 'postArticle')) // e.g. update variables in article
|
||||
$this->postArticle();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,14 +488,16 @@ class GenericPage
|
||||
// display occured notices
|
||||
if ($_ = Util::getNotes())
|
||||
{
|
||||
array_unshift($_, 'One or more errors occured, while generating this page.');
|
||||
|
||||
$this->announcements[0] = array(
|
||||
'parent' => 'announcement-0',
|
||||
'id' => 0,
|
||||
'mode' => 1,
|
||||
'status' => 1,
|
||||
'name' => 'internal error',
|
||||
'style' => 'padding-left: 40px; background-image: url('.STATIC_URL.'/images/announcements/warn-small.png); background-size: 15px 15px; background-position: 12px center; border: dashed 2px #C03030;',
|
||||
'text' => '[span id=inputbox-error]'.implode("[br]", $_).'[/span]',
|
||||
'style' => 'color: #ff3333; font-weight: bold; font-size: 14px; padding-left: 40px; background-image: url('.STATIC_URL.'/images/announcements/warn-small.png); background-size: 15px 15px; background-position: 12px center; border: dashed 2px #C03030;',
|
||||
'text' => '[span]'.implode("[br]", $_).'[/span]'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -316,22 +509,17 @@ class GenericPage
|
||||
{
|
||||
if ($t = Util::localizedString($v, 'text'))
|
||||
{
|
||||
$replace = array(
|
||||
'HOST_URL' => HOST_URL,
|
||||
'STATIC_URL' => STATIC_URL
|
||||
);
|
||||
|
||||
$_ = array(
|
||||
'parent' => 'announcement-'.$k,
|
||||
'id' => $v['id'],
|
||||
'mode' => $v['mode'],
|
||||
'status' => $v['status'],
|
||||
'name' => $v['name'],
|
||||
'text' => strtr($t, $replace)
|
||||
'text' => Util::defStatic($t)
|
||||
);
|
||||
|
||||
if ($v['style']) // may be empty
|
||||
$_['style'] = strtr($v['style'], $replace);
|
||||
$_['style'] = Util::defStatic($v['style']);
|
||||
|
||||
$this->announcements[$k] = $_;
|
||||
}
|
||||
@@ -366,8 +554,8 @@ class GenericPage
|
||||
array_unshift($this->title, Lang::main('nfPageTitle'));
|
||||
|
||||
$this->notFound = array(
|
||||
'title' => $this->typeId ? Util::ucFirst($title).' #'.$this->typeId : $title,
|
||||
'msg' => !$msg && $this->typeId ? sprintf(Lang::main('pageNotFound'), $title) : $msg
|
||||
'title' => isset($this->typeId) ? Util::ucFirst($title).' #'.$this->typeId : $title,
|
||||
'msg' => !$msg && isset($this->typeId) ? sprintf(Lang::main('pageNotFound'), $title) : $msg
|
||||
);
|
||||
$this->hasComContent = false;
|
||||
Util::arraySumByKey($this->mysql, DB::Aowow()->getStatistics(), DB::World()->getStatistics());
|
||||
@@ -375,29 +563,36 @@ class GenericPage
|
||||
if (isset($this->tabId))
|
||||
$this->pageTemplate['activeTab'] = $this->tabId;
|
||||
|
||||
$this->display('text-page-generic');
|
||||
header('HTTP/1.0 404 Not Found', true, 404);
|
||||
|
||||
$this->display('list-page-generic');
|
||||
exit();
|
||||
}
|
||||
|
||||
public function error() // unknown page
|
||||
{
|
||||
$this->path = null;
|
||||
$this->tabId = null;
|
||||
$this->type = -99; // get error-article
|
||||
$this->typeId = 0;
|
||||
$this->title[] = Lang::main('errPageTitle');
|
||||
$this->name = Lang::main('errPageTitle');
|
||||
$this->path = null;
|
||||
$this->tabId = null;
|
||||
$this->articleUrl = 'page-not-found';
|
||||
$this->title[] = Lang::main('errPageTitle');
|
||||
$this->name = Lang::main('errPageTitle');
|
||||
$this->lvTabs = [];
|
||||
|
||||
$this->addArticle();
|
||||
|
||||
Util::arraySumByKey($this->mysql, DB::Aowow()->getStatistics(), DB::World()->getStatistics());
|
||||
|
||||
$this->display('text-page-generic');
|
||||
header('HTTP/1.0 404 Not Found', true, 404);
|
||||
|
||||
$this->display('list-page-generic');
|
||||
exit();
|
||||
}
|
||||
|
||||
public function maintenance() // display brb gnomes
|
||||
{
|
||||
header('HTTP/1.0 503 Service Temporarily Unavailable', true, 503);
|
||||
header('Retry-After: '.(3 * HOUR));
|
||||
|
||||
$this->display('maintenance');
|
||||
exit();
|
||||
}
|
||||
@@ -427,7 +622,10 @@ class GenericPage
|
||||
$this->prepareContent();
|
||||
|
||||
if (!$this->isSaneInclude('template/pages/', $this->tpl))
|
||||
die(User::isInGroup(U_GROUP_EMPLOYEE) ? 'Error: nonexistant template requested: template/pages/'.$this->tpl.'.tpl.php' : null);
|
||||
{
|
||||
trigger_error('Error: nonexistant template requested: template/pages/'.$this->tpl.'.tpl.php', E_USER_ERROR);
|
||||
$this->error();
|
||||
}
|
||||
|
||||
$this->addAnnouncements();
|
||||
|
||||
@@ -490,22 +688,32 @@ class GenericPage
|
||||
$$n = $v;
|
||||
|
||||
if (!$this->isSaneInclude('template/bricks/', $file))
|
||||
echo User::isInGroup(U_GROUP_EMPLOYEE) ? "\n\nError: nonexistant template requested: template/bricks/".$file.".tpl.php\n\n" : null;
|
||||
trigger_error('Nonexistant template requested: template/bricks/'.$file.'.tpl.php', E_USER_ERROR);
|
||||
else
|
||||
include('template/bricks/'.$file.'.tpl.php');
|
||||
}
|
||||
|
||||
public function lvBrick($file, array $localVars = []) // load listview
|
||||
public function lvBrick($file) // load listview addIns
|
||||
{
|
||||
foreach ($localVars as $n => $v)
|
||||
$$n = $v;
|
||||
|
||||
if (!$this->isSaneInclude('template/listviews/', $file))
|
||||
echo User::isInGroup(U_GROUP_EMPLOYEE) ? "\n\nError: nonexistant template requested: template/listviews/".$file.".tpl.php\n\n" : null;
|
||||
trigger_error('Nonexistant Listview addin requested: template/listviews/'.$file.'.tpl.php', E_USER_ERROR);
|
||||
else
|
||||
include('template/listviews/'.$file.'.tpl.php');
|
||||
}
|
||||
|
||||
public function localizedBrick($file, $loc = LOCALE_EN) // load brick with more text then vars
|
||||
{
|
||||
if (!$this->isSaneInclude('template/localized/', $file.'_'.$loc))
|
||||
{
|
||||
if ($loc == LOCALE_EN || !$this->isSaneInclude('template/localized/', $file.'_'.LOCALE_EN))
|
||||
trigger_error('Nonexistant template requested: template/localized/'.$file.'_'.$loc.'.tpl.php', E_USER_ERROR);
|
||||
else
|
||||
include('template/localized/'.$file.'_'.LOCALE_EN.'.tpl.php');
|
||||
}
|
||||
else
|
||||
include('template/localized/'.$file.'_'.$loc.'.tpl.php');
|
||||
}
|
||||
|
||||
/**********************/
|
||||
/* Prepare js-Globals */
|
||||
/**********************/
|
||||
@@ -577,8 +785,12 @@ class GenericPage
|
||||
case TYPE_RACE: $jsg[TYPE_RACE] = ['g_races', [], []]; break;
|
||||
case TYPE_SKILL: $jsg[TYPE_SKILL] = ['g_skills', [], []]; break;
|
||||
case TYPE_CURRENCY: $jsg[TYPE_CURRENCY] = ['g_gatheredcurrencies', [], []]; break;
|
||||
case TYPE_SOUND: $jsg[TYPE_SOUND] = ['g_sounds', [], []]; break;
|
||||
case TYPE_ICON: $jsg[TYPE_ICON] = ['g_icons', [], []]; break;
|
||||
// well, this is awkward
|
||||
case TYPE_USER: $jsg[TYPE_USER] = ['g_users', [], []]; break;
|
||||
case TYPE_EMOTE: $jsg[TYPE_EMOTE] = ['g_emotes', [], []]; break;
|
||||
case TYPE_ENCHANTMENT: $jsg[TYPE_ENCHANTMENT] = ['g_enchantments', [], []]; break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,27 +807,7 @@ class GenericPage
|
||||
|
||||
$this->initJSGlobal($type);
|
||||
|
||||
// todo (med): properly distinguish holidayId and eventId
|
||||
$cnd = [CFG_SQL_LIMIT_NONE];
|
||||
if ($type == TYPE_WORLDEVENT)
|
||||
{
|
||||
$hIds = array_filter($ids, function($v) { return $v > 0; });
|
||||
$eIds = array_filter($ids, function($v) { return $v < 0; });
|
||||
|
||||
if ($hIds)
|
||||
$cnd[] = ['holidayId', array_unique($hIds, SORT_NUMERIC)];
|
||||
|
||||
if ($eIds)
|
||||
{
|
||||
array_walk($eIds, function(&$v) { $v = abs($v);});
|
||||
$cnd[] = ['e.id', array_unique($eIds, SORT_NUMERIC)];
|
||||
}
|
||||
|
||||
if ($eIds && $hIds)
|
||||
$cnd[] = 'OR';
|
||||
}
|
||||
else
|
||||
$cnd [] = ['id', array_unique($ids, SORT_NUMERIC)];
|
||||
$cnd = [CFG_SQL_LIMIT_NONE, ['id', array_unique($ids, SORT_NUMERIC)]];
|
||||
|
||||
switch ($type)
|
||||
{
|
||||
@@ -635,8 +827,11 @@ class GenericPage
|
||||
case TYPE_RACE: $obj = new CharRaceList($cnd); break;
|
||||
case TYPE_SKILL: $obj = new SkillList($cnd); break;
|
||||
case TYPE_CURRENCY: $obj = new CurrencyList($cnd); break;
|
||||
case TYPE_SOUND: $obj = new SoundList($cnd); break;
|
||||
// "um, eh":, he ums and ehs.
|
||||
case TYPE_USER: $obj = new UserList($cnd); break;
|
||||
case TYPE_EMOTE: $obj = new EmoteList($cnd); break;
|
||||
case TYPE_ENCHANTMENT: $obj = new EnchantmentList($cnd); break;
|
||||
default: continue;
|
||||
}
|
||||
|
||||
@@ -659,8 +854,9 @@ class GenericPage
|
||||
if (!CFG_CACHE_MODE || CFG_DEBUG)
|
||||
return;
|
||||
|
||||
$cKey = $this->generateCacheKey();
|
||||
$cache = [];
|
||||
$noCache = ['coError', 'ssError', 'viError'];
|
||||
$cKey = $this->generateCacheKey();
|
||||
$cache = [];
|
||||
if (!$saveString)
|
||||
{
|
||||
foreach ($this as $key => $val)
|
||||
@@ -669,7 +865,8 @@ class GenericPage
|
||||
{
|
||||
// public, protected and an undocumented flag added to properties created on the fly..?
|
||||
if ((new ReflectionProperty($this, $key))->getModifiers() & 0x1300)
|
||||
$cache[$key] = $val;
|
||||
if (!in_array($key, $noCache))
|
||||
$cache[$key] = $val;
|
||||
}
|
||||
catch (ReflectionException $e) { } // shut up!
|
||||
}
|
||||
@@ -748,7 +945,7 @@ class GenericPage
|
||||
$type = $cache['isString'];
|
||||
$data = $cache['data'];
|
||||
|
||||
if ($cache['timestamp'] + CFG_CACHE_DECAY <= time() || $cache['revision'] < AOWOW_REVISION)
|
||||
if ($cache['timestamp'] + CFG_CACHE_DECAY <= time() || $cache['revision'] != AOWOW_REVISION)
|
||||
$cache = null;
|
||||
else
|
||||
$this->cacheLoaded = [CACHE_MODE_MEMCACHED, $cache['timestamp']];
|
||||
@@ -771,7 +968,7 @@ class GenericPage
|
||||
|
||||
list($time, $rev, $type) = explode(' ', $cache[0]);
|
||||
|
||||
if ($time + CFG_CACHE_DECAY <= time() || $rev < AOWOW_REVISION)
|
||||
if ($time + CFG_CACHE_DECAY <= time() || $rev != AOWOW_REVISION)
|
||||
$cache = null;
|
||||
else
|
||||
{
|
||||
|
||||
143
pages/guild.php
Normal file
143
pages/guild.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// menuId 5: Profiler g_initPath()
|
||||
// tabId 1: Tools g_initHeader()
|
||||
class GuildPage extends GenericPage
|
||||
{
|
||||
use TrProfiler;
|
||||
|
||||
protected $lvTabs = [];
|
||||
|
||||
protected $tabId = 1;
|
||||
protected $path = [1, 5, 2];
|
||||
protected $tpl = 'roster';
|
||||
protected $js = ['profile_all.js', 'profile.js'];
|
||||
protected $css = [['path' => 'Profiler.css']];
|
||||
|
||||
public function __construct($pageCall, $pageParam)
|
||||
{
|
||||
$params = array_map('urldecode', explode('.', $pageParam));
|
||||
if ($params[0])
|
||||
$params[0] = Profiler::urlize($params[0]);
|
||||
if (isset($params[1]))
|
||||
$params[1] = Profiler::urlize($params[1]);
|
||||
|
||||
parent::__construct($pageCall, $pageParam);
|
||||
|
||||
if (count($params) == 1 && intval($params[0]))
|
||||
{
|
||||
$this->subject = new LocalGuildList(array(['g.id', intval($params[0])]));
|
||||
if ($this->subject->error)
|
||||
$this->notFound();
|
||||
|
||||
header('Location: '.$this->subject->getProfileUrl(), true, 302);
|
||||
}
|
||||
else if (count($params) == 3)
|
||||
{
|
||||
$this->getSubjectFromUrl($pageParam);
|
||||
if (!$this->subjectName)
|
||||
$this->notFound();
|
||||
|
||||
// 3 possibilities
|
||||
// 1) already synced to aowow
|
||||
if ($subject = DB::Aowow()->selectRow('SELECT id, realmGUID, cuFlags FROM ?_profiler_guild WHERE realm = ?d AND nameUrl = ?', $this->realmId, Profiler::urlize($this->subjectName)))
|
||||
{
|
||||
if ($subject['cuFlags'] & PROFILER_CU_NEEDS_RESYNC)
|
||||
{
|
||||
$this->handleIncompleteData($subject['realmGUID']);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->subjectGUID = $subject['id'];
|
||||
$this->subject = new LocalGuildList(array(['id', $subject['id']]));
|
||||
if ($this->subject->error)
|
||||
$this->notFound();
|
||||
|
||||
$this->profile = $params;
|
||||
$this->name = sprintf(Lang::profiler('guildRoster'), $this->subject->getField('name'));
|
||||
}
|
||||
// 2) not yet synced but exists on realm (wont work if we get passed an urlized name, but there is nothing we can do about it)
|
||||
else if ($team = DB::Characters($this->realmId)->selectRow('SELECT guildid AS realmGUID, name FROM guild WHERE name = ?', Util::ucFirst($this->subjectName)))
|
||||
{
|
||||
$team['realm'] = $this->realmId;
|
||||
$team['cuFlags'] = PROFILER_CU_NEEDS_RESYNC;
|
||||
|
||||
// create entry from realm with basic info
|
||||
DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_guild (?#) VALUES (?a)', array_keys($team), array_values($team));
|
||||
|
||||
$this->handleIncompleteData($team['realmGUID']);
|
||||
}
|
||||
// 3) does not exist at all
|
||||
else
|
||||
$this->notFound();
|
||||
}
|
||||
else
|
||||
$this->notFound();
|
||||
}
|
||||
|
||||
protected function generateTitle()
|
||||
{
|
||||
$team = !empty($this->subject) ? $this->subject->getField('name') : $this->subjectName;
|
||||
$team .= ' ('.$this->realm.' - '.Lang::profiler('regions', $this->region).')';
|
||||
|
||||
array_unshift($this->title, $team, Util::ucFirst(Lang::profiler('profiler')));
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
if ($this->doResync)
|
||||
return;
|
||||
|
||||
$this->addJS('?data=realms.weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
||||
|
||||
$this->redButtons[BUTTON_RESYNC] = [$this->subjectGUID, 'guild'];
|
||||
|
||||
/****************/
|
||||
/* Main Content */
|
||||
/****************/
|
||||
|
||||
|
||||
// statistic calculations here
|
||||
|
||||
// smuggle the guild ranks into the html
|
||||
if ($ranks = DB::Aowow()->selectCol('SELECT rank AS ARRAY_KEY, name FROM ?_profiler_guild_rank WHERE guildId = ?d', $this->subjectGUID))
|
||||
$this->extraHTML = '<script type="text/javascript">var guild_ranks = '.Util::toJSON($ranks).';</script>';
|
||||
|
||||
|
||||
/**************/
|
||||
/* Extra Tabs */
|
||||
/**************/
|
||||
|
||||
// tab: members
|
||||
$member = new LocalProfileList(array(['p.guild', $this->subjectGUID]));
|
||||
if (!$member->error)
|
||||
{
|
||||
$this->lvTabs[] = ['profile', array(
|
||||
'data' => array_values($member->getListviewData(PROFILEINFO_CHARACTER | PROFILEINFO_ARENA)),
|
||||
'sort' => [-15],
|
||||
'visibleCols' => ['race', 'classs', 'level', 'talents', 'gearscore', 'achievementpoints', 'guildrank'],
|
||||
'hiddenCols' => ['guild', 'location']
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
public function notFound($title = '', $msg = '')
|
||||
{
|
||||
return parent::notFound($title ?: Util::ucFirst(Lang::profiler('profiler')), $msg ?: Lang::profiler('notFound', 'guild'));
|
||||
}
|
||||
|
||||
private function handleIncompleteData($teamGuid)
|
||||
{
|
||||
//display empty page and queue status
|
||||
$newId = Profiler::scheduleResync(TYPE_GUILD, $this->realmId, $teamGuid);
|
||||
|
||||
$this->doResync = ['guild', $newId];
|
||||
$this->initialSync();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
116
pages/guilds.php
Normal file
116
pages/guilds.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// menuId 5: Profiler g_initPath()
|
||||
// tabId 1: Tools g_initHeader()
|
||||
class GuildsPage extends GenericPage
|
||||
{
|
||||
use TrProfiler;
|
||||
|
||||
protected $tabId = 1;
|
||||
protected $path = [1, 5, 2];
|
||||
protected $tpl = 'guilds';
|
||||
protected $js = ['filters.js', 'profile_all.js', 'profile.js'];
|
||||
|
||||
public function __construct($pageCall, $pageParam)
|
||||
{
|
||||
$this->getSubjectFromUrl($pageParam);
|
||||
|
||||
$this->filterObj = new GuildListFilter();
|
||||
|
||||
foreach (Profiler::getRealms() as $idx => $r)
|
||||
{
|
||||
if ($this->region && $r['region'] != $this->region)
|
||||
continue;
|
||||
|
||||
if ($this->realm && $r['name'] != $this->realm)
|
||||
continue;
|
||||
|
||||
$this->sumSubjects += DB::Characters($idx)->selectCell('SELECT COUNT(*) FROM guild');
|
||||
}
|
||||
|
||||
parent::__construct($pageCall, $pageParam);
|
||||
|
||||
$this->name = Lang::profiler('guilds');
|
||||
$this->subCat = $pageParam ? '='.$pageParam : '';
|
||||
}
|
||||
|
||||
protected function generateTitle()
|
||||
{
|
||||
if ($this->realm)
|
||||
array_unshift($this->title, $this->realm,/* CFG_BATTLEGROUP,*/ Lang::profiler('regions', $this->region), Lang::profiler('guilds'));
|
||||
else if ($this->region)
|
||||
array_unshift($this->title, Lang::profiler('regions', $this->region), Lang::profiler('guilds'));
|
||||
else
|
||||
array_unshift($this->title, Lang::profiler('guilds'));
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
$this->addJS('?data=realms&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
||||
|
||||
$conditions = array(
|
||||
['c.deleteInfos_Account', null],
|
||||
['c.level', MAX_LEVEL, '<='], // prevents JS errors
|
||||
[['c.extra_flags', Profiler::CHAR_GMFLAGS, '&'], 0]
|
||||
);
|
||||
if ($_ = $this->filterObj->getConditions())
|
||||
$conditions[] = $_;
|
||||
|
||||
// recreate form selection
|
||||
$this->filter = $this->filterObj->getForm();
|
||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
|
||||
$this->filter['initData'] = ['type' => 'guilds'];
|
||||
|
||||
$tabData = array(
|
||||
'id' => 'guilds',
|
||||
'hideCount' => 1,
|
||||
'sort' => [-3],
|
||||
'visibleCols' => ['members', 'achievementpoints', 'gearscore'],
|
||||
'hiddenCols' => ['guild'],
|
||||
);
|
||||
|
||||
$miscParams = [];
|
||||
if ($this->realm)
|
||||
$miscParams['sv'] = $this->realm;
|
||||
if ($this->region)
|
||||
$miscParams['rg'] = $this->region;
|
||||
|
||||
$guilds = new RemoteGuildList($conditions, $miscParams);
|
||||
if (!$guilds->error)
|
||||
{
|
||||
$guilds->initializeLocalEntries();
|
||||
|
||||
$dFields = $guilds->hasDiffFields(['faction', 'type']);
|
||||
if (!($dFields & 0x1))
|
||||
$tabData['hiddenCols'][] = 'faction';
|
||||
|
||||
if (($dFields & 0x2))
|
||||
$tabData['visibleCols'][] = 'size';
|
||||
|
||||
$tabData['data'] = array_values($guilds->getListviewData());
|
||||
|
||||
// create note if search limit was exceeded
|
||||
if ($this->filter['query'] && $guilds->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
{
|
||||
$tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_guildsfound2', $this->sumSubjects, $guilds->getMatches());
|
||||
$tabData['_truncated'] = 1;
|
||||
}
|
||||
else if ($guilds->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
$tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_guildsfound', $this->sumSubjects, 0);
|
||||
|
||||
if ($this->filterObj->error)
|
||||
$tabData['_errors'] = 1;
|
||||
}
|
||||
|
||||
$this->lvTabs[] = ['profile', $tabData, 'membersCol'];
|
||||
|
||||
Lang::sort('game', 'cl');
|
||||
Lang::sort('game', 'ra');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -6,11 +6,12 @@ if (!defined('AOWOW_REVISION'))
|
||||
|
||||
class HomePage extends GenericPage
|
||||
{
|
||||
protected $tpl = 'home';
|
||||
protected $js = ['home.js'];
|
||||
protected $css = [['path' => 'home.css']];
|
||||
protected $tpl = 'home';
|
||||
protected $js = ['home.js'];
|
||||
protected $css = [['path' => 'home.css']];
|
||||
|
||||
protected $news = [];
|
||||
protected $featuredBox = [];
|
||||
protected $oneliner = '';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -21,31 +22,40 @@ class HomePage extends GenericPage
|
||||
{
|
||||
$this->addCSS(['string' => '.announcement { margin: auto; max-width: 1200px; padding: 0px 15px 15px 15px }']);
|
||||
|
||||
// load news
|
||||
$this->news = DB::Aowow()->selectRow('SELECT id as ARRAY_KEY, n.* FROM ?_news n WHERE active = 1 ORDER BY id DESC LIMIT 1');
|
||||
if (!$this->news)
|
||||
// load oneliner
|
||||
if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_home_oneliner WHERE active = 1 LIMIT 1'))
|
||||
$this->oneliner = Util::jsEscape(Util::localizedString($_, 'text'));
|
||||
|
||||
// load featuredBox (user web server time)
|
||||
$this->featuredBox = DB::Aowow()->selectRow('SELECT id as ARRAY_KEY, n.* FROM ?_home_featuredbox n WHERE ?d BETWEEN startDate AND endDate ORDER BY id DESC LIMIT 1', time());
|
||||
if (!$this->featuredBox)
|
||||
return;
|
||||
|
||||
$this->news['text'] = Util::localizedString($this->news, 'text', true);
|
||||
$this->featuredBox = Util::defStatic($this->featuredBox);
|
||||
|
||||
if ($_ = (new Markup($this->news['text']))->parseGlobalsFromText())
|
||||
$this->featuredBox['text'] = Util::localizedString($this->featuredBox, 'text', true);
|
||||
|
||||
if ($_ = (new Markup($this->featuredBox['text']))->parseGlobalsFromText())
|
||||
$this->extendGlobalData($_);
|
||||
|
||||
if (empty($this->news['bgImgUrl']))
|
||||
$this->news['bgImgUrl'] = STATIC_URL.'/images/'.User::$localeString.'/mainpage-bg-news.jpg';
|
||||
else
|
||||
$this->news['bgImgUrl'] = strtr($this->news['bgImgUrl'], ['HOST_URL' => HOST_URL, 'STATIC_URL' => STATIC_URL]);
|
||||
if (empty($this->featuredBox['boxBG']))
|
||||
$this->featuredBox['boxBG'] = STATIC_URL.'/images/'.User::$localeString.'/mainpage-bg-news.jpg';
|
||||
|
||||
// load overlay links
|
||||
$this->news['overlays'] = DB::Aowow()->select('SELECT * FROM ?_news_overlay WHERE newsId = ?d', $this->news['id']);
|
||||
foreach ($this->news['overlays'] as &$o)
|
||||
$this->featuredBox['overlays'] = DB::Aowow()->select('SELECT * FROM ?_home_featuredbox_overlay WHERE featureId = ?d', $this->featuredBox['id']);
|
||||
foreach ($this->featuredBox['overlays'] as &$o)
|
||||
{
|
||||
$o['title'] = Util::localizedString($o, 'title', true);
|
||||
$o['title'] = strtr($o['title'], ['HOST_URL' => HOST_URL, 'STATIC_URL' => STATIC_URL]);
|
||||
$o['title'] = Util::defStatic($o['title']);
|
||||
}
|
||||
}
|
||||
|
||||
protected function generateTitle() {}
|
||||
protected function generateTitle()
|
||||
{
|
||||
if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_home_titles WHERE active = 1 AND title_loc?d <> "" ORDER BY RAND() LIMIT 1', User::$localeId))
|
||||
$this->title[0] .= Lang::main('colon').Util::localizedString($_, 'title');
|
||||
}
|
||||
|
||||
protected function generatePath() {}
|
||||
}
|
||||
|
||||
|
||||
116
pages/icon.php
Normal file
116
pages/icon.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// menuId 31: Icons g_initPath()
|
||||
// tabId 0: Database g_initHeader()
|
||||
class IconPage extends GenericPage
|
||||
{
|
||||
use DetailPage;
|
||||
|
||||
protected $type = TYPE_ICON;
|
||||
protected $typeId = 0;
|
||||
protected $tpl = 'icon';
|
||||
protected $path = [0, 31];
|
||||
protected $tabId = 0;
|
||||
protected $mode = CACHE_TYPE_PAGE;
|
||||
|
||||
public function __construct($pageCall, $id)
|
||||
{
|
||||
parent::__construct($pageCall, $id);
|
||||
|
||||
$this->typeId = intVal($id);
|
||||
|
||||
$this->subject = new IconList(array(['id', $this->typeId]));
|
||||
if ($this->subject->error)
|
||||
$this->notFound(Util::ucFirst(Lang::game('icon')), Lang::icon('notFound'));
|
||||
|
||||
$this->extendGlobalData($this->subject->getJSGlobals());
|
||||
|
||||
$this->name = Util::ucFirst($this->subject->getField('name'));
|
||||
$this->icon = $this->subject->getField('name', true, true);
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
/****************/
|
||||
/* Main Content */
|
||||
/****************/
|
||||
|
||||
$this->redButtons = array(
|
||||
BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId],
|
||||
BUTTON_WOWHEAD => false
|
||||
);
|
||||
|
||||
|
||||
/**************/
|
||||
/* Extra Tabs */
|
||||
/**************/
|
||||
|
||||
// used by: spell
|
||||
$ubSpells = new SpellList(array(['iconId', $this->typeId]));
|
||||
if (!$ubSpells->error)
|
||||
{
|
||||
$this->extendGlobalData($ubSpells->getJsGlobals());
|
||||
$this->lvTabs[] = [SpellList::$brickFile, array(
|
||||
'data' => array_values($ubSpells->getListviewData()),
|
||||
'id' => 'used-by-spell'
|
||||
)];
|
||||
}
|
||||
|
||||
// used by: item
|
||||
$ubItems = new ItemList(array(['iconId', $this->typeId]));
|
||||
if (!$ubItems->error)
|
||||
{
|
||||
$this->extendGlobalData($ubItems->getJsGlobals());
|
||||
$this->lvTabs[] = [ItemList::$brickFile, array(
|
||||
'data' => array_values($ubItems->getListviewData()),
|
||||
'id' => 'used-by-item'
|
||||
)];
|
||||
}
|
||||
|
||||
// used by: achievement
|
||||
$ubAchievements = new AchievementList(array(['iconId', $this->typeId]));
|
||||
if (!$ubAchievements->error)
|
||||
{
|
||||
$this->extendGlobalData($ubAchievements->getJsGlobals());
|
||||
$this->lvTabs[] = [AchievementList::$brickFile, array(
|
||||
'data' => array_values($ubAchievements->getListviewData()),
|
||||
'id' => 'used-by-achievement'
|
||||
)];
|
||||
}
|
||||
|
||||
// used by: currency
|
||||
$ubCurrencies = new CurrencyList(array(['iconId', $this->typeId]));
|
||||
if (!$ubCurrencies->error)
|
||||
{
|
||||
$this->extendGlobalData($ubCurrencies->getJsGlobals());
|
||||
$this->lvTabs[] = [CurrencyList::$brickFile, array(
|
||||
'data' => array_values($ubCurrencies->getListviewData()),
|
||||
'id' => 'used-by-currency'
|
||||
)];
|
||||
}
|
||||
|
||||
// used by: hunter pet
|
||||
$ubPets = new PetList(array(['iconId', $this->typeId]));
|
||||
if (!$ubPets->error)
|
||||
{
|
||||
$this->extendGlobalData($ubPets->getJsGlobals());
|
||||
$this->lvTabs[] = [PetList::$brickFile, array(
|
||||
'data' => array_values($ubPets->getListviewData()),
|
||||
'id' => 'used-by-pet'
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
protected function generateTitle()
|
||||
{
|
||||
array_unshift($this->title, $this->name, Util::ucFirst(Lang::game('icon')));
|
||||
}
|
||||
|
||||
protected function generatePath() { }
|
||||
}
|
||||
|
||||
?>
|
||||
110
pages/icons.php
Normal file
110
pages/icons.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// menuId 31: Icons g_initPath()
|
||||
// tabId 0: Database g_initHeader()
|
||||
class IconsPage extends GenericPage
|
||||
{
|
||||
use ListPage;
|
||||
|
||||
protected $type = TYPE_ICON;
|
||||
protected $tpl = 'icons';
|
||||
protected $path = [0, 31];
|
||||
protected $tabId = 0;
|
||||
protected $mode = CACHE_TYPE_PAGE;
|
||||
protected $js = ['filters.js'];
|
||||
|
||||
public function __construct($pageCall)
|
||||
{
|
||||
$this->filterObj = new IconListFilter();
|
||||
|
||||
parent::__construct($pageCall);
|
||||
|
||||
$this->name = Util::ucFirst(Lang::game('icons'));
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
$tabData = array(
|
||||
'data' => [],
|
||||
);
|
||||
|
||||
$sqlLimit = 600; // fits better onto the grid
|
||||
|
||||
$conditions = [$sqlLimit];
|
||||
|
||||
if (!User::isInGroup(U_GROUP_EMPLOYEE))
|
||||
$conditions[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0];
|
||||
|
||||
if ($_ = $this->filterObj->getConditions())
|
||||
$conditions[] = $_;
|
||||
|
||||
$icons = new IconList($conditions);
|
||||
|
||||
$tabData['data'] = array_values($icons->getListviewData());
|
||||
$this->extendGlobalData($icons->getJSGlobals());
|
||||
|
||||
// recreate form selection
|
||||
$this->filter = $this->filterObj->getForm();
|
||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
|
||||
$this->filter['initData'] = ['init' => 'icons'];
|
||||
|
||||
if ($x = $this->filterObj->getSetCriteria())
|
||||
$this->filter['initData']['sc'] = $x;
|
||||
|
||||
if ($icons->getMatches() > $sqlLimit)
|
||||
{
|
||||
$tabData['note'] = sprintf(Util::$tryFilteringEntityString, $icons->getMatches(), 'LANG.types[29][3]', $sqlLimit);
|
||||
$tabData['_truncated'] = 1;
|
||||
}
|
||||
|
||||
if ($this->filterObj->error)
|
||||
$tabData['_errors'] = '$1';
|
||||
|
||||
$this->lvTabs[] = ['icongallery', $tabData];
|
||||
}
|
||||
|
||||
protected function generateTitle()
|
||||
{
|
||||
$setCrt = $this->filterObj->getSetCriteria();
|
||||
$title = $this->name;
|
||||
if (isset($setCrt['cr']) && count($setCrt['cr']) == 1)
|
||||
{
|
||||
switch ($setCrt['cr'][0])
|
||||
{
|
||||
case 1:
|
||||
$title = Util::ucFirst(Lang::game('item')).' '.$title;
|
||||
break;
|
||||
case 2:
|
||||
$title = Util::ucFirst(Lang::game('spell')).' '.$title;
|
||||
break;
|
||||
case 3:
|
||||
$title = Util::ucFirst(Lang::game('achievement')).' '.$title;
|
||||
break;
|
||||
case 6:
|
||||
$title = Util::ucFirst(Lang::game('currency')).' '.$title;
|
||||
break;
|
||||
case 9:
|
||||
$title = Util::ucFirst(Lang::game('pet')).' '.$title;
|
||||
break;
|
||||
case 11:
|
||||
$title = Util::ucFirst(Lang::game('class')).' '.$title;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
array_unshift($this->title, $title);
|
||||
}
|
||||
|
||||
protected function generatePath()
|
||||
{
|
||||
$setCrt = $this->filterObj->getSetCriteria();
|
||||
if (isset($setCrt['cr']) && count($setCrt['cr']) == 1)
|
||||
$this->path[] = $setCrt['cr'][0];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
484
pages/item.php
484
pages/item.php
@@ -54,7 +54,7 @@ class ItemPage extends genericPage
|
||||
|
||||
// allow lookup by name for xml
|
||||
if (!is_numeric($param))
|
||||
$conditions = [['name_loc'.User::$localeId, utf8_encode(urldecode($param))]];
|
||||
$conditions = [['name_loc'.User::$localeId, urldecode($param)]];
|
||||
}
|
||||
|
||||
$this->subject = new ItemList($conditions);
|
||||
@@ -167,9 +167,11 @@ class ItemPage extends genericPage
|
||||
}
|
||||
|
||||
// related holiday
|
||||
if ($hId = $this->subject->getField('holidayId'))
|
||||
if ($hName = DB::Aowow()->selectRow('SELECT * FROM ?_holidays WHERE id = ?d', $hId))
|
||||
$infobox[] = Lang::game('eventShort').Lang::main('colon').'[url=?event='.$hId.']'.Util::localizedString($hName, 'name').'[/url]';
|
||||
if ($eId = $this->subject->getField('eventId'))
|
||||
{
|
||||
$this->extendGlobalIds(TYPE_WORLDEVENT, $eId);
|
||||
$infobox[] = Lang::game('eventShort').Lang::main('colon').'[event='.$eId.']';
|
||||
}
|
||||
|
||||
// tool
|
||||
if ($tId = $this->subject->getField('totemCategory'))
|
||||
@@ -259,7 +261,7 @@ class ItemPage extends genericPage
|
||||
|
||||
// avg auction buyout
|
||||
if (in_array($this->subject->getField('bonding'), [0, 2, 3]))
|
||||
if ($_ = Util::getBuyoutForItem($this->typeId))
|
||||
if ($_ = Profiler::getBuyoutForItem($this->typeId))
|
||||
$infobox[] = '[tooltip=tooltip_buyoutprice]'.Lang::item('buyout.').'[/tooltip]'.Lang::main('colon').'[money='.$_.']'.$each;
|
||||
|
||||
// avg money contained
|
||||
@@ -326,34 +328,34 @@ class ItemPage extends genericPage
|
||||
|
||||
$_cu = in_array($_class, [ITEM_CLASS_WEAPON, ITEM_CLASS_ARMOR]) || $this->subject->getField('gemEnchantmentId');
|
||||
|
||||
// pageText
|
||||
$pageText = [];
|
||||
if ($this->pageText = Game::getPageText($this->subject->getField('pageTextId')))
|
||||
{
|
||||
$this->addJS('Book.js');
|
||||
$this->addCSS(['path' => 'Book.css']);
|
||||
}
|
||||
|
||||
$this->headIcons = [$this->subject->getField('iconString'), $this->subject->getField('stackable')];
|
||||
$this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
|
||||
$this->tooltip = $this->subject->renderTooltip(true);
|
||||
$this->redButtons = array(
|
||||
BUTTON_WOWHEAD => true,
|
||||
BUTTON_LINKS => ['color' => 'ff'.Util::$rarityColorStings[$this->subject->getField('quality')], 'linkId' => 'item:'.$this->typeId.':0:0:0:0:0:0:0:0'],
|
||||
BUTTON_VIEW3D => in_array($_slot, $_visSlots) && $_model ? ['displayId' => $this->subject->getField('displayId'), 'slot' => $_slot, 'type' => TYPE_ITEM, 'typeId' => $this->typeId] : false,
|
||||
BUTTON_COMPARE => $_cu,
|
||||
BUTTON_EQUIP => in_array($_class, [ITEM_CLASS_WEAPON, ITEM_CLASS_ARMOR]),
|
||||
BUTTON_UPGRADE => $_cu ? ['class' => $_class, 'slot' => $_slot] : false
|
||||
BUTTON_UPGRADE => ($_cu ? ['class' => $_class, 'slot' => $_slot] : false),
|
||||
BUTTON_LINKS => array(
|
||||
'linkColor' => 'ff'.Game::$rarityColorStings[$this->subject->getField('quality')],
|
||||
'linkId' => 'item:'.$this->typeId.':0:0:0:0:0:0:0:0',
|
||||
'linkName' => $this->name,
|
||||
'type' => $this->type,
|
||||
'typeId' => $this->typeId
|
||||
)
|
||||
);
|
||||
|
||||
// availablility
|
||||
$this->disabled = false; // todo (med): get itemSources (which are not yet in DB :x) or
|
||||
|
||||
// pageText
|
||||
if ($next = $this->subject->getField('pageTextId'))
|
||||
{
|
||||
$this->addJS('Book.js');
|
||||
$this->addCSS(['path' => 'Book.css']);
|
||||
|
||||
while ($next)
|
||||
{
|
||||
$row = DB::World()->selectRow('SELECT *, text as Text_loc0 FROM page_text pt LEFT JOIN locales_page_text lpt ON pt.entry = lpt.entry WHERE pt.entry = ?d', $next);
|
||||
$next = $row['next_page'];
|
||||
$this->pageText[] = Util::parseHtmlText(Util::localizedString($row, 'Text'));
|
||||
}
|
||||
}
|
||||
$this->unavailable = $this->subject->getField('cuFlags') & CUSTOM_UNAVAILABLE;
|
||||
|
||||
// subItems
|
||||
$this->subject->initSubItems();
|
||||
@@ -362,10 +364,12 @@ class ItemPage extends genericPage
|
||||
uaSort($this->subject->subItems[$this->typeId], function($a, $b) { return strcmp($a['name'], $b['name']); });
|
||||
$this->subItems = array(
|
||||
'data' => array_values($this->subject->subItems[$this->typeId]),
|
||||
'randIds' => array_keys($this->subject->subItems[$this->typeId]),
|
||||
'quality' => $this->subject->getField('quality')
|
||||
);
|
||||
|
||||
// merge identical stats and names for normal users (e.g. spellPower of a specific school became generel spellPower with 3.0)
|
||||
|
||||
if (!User::isInGroup(U_GROUP_EMPLOYEE))
|
||||
{
|
||||
for ($i = 1; $i < count($this->subItems['data']); $i++)
|
||||
@@ -376,6 +380,7 @@ class ItemPage extends genericPage
|
||||
{
|
||||
$prev['chance'] += $cur['chance'];
|
||||
array_splice($this->subItems['data'], $i , 1);
|
||||
array_splice($this->subItems['randIds'], $i , 1);
|
||||
$i = 1;
|
||||
}
|
||||
}
|
||||
@@ -404,6 +409,31 @@ class ItemPage extends genericPage
|
||||
/* Extra Tabs */
|
||||
/**************/
|
||||
|
||||
// tab: createdBy (perfect item specific)
|
||||
if ($perfItem = DB::World()->select('SELECT *, spellId AS ARRAY_KEY FROM skill_perfect_item_template WHERE perfectItemType = ?d', $this->typeId))
|
||||
{
|
||||
$perfSpells = new SpellList(array(['id', array_column($perfItem, 'spellId')]));
|
||||
if (!$perfSpells->error)
|
||||
{
|
||||
$lvData = $perfSpells->getListviewData();
|
||||
$this->extendGlobalData($perfSpells->getJSGlobals(GLOBALINFO_RELATED));
|
||||
|
||||
foreach ($lvData as $sId => &$data)
|
||||
{
|
||||
$data['percent'] = $perfItem[$sId]['perfectCreateChance'];
|
||||
$data['condition'][0][$this->typeId] = [[[CND_SPELL, $perfItem[$sId]['requiredSpecialization']]]];
|
||||
$this->extendGlobalIDs(TYPE_SPELL, $perfItem[$sId]['requiredSpecialization']);
|
||||
}
|
||||
|
||||
$this->lvTabs[] = ['spell', array(
|
||||
'data' => array_values($lvData),
|
||||
'name' => '$LANG.tab_createdby',
|
||||
'id' => 'created-by', // should by exclusive with created-by from spell_loot
|
||||
'extraCols' => ['$Listview.extraCols.percent', '$Listview.extraCols.condition']
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
// tabs: this item is contained in..
|
||||
$lootTabs = new Loot();
|
||||
$createdBy = [];
|
||||
@@ -411,34 +441,24 @@ class ItemPage extends genericPage
|
||||
{
|
||||
$this->extendGlobalData($lootTabs->jsGlobals);
|
||||
|
||||
foreach ($lootTabs->iterate() as $idx => $tab)
|
||||
foreach ($lootTabs->iterate() as $idx => list($file, $tabData))
|
||||
{
|
||||
if (!$tab[1])
|
||||
if (!$tabData['data'])
|
||||
continue;
|
||||
|
||||
if ($idx == 16)
|
||||
$createdBy = array_column($tab[1], 'id');
|
||||
$createdBy = array_column($tabData['data'], 'id');
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => $tab[0],
|
||||
'data' => $tab[1],
|
||||
'params' => [
|
||||
'name' => $tab[2],
|
||||
'id' => $tab[3],
|
||||
'extraCols' => $tab[4] ? '$['.implode(', ', array_unique($tab[4])).']' : null,
|
||||
'hiddenCols' => $tab[5] ? '$ '.Util::toJSON( array_unique($tab[5])) : null,
|
||||
'visibleCols' => $tab[6] ? '$'. Util::toJSON( array_unique($tab[6])) : null
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = [$file, $tabData];
|
||||
}
|
||||
}
|
||||
|
||||
// tabs: this item contains..
|
||||
$sourceFor = array(
|
||||
[LOOT_ITEM, $this->subject->id, '$LANG.tab_contains', 'contains', ['Listview.extraCols.percent'], [] , []],
|
||||
[LOOT_PROSPECTING, $this->subject->id, '$LANG.tab_prospecting', 'prospecting', ['Listview.extraCols.percent'], ['side', 'slot', 'reqlevel'], []],
|
||||
[LOOT_MILLING, $this->subject->id, '$LANG.tab_milling', 'milling', ['Listview.extraCols.percent'], ['side', 'slot', 'reqlevel'], []],
|
||||
[LOOT_DISENCHANT, $this->subject->getField('disenchantId'), '$LANG.tab_disenchanting', 'disenchanting', ['Listview.extraCols.percent'], ['side', 'slot', 'reqlevel'], []]
|
||||
[LOOT_ITEM, $this->subject->id, '$LANG.tab_contains', 'contains', ['$Listview.extraCols.percent'], [] , []],
|
||||
[LOOT_PROSPECTING, $this->subject->id, '$LANG.tab_prospecting', 'prospecting', ['$Listview.extraCols.percent'], ['side', 'slot', 'reqlevel'], []],
|
||||
[LOOT_MILLING, $this->subject->id, '$LANG.tab_milling', 'milling', ['$Listview.extraCols.percent'], ['side', 'slot', 'reqlevel'], []],
|
||||
[LOOT_DISENCHANT, $this->subject->getField('disenchantId'), '$LANG.tab_disenchanting', 'disenchanting', ['$Listview.extraCols.percent'], ['side', 'slot', 'reqlevel'], []]
|
||||
);
|
||||
|
||||
$reqQuest = [];
|
||||
@@ -462,17 +482,22 @@ class ItemPage extends genericPage
|
||||
$lv['condition'][0][$this->typeId][] = [[CND_QUESTTAKEN, &$reqQuest[$lv['id']]]];
|
||||
}
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'item',
|
||||
'data' => $lootTab->getResult(),
|
||||
'params' => [
|
||||
'name' => $sf[2],
|
||||
'id' => $sf[3],
|
||||
'extraCols' => $sf[4] ? "$[".implode(', ', array_unique($sf[4]))."]" : null,
|
||||
'hiddenCols' => $sf[5] ? "$".Util::toJSON($sf[5]) : null,
|
||||
'visibleCols' => $sf[6] ? '$'.Util::toJSON($sf[6]) : null
|
||||
]
|
||||
$tabData = array(
|
||||
'data' => array_values($lootTab->getResult()),
|
||||
'name' => $sf[2],
|
||||
'id' => $sf[3],
|
||||
);
|
||||
|
||||
if ($sf[4])
|
||||
$tabData['extraCols'] = array_unique($sf[4]);
|
||||
|
||||
if ($sf[5])
|
||||
$tabData['hiddenCols'] = array_unique($sf[5]);
|
||||
|
||||
if ($sf[6])
|
||||
$tabData['visibleCols'] = array_unique($sf[6]);
|
||||
|
||||
$this->lvTabs[] = ['item', $tabData];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,15 +537,12 @@ class ItemPage extends genericPage
|
||||
if (!$contains->hasSetFields(['slot']))
|
||||
$hCols[] = 'slot';
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'item',
|
||||
'data' => $contains->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_cancontain',
|
||||
'id' => 'can-contain',
|
||||
'hiddenCols' => '$'.Util::toJSON($hCols)
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['item', array(
|
||||
'data' => array_values($contains->getListviewData()),
|
||||
'name' => '$LANG.tab_cancontain',
|
||||
'id' => 'can-contain',
|
||||
'hiddenCols' => $hCols
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,15 +554,12 @@ class ItemPage extends genericPage
|
||||
{
|
||||
$this->extendGlobalData($contains->getJSGlobals(GLOBALINFO_SELF));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'item',
|
||||
'data' => $contains->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_canbeplacedin',
|
||||
'id' => 'can-be-placed-in',
|
||||
'hiddenCols' => "$['side']"
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['item', array(
|
||||
'data' => array_values($contains->getListviewData()),
|
||||
'name' => '$LANG.tab_canbeplacedin',
|
||||
'id' => 'can-be-placed-in',
|
||||
'hiddenCols' => ['side']
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,22 +572,19 @@ class ItemPage extends genericPage
|
||||
$criteriaOf = new AchievementList($conditions);
|
||||
if (!$criteriaOf->error)
|
||||
{
|
||||
$this->extendGlobalData($criteriaOf->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
|
||||
$this->extendGlobalData($criteriaOf->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
|
||||
|
||||
$hCols = [];
|
||||
if (!$criteriaOf->hasSetFields(['reward_loc0']))
|
||||
$hCols = ['rewards'];
|
||||
$tabData = array(
|
||||
'data' => array_values($criteriaOf->getListviewData()),
|
||||
'name' => '$LANG.tab_criteriaof',
|
||||
'id' => 'criteria-of',
|
||||
'visibleCols' => ['category']
|
||||
);
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'achievement',
|
||||
'data' => $criteriaOf->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_criteriaof',
|
||||
'id' => 'criteria-of',
|
||||
'visibleCols' => "$['category']",
|
||||
'hiddenCols' => '$'.Util::toJSON($hCols)
|
||||
]
|
||||
);
|
||||
if (!$criteriaOf->hasSetFields(['reward_loc0']))
|
||||
$tabData['hiddenCols'] = ['rewards'];
|
||||
|
||||
$this->lvTabs[] = ['achievement', $tabData];
|
||||
}
|
||||
|
||||
// tab: reagent for
|
||||
@@ -583,15 +599,12 @@ class ItemPage extends genericPage
|
||||
{
|
||||
$this->extendGlobalData($reagent->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'spell',
|
||||
'data' => $reagent->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_reagentfor',
|
||||
'id' => 'reagent-for',
|
||||
'visibleCols' => "$['reagents']"
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['spell', array(
|
||||
'data' => array_values($reagent->getListviewData()),
|
||||
'name' => '$LANG.tab_reagentfor',
|
||||
'id' => 'reagent-for',
|
||||
'visibleCols' => ['reagents']
|
||||
)];
|
||||
}
|
||||
|
||||
// tab: unlocks (object or item)
|
||||
@@ -608,14 +621,11 @@ class ItemPage extends genericPage
|
||||
$lockedObj = new GameObjectList(array(['lockId', $lockIds]));
|
||||
if (!$lockedObj->error)
|
||||
{
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'object',
|
||||
'data' => $lockedObj->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_unlocks',
|
||||
'id' => 'unlocks-object'
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['object', array(
|
||||
'data' => array_values($lockedObj->getListviewData()),
|
||||
'name' => '$LANG.tab_unlocks',
|
||||
'id' => 'unlocks-object'
|
||||
)];
|
||||
}
|
||||
|
||||
// items (generally unused. It's the spell on the item, that unlocks stuff)
|
||||
@@ -624,14 +634,11 @@ class ItemPage extends genericPage
|
||||
{
|
||||
$this->extendGlobalData($lockedItm->getJSGlobals(GLOBALINFO_SELF));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'item',
|
||||
'data' => $lockedItm->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_unlocks',
|
||||
'id' => 'unlocks-item'
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['item', array(
|
||||
'data' => array_values($lockedItm->getListviewData()),
|
||||
'name' => '$LANG.tab_unlocks',
|
||||
'id' => 'unlocks-item'
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,14 +666,11 @@ class ItemPage extends genericPage
|
||||
{
|
||||
$this->extendGlobalData($saItems->getJSGlobals(GLOBALINFO_SELF));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'item',
|
||||
'data' => $saItems->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_seealso',
|
||||
'id' => 'see-also'
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['item', array(
|
||||
'data' => array_values($saItems->getListviewData()),
|
||||
'name' => '$LANG.tab_seealso',
|
||||
'id' => 'see-also'
|
||||
)];
|
||||
}
|
||||
|
||||
// tab: starts (quest)
|
||||
@@ -677,14 +681,11 @@ class ItemPage extends genericPage
|
||||
{
|
||||
$this->extendGlobalData($starts->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'quest',
|
||||
'data' => $starts->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_starts',
|
||||
'id' => 'starts-quest'
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['quest', array(
|
||||
'data' => array_values($starts->getListviewData()),
|
||||
'name' => '$LANG.tab_starts',
|
||||
'id' => 'starts-quest'
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,14 +700,11 @@ class ItemPage extends genericPage
|
||||
{
|
||||
$this->extendGlobalData($objective->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'quest',
|
||||
'data' => $objective->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_objectiveof',
|
||||
'id' => 'objective-of-quest'
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['quest', array(
|
||||
'data' => array_values($objective->getListviewData()),
|
||||
'name' => '$LANG.tab_objectiveof',
|
||||
'id' => 'objective-of-quest'
|
||||
)];
|
||||
}
|
||||
|
||||
// tab: provided for (quest)
|
||||
@@ -720,14 +718,11 @@ class ItemPage extends genericPage
|
||||
{
|
||||
$this->extendGlobalData($provided->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'quest',
|
||||
'data' => $provided->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_providedfor',
|
||||
'id' => 'provided-for-quest'
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['quest', array(
|
||||
'data' => array_values($provided->getListviewData()),
|
||||
'name' => '$LANG.tab_providedfor',
|
||||
'id' => 'provided-for-quest'
|
||||
)];
|
||||
}
|
||||
|
||||
// tab: same model as
|
||||
@@ -739,15 +734,12 @@ class ItemPage extends genericPage
|
||||
{
|
||||
$this->extendGlobalData($sameModel->getJSGlobals(GLOBALINFO_SELF));
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'genericmodel',
|
||||
'data' => $sameModel->getListviewData(ITEMINFO_MODEL),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_samemodelas',
|
||||
'id' => 'same-model-as',
|
||||
'genericlinktype' => 'item'
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['genericmodel', array(
|
||||
'data' => array_values($sameModel->getListviewData(ITEMINFO_MODEL)),
|
||||
'name' => '$LANG.tab_samemodelas',
|
||||
'id' => 'same-model-as',
|
||||
'genericlinktype' => 'item'
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -761,7 +753,7 @@ class ItemPage extends genericPage
|
||||
$sbData = $soldBy->getListviewData();
|
||||
$this->extendGlobalData($soldBy->getJSGlobals(GLOBALINFO_SELF));
|
||||
|
||||
$extraCols = ['Listview.extraCols.stock', "Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", 'Listview.extraCols.cost'];
|
||||
$extraCols = ['$Listview.extraCols.stock', "\$Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", '$Listview.extraCols.cost'];
|
||||
|
||||
$holidays = [];
|
||||
foreach ($sbData as $k => &$row)
|
||||
@@ -791,7 +783,7 @@ class ItemPage extends genericPage
|
||||
if ($e = $vendors[$k]['event'])
|
||||
{
|
||||
if (count($extraCols) == 3)
|
||||
$extraCols[] = 'Listview.extraCols.condition';
|
||||
$extraCols[] = '$Listview.extraCols.condition';
|
||||
|
||||
$this->extendGlobalIds(TYPE_WORLDEVENT, $e);
|
||||
$row['condition'][0][$this->typeId][] = [[CND_ACTIVE_EVENT, $e]];
|
||||
@@ -814,16 +806,13 @@ class ItemPage extends genericPage
|
||||
}
|
||||
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'creature',
|
||||
'data' => $sbData,
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_soldby',
|
||||
'id' => 'sold-by-npc',
|
||||
'extraCols' => '$['.implode(', ', $extraCols).']',
|
||||
'hiddenCols' => "$['level', 'type']"
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['creature', array(
|
||||
'data' => array_values($sbData),
|
||||
'name' => '$LANG.tab_soldby',
|
||||
'id' => 'sold-by-npc',
|
||||
'extraCols' => $extraCols,
|
||||
'hiddenCols' => ['level', 'type']
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -852,23 +841,22 @@ class ItemPage extends genericPage
|
||||
$boughtBy = new ItemList(array(['id', $boughtBy]));
|
||||
if (!$boughtBy->error)
|
||||
{
|
||||
if ($boughtBy->getMatches() <= CFG_SQL_LIMIT_DEFAULT)
|
||||
$n = null;
|
||||
|
||||
$iCur = new CurrencyList(array(['itemId', $this->typeId]));
|
||||
$filter = $iCur->error ? [TYPE_ITEM => $this->typeId] : [TYPE_CURRENCY => $iCur->id];
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'item',
|
||||
'data' => $boughtBy->getListviewData(ITEMINFO_VENDOR, $filter),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_currencyfor',
|
||||
'id' => 'currency-for',
|
||||
'extraCols' => "$[Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack'), Listview.extraCols.cost]",
|
||||
'note' => $n ? sprintf(Util::$filterResultString, $n) : null
|
||||
]
|
||||
$tabData = array(
|
||||
'data' => array_values($boughtBy->getListviewData(ITEMINFO_VENDOR, $filter)),
|
||||
'name' => '$LANG.tab_currencyfor',
|
||||
'id' => 'currency-for',
|
||||
'extraCols' => ["\$Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", '$Listview.extraCols.cost'],
|
||||
);
|
||||
$this->extendGlobalData($boughtBy->getJSGlobals(GLOBALINFO_ANY));
|
||||
|
||||
if ($boughtBy->getMatches() > CFG_SQL_LIMIT_DEFAULT && $n)
|
||||
$tabData['note'] = sprintf(Util::$filterResultString, $n);
|
||||
|
||||
$this->lvTabs[] = ['item', $tabData];
|
||||
|
||||
$this->extendGlobalData($boughtBy->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -891,7 +879,7 @@ class ItemPage extends genericPage
|
||||
foreach ($_ as $idx)
|
||||
$ids[] = $indirectSpells->getField('effect'.$idx.'TriggerSpell');
|
||||
|
||||
$ids = array_merge($ids, Util::getTaughtSpells($indirect));
|
||||
$ids = array_merge($ids, Game::getTaughtSpells($indirect));
|
||||
}
|
||||
|
||||
if ($ids)
|
||||
@@ -905,15 +893,12 @@ class ItemPage extends genericPage
|
||||
if ($taughtSpells->hasSetFields(['reagent1']))
|
||||
$visCols[] = 'reagents';
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'spell',
|
||||
'data' => $taughtSpells->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_teaches',
|
||||
'id' => 'teaches',
|
||||
'visibleCols' => '$'.Util::toJSON($visCols)
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['spell', array(
|
||||
'data' => array_values($taughtSpells->getListviewData()),
|
||||
'name' => '$LANG.tab_teaches',
|
||||
'id' => 'teaches',
|
||||
'visibleCols' => $visCols
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -926,29 +911,68 @@ class ItemPage extends genericPage
|
||||
if ($cdCats)
|
||||
{
|
||||
$conditions = array(
|
||||
'OR',
|
||||
['spellCategory1', $cdCats],
|
||||
['spellCategory2', $cdCats],
|
||||
['spellCategory3', $cdCats],
|
||||
['spellCategory4', $cdCats],
|
||||
['spellCategory5', $cdCats]
|
||||
['id', $this->typeId, '!'],
|
||||
[
|
||||
'OR',
|
||||
['spellCategory1', $cdCats],
|
||||
['spellCategory2', $cdCats],
|
||||
['spellCategory3', $cdCats],
|
||||
['spellCategory4', $cdCats],
|
||||
['spellCategory5', $cdCats],
|
||||
]
|
||||
);
|
||||
$cdItems = new ItemList($conditions);
|
||||
if (!$cdItems->error)
|
||||
{
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'item',
|
||||
'data' => $cdItems->getListviewData(),
|
||||
'params' => [
|
||||
'name' => '$LANG.tab_sharedcooldown',
|
||||
'id' => 'shared-cooldown'
|
||||
]
|
||||
);
|
||||
$this->lvTabs[] = ['item', array(
|
||||
'data' => array_values($cdItems->getListviewData()),
|
||||
'name' => '$LANG.tab_sharedcooldown',
|
||||
'id' => 'shared-cooldown'
|
||||
)];
|
||||
|
||||
$this->extendGlobalData($cdItems->getJSGlobals(GLOBALINFO_SELF));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// tab: sounds
|
||||
$soundIds = [];
|
||||
if ($_class == ITEM_CLASS_WEAPON)
|
||||
{
|
||||
$scm = (1 << $_subClass);
|
||||
if ($this->subject->getField('soundOverrideSubclass') > 0)
|
||||
$scm = (1 << $this->subject->getField('soundOverrideSubclass'));
|
||||
|
||||
$soundIds = DB::Aowow()->selectCol('SELECT soundId FROM ?_items_sounds WHERE subClassMask & ?d', $scm);
|
||||
}
|
||||
|
||||
$fields = ['pickUpSoundId', 'dropDownSoundId', 'sheatheSoundId', 'unsheatheSoundId'];
|
||||
foreach ($fields as $f)
|
||||
if ($x = $this->subject->getField($f))
|
||||
$soundIds[] = $x;
|
||||
|
||||
if ($x = $this->subject->getField('spellVisualId'))
|
||||
{
|
||||
if ($spellSounds = DB::Aowow()->selectRow('SELECT * FROM ?_spell_sounds WHERE id = ?d', $x))
|
||||
{
|
||||
array_shift($spellSounds); // bye 'id'-field
|
||||
foreach ($spellSounds as $ss)
|
||||
if ($ss)
|
||||
$soundIds[] = $ss;
|
||||
}
|
||||
}
|
||||
|
||||
if ($soundIds)
|
||||
{
|
||||
$sounds = new SoundList(array(['id', $soundIds]));
|
||||
if (!$sounds->error)
|
||||
{
|
||||
$this->extendGlobalData($sounds->getJSGlobals(GLOBALINFO_SELF));
|
||||
$this->lvTabs[] = ['sound', ['data' => array_values($sounds->getListviewData())]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// // todo - tab: taught by
|
||||
// use var $createdBy to find source of this spell
|
||||
// id: 'taught-by-X',
|
||||
@@ -965,9 +989,9 @@ class ItemPage extends genericPage
|
||||
return '$WowheadPower.registerItem(\''.$itemString.'\', '.User::$localeId.', {})';
|
||||
|
||||
$x = '$WowheadPower.registerItem(\''.$itemString.'\', '.User::$localeId.", {\n";
|
||||
$x .= "\tname_".User::$localeString.": '".Util::jsEscape($this->subject->getField('name', true))."',\n";
|
||||
$x .= "\tname_".User::$localeString.": '".Util::jsEscape($this->subject->getField('name', true, false, $this->enhancedTT))."',\n";
|
||||
$x .= "\tquality: ".$this->subject->getField('quality').",\n";
|
||||
$x .= "\ticon: '".urlencode($this->subject->getField('iconString'))."',\n";
|
||||
$x .= "\ticon: '".rawurlencode($this->subject->getField('iconString', true, true))."',\n";
|
||||
$x .= "\ttooltip_".User::$localeString.": '".Util::jsEscape($this->subject->renderTooltip(false, 0, $this->enhancedTT))."'\n";
|
||||
$x .= "});";
|
||||
|
||||
@@ -984,7 +1008,7 @@ class ItemPage extends genericPage
|
||||
{
|
||||
// item root
|
||||
$xml = $root->addChild('item');
|
||||
$xml->addAttribute('id', $this->subject->id);
|
||||
$xml->addAttribute('id', $this->typeId);
|
||||
|
||||
// name
|
||||
$xml->addChild('name')->addCData($this->subject->getField('name', true));
|
||||
@@ -1008,50 +1032,62 @@ class ItemPage extends genericPage
|
||||
$this->subject->extendJsonStats();
|
||||
|
||||
// json
|
||||
$fields = ["classs", "displayid", "dps", "id", "level", "name", "reqlevel", "slot", "slotbak", "source", "sourcemore", "speed", "subclass"];
|
||||
$json = '';
|
||||
$fields = ['classs', 'displayid', 'dps', 'id', 'level', 'name', 'reqlevel', 'slot', 'slotbak', 'speed', 'subclass'];
|
||||
$json = [];
|
||||
foreach ($fields as $f)
|
||||
{
|
||||
if (isset($this->subject->json[$this->subject->id][$f]))
|
||||
if (isset($this->subject->json[$this->typeId][$f]))
|
||||
{
|
||||
$_ = $this->subject->json[$this->subject->id][$f];
|
||||
$_ = $this->subject->json[$this->typeId][$f];
|
||||
if ($f == 'name')
|
||||
$_ = (7 - $this->subject->getField('quality')).$_;
|
||||
|
||||
$json .= ',"'.$f.'":'.$_;
|
||||
$json[$f] = $_;
|
||||
}
|
||||
}
|
||||
$xml->addChild('json')->addCData(substr($json, 1));
|
||||
|
||||
// jsonEquip missing: avgbuyout, cooldown, source, sourcemore
|
||||
$json = '';
|
||||
// itemsource
|
||||
if ($this->subject->getSources($s, $m))
|
||||
{
|
||||
$json['source'] = $s;
|
||||
if ($m)
|
||||
$json['sourcemore'] = $m;
|
||||
}
|
||||
|
||||
$xml->addChild('json')->addCData(substr(json_encode($json), 1, -1));
|
||||
|
||||
// jsonEquip missing: avgbuyout
|
||||
$json = [];
|
||||
if ($_ = $this->subject->getField('sellPrice')) // sellprice
|
||||
$json .= ',"sellprice":'.$_;
|
||||
$json['sellprice'] = $_;
|
||||
|
||||
if ($_ = $this->subject->getField('requiredLevel')) // reqlevel
|
||||
$json .= ',"reqlevel":'.$_;
|
||||
$json['reqlevel'] = $_;
|
||||
|
||||
if ($_ = $this->subject->getField('requiredSkill')) // reqskill
|
||||
$json .= ',"reqskill":'.$_;
|
||||
$json['reqskill'] = $_;
|
||||
|
||||
if ($_ = $this->subject->getField('requiredSkillRank')) // reqskillrank
|
||||
$json .= ',"reqskillrank":'.$_;
|
||||
$json['reqskillrank'] = $_;
|
||||
|
||||
foreach ($this->subject->itemMods[$this->subject->id] as $mod => $qty)
|
||||
$json .= ',"'.$mod.'":'.$qty;
|
||||
if ($_ = $this->subject->getField('cooldown')) // cooldown
|
||||
$json['cooldown'] = $_ / 1000;
|
||||
|
||||
foreach ($_ = $this->subject->json[$this->subject->id] as $name => $qty)
|
||||
foreach ($this->subject->itemMods[$this->typeId] as $mod => $qty)
|
||||
$json[$mod] = $qty;
|
||||
|
||||
foreach ($this->subject->json[$this->typeId] as $name => $qty)
|
||||
if (in_array($name, Util::$itemFilter))
|
||||
$json .= ',"'.$name.'":'.$qty;
|
||||
$json[$name] = $qty;
|
||||
|
||||
$xml->addChild('jsonEquip')->addCData(substr($json, 1));
|
||||
$xml->addChild('jsonEquip')->addCData(substr(json_encode($json), 1, -1));
|
||||
|
||||
// jsonUse
|
||||
if ($onUse = $this->subject->getOnUseStats())
|
||||
{
|
||||
$j = '';
|
||||
foreach ($onUse as $idx => $qty)
|
||||
$j .= ',"'.Util::$itemMods[$idx].'":'.$qty;
|
||||
$j .= ',"'.Game::$itemMods[$idx].'":'.$qty;
|
||||
|
||||
$xml->addChild('jsonUse')->addCData(substr($j, 1));
|
||||
}
|
||||
@@ -1059,9 +1095,9 @@ class ItemPage extends genericPage
|
||||
// reagents
|
||||
$cnd = array(
|
||||
'OR',
|
||||
['AND', ['effect1CreateItemId', $this->subject->id], ['OR', ['effect1Id', SpellList::$effects['itemCreate']], ['effect1AuraId', SpellList::$auras['itemCreate']]]],
|
||||
['AND', ['effect2CreateItemId', $this->subject->id], ['OR', ['effect2Id', SpellList::$effects['itemCreate']], ['effect2AuraId', SpellList::$auras['itemCreate']]]],
|
||||
['AND', ['effect3CreateItemId', $this->subject->id], ['OR', ['effect3Id', SpellList::$effects['itemCreate']], ['effect3AuraId', SpellList::$auras['itemCreate']]]],
|
||||
['AND', ['effect1CreateItemId', $this->typeId], ['OR', ['effect1Id', SpellList::$effects['itemCreate']], ['effect1AuraId', SpellList::$auras['itemCreate']]]],
|
||||
['AND', ['effect2CreateItemId', $this->typeId], ['OR', ['effect2Id', SpellList::$effects['itemCreate']], ['effect2AuraId', SpellList::$auras['itemCreate']]]],
|
||||
['AND', ['effect3CreateItemId', $this->typeId], ['OR', ['effect3Id', SpellList::$effects['itemCreate']], ['effect3AuraId', SpellList::$auras['itemCreate']]]],
|
||||
);
|
||||
|
||||
$spellSource = new SpellList($cnd);
|
||||
@@ -1073,7 +1109,7 @@ class ItemPage extends genericPage
|
||||
{
|
||||
foreach ($spellSource->canCreateItem() as $idx)
|
||||
{
|
||||
if ($spellSource->getField('effect'.$idx.'CreateItemId') != $this->subject->id)
|
||||
if ($spellSource->getField('effect'.$idx.'CreateItemId') != $this->typeId)
|
||||
continue;
|
||||
|
||||
$splNode = $cbNode->addChild('spell');
|
||||
@@ -1136,7 +1172,7 @@ class ItemPage extends genericPage
|
||||
return parent::display($override);
|
||||
}
|
||||
|
||||
public function notFound()
|
||||
public function notFound($title = '', $msg = '')
|
||||
{
|
||||
if ($this->mode == CACHE_TYPE_TOOLTIP)
|
||||
{
|
||||
@@ -1151,7 +1187,7 @@ class ItemPage extends genericPage
|
||||
exit();
|
||||
}
|
||||
else
|
||||
return parent::notFound(Lang::game('item'), Lang::item('notFound'));
|
||||
return parent::notFound($title ?: Lang::game('item'), $msg ?: Lang::item('notFound'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
106
pages/items.php
106
pages/items.php
@@ -81,13 +81,14 @@ class ItemsPage extends GenericPage
|
||||
|
||||
public function __construct($pageCall, $pageParam)
|
||||
{
|
||||
$this->filterObj = new ItemListFilter();
|
||||
$this->getCategoryFromUrl($pageParam);
|
||||
|
||||
$this->filterObj = new ItemListFilter(false, ['parentCats' => $this->category]);
|
||||
|
||||
parent::__construct($pageCall, $pageParam);
|
||||
|
||||
$this->name = Util::ucFirst(Lang::game('items'));
|
||||
$this->subCat = $pageParam ? '='.$pageParam : '';
|
||||
$this->subCat = $pageParam !== null ? '='.$pageParam : '';
|
||||
}
|
||||
|
||||
protected function generateContent()
|
||||
@@ -107,12 +108,21 @@ class ItemsPage extends GenericPage
|
||||
if ($_ = $this->filterObj->getConditions())
|
||||
$conditions[] = $_;
|
||||
|
||||
$this->filter = array_merge($this->filterObj->getForm('form'), $this->filter);
|
||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
|
||||
$this->filter['fi'] = $this->filterObj->getForm();
|
||||
$this->filter = $this->filterObj->getForm();
|
||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
|
||||
$this->filter['initData'] = ['init' => 'items'];
|
||||
|
||||
if ($x = $this->filterObj->getSetCriteria())
|
||||
$this->filter['initData']['sc'] = $x;
|
||||
|
||||
$xCols = $this->filterObj->getExtraCols();
|
||||
if ($xCols)
|
||||
$this->filter['initData']['ec'] = $xCols;
|
||||
|
||||
if ($x = $this->filterObj->getSetWeights())
|
||||
$this->filter['initData']['sw'] = $x;
|
||||
|
||||
$menu = $this->createExtraMenus();
|
||||
|
||||
foreach ($menu['type'][0] as $k => $str)
|
||||
if ($str && (!$menu['type'][1] || ($menu['type'][1] & (1 << $k))))
|
||||
$this->filter['type'][$k] = $str;
|
||||
@@ -124,13 +134,12 @@ class ItemsPage extends GenericPage
|
||||
if (isset($this->filter['slot'][INVTYPE_SHIELD])) // "Off Hand" => "Shield"
|
||||
$this->filter['slot'][INVTYPE_SHIELD] = Lang::item('armorSubClass', 6);
|
||||
|
||||
$xCols = $this->filterObj->getForm('extraCols', true);
|
||||
|
||||
$infoMask = ITEMINFO_JSON;
|
||||
if (array_intersect([63, 64, 125], $xCols)) // 63:buyPrice; 64:sellPrice; 125:reqarenartng
|
||||
$infoMask |= ITEMINFO_VENDOR;
|
||||
|
||||
if (!empty($this->filter['fi']['extraCols']))
|
||||
if ($xCols)
|
||||
$this->sharedLV['extraCols'] = '$fi_getExtraCols(fi_extraCols, '.(isset($this->filter['gm']) ? $this->filter['gm'] : 0).', '.(array_intersect([63], $xCols) ? 1 : 0).')';
|
||||
|
||||
if ($this->filterObj->error)
|
||||
@@ -158,7 +167,7 @@ class ItemsPage extends GenericPage
|
||||
/*************************/
|
||||
|
||||
$upgItemData = [];
|
||||
if (!empty($this->filter['upg']) && !empty($this->filter['fi']['setWeights']))
|
||||
if (!empty($this->filter['upg']) && !empty($this->filterObj->getSetWeights()))
|
||||
{
|
||||
$upgItems = new ItemList(array(['id', array_keys($this->filter['upg'])]), ['extraOpts' => $this->filterObj->extraOpts]);
|
||||
if (!$upgItems->error)
|
||||
@@ -232,7 +241,7 @@ class ItemsPage extends GenericPage
|
||||
if (isset($this->filter['sl'])) // skip lookups for unselected slots
|
||||
$groups = array_intersect($groups, (array)$this->filter['sl']);
|
||||
|
||||
if (isset($this->filter['upg'])) // skip lookups for slots we dont have items to upgrade for
|
||||
if (!empty($this->filter['upg'])) // skip lookups for slots we dont have items to upgrade for
|
||||
$groups = array_intersect($groups, (array)$this->filter['upg']);
|
||||
|
||||
if ($groups)
|
||||
@@ -249,7 +258,6 @@ class ItemsPage extends GenericPage
|
||||
$extraOpts = array_merge($this->filterOpts, ['i' => ['g' => ['itemlevel'], 'o' => ['itemlevel DESC']]]);
|
||||
|
||||
$levelRef = new ItemList(array_merge($conditions, [10]), ['extraOpts' => $extraOpts]);
|
||||
|
||||
foreach ($levelRef->iterate() as $_)
|
||||
{
|
||||
$l = $levelRef->getField('itemLevel');
|
||||
@@ -306,10 +314,9 @@ class ItemsPage extends GenericPage
|
||||
continue;
|
||||
|
||||
$this->extendGlobalData($items->getJSGlobals());
|
||||
$tab = array(
|
||||
'file' => 'item',
|
||||
'data' => $items->getListviewData($infoMask),
|
||||
'params' => $this->sharedLV
|
||||
$tabData = array_merge(
|
||||
['data' => $items->getListviewData($infoMask)],
|
||||
$this->sharedLV
|
||||
);
|
||||
|
||||
$upg = [];
|
||||
@@ -322,17 +329,17 @@ class ItemsPage extends GenericPage
|
||||
}));
|
||||
|
||||
foreach ($upg as $uId)
|
||||
$tab['data'][$uId] = $upgItemData[$uId];
|
||||
$tabData['data'][$uId] = $upgItemData[$uId];
|
||||
|
||||
if ($upg)
|
||||
$tab['params']['_upgradeIds'] = '$'.Util::toJSON($upg);
|
||||
$tabData['_upgradeIds'] = $upg;
|
||||
}
|
||||
else if ($grouping)
|
||||
{
|
||||
$upg = array_keys($this->filter['upg']);
|
||||
$tab['params']['_upgradeIds'] = '$'.Util::toJSON($upg);
|
||||
$tabData['_upgradeIds'] = $upg;
|
||||
foreach ($upgItemData as $uId => $data) // using numeric keys => cant use array_merge
|
||||
$tab['data'][$uId] = $data;
|
||||
$tabData['data'][$uId] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,28 +348,28 @@ class ItemsPage extends GenericPage
|
||||
switch ($grouping)
|
||||
{
|
||||
case 1:
|
||||
$tab['params']['id'] = 'slot-'.$group;
|
||||
$tabData['id'] = 'slot-'.$group;
|
||||
break;
|
||||
case 2:
|
||||
$tab['params']['id'] = $group > 0 ? 'level-'.$group : 'other';
|
||||
$tabData['id'] = $group > 0 ? 'level-'.$group : 'other';
|
||||
break;
|
||||
case 3:
|
||||
$tab['params']['id'] = $group ? 'source-'.$group : 'unknown';
|
||||
$tabData['id'] = $group ? 'source-'.$group : 'unknown';
|
||||
break;
|
||||
}
|
||||
|
||||
$tab['params']['name'] = $nameSource[$group];
|
||||
$tab['params']['tabs'] = '$tabsGroups';
|
||||
$tabData['name'] = $nameSource[$group];
|
||||
$tabData['tabs'] = '$tabsGroups';
|
||||
}
|
||||
|
||||
if (!empty($this->filter['fi']['setWeights']))
|
||||
if (!empty($this->filterObj->getSetWeights()))
|
||||
if ($items->hasSetFields(['armor']))
|
||||
$tab['params']['visibleCols'][] = 'armor';
|
||||
$tabData['visibleCols'][] = 'armor';
|
||||
|
||||
// create note if search limit was exceeded; overwriting 'note' is intentional
|
||||
if ($items->getMatches() > $maxResults && count($groups) > 1)
|
||||
{
|
||||
$tab['params']['_truncated'] = 1;
|
||||
$tabData['_truncated'] = 1;
|
||||
|
||||
$cls = isset($this->category[0]) ? '='.$this->category[0] : '';
|
||||
$override = ['gb' => ''];
|
||||
@@ -373,7 +380,7 @@ class ItemsPage extends GenericPage
|
||||
{
|
||||
case 1:
|
||||
$override['sl'] = $group;
|
||||
$tab['params']['note'] = '$$WH.sprintf(LANG.lvnote_viewmoreslot, \''.$cls.'\', \''.$this->filterObj->urlize($override).'\')';
|
||||
$tabData['note'] = '$$WH.sprintf(LANG.lvnote_viewmoreslot, \''.$cls.'\', \''.$this->filterObj->getFilterString($override).'\')';
|
||||
break;
|
||||
case 2:
|
||||
if ($group > 0)
|
||||
@@ -384,46 +391,42 @@ class ItemsPage extends GenericPage
|
||||
else
|
||||
$override['maxle'] = abs($group) - 1;
|
||||
|
||||
$tab['params']['note'] = '$$WH.sprintf(LANG.lvnote_viewmorelevel, \''.$cls.'\', \''.$this->filterObj->urlize($override).'\')';
|
||||
$tabData['note'] = '$$WH.sprintf(LANG.lvnote_viewmorelevel, \''.$cls.'\', \''.$this->filterObj->getFilterString($override).'\')';
|
||||
break;
|
||||
case 3:
|
||||
if ($_ = [null, 3, 4, 5, 6, 7, 9, 10, 11][$group])
|
||||
$tab['params']['note'] = '$$WH.sprintf(LANG.lvnote_viewmoresource, \''.$cls.'\', \''.$this->filterObj->urlize($override, ['cr' => 128, 'crs' => $_, 'crv' => 0]).'\')';
|
||||
$tabData['note'] = '$$WH.sprintf(LANG.lvnote_viewmoresource, \''.$cls.'\', \''.$this->filterObj->getFilterString($override, ['cr' => 128, 'crs' => $_, 'crv' => 0]).'\')';
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ($items->getMatches() > $maxResults)
|
||||
{
|
||||
$tab['params']['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_itemsfound', $items->getMatches(), CFG_SQL_LIMIT_DEFAULT);
|
||||
$tab['params']['_truncated'] = 1;
|
||||
$tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_itemsfound', $items->getMatches(), CFG_SQL_LIMIT_DEFAULT);
|
||||
$tabData['_truncated'] = 1;
|
||||
}
|
||||
|
||||
if (!empty($tab['params']['hiddenCols']))
|
||||
$tab['params']['hiddenCols'] = '$'.Util::toJSON($tab['params']['hiddenCols']);
|
||||
|
||||
if (!empty($tab['params']['visibleCols']))
|
||||
$tab['params']['visibleCols'] = '$'.Util::toJSON($tab['params']['visibleCols']);
|
||||
|
||||
foreach ($tab['params'] as $k => $p)
|
||||
if (!$p)
|
||||
unset($tab['params'][$k]);
|
||||
foreach ($tabData as $k => $p)
|
||||
if (!$p && $k != 'data')
|
||||
unset($tabData[$k]);
|
||||
|
||||
if ($grouping)
|
||||
$tab['params']['hideCount'] = '$1';
|
||||
$tabData['hideCount'] = 1;
|
||||
|
||||
$this->lvTabs[] = $tab;
|
||||
$tabData['data'] = array_values($tabData['data']);
|
||||
|
||||
$this->lvTabs[] = ['item', $tabData];
|
||||
}
|
||||
|
||||
// reformat for use in template
|
||||
if (isset($this->filter['upg']))
|
||||
if (!empty($this->filter['upg']))
|
||||
$this->filter['upg'] = implode(':', array_keys($this->filter['upg']));
|
||||
|
||||
// whoops, we have no data? create emergency content
|
||||
if (empty($this->lvTabs))
|
||||
{
|
||||
$this->forceTabs = false;
|
||||
$this->lvTabs[] = ['file' => 'item', 'data' => [], 'params' => []];
|
||||
$this->lvTabs[] = ['item', ['data' => []]];
|
||||
}
|
||||
|
||||
// sort for dropdown-menus
|
||||
@@ -442,6 +445,8 @@ class ItemsPage extends GenericPage
|
||||
$tPart = Lang::item('cat', $this->category[0], 1, $this->category[1], 1, $this->category[2]);
|
||||
else if (isset($this->category[1]) && is_array(Lang::item('cat', $this->category[0])))
|
||||
$tPart = Lang::item('cat', $this->category[0], 1, $this->category[1]);
|
||||
else if ($this->category[0] == 0 && isset($this->filter['ty']) && !is_array($this->filter['ty']))
|
||||
$tPart = Lang::item('cat', 0, 1, $this->filter['ty']);
|
||||
else
|
||||
$tPart = Lang::item('cat', $this->category[0]);
|
||||
|
||||
@@ -454,9 +459,11 @@ class ItemsPage extends GenericPage
|
||||
$this->path[] = $c;
|
||||
|
||||
// if slot-dropdown is available && Armor && $path points to Armor-Class
|
||||
$form = $this->filterObj->getForm('form');
|
||||
$form = $this->filterObj->getForm();
|
||||
if (count($this->path) == 4 && $this->category[0] == 4 && isset($form['sl']) && !is_array($form['sl']))
|
||||
$this->path[] = $form['sl'];
|
||||
else if (!empty($this->category[0]) && $this->category[0] == 0 && isset($form['ty']) && !is_array($form['ty']))
|
||||
$this->path[] = $form['ty'];
|
||||
}
|
||||
|
||||
// fetch best possible gems for chosen weights
|
||||
@@ -464,7 +471,7 @@ class ItemsPage extends GenericPage
|
||||
{
|
||||
$gemScores = [];
|
||||
|
||||
if (empty($this->filter['fi']['setWeights']))
|
||||
if (empty($this->filterObj->getSetWeights()))
|
||||
return [];
|
||||
|
||||
if (!empty($this->filter['gm']))
|
||||
@@ -502,7 +509,7 @@ class ItemsPage extends GenericPage
|
||||
|
||||
$this->sharedLV['onBeforeCreate'] = '$fi_initWeightedListview';
|
||||
$this->sharedLV['onAfterCreate'] = '$fi_addUpgradeIndicator';
|
||||
$this->sharedLV['sort'] = "$['-score', 'name']";
|
||||
$this->sharedLV['sort'] = ['-score', 'name'];
|
||||
|
||||
array_push($this->sharedLV['hiddenCols'], 'type', 'source');
|
||||
|
||||
@@ -534,8 +541,7 @@ class ItemsPage extends GenericPage
|
||||
switch ($this->category[0])
|
||||
{
|
||||
case 0:
|
||||
if (!isset($this->category[1]))
|
||||
$menu['type'] = [Lang::item('cat', 0, 1), null];
|
||||
$menu['type'] = [Lang::item('cat', 0, 1), null];
|
||||
|
||||
if (!isset($this->category[1]) || in_array($this->category[1], [6, -3]))
|
||||
{
|
||||
|
||||
@@ -25,11 +25,15 @@ class ItemsetPage extends GenericPage
|
||||
{
|
||||
parent::__construct($pageCall, $id);
|
||||
|
||||
// temp locale
|
||||
if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain']))
|
||||
Util::powerUseLocale($_GET['domain']);
|
||||
|
||||
$this->typeId = intVal($id);
|
||||
|
||||
$this->subject = new ItemsetList(array(['id', $this->typeId]));
|
||||
if ($this->subject->error)
|
||||
$this->notFound(Lang::game('itemset'), Lang::itemset('notFound'));
|
||||
$this->notFound();
|
||||
|
||||
$this->name = $this->subject->getField('name', true);
|
||||
$this->extendGlobalData($this->subject->getJSGlobals());
|
||||
@@ -68,11 +72,11 @@ class ItemsetPage extends GenericPage
|
||||
if ($this->subject->getField('cuFlags') & CUSTOM_UNAVAILABLE)
|
||||
$infobox[] = Lang::main('unavailable');
|
||||
|
||||
// holiday
|
||||
if ($h = $this->subject->getField('holidayId'))
|
||||
// worldevent
|
||||
if ($e = $this->subject->getField('eventId'))
|
||||
{
|
||||
$infobox[] = Lang::game('eventShort').Lang::main('colon').'[event='.$h.']';
|
||||
$this->extendGlobalIds(TYPE_WORLDEVENT, $h);
|
||||
$infobox[] = Lang::game('eventShort').Lang::main('colon').'[event='.$e.']';
|
||||
$this->extendGlobalIds(TYPE_WORLDEVENT, $e);
|
||||
}
|
||||
|
||||
// itemLevel
|
||||
@@ -135,54 +139,14 @@ class ItemsetPage extends GenericPage
|
||||
|
||||
$compare[] = $itemId;
|
||||
|
||||
$pieces[] = array(
|
||||
'id' => $itemId,
|
||||
'name' => $iList->getField('name', true),
|
||||
'quality' => $iList->getField('quality'),
|
||||
'icon' => $iList->getField('iconString'),
|
||||
'json' => $data[$itemId]
|
||||
$pieces[$itemId] = array(
|
||||
'name_'.User::$localeString => $iList->getField('name', true),
|
||||
'quality' => $iList->getField('quality'),
|
||||
'icon' => $iList->getField('iconString'),
|
||||
'jsonequip' => $data[$itemId]
|
||||
);
|
||||
}
|
||||
|
||||
// spells
|
||||
$foo = [];
|
||||
$spells = [];
|
||||
for ($i = 1; $i < 9; $i++)
|
||||
{
|
||||
$spl = $this->subject->getField('spell'.$i);
|
||||
$qty = $this->subject->getField('bonus'.$i);
|
||||
|
||||
if ($spl && $qty)
|
||||
{
|
||||
$foo[] = $spl;
|
||||
$spells[] = array( // cant use spell as index, would change order
|
||||
'id' => $spl,
|
||||
'bonus' => $qty,
|
||||
'desc' => ''
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// sort by required pieces ASC
|
||||
usort($spells, function($a, $b) {
|
||||
if ($a['bonus'] == $b['bonus'])
|
||||
return 0;
|
||||
|
||||
return ($a['bonus'] > $b['bonus']) ? 1 : -1;
|
||||
});
|
||||
|
||||
$setSpells = new SpellList(array(['s.id', $foo]));
|
||||
foreach ($setSpells->iterate() as $spellId => $__)
|
||||
{
|
||||
foreach ($spells as &$s)
|
||||
{
|
||||
if ($spellId != $s['id'])
|
||||
continue;
|
||||
|
||||
$s['desc'] = $setSpells->parseText('description')[0];
|
||||
}
|
||||
}
|
||||
|
||||
$skill = '';
|
||||
if ($_sk = $this->subject->getField('skillId'))
|
||||
{
|
||||
@@ -195,19 +159,20 @@ class ItemsetPage extends GenericPage
|
||||
$this->unavailable = $this->subject->getField('cuFlags') & CUSTOM_UNAVAILABLE;
|
||||
$this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
|
||||
$this->pieces = $pieces;
|
||||
$this->spells = $spells;
|
||||
$this->spells = $this->subject->getBonuses();
|
||||
$this->expansion = 0;
|
||||
$this->redButtons = array(
|
||||
BUTTON_WOWHEAD => $this->typeId > 0, // bool only
|
||||
BUTTON_LINKS => ['color' => '', 'linkId' => ''],
|
||||
BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId],
|
||||
BUTTON_VIEW3D => ['type' => TYPE_ITEMSET, 'typeId' => $this->typeId, 'equipList' => $eqList],
|
||||
BUTTON_COMPARE => ['eqList' => implode(':', $compare), 'qty' => $_cnt]
|
||||
);
|
||||
$this->compare = array(
|
||||
'level' => $this->subject->getField('reqLevel'),
|
||||
'items' => array_map(function ($v) {
|
||||
return [[$v]];
|
||||
}, $compare)
|
||||
$this->summary = array(
|
||||
'id' => 'itemset',
|
||||
'template' => 'itemset',
|
||||
'parent' => 'summary-generic',
|
||||
'groups' => array_map(function ($v) { return [[$v]]; }, $compare),
|
||||
'level' => $this->subject->getField('reqLevel'),
|
||||
);
|
||||
|
||||
/**************/
|
||||
@@ -223,10 +188,10 @@ class ItemsetPage extends GenericPage
|
||||
$rel[] = ['classMask', 1 << (end($this->path) - 1), '&'];
|
||||
$rel[] = ['contentGroup', (int)$_ta];
|
||||
}
|
||||
else if ($this->subject->getField('holidayId'))
|
||||
else if ($this->subject->getField('eventId'))
|
||||
{
|
||||
$rel[] = ['id', $this->typeId, '!'];
|
||||
$rel[] = ['holidayId', 0, '!'];
|
||||
$rel[] = ['eventId', 0, '!'];
|
||||
}
|
||||
else if ($this->subject->getField('skillId'))
|
||||
{
|
||||
@@ -248,24 +213,59 @@ class ItemsetPage extends GenericPage
|
||||
$relSets = new ItemsetList($rel);
|
||||
if (!$relSets->error)
|
||||
{
|
||||
$lv = array(
|
||||
'file' => 'itemset',
|
||||
'data' => $relSets->getListviewData(),
|
||||
'params' => array(
|
||||
'id' => 'see-also',
|
||||
'name' => '$LANG.tab_seealso'
|
||||
)
|
||||
$tabData = array(
|
||||
'data' => array_values($relSets->getListviewData()),
|
||||
'id' => 'see-also',
|
||||
'name' => '$LANG.tab_seealso'
|
||||
);
|
||||
|
||||
if (!$relSets->hasDiffFields(['classMask']))
|
||||
$lv['params']['hiddenCols'] = "$['classes']";
|
||||
$tabData['hiddenCols'] = ['classes'];
|
||||
|
||||
$this->lvTabs[] = $lv;
|
||||
$this->lvTabs[] = ['itemset', $tabData];
|
||||
|
||||
$this->extendGlobalData($relSets->getJSGlobals());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function generateTooltip($asError = false)
|
||||
{
|
||||
if ($asError)
|
||||
return '$WowheadPower.registerItemSet('.$this->typeId.', '.User::$localeId.', {});';
|
||||
|
||||
$x = '$WowheadPower.registerItemSet('.$this->typeId.', '.User::$localeId.", {\n";
|
||||
$x .= "\tname_".User::$localeString.": '".Util::jsEscape($this->subject->getField('name', true))."',\n";
|
||||
$x .= "\ttooltip_".User::$localeString.": '".$this->subject->renderTooltip()."'\n";
|
||||
$x .= "});";
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
public function display($override = '')
|
||||
{
|
||||
if ($this->mode != CACHE_TYPE_TOOLTIP)
|
||||
return parent::display($override);
|
||||
|
||||
if (!$this->loadCache($tt))
|
||||
{
|
||||
$tt = $this->generateTooltip();
|
||||
$this->saveCache($tt);
|
||||
}
|
||||
|
||||
header('Content-type: application/x-javascript; charset=utf-8');
|
||||
die($tt);
|
||||
}
|
||||
|
||||
public function notFound($title = '', $msg = '')
|
||||
{
|
||||
if ($this->mode != CACHE_TYPE_TOOLTIP)
|
||||
return parent::notFound($title ?: Lang::game('itemset'), $msg ?: Lang::itemset('notFound'));
|
||||
|
||||
header('Content-type: application/x-javascript; charset=utf-8');
|
||||
echo $this->generateTooltip(true);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ class ItemsetsPage extends GenericPage
|
||||
|
||||
public function __construct($pageCall, $pageParam)
|
||||
{
|
||||
$this->filterObj = new ItemsetListFilter();
|
||||
$this->getCategoryFromUrl($pageParam);
|
||||
$this->filterObj = new ItemsetListFilter(false, ['parentCats' => $this->category]);
|
||||
|
||||
parent::__construct($pageCall, $pageParam);
|
||||
|
||||
@@ -29,6 +29,8 @@ class ItemsetsPage extends GenericPage
|
||||
|
||||
protected function generateContent()
|
||||
{
|
||||
$this->addJS('?data=weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
||||
|
||||
$conditions = [];
|
||||
|
||||
if (!User::isInGroup(U_GROUP_EMPLOYEE))
|
||||
@@ -41,32 +43,33 @@ class ItemsetsPage extends GenericPage
|
||||
$this->extendGlobalData($itemsets->getJSGlobals());
|
||||
|
||||
// recreate form selection
|
||||
$this->filter = array_merge($this->filterObj->getForm('form'), $this->filter);
|
||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL;
|
||||
$this->filter['fi'] = $this->filterObj->getForm();
|
||||
$this->filter = $this->filterObj->getForm();
|
||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL;
|
||||
$this->filter['initData'] = ['init' => 'itemsets'];
|
||||
|
||||
$this->addJS('?data=weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
||||
if ($x = $this->filterObj->getSetCriteria())
|
||||
$this->filter['initData']['sc'] = $x;
|
||||
|
||||
$lv = array(
|
||||
'file' => 'itemset',
|
||||
'data' => $itemsets->getListviewData(), // listview content
|
||||
'params' => []
|
||||
);
|
||||
$xCols = $this->filterObj->getExtraCols();
|
||||
if ($xCols)
|
||||
$this->filter['initData']['ec'] = $xCols;
|
||||
|
||||
if (!empty($this->filter['fi']['extraCols']))
|
||||
$lv['params']['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
|
||||
$tabData = ['data' => array_values($itemsets->getListviewData())];
|
||||
|
||||
if ($xCols)
|
||||
$tabData['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
|
||||
|
||||
// create note if search limit was exceeded
|
||||
if ($itemsets->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
{
|
||||
$lv['params']['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_itemsetsfound', $itemsets->getMatches(), CFG_SQL_LIMIT_DEFAULT);
|
||||
$lv['params']['_truncated'] = 1;
|
||||
$tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_itemsetsfound', $itemsets->getMatches(), CFG_SQL_LIMIT_DEFAULT);
|
||||
$tabData['_truncated'] = 1;
|
||||
}
|
||||
|
||||
if ($this->filterObj->error)
|
||||
$lv['params']['_errors'] = '$1';
|
||||
$tabData['_errors'] = 1;
|
||||
|
||||
$this->lvTabs[] = $lv;
|
||||
$this->lvTabs[] = ['itemset', $tabData];
|
||||
|
||||
// sort for dropdown-menus
|
||||
Lang::sort('itemset', 'notes', SORT_NATURAL);
|
||||
|
||||
230
pages/more.php
230
pages/more.php
@@ -10,21 +10,41 @@ if (!defined('AOWOW_REVISION'))
|
||||
|
||||
class MorePage extends GenericPage
|
||||
{
|
||||
protected $tpl = 'text-page-generic';
|
||||
protected $path = [2];
|
||||
protected $tabId = 2;
|
||||
protected $mode = CACHE_TYPE_NONE;
|
||||
protected $js = ['swfobject.js'];
|
||||
protected $tpl = 'list-page-generic';
|
||||
protected $path = [];
|
||||
protected $tabId = 0;
|
||||
protected $mode = CACHE_TYPE_NONE;
|
||||
protected $js = ['swfobject.js'];
|
||||
|
||||
private $subPages = [ -13 => ['commenting-and-you', 'modelviewer', 'screenshots-tips-tricks', 'stat-weighting', 'talent-calculator', 'item-comparison', 'profiler', 'markup-guide']];
|
||||
private $validPages = array( // [type, typeId, name]
|
||||
'whats-new' => [ -7, 0, "What's New"],
|
||||
'searchbox' => [-16, 0, 'Search Box'],
|
||||
'tooltips' => [-10, 0, 'Tooltips'],
|
||||
'faq' => [ -3, 0, 'Frequently Asked Questions'],
|
||||
'aboutus' => [ -1, 0, 'What is AoWoW?'],
|
||||
'searchplugins' => [ -8, 0, 'Search Plugins'],
|
||||
'help' => [-13, null, '']
|
||||
private $page = [];
|
||||
private $req2priv = array(
|
||||
1 => CFG_REP_REQ_COMMENT, // write comments
|
||||
2 => 0, // NYI post external links
|
||||
4 => 0, // NYI no captcha
|
||||
5 => CFG_REP_REQ_SUPERVOTE, // votes count for more
|
||||
9 => CFG_REP_REQ_VOTEMORE_BASE, // more votes per day
|
||||
10 => CFG_REP_REQ_UPVOTE, // can upvote
|
||||
11 => CFG_REP_REQ_DOWNVOTE, // can downvote
|
||||
12 => CFG_REP_REQ_REPLY, // can reply
|
||||
13 => 0, // avatar border [NYI: checked by js, avatars not in use]
|
||||
14 => 0, // avatar border [NYI: checked by js, avatars not in use]
|
||||
15 => 0, // avatar border [NYI: checked by js, avatars not in use]
|
||||
16 => 0, // avatar border [NYI: checked by js, avatars not in use]
|
||||
17 => CFG_REP_REQ_PREMIUM // premium status
|
||||
);
|
||||
|
||||
private $validPages = array( // [tabId, path[, subPaths]]
|
||||
'whats-new' => [2, [2, 7]],
|
||||
'searchbox' => [2, [2, 16]],
|
||||
'tooltips' => [2, [2, 10]],
|
||||
'faq' => [2, [2, 3]],
|
||||
'aboutus' => [2, [2, 0]],
|
||||
'searchplugins' => [2, [2, 8]],
|
||||
'help' => [2, [2, 13], ['commenting-and-you', 'modelviewer', 'screenshots-tips-tricks', 'stat-weighting', 'talent-calculator', 'item-comparison', 'profiler', 'markup-guide']],
|
||||
'reputation' => [1, [3, 10]],
|
||||
'privilege' => [1, [3, 10], [1, 2, 4, 5, 9, 10, 11, 12, 13, 14, 15, 16, 17]],
|
||||
'privileges' => [1, [3, 10, 0]],
|
||||
'top-users' => [1, [3, 11]]
|
||||
);
|
||||
|
||||
public function __construct($pageCall, $subPage)
|
||||
@@ -34,44 +54,186 @@ class MorePage extends GenericPage
|
||||
// chack if page is valid
|
||||
if (isset($this->validPages[$pageCall]))
|
||||
{
|
||||
$_ = $this->validPages[$pageCall];
|
||||
$pageData = $this->validPages[$pageCall];
|
||||
|
||||
// check if subpage is valid
|
||||
if (!isset($_[1]))
|
||||
$this->tab = $pageData[0];
|
||||
$this->path = $pageData[1];
|
||||
$this->page = [$pageCall, $subPage];
|
||||
|
||||
if ($subPage && isset($pageData[2]))
|
||||
{
|
||||
if (($_[1] = array_search($subPage, $this->subPages[$_[0]])) === false)
|
||||
$exists = array_search($subPage, $pageData[2]);
|
||||
if ($exists === false)
|
||||
$this->error();
|
||||
|
||||
if ($pageCall == 'help') // ye.. hack .. class definitions only allow static values
|
||||
$_[2] = Lang::main('helpTopics', $_[1]);
|
||||
if (is_numeric($subPage))
|
||||
$this->articleUrl = $pageCall.'='.$subPage;
|
||||
else
|
||||
$this->articleUrl = $subPage;
|
||||
|
||||
$this->path[] = $subPage;
|
||||
$this->name = Lang::main('moreTitles', $pageCall, $subPage);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->articleUrl = $pageCall;
|
||||
$this->name = Lang::main('moreTitles', $pageCall);
|
||||
}
|
||||
$this->type = $_[0];
|
||||
$this->typeId = $_[1];
|
||||
$this->name = $_[2];
|
||||
$this->gPageInfo = array(
|
||||
'type' => $this->type,
|
||||
'typeId' => $this->typeId,
|
||||
'name' => $this->name
|
||||
);
|
||||
}
|
||||
else
|
||||
$this->error();
|
||||
|
||||
// order by requirement ASC
|
||||
asort($this->req2priv);
|
||||
}
|
||||
|
||||
protected function generatePath()
|
||||
protected function generateContent()
|
||||
{
|
||||
$this->path[] = abs($this->type);
|
||||
|
||||
if ($this->typeId > -1)
|
||||
$this->path[] = $this->typeId;
|
||||
switch ($this->page[0])
|
||||
{
|
||||
case 'reputation':
|
||||
$this->handleReputationPage();
|
||||
return;
|
||||
case 'privileges':
|
||||
$this->handlePrivilegesPage();
|
||||
return;
|
||||
case 'privilege':
|
||||
$this->tpl = 'privilege';
|
||||
$this->privReqPoints = sprintf(Lang::privileges('reqPoints'), Lang::nf($this->req2priv[$this->page[1]]));
|
||||
return;
|
||||
case 'top-users':
|
||||
$this->handleTopUsersPage();
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected function postArticle()
|
||||
{
|
||||
if ($this->page[0] != 'reputation' &&
|
||||
$this->page[0] != 'privileges' &&
|
||||
$this->page[0] != 'privilege')
|
||||
return;
|
||||
|
||||
$txt = &$this->article['text'];
|
||||
$consts = get_defined_constants(true);
|
||||
foreach ($consts['user'] as $k => $v)
|
||||
{
|
||||
if (strstr($k, 'CFG_REP_'))
|
||||
$txt = str_replace($k, Lang::nf($v), $txt);
|
||||
else if ($k == 'CFG_USER_MAX_VOTES' || $k == 'CFG_BOARD_URL')
|
||||
$txt = str_replace($k, $v, $txt);
|
||||
}
|
||||
}
|
||||
|
||||
protected function generatePath() { }
|
||||
|
||||
protected function generateTitle()
|
||||
{
|
||||
array_unshift($this->title, $this->name);
|
||||
}
|
||||
|
||||
protected function generateContent() {} // its just articles here
|
||||
private function handleReputationPage()
|
||||
{
|
||||
if (!User::$id)
|
||||
return;
|
||||
|
||||
if ($repData = DB::Aowow()->select('SELECT action, amount, date AS \'when\', IF(action IN (3, 4, 5), sourceA, 0) AS param FROM ?_account_reputation WHERE userId = ?d', User::$id))
|
||||
{
|
||||
foreach ($repData as &$r)
|
||||
$r['when'] = date(Util::$dateFormatInternal, $r['when']);
|
||||
|
||||
$this->tabsTitle = Lang::main('yourRepHistory');
|
||||
$this->forceTabs = true;
|
||||
$this->lvTabs[] = ['reputationhistory', array(
|
||||
'id' => 'reputation-history',
|
||||
'name' => '$LANG.reputationhistory',
|
||||
'data' => $repData
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
private function handlePrivilegesPage()
|
||||
{
|
||||
$this->tpl = 'privileges';
|
||||
$this->privileges = [];
|
||||
|
||||
foreach ($this->req2priv as $id => $val)
|
||||
if ($val)
|
||||
$this->privileges[$id] = array(
|
||||
User::getReputation() >= $val,
|
||||
Lang::privileges('_privileges', $id),
|
||||
$val
|
||||
);
|
||||
}
|
||||
|
||||
private function handleTopUsersPage()
|
||||
{
|
||||
$tabs = array(
|
||||
[0, 'top-users-alltime', '$LANG.alltime_stc' ],
|
||||
[time() - MONTH, 'top-users-monthly', '$LANG.lastmonth_stc'],
|
||||
[time() - WEEK, 'top-users-weekly', '$LANG.lastweek_stc' ]
|
||||
);
|
||||
|
||||
$nullFields = array(
|
||||
'uploads' => 0,
|
||||
'posts' => 0,
|
||||
'gold' => 0,
|
||||
'silver' => 0,
|
||||
'copper' => 0
|
||||
);
|
||||
|
||||
foreach ($tabs as list($t, $tabId, $tabName))
|
||||
{
|
||||
// stuff received
|
||||
$res = DB::Aowow()->select('
|
||||
SELECT
|
||||
a.id AS ARRAY_KEY,
|
||||
a.displayName AS username,
|
||||
a.userGroups AS groups,
|
||||
a.joinDate AS creation,
|
||||
SUM(r.amount) AS reputation,
|
||||
SUM(IF(r.`action` = 3, 1, 0)) AS comments,
|
||||
SUM(IF(r.`action` = 6, 1, 0)) AS screenshots,
|
||||
SUM(IF(r.`action` = 9, 1, 0)) AS reports
|
||||
FROM ?_account_reputation r
|
||||
JOIN ?_account a ON a.id = r.userId
|
||||
{WHERE r.date > ?d}
|
||||
GROUP BY a.id
|
||||
ORDER BY reputation DESC
|
||||
LIMIT ?d
|
||||
', $t ?: DBSIMPLE_SKIP, CFG_SQL_LIMIT_SEARCH);
|
||||
|
||||
$data = [];
|
||||
if ($res)
|
||||
{
|
||||
// stuff given
|
||||
$votes = DB::Aowow()->selectCol(
|
||||
'SELECT sourceB AS ARRAY_KEY, SUM(1) FROM ?_account_reputation WHERE action IN (4, 5) AND sourceB IN (?a) {AND date > ?d} GROUP BY sourceB',
|
||||
array_keys($res),
|
||||
$t ?: DBSIMPLE_SKIP
|
||||
);
|
||||
foreach ($res as $uId => &$r)
|
||||
{
|
||||
$r['creation'] = date('c', $r['creation']);
|
||||
$r['votes'] = empty($votes[$uId]) ? 0 : $votes[$uId];
|
||||
$r = array_merge($r, $nullFields);
|
||||
}
|
||||
|
||||
$data = array_values($res);
|
||||
}
|
||||
|
||||
$this->lvTabs[] = ['topusers', array(
|
||||
'hiddenCols' => ['achievements', 'posts', 'uploads'],
|
||||
'visibleCols' => ['created'],
|
||||
'name' => '$LANG.lastweek_stc',
|
||||
'name' => $tabName,
|
||||
'id' => $tabId,
|
||||
'data' => $data
|
||||
)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
390
pages/npc.php
390
pages/npc.php
@@ -18,6 +18,8 @@ class NpcPage extends GenericPage
|
||||
protected $mode = CACHE_TYPE_PAGE;
|
||||
protected $js = ['swfobject.js'];
|
||||
|
||||
private $soundIds = [];
|
||||
|
||||
public function __construct($pageCall, $id)
|
||||
{
|
||||
parent::__construct($pageCall, $id);
|
||||
@@ -53,15 +55,15 @@ class NpcPage extends GenericPage
|
||||
{
|
||||
$this->addJS('?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
||||
|
||||
$_typeFlags = $this->subject->getField('typeFlags');
|
||||
$_altIds = [];
|
||||
$_altNPCs = null;
|
||||
$position = null;
|
||||
$accessory = [];
|
||||
$_typeFlags = $this->subject->getField('typeFlags');
|
||||
$_altIds = [];
|
||||
$_altNPCs = null;
|
||||
$placeholder = null;
|
||||
$accessory = [];
|
||||
|
||||
// difficulty entries of self
|
||||
if ($this->subject->getField('cuFlags') & NPC_CU_DIFFICULTY_DUMMY)
|
||||
$position = [$this->subject->getField('parentId'), $this->subject->getField('parent', true)];
|
||||
$placeholder = [$this->subject->getField('parentId'), $this->subject->getField('parent', true)];
|
||||
else
|
||||
{
|
||||
for ($i = 1; $i < 4; $i++)
|
||||
@@ -85,7 +87,7 @@ class NpcPage extends GenericPage
|
||||
{
|
||||
if (count($maps) == 1) // should only exist in one instance
|
||||
{
|
||||
switch ((new ZoneList(array(['id', $maps], 1)))->getField('type'))
|
||||
switch (DB::Aowow()->selectCell('SELECT `type` FROM ?_zones WHERE id = ?d', $maps[0]))
|
||||
{
|
||||
case 2:
|
||||
case 5: $mapType = 1; break;
|
||||
@@ -103,6 +105,7 @@ class NpcPage extends GenericPage
|
||||
$mapType = 1;
|
||||
}
|
||||
|
||||
|
||||
/***********/
|
||||
/* Infobox */
|
||||
/***********/
|
||||
@@ -110,7 +113,7 @@ class NpcPage extends GenericPage
|
||||
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
|
||||
|
||||
// Event (ignore events, where the object only gets removed)
|
||||
if ($_ = DB::World()->selectCol('SELECT DISTINCT IF(ge.holiday, ge.holiday, -ge.eventEntry) FROM game_event ge, game_event_creature gec, creature c WHERE ge.eventEntry = gec.eventEntry AND c.guid = gec.guid AND c.id = ?d', $this->typeId))
|
||||
if ($_ = DB::World()->selectCol('SELECT DISTINCT ge.eventEntry FROM game_event ge, game_event_creature gec, creature c WHERE ge.eventEntry = gec.eventEntry AND c.guid = gec.guid AND c.id = ?d', $this->typeId))
|
||||
{
|
||||
$this->extendGlobalIds(TYPE_WORLDEVENT, $_);
|
||||
$ev = [];
|
||||
@@ -136,7 +139,7 @@ class NpcPage extends GenericPage
|
||||
// Classification
|
||||
if ($_ = $this->subject->getField('rank')) // != NPC_RANK_NORMAL
|
||||
{
|
||||
$str = $_typeFlags & 0x4 ? '[span class=icon-boss]'.Lang::npc('rank', $_).'[/span]' : Lang::npc('rank', $_);
|
||||
$str = $this->subject->isBoss() ? '[span class=icon-boss]'.Lang::npc('rank', $_).'[/span]' : Lang::npc('rank', $_);
|
||||
$infobox[] = Lang::npc('classification').Lang::main('colon').$str;
|
||||
}
|
||||
|
||||
@@ -227,33 +230,32 @@ class NpcPage extends GenericPage
|
||||
}
|
||||
|
||||
// > Stats
|
||||
$_nf = function ($num) { return number_format($num, 0, '', '.'); };
|
||||
$stats = [];
|
||||
$modes = []; // get difficulty versions if set
|
||||
$hint = '[tooltip name=%3$s][table cellspacing=10][tr]%1s[/tr][/table][/tooltip][span class=tip tooltip=%3$s]%2s[/span]';
|
||||
$modeRow = '[tr][td]%s [/td][td]%s[/td][/tr]';
|
||||
// Health
|
||||
$health = $this->subject->getBaseStats('health');
|
||||
$stats['health'] = Util::ucFirst(Lang::spell('powerTypes', -2)).Lang::main('colon').($health[0] < $health[1] ? $_nf($health[0]).' - '.$_nf($health[1]) : $_nf($health[0]));
|
||||
$stats['health'] = Util::ucFirst(Lang::spell('powerTypes', -2)).Lang::main('colon').($health[0] < $health[1] ? Lang::nf($health[0]).' - '.Lang::nf($health[1]) : Lang::nf($health[0]));
|
||||
|
||||
// Mana (may be 0)
|
||||
$mana = $this->subject->getBaseStats('power');
|
||||
$stats['mana'] = $mana[0] ? Lang::spell('powerTypes', 0).Lang::main('colon').($mana[0] < $mana[1] ? $_nf($mana[0]).' - '.$_nf($mana[1]) : $_nf($mana[0])) : null;
|
||||
$stats['mana'] = $mana[0] ? Lang::spell('powerTypes', 0).Lang::main('colon').($mana[0] < $mana[1] ? Lang::nf($mana[0]).' - '.Lang::nf($mana[1]) : Lang::nf($mana[0])) : null;
|
||||
|
||||
// Armor
|
||||
$armor = $this->subject->getBaseStats('armor');
|
||||
$stats['armor'] = Lang::npc('armor').Lang::main('colon').($armor[0] < $armor[1] ? $_nf($armor[0]).' - '.$_nf($armor[1]) : $_nf($armor[0]));
|
||||
$stats['armor'] = Lang::npc('armor').Lang::main('colon').($armor[0] < $armor[1] ? Lang::nf($armor[0]).' - '.Lang::nf($armor[1]) : Lang::nf($armor[0]));
|
||||
|
||||
// Melee Damage
|
||||
$melee = $this->subject->getBaseStats('melee');
|
||||
if ($_ = $this->subject->getField('dmgSchool')) // magic damage
|
||||
$stats['melee'] = Lang::npc('melee').Lang::main('colon').$_nf($melee[0]).' - '.$_nf($melee[1]).' ('.Lang::game('sc', $_).')';
|
||||
$stats['melee'] = Lang::npc('melee').Lang::main('colon').Lang::nf($melee[0]).' - '.Lang::nf($melee[1]).' ('.Lang::game('sc', $_).')';
|
||||
else // phys. damage
|
||||
$stats['melee'] = Lang::npc('melee').Lang::main('colon').$_nf($melee[0]).' - '.$_nf($melee[1]);
|
||||
$stats['melee'] = Lang::npc('melee').Lang::main('colon').Lang::nf($melee[0]).' - '.Lang::nf($melee[1]);
|
||||
|
||||
// Ranged Damage
|
||||
$ranged = $this->subject->getBaseStats('ranged');
|
||||
$stats['ranged'] = Lang::npc('ranged').Lang::main('colon').$_nf($ranged[0]).' - '.$_nf($ranged[1]);
|
||||
$stats['ranged'] = Lang::npc('ranged').Lang::main('colon').Lang::nf($ranged[0]).' - '.Lang::nf($ranged[1]);
|
||||
|
||||
if (in_array($mapType, [1, 2])) // Dungeon or Raid
|
||||
{
|
||||
@@ -268,26 +270,26 @@ class NpcPage extends GenericPage
|
||||
|
||||
// Health
|
||||
$health = $_altNPCs->getBaseStats('health');
|
||||
$modes['health'][] = sprintf($modeRow, $m, $health[0] < $health[1] ? $_nf($health[0]).' - '.$_nf($health[1]) : $_nf($health[0]));
|
||||
$modes['health'][] = sprintf($modeRow, $m, $health[0] < $health[1] ? Lang::nf($health[0]).' - '.Lang::nf($health[1]) : Lang::nf($health[0]));
|
||||
|
||||
// Mana (may be 0)
|
||||
$mana = $_altNPCs->getBaseStats('power');
|
||||
$modes['mana'][] = $mana[0] ? sprintf($modeRow, $m, $mana[0] < $mana[1] ? $_nf($mana[0]).' - '.$_nf($mana[1]) : $_nf($mana[0])) : null;
|
||||
$modes['mana'][] = $mana[0] ? sprintf($modeRow, $m, $mana[0] < $mana[1] ? Lang::nf($mana[0]).' - '.Lang::nf($mana[1]) : Lang::nf($mana[0])) : null;
|
||||
|
||||
// Armor
|
||||
$armor = $_altNPCs->getBaseStats('armor');
|
||||
$modes['armor'][] = sprintf($modeRow, $m, $armor[0] < $armor[1] ? $_nf($armor[0]).' - '.$_nf($armor[1]) : $_nf($armor[0]));
|
||||
$modes['armor'][] = sprintf($modeRow, $m, $armor[0] < $armor[1] ? Lang::nf($armor[0]).' - '.Lang::nf($armor[1]) : Lang::nf($armor[0]));
|
||||
|
||||
// Melee Damage
|
||||
$melee = $_altNPCs->getBaseStats('melee');
|
||||
if ($_ = $_altNPCs->getField('dmgSchool')) // magic damage
|
||||
$modes['melee'][] = sprintf($modeRow, $m, $_nf($melee[0]).' - '.$_nf($melee[1]).' ('.Lang::game('sc', $_).')');
|
||||
$modes['melee'][] = sprintf($modeRow, $m, Lang::nf($melee[0]).' - '.Lang::nf($melee[1]).' ('.Lang::game('sc', $_).')');
|
||||
else // phys. damage
|
||||
$modes['melee'][] = sprintf($modeRow, $m, $_nf($melee[0]).' - '.$_nf($melee[1]));
|
||||
$modes['melee'][] = sprintf($modeRow, $m, Lang::nf($melee[0]).' - '.Lang::nf($melee[1]));
|
||||
|
||||
// Ranged Damage
|
||||
$ranged = $_altNPCs->getBaseStats('ranged');
|
||||
$modes['ranged'][] = sprintf($modeRow, $m, $_nf($ranged[0]).' - '.$_nf($ranged[1]));
|
||||
$modes['ranged'][] = sprintf($modeRow, $m, Lang::nf($ranged[0]).' - '.Lang::nf($ranged[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -301,6 +303,7 @@ class NpcPage extends GenericPage
|
||||
if ($stats)
|
||||
$infobox[] = Lang::npc('stats').($modes ? ' ('.Lang::npc('modes', $mapType, 0).')' : null).Lang::main('colon').'[ul][li]'.implode('[/li][li]', $stats).'[/li][/ul]';
|
||||
|
||||
|
||||
/****************/
|
||||
/* Main Content */
|
||||
/****************/
|
||||
@@ -318,16 +321,20 @@ class NpcPage extends GenericPage
|
||||
|
||||
$this->map = $map;
|
||||
$this->infobox = '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]';
|
||||
$this->position = $position;
|
||||
$this->placeholder = $placeholder;
|
||||
$this->accessory = $accessory;
|
||||
$this->quotes = $this->getQuotes();
|
||||
$this->reputation = $this->getOnKillRep($_altIds, $mapType);
|
||||
$this->redButtons = array(
|
||||
BUTTON_WOWHEAD => true,
|
||||
BUTTON_LINKS => true,
|
||||
BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId],
|
||||
BUTTON_VIEW3D => ['type' => TYPE_NPC, 'typeId' => $this->typeId, 'displayId' => $this->subject->getRandomModelId()]
|
||||
);
|
||||
|
||||
if ($this->subject->getField('humanoid'))
|
||||
$this->redButtons[BUTTON_VIEW3D]['humanoid'] = 1;
|
||||
|
||||
|
||||
/**************/
|
||||
/* Extra Tabs */
|
||||
/**************/
|
||||
@@ -356,7 +363,7 @@ class NpcPage extends GenericPage
|
||||
{
|
||||
$skill = 0;
|
||||
$mask = 0x0;
|
||||
foreach (Util::$skillLineMask[-1] as $idx => $pair)
|
||||
foreach (Game::$skillLineMask[-1] as $idx => $pair)
|
||||
{
|
||||
if ($pair[0] != $_)
|
||||
continue;
|
||||
@@ -404,24 +411,18 @@ class NpcPage extends GenericPage
|
||||
}
|
||||
|
||||
if ($normal)
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'spell',
|
||||
'data' => $normal,
|
||||
'params' => array(
|
||||
'name' => '$LANG.tab_abilities',
|
||||
'id' => 'abilities'
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['spell', array(
|
||||
'data' => array_values($normal),
|
||||
'name' => '$LANG.tab_abilities',
|
||||
'id' => 'abilities'
|
||||
)];
|
||||
|
||||
if ($controled)
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'spell',
|
||||
'data' => $controled,
|
||||
'params' => array(
|
||||
'name' => '$LANG.tab_controlledabilities',
|
||||
'id' => 'controlled-abilities'
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['spell', array(
|
||||
'data' => array_values($controled),
|
||||
'name' => '$LANG.tab_controlledabilities',
|
||||
'id' => 'controlled-abilities'
|
||||
)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,28 +439,25 @@ class NpcPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($summoned->getJSGlobals());
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'spell',
|
||||
'data' => $summoned->getListviewData(),
|
||||
'params' => array(
|
||||
'name' => '$LANG.tab_summonedby',
|
||||
'id' => 'summoned-by'
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['spell', array(
|
||||
'data' => array_values($summoned->getListviewData()),
|
||||
'name' => '$LANG.tab_summonedby',
|
||||
'id' => 'summoned-by'
|
||||
)];
|
||||
}
|
||||
|
||||
// tab: teaches
|
||||
if ($this->subject->getField('npcflag') & NPC_FLAG_TRAINER)
|
||||
{
|
||||
$teachQuery = '
|
||||
SELECT IFNULL(t2.spell, t1.spell) AS ARRAY_KEY,
|
||||
IFNULL(t2.spellcost, t1.spellcost) AS cost,
|
||||
IFNULL(t2.reqskill, t1.reqskill) AS reqSkillId,
|
||||
IFNULL(t2.reqskillvalue, t1.reqskillvalue) AS reqSkillValue,
|
||||
IFNULL(t2.reqlevel, t1.reqlevel) AS reqLevel
|
||||
SELECT IFNULL(t2.SpellID, t1.SpellID) AS ARRAY_KEY,
|
||||
IFNULL(t2.MoneyCost, t1.MoneyCost) AS cost,
|
||||
IFNULL(t2.ReqSkillLine, t1.ReqSkillLine) AS reqSkillId,
|
||||
IFNULL(t2.ReqSkillRank, t1.ReqSkillRank) AS reqSkillValue,
|
||||
IFNULL(t2.ReqLevel, t1.ReqLevel) AS reqLevel
|
||||
FROM npc_trainer t1
|
||||
LEFT JOIN npc_trainer t2 ON t2.entry = IF(t1.spell < 0, -t1.spell, null)
|
||||
WHERE t1.entry = ?d
|
||||
LEFT JOIN npc_trainer t2 ON t2.ID = IF(t1.SpellID < 0, -t1.SpellID, null)
|
||||
WHERE t1.ID = ?d
|
||||
';
|
||||
|
||||
if ($tSpells = DB::World()->select($teachQuery, $this->typeId))
|
||||
@@ -480,7 +478,7 @@ class NpcPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalIds(TYPE_SKILL, $_);
|
||||
if (!isset($extra[0]))
|
||||
$extra[0] = 'Listview.extraCols.condition';
|
||||
$extra[0] = '$Listview.extraCols.condition';
|
||||
|
||||
$data[$sId]['condition'][0][$this->typeId][] = [[CND_SKILL, $_, $train['reqSkillValue']]];
|
||||
}
|
||||
@@ -488,7 +486,7 @@ class NpcPage extends GenericPage
|
||||
if ($_ = $train['reqLevel'])
|
||||
{
|
||||
if (!isset($extra[1]))
|
||||
$extra[1] = "Listview.funcBox.createSimpleCol('reqLevel', LANG.tooltip_reqlevel, '7%', 'reqLevel')";
|
||||
$extra[1] = "\$Listview.funcBox.createSimpleCol('reqLevel', LANG.tooltip_reqlevel, '7%', 'reqLevel')";
|
||||
|
||||
$data[$sId]['reqLevel'] = $_;
|
||||
}
|
||||
@@ -497,20 +495,21 @@ class NpcPage extends GenericPage
|
||||
$data[$sId]['trainingcost'] = $_;
|
||||
}
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'spell',
|
||||
'data' => $data,
|
||||
'params' => array(
|
||||
'name' => '$LANG.tab_teaches',
|
||||
'id' => 'teaches',
|
||||
'visibleCols' => "$['trainingcost']",
|
||||
'extraCols' => $extra ? '$['.implode(', ', $extra).']' : null
|
||||
)
|
||||
$tabData = array(
|
||||
'data' => array_values($data),
|
||||
'name' => '$LANG.tab_teaches',
|
||||
'id' => 'teaches',
|
||||
'visibleCols' => ['trainingcost']
|
||||
);
|
||||
|
||||
if ($extra)
|
||||
$tabData['extraCols'] = $extra;
|
||||
|
||||
$this->lvTabs[] = ['spell', $tabData];
|
||||
}
|
||||
}
|
||||
else
|
||||
Util::addNote(U_GROUP_EMPLOYEE, 'NPC '.$this->typeId.' is flagged as trainer, but doesn\'t have any spells set');
|
||||
trigger_error('NPC '.$this->typeId.' is flagged as trainer, but doesn\'t have any spells set', E_USER_WARNING);
|
||||
}
|
||||
|
||||
// tab: sells
|
||||
@@ -519,9 +518,9 @@ class NpcPage extends GenericPage
|
||||
$soldItems = new ItemList(array(['id', $sells]));
|
||||
if (!$soldItems->error)
|
||||
{
|
||||
$extraCols = ["Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", 'Listview.extraCols.cost'];
|
||||
$extraCols = ["\$Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", '$Listview.extraCols.cost'];
|
||||
if ($soldItems->hasSetFields(['condition']))
|
||||
$extraCols[] = 'Listview.extraCols.condition';
|
||||
$extraCols[] = '$Listview.extraCols.condition';
|
||||
|
||||
$lvData = $soldItems->getListviewData(ITEMINFO_VENDOR, [TYPE_NPC => [$this->typeId]]);
|
||||
|
||||
@@ -530,8 +529,7 @@ class NpcPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($sc[1]);
|
||||
|
||||
if (!array_search('Listview.extraCols.condition', $extraCols))
|
||||
$extraCols[] = 'Listview.extraCols.condition';
|
||||
$extraCols[] = '$Listview.extraCols.condition';
|
||||
|
||||
foreach ($lvData as $id => &$row)
|
||||
foreach ($sc[0] as $srcType => $cndData)
|
||||
@@ -539,15 +537,12 @@ class NpcPage extends GenericPage
|
||||
$row['condition'][0][$id.':'.$this->typeId] = $cndData[$id.':'.$this->typeId];
|
||||
}
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'item',
|
||||
'data' => $lvData,
|
||||
'params' => array(
|
||||
'name' => '$LANG.tab_sells',
|
||||
'id' => 'currency-for',
|
||||
'extraCols' => '$['.implode(', ', $extraCols).']'
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['item', array(
|
||||
'data' => array_values($lvData),
|
||||
'name' => '$LANG.tab_sells',
|
||||
'id' => 'currency-for',
|
||||
'extraCols' => array_unique($extraCols)
|
||||
)];
|
||||
|
||||
$this->extendGlobalData($soldItems->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED));
|
||||
}
|
||||
@@ -572,9 +567,9 @@ class NpcPage extends GenericPage
|
||||
*/
|
||||
|
||||
$sourceFor = array(
|
||||
[LOOT_CREATURE, $this->subject->getField('lootId'), '$LANG.tab_drops', 'drops', ['Listview.extraCols.percent'], [] , []],
|
||||
[LOOT_PICKPOCKET, $this->subject->getField('pickpocketLootId'), '$LANG.tab_pickpocketing', 'pickpocketing', ['Listview.extraCols.percent'], ['side', 'slot', 'reqlevel'], []],
|
||||
[LOOT_SKINNING, $this->subject->getField('skinLootId'), '$LANG.'.$skinTab[0], $skinTab[1], ['Listview.extraCols.percent'], ['side', 'slot', 'reqlevel'], []]
|
||||
[LOOT_CREATURE, $this->subject->getField('lootId'), '$LANG.tab_drops', 'drops', [] ],
|
||||
[LOOT_PICKPOCKET, $this->subject->getField('pickpocketLootId'), '$LANG.tab_pickpocketing', 'pickpocketing', ['side', 'slot', 'reqlevel']],
|
||||
[LOOT_SKINNING, $this->subject->getField('skinLootId'), '$LANG.'.$skinTab[0], $skinTab[1], ['side', 'slot', 'reqlevel']]
|
||||
);
|
||||
|
||||
// temp: manually add loot for difficulty-versions
|
||||
@@ -589,22 +584,29 @@ class NpcPage extends GenericPage
|
||||
|
||||
if ($_altIds)
|
||||
{
|
||||
$sourceFor[0][2] = $langref[1];
|
||||
$sourceFor[0][2] = $mapType == 1 ? $langref[-1] : $langref[1];
|
||||
foreach ($_altNPCs->iterate() as $id => $__)
|
||||
{
|
||||
$mode = $_altIds[$id];
|
||||
array_splice($sourceFor, 1, 0, [[LOOT_CREATURE, $_altNPCs->getField('lootId'), $langref[$mode + 1], 'drops-'.$mode, ['Listview.extraCols.percent'], [], []]]);
|
||||
$mode = ($_altIds[$id] + 1) * ($mapType == 1 ? -1 : 1);
|
||||
if ($lootGO = DB::Aowow()->selectRow('SELECT o.id, o.lootId, o.name_loc0, o.name_loc2, o.name_loc3, o.name_loc6, o.name_loc8 FROM ?_loot_link l JOIN ?_objects o ON o.id = l.objectId WHERE l.npcId = ?d', $id))
|
||||
array_splice($sourceFor, 1, 0, [[LOOT_GAMEOBJECT, $lootGO['lootId'], $langref[$mode], 'drops-object-'.abs($mode), [], 'note' => '$$WH.sprintf(LANG.lvnote_npcobjectsource, '.$lootGO['id'].', "'.Util::localizedString($lootGO, 'name').'")']]);
|
||||
if ($lootId = $_altNPCs->getField('lootId'))
|
||||
array_splice($sourceFor, 1, 0, [[LOOT_CREATURE, $lootId, $langref[$mode], 'drops-'.abs($mode), []]]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($lootGOs = DB::Aowow()->select('SELECT o.id, IF(npcId < 0, 1, 0) AS modeDummy, o.lootId, o.name_loc0, o.name_loc2, o.name_loc3, o.name_loc6, o.name_loc8 FROM ?_loot_link l JOIN ?_objects o ON o.id = l.objectId WHERE ABS(l.npcId) = ?d', $this->typeId))
|
||||
foreach ($lootGOs as $idx => $lgo)
|
||||
array_splice($sourceFor, 1, 0, [[LOOT_GAMEOBJECT, $lgo['lootId'], $mapType ? $langref[($mapType == 1 ? -1 : 1) + ($lgo['modeDummy'] ? 1 : 0)] : '$LANG.tab_drops', 'drops-object-'.$idx, [], 'note' => '$$WH.sprintf(LANG.lvnote_npcobjectsource, '.$lgo['id'].', "'.Util::localizedString($lgo, 'name').'")']]);
|
||||
|
||||
$reqQuest = [];
|
||||
foreach ($sourceFor as $sf)
|
||||
{
|
||||
$creatureLoot = new Loot();
|
||||
if ($creatureLoot->getByContainer($sf[0], $sf[1]))
|
||||
{
|
||||
if ($_ = $creatureLoot->extraCols)
|
||||
$sf[4] = array_merge($sf[4], $_);
|
||||
$extraCols = $creatureLoot->extraCols;
|
||||
$extraCols[] = '$Listview.extraCols.percent';
|
||||
|
||||
$this->extendGlobalData($creatureLoot->jsGlobals);
|
||||
|
||||
@@ -613,23 +615,26 @@ class NpcPage extends GenericPage
|
||||
if (!$lv['quest'])
|
||||
continue;
|
||||
|
||||
$sf[4][] = 'Listview.extraCols.condition';
|
||||
$extraCols[] = '$Listview.extraCols.condition';
|
||||
$reqQuest[$lv['id']] = 0;
|
||||
$lv['condition'][0][$this->typeId][] = [[CND_QUESTTAKEN, &$reqQuest[$lv['id']]]];
|
||||
}
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'item',
|
||||
'data' => $creatureLoot->getResult(),
|
||||
'params' => array(
|
||||
'name' => $sf[2],
|
||||
'id' => $sf[3],
|
||||
'extraCols' => $sf[4] ? "$[".implode(', ', array_unique($sf[4]))."]" : null,
|
||||
'hiddenCols' => $sf[5] ? "$".Util::toJSON($sf[5]) : null,
|
||||
'visibleCols' => $sf[6] ? '$'.Util::toJSON($sf[6]) : null,
|
||||
'sort' => "$['-percent', 'name']",
|
||||
)
|
||||
$tabData = array(
|
||||
'data' => array_values($creatureLoot->getResult()),
|
||||
'name' => $sf[2],
|
||||
'id' => $sf[3],
|
||||
'extraCols' => array_unique($extraCols),
|
||||
'sort' => ['-percent', 'name'],
|
||||
);
|
||||
|
||||
if (!empty($sf['note']))
|
||||
$tabData['note'] = $sf['note'];
|
||||
|
||||
if ($sf[4])
|
||||
$tabData['hiddenCols'] = $sf[4];
|
||||
|
||||
$this->lvTabs[] = ['item', $tabData];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -676,28 +681,18 @@ class NpcPage extends GenericPage
|
||||
}
|
||||
|
||||
if ($_[0])
|
||||
{
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'quest',
|
||||
'data' => $_[0],
|
||||
'params' => array(
|
||||
'name' => '$LANG.tab_starts',
|
||||
'id' => 'starts'
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->lvTabs[] = ['quest', array(
|
||||
'data' => array_values($_[0]),
|
||||
'name' => '$LANG.tab_starts',
|
||||
'id' => 'starts'
|
||||
)];
|
||||
|
||||
if ($_[1])
|
||||
{
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'quest',
|
||||
'data' => $_[1],
|
||||
'params' => array(
|
||||
'name' => '$LANG.tab_ends',
|
||||
'id' => 'ends'
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->lvTabs[] = ['quest', array(
|
||||
'data' => array_values($_[1]),
|
||||
'name' => '$LANG.tab_ends',
|
||||
'id' => 'ends'
|
||||
)];
|
||||
}
|
||||
|
||||
// tab: objective of quest
|
||||
@@ -714,14 +709,11 @@ class NpcPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($objectiveOf->getJSGlobals());
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'quest',
|
||||
'data' => $objectiveOf->getListviewData(),
|
||||
'params' => array(
|
||||
'name' => '$LANG.tab_objectiveof',
|
||||
'id' => 'objective-of'
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['quest', array(
|
||||
'data' => array_values($objectiveOf->getListviewData()),
|
||||
'name' => '$LANG.tab_objectiveof',
|
||||
'id' => 'objective-of'
|
||||
)];
|
||||
}
|
||||
|
||||
// tab: criteria of [ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE have no data set to check for]
|
||||
@@ -735,14 +727,11 @@ class NpcPage extends GenericPage
|
||||
{
|
||||
$this->extendGlobalData($crtOf->getJSGlobals());
|
||||
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'achievement',
|
||||
'data' => $crtOf->getListviewData(),
|
||||
'params' => array(
|
||||
'name' => '$LANG.tab_criteriaof',
|
||||
'id' => 'criteria-of'
|
||||
)
|
||||
);
|
||||
$this->lvTabs[] = ['achievement', array(
|
||||
'data' => array_values($crtOf->getListviewData()),
|
||||
'name' => '$LANG.tab_criteriaof',
|
||||
'id' => 'criteria-of'
|
||||
)];
|
||||
}
|
||||
|
||||
// tab: passengers
|
||||
@@ -753,25 +742,74 @@ class NpcPage extends GenericPage
|
||||
{
|
||||
$data = $passengers->getListviewData();
|
||||
|
||||
$xCols = null;
|
||||
if (User::isInGroup(U_GROUP_STAFF))
|
||||
{
|
||||
foreach ($data as $id => &$d)
|
||||
$d['seat'] = str_replace(',', ', ', $_[$id]);
|
||||
|
||||
$xCols = "$[Listview.funcBox.createSimpleCol('seat', '".Lang::npc('seat')."', '10%', 'seat')]";
|
||||
}
|
||||
|
||||
$this->extendGlobalData($passengers->getJSGlobals(GLOBALINFO_SELF));
|
||||
$this->lvTabs[] = array(
|
||||
'file' => 'creature',
|
||||
'data' => $data,
|
||||
'params' => array(
|
||||
'extraCols' => $xCols,
|
||||
'name' => Lang::npc('accessory'),
|
||||
'id' => 'accessory'
|
||||
)
|
||||
|
||||
$tabData = array(
|
||||
'data' => array_values($data),
|
||||
'name' => Lang::npc('accessory'),
|
||||
'id' => 'accessory'
|
||||
);
|
||||
|
||||
if (User::isInGroup(U_GROUP_STAFF))
|
||||
$tabData['extraCols'] = ["\$Listview.funcBox.createSimpleCol('seat', '".Lang::npc('seat')."', '10%', 'seat')"];
|
||||
|
||||
$this->lvTabs[] = ['creature', $tabData];
|
||||
}
|
||||
}
|
||||
|
||||
/* tab sounds:
|
||||
* activity sounds => CreatureDisplayInfo.dbc => (CreatureModelData.dbc => ) CreatureSoundData.dbc
|
||||
* AI => smart_scripts
|
||||
* Dialogue VO => creature_text
|
||||
* onClick VO => CreatureDisplayInfo.dbc => NPCSounds.dbc
|
||||
*/
|
||||
$ssActionLists = DB::World()->select('SELECT action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6 FROM smart_scripts WHERE entryorguid = ?d AND source_type = 0 AND action_type IN (80, 87, 88)', $this->typeId);
|
||||
$actionListIds = [];
|
||||
foreach ($ssActionLists as $sal)
|
||||
{
|
||||
$iMax = 0;
|
||||
switch ($sal['action_type'])
|
||||
{
|
||||
case 80: $iMax = 1; break;
|
||||
case 87: $iMax = 6; break;
|
||||
case 88: $iMax = 2; break;
|
||||
default: continue;
|
||||
}
|
||||
|
||||
for ($i = 1; $i <= $iMax; $i++)
|
||||
if ($sal['action_param'.$i])
|
||||
$actionListIds[] = $sal['action_param'.$i];
|
||||
}
|
||||
|
||||
// not going for a per guid basis. The infos are nested enough as is.
|
||||
$smartScripts = DB::World()->selectCol('SELECT action_param1 FROM smart_scripts WHERE action_type = 4 AND ((source_type = 0 AND entryorguid = ?d) { OR (source_type = 9 AND entryorguid IN (?a)) } )', $this->typeId, $actionListIds ?: DBSIMPLE_SKIP);
|
||||
$this->soundIds = array_merge($this->soundIds, $smartScripts);
|
||||
|
||||
// up to 4 possible displayIds .. for the love of things betwixt, just use the first!
|
||||
$activitySounds = DB::Aowow()->selectRow('SELECT * FROM ?_creature_sounds WHERE id = ?d', $this->subject->getField('displayId1'));
|
||||
array_shift($activitySounds); // remove id-column
|
||||
$this->soundIds = array_merge($this->soundIds, array_values($activitySounds));
|
||||
|
||||
if ($this->soundIds)
|
||||
{
|
||||
$sounds = new SoundList(array(['id', $this->soundIds]));
|
||||
if (!$sounds->error)
|
||||
{
|
||||
$data = $sounds->getListviewData();
|
||||
foreach ($activitySounds as $activity => $id)
|
||||
if (isset($data[$id]))
|
||||
$data[$id]['activity'] = $activity; // no index, js wants a string :(
|
||||
|
||||
$tabData = ['data' => array_values($data)];
|
||||
if ($activitySounds)
|
||||
$tabData['visibleCols'] = ['activity'];
|
||||
|
||||
$this->extendGlobalData($sounds->getJSGlobals(GLOBALINFO_SELF));
|
||||
$this->lvTabs[] = ['sound', $tabData];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -807,10 +845,10 @@ class NpcPage extends GenericPage
|
||||
die($tt);
|
||||
}
|
||||
|
||||
public function notFound()
|
||||
public function notFound($title = '', $msg = '')
|
||||
{
|
||||
if ($this->mode != CACHE_TYPE_TOOLTIP)
|
||||
return parent::notFound(Lang::game('npc'), Lang::npc('notFound'));
|
||||
return parent::notFound($title ?: Lang::game('npc'), $msg ?: Lang::npc('notFound'));
|
||||
|
||||
header('Content-type: application/x-javascript; charset=utf-8');
|
||||
echo $this->generateTooltip(true);
|
||||
@@ -837,15 +875,22 @@ class NpcPage extends GenericPage
|
||||
|
||||
$set = array(
|
||||
'id' => $row['faction'],
|
||||
'qty' => $row['qty'],
|
||||
'qty' => [$row['qty'], 0],
|
||||
'name' => $factions->getField('name', true),
|
||||
'npc' => $row['npc'],
|
||||
'cap' => $row['maxRank'] && $row['maxRank'] < REP_EXALTED ? Lang::game('rep', $row['maxRank']) : null
|
||||
);
|
||||
|
||||
$cuRate = DB::World()->selectCell('SELECT creature_rate FROM reputation_reward_rate WHERE creature_rate <> 1 AND faction = ?d', $row['faction']);
|
||||
if ($cuRate !== null)
|
||||
$set['qty'][1] = $set['qty'][0] * ($cuRate - 1);
|
||||
|
||||
if ($row['spillover'])
|
||||
{
|
||||
$spillover[$factions->getField('cat')] = [intVal($row['qty'] / 2), $row['maxRank']];
|
||||
$spillover[$factions->getField('cat')] = array(
|
||||
[ $set['qty'][0] / 2, $set['qty'][1] / 2 ],
|
||||
$row['maxRank']
|
||||
);
|
||||
$set['spillover'] = $factions->getField('cat');
|
||||
}
|
||||
|
||||
@@ -923,24 +968,25 @@ class NpcPage extends GenericPage
|
||||
$quotes = [];
|
||||
$quoteSrc = DB::World()->select('
|
||||
SELECT
|
||||
ct.groupid AS ARRAY_KEY, ct.id as ARRAY_KEY2, ct.`type`,
|
||||
ct.GroupID AS ARRAY_KEY, ct.ID as ARRAY_KEY2, ct.`Type`,
|
||||
ct.TextRange AS `range`,
|
||||
IFNULL(bct.`Language`, ct.`language`) AS lang,
|
||||
IFNULL(NULLIF(bct.MaleText, ""), IFNULL(NULLIF(bct.FemaleText, ""), IFNULL(ct.`text`, ""))) AS text_loc0,
|
||||
IFNULL(NULLIF(lbct.MaleText_loc2, ""), IFNULL(NULLIF(lbct.FemaleText_loc2, ""), IFNULL(lct.text_loc2, ""))) AS text_loc2,
|
||||
IFNULL(NULLIF(lbct.MaleText_loc3, ""), IFNULL(NULLIF(lbct.FemaleText_loc3, ""), IFNULL(lct.text_loc3, ""))) AS text_loc3,
|
||||
IFNULL(NULLIF(lbct.MaleText_loc6, ""), IFNULL(NULLIF(lbct.FemaleText_loc6, ""), IFNULL(lct.text_loc6, ""))) AS text_loc6,
|
||||
IFNULL(NULLIF(lbct.MaleText_loc8, ""), IFNULL(NULLIF(lbct.FemaleText_loc8, ""), IFNULL(lct.text_loc8, ""))) AS text_loc8
|
||||
IFNULL(bct.`Language`, ct.`Language`) AS lang,
|
||||
IFNULL(NULLIF(bct.MaleText, ""), IFNULL(NULLIF(bct.FemaleText, ""), IFNULL(ct.`Text`, ""))) AS text_loc0,
|
||||
{IFNULL(NULLIF(bctl.MaleText, ""), IFNULL(NULLIF(bctl.FemaleText, ""), IFNULL(ctl.Text, ""))) AS text_loc?d,}
|
||||
IF(bct.SoundId > 0, bct.SoundId, ct.Sound) AS soundId
|
||||
FROM
|
||||
creature_text ct
|
||||
LEFT JOIN
|
||||
locales_creature_text lct ON ct.entry = lct.entry AND ct.groupid = lct.groupid AND ct.id = lct.id
|
||||
{LEFT JOIN
|
||||
creature_text_locale ctl ON ct.CreatureID = ctl.CreatureID AND ct.GroupID = ctl.GroupID AND ct.ID = ctl.ID AND ctl.Locale = ?}
|
||||
LEFT JOIN
|
||||
broadcast_text bct ON ct.BroadcastTextId = bct.ID
|
||||
LEFT JOIN
|
||||
locales_broadcast_text lbct ON ct.BroadcastTextId = lbct.ID
|
||||
{LEFT JOIN
|
||||
broadcast_text_locale bctl ON ct.BroadcastTextId = bctl.ID AND bctl.locale = ?}
|
||||
WHERE
|
||||
ct.entry = ?d',
|
||||
ct.CreatureID = ?d',
|
||||
User::$localeId ?: DBSIMPLE_SKIP,
|
||||
User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP,
|
||||
User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP,
|
||||
$this->typeId
|
||||
);
|
||||
|
||||
@@ -949,22 +995,28 @@ class NpcPage extends GenericPage
|
||||
$group = [];
|
||||
foreach ($text as $t)
|
||||
{
|
||||
if ($t['soundId'])
|
||||
$this->soundIds[] = $t['soundId'];
|
||||
|
||||
$msg = Util::localizedString($t, 'text');
|
||||
if (!$msg)
|
||||
continue;
|
||||
|
||||
// fixup .. either set %s for emotes or dont >.<
|
||||
if (in_array($t['type'], [2, 16]) && strpos($msg, '%s') === false)
|
||||
if (in_array($t['Type'], [2, 16]) && strpos($msg, '%s') === false)
|
||||
$msg = '%s '.$msg;
|
||||
|
||||
// fixup: bad case-insensivity
|
||||
$msg = str_replace('%S', '%s', $msg);
|
||||
|
||||
$line = array(
|
||||
'range' => $t['range'],
|
||||
'type' => 2, // [type: 0, 12] say: yellow-ish
|
||||
'lang' => !empty($t['language']) ? Lang::game('languages', $t['language']) : null,
|
||||
'lang' => !empty($t['lang']) ? Lang::game('languages', $t['lang']) : null,
|
||||
'text' => sprintf(Util::parseHtmlText(htmlentities($msg)), $this->name),
|
||||
);
|
||||
|
||||
switch ($t['type'])
|
||||
switch ($t['Type'])
|
||||
{
|
||||
case 1: // yell:
|
||||
case 14: $line['type'] = 1; break; // - dark red
|
||||
|
||||
@@ -20,8 +20,8 @@ class NpcsPage extends GenericPage
|
||||
|
||||
public function __construct($pageCall, $pageParam)
|
||||
{
|
||||
$this->filterObj = new CreatureListFilter();
|
||||
$this->getCategoryFromUrl($pageParam);;
|
||||
$this->filterObj = new CreatureListFilter(false, ['parentCats' => $this->category]);
|
||||
|
||||
parent::__construct($pageCall, $pageParam);
|
||||
|
||||
@@ -53,33 +53,42 @@ class NpcsPage extends GenericPage
|
||||
$npcs = new CreatureList($conditions, ['extraOpts' => $this->filterObj->extraOpts]);
|
||||
|
||||
// recreate form selection
|
||||
$this->filter = array_merge($this->filterObj->getForm('form'), $this->filter);
|
||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL;
|
||||
$this->filter['fi'] = $this->filterObj->getForm();
|
||||
$this->filter = $this->filterObj->getForm();
|
||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
|
||||
$this->filter['initData'] = ['init' => 'npcs'];
|
||||
|
||||
$lv = array(
|
||||
'file' => 'creature',
|
||||
'data' => $npcs->getListviewData(), // listview content
|
||||
'params' => []
|
||||
);
|
||||
$rCols = $this->filterObj->getReputationCols();
|
||||
$xCols = $this->filterObj->getExtraCols();
|
||||
if ($rCols)
|
||||
$this->filter['initData']['rc'] = $rCols;
|
||||
|
||||
if (!empty($this->filter['fi']['extraCols']))
|
||||
$lv['params']['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
|
||||
if ($xCols)
|
||||
$this->filter['initData']['ec'] = $xCols;
|
||||
|
||||
if ($x = $this->filterObj->getSetCriteria())
|
||||
$this->filter['initData']['sc'] = $x;
|
||||
|
||||
$tabData = ['data' => array_values($npcs->getListviewData($rCols ? NPCINFO_REP : 0x0))];
|
||||
|
||||
if ($rCols) // never use pretty-print
|
||||
$tabData['extraCols'] = '$fi_getReputationCols('.Util::toJSON($rCols, JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE).')';
|
||||
else if ($xCols)
|
||||
$tabData['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
|
||||
|
||||
if ($this->category)
|
||||
$lv['params']['hiddenCols'] = "$['type']";
|
||||
$tabData['hiddenCols'] = ['type'];
|
||||
|
||||
// create note if search limit was exceeded
|
||||
if ($npcs->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||
{
|
||||
$lv['params']['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_npcsfound', $npcs->getMatches(), CFG_SQL_LIMIT_DEFAULT);
|
||||
$lv['params']['_truncated'] = 1;
|
||||
$tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_npcsfound', $npcs->getMatches(), CFG_SQL_LIMIT_DEFAULT);
|
||||
$tabData['_truncated'] = 1;
|
||||
}
|
||||
|
||||
if ($this->filterObj->error)
|
||||
$lv['params']['_errors'] = '$1';
|
||||
$tabData['_errors'] = 1;
|
||||
|
||||
$this->lvTabs[] = $lv;
|
||||
$this->lvTabs[] = ['creature', $tabData];
|
||||
|
||||
// sort for dropdown-menus
|
||||
Lang::sort('game', 'fa');
|
||||
@@ -90,6 +99,10 @@ class NpcsPage extends GenericPage
|
||||
array_unshift($this->title, $this->name);
|
||||
if ($this->category)
|
||||
array_unshift($this->title, Lang::npc('cat', $this->category[0]));
|
||||
|
||||
$form = $this->filterObj->getForm();
|
||||
if (isset($form['fa']) && !is_array($form['fa']))
|
||||
array_unshift($this->title, Lang::game('fa', $form['fa']));
|
||||
}
|
||||
|
||||
protected function generatePath()
|
||||
@@ -97,7 +110,7 @@ class NpcsPage extends GenericPage
|
||||
if ($this->category)
|
||||
$this->path[] = $this->category[0];
|
||||
|
||||
$form = $this->filterObj->getForm('form');
|
||||
$form = $this->filterObj->getForm();
|
||||
if (isset($form['fa']) && !is_array($form['fa']))
|
||||
$this->path[] = $form['fa'];
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user