mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
Compare commits
266 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b890d6504e | ||
|
|
33a870ef78 | ||
|
|
e109a6deed | ||
|
|
feb6ee25dd | ||
|
|
a8edf6c912 | ||
|
|
3cb02f2204 | ||
|
|
4b32811424 | ||
|
|
4972cc0faf | ||
|
|
e092a69175 | ||
|
|
1c7acf6a08 | ||
|
|
012ebe578b | ||
|
|
e125cab690 | ||
|
|
a1e7bfaa02 | ||
|
|
73c1118601 | ||
|
|
33ec14f232 | ||
|
|
366f68f24f | ||
|
|
91f8fe8925 | ||
|
|
8431329645 | ||
|
|
19584feab0 | ||
|
|
bc71ae762c | ||
|
|
10805a1f70 | ||
|
|
a24e8594fb | ||
|
|
01a9744ba7 | ||
|
|
53e2af2116 | ||
|
|
4255933328 | ||
|
|
1856f0ef8f | ||
|
|
731f648cd2 | ||
|
|
6a2511866e | ||
|
|
b777262670 | ||
|
|
c950cdc757 | ||
|
|
541224f87b | ||
|
|
dcb8995b1a | ||
|
|
2ec4809c7f | ||
|
|
061449686d | ||
|
|
f3f8dacef9 | ||
|
|
a1f0f3d30d | ||
|
|
e4b8a8e908 | ||
|
|
41f415095a | ||
|
|
b824bc54c2 | ||
|
|
35aca18346 | ||
|
|
4b37a4fd70 | ||
|
|
c665062faa | ||
|
|
fca627c408 | ||
|
|
ea25776225 | ||
|
|
5781dfb69e | ||
|
|
60e3f62504 | ||
|
|
9cda84ef88 | ||
|
|
3495a7a40d | ||
|
|
8acc93c325 | ||
|
|
4755058fd0 | ||
|
|
306f8eb9b6 | ||
|
|
5fe9c23be2 | ||
|
|
68e262d96c | ||
|
|
8727d4f66f | ||
|
|
07b9ed4275 | ||
|
|
cb2274bbab | ||
|
|
7c293c405f | ||
|
|
6819c1b1f2 | ||
|
|
57864d2544 | ||
|
|
f9ed75d5af | ||
|
|
453690c575 | ||
|
|
557638b3fe | ||
|
|
f9584f09b5 | ||
|
|
6b49aa6069 | ||
|
|
56e70e22bb | ||
|
|
6f69144498 | ||
|
|
aa82655845 | ||
|
|
c456ade870 | ||
|
|
aa70ea0323 | ||
|
|
fbc5d43aab | ||
|
|
43778b01e7 | ||
|
|
f5701e7979 | ||
|
|
33c3132346 | ||
|
|
d6ca3d70cf | ||
|
|
392b5bbdda | ||
|
|
e810554695 | ||
|
|
8313bb4194 | ||
|
|
0c1b73d6ac | ||
|
|
7a74c36448 | ||
|
|
23abce304c | ||
|
|
e5e62e2936 | ||
|
|
c0a1e393b0 | ||
|
|
898a4fd8a4 | ||
|
|
3978169bf6 | ||
|
|
01e89db491 | ||
|
|
59f58f8506 | ||
|
|
c65bd88867 | ||
|
|
2eaed47ba4 | ||
|
|
888ff28121 | ||
|
|
baf47433dd | ||
|
|
89275a0e71 | ||
|
|
15fb7b8711 | ||
|
|
467a31fa3b | ||
|
|
5b414500a7 | ||
|
|
cac57f5cd8 | ||
|
|
3188a7b55f | ||
|
|
4ed2d0836f | ||
|
|
be77474637 | ||
|
|
82d3a8508d | ||
|
|
d070b303b4 | ||
|
|
7062ff74a4 | ||
|
|
df1f29c986 | ||
|
|
178c13ec72 | ||
|
|
e2fe765980 | ||
|
|
003ac1c931 | ||
|
|
0430d75989 | ||
|
|
59fb6c1bc9 | ||
|
|
12c5f6f468 | ||
|
|
c92ab37de1 | ||
|
|
88417cd5a6 | ||
|
|
583f8658d7 | ||
|
|
04a14393e5 | ||
|
|
f34b4827ee | ||
|
|
aac9aab3c9 | ||
|
|
349c32d0a6 | ||
|
|
5179e6e09b | ||
|
|
366a0f2040 | ||
|
|
93948a2ec5 | ||
|
|
3e24814518 | ||
|
|
726fe90bb0 | ||
|
|
fb2ab8f613 | ||
|
|
72e950713a | ||
|
|
ce90229a8b | ||
|
|
4bd32207db | ||
|
|
844a4c0e52 | ||
|
|
d858c85465 | ||
|
|
82d3441b22 | ||
|
|
c08773eb6f | ||
|
|
240024fb10 | ||
|
|
321f28d35c | ||
|
|
8e14e4a9f3 | ||
|
|
184e5e5c8d | ||
|
|
7b9b542e65 | ||
|
|
a3d35a7ad5 | ||
|
|
366bdf54a6 | ||
|
|
d22e90ca85 | ||
|
|
c290f845d6 | ||
|
|
8741c7479f | ||
|
|
62acd541b2 | ||
|
|
7db841b823 | ||
|
|
6cabfd3864 | ||
|
|
b044488308 | ||
|
|
a1d3be86f7 | ||
|
|
8378354f8b | ||
|
|
08f8297629 | ||
|
|
9b4c0bb09e | ||
|
|
92a1016a0f | ||
|
|
08c98bc8ee | ||
|
|
b7bf58a664 | ||
|
|
64ce4826c6 | ||
|
|
96bbe326a8 | ||
|
|
0f9a3e8cb6 | ||
|
|
9f8c643cf4 | ||
|
|
c2a1556e8a | ||
|
|
15246ea964 | ||
|
|
3b749025de | ||
|
|
bf2e1bd612 | ||
|
|
301c29e944 | ||
|
|
54b20c3131 | ||
|
|
55d19589b8 | ||
|
|
59ef124a26 | ||
|
|
47458e3ec2 | ||
|
|
4d08fb974d | ||
|
|
3f1e44d3e2 | ||
|
|
aa66a7644b | ||
|
|
3ff855afe8 | ||
|
|
3c088cd4e8 | ||
|
|
0694367ee9 | ||
|
|
4bda806b9b | ||
|
|
b37efc480a | ||
|
|
717e9c43be | ||
|
|
1f84cae1dd | ||
|
|
5bb15d47d7 | ||
|
|
16bd59e0cc | ||
|
|
d4c0c0535a | ||
|
|
eaa982e5b3 | ||
|
|
48552a97ab | ||
|
|
243429bf68 | ||
|
|
bc18ca174c | ||
|
|
1c08e5d9cf | ||
|
|
d3c5011694 | ||
|
|
c77cd92609 | ||
|
|
1ff81ab07c | ||
|
|
1c7660316d | ||
|
|
eeb39bb83f | ||
|
|
f99ff8c4b8 | ||
|
|
cf129ca3ce | ||
|
|
fd04e9f977 | ||
|
|
ccef11323b | ||
|
|
163e3d82b0 | ||
|
|
fc0902d476 | ||
|
|
0fd2944d8b | ||
|
|
7f36dc87cf | ||
|
|
34fe4c2654 | ||
|
|
392610b899 | ||
|
|
ead6e72668 | ||
|
|
db012cfa8c | ||
|
|
09176d1ae9 | ||
|
|
972a7f241e | ||
|
|
da1946df0f | ||
|
|
cc5be5261c | ||
|
|
af7b9f57b0 | ||
|
|
d9cd24026c | ||
|
|
f8a34aa98e | ||
|
|
13db19c64f | ||
|
|
04209cfc6d | ||
|
|
470498f63c | ||
|
|
484944bfc0 | ||
|
|
8620cbcf20 | ||
|
|
0286cb20f1 | ||
|
|
31ec17d279 | ||
|
|
6f578b31e0 | ||
|
|
0fd0a66137 | ||
|
|
ceedf3fbdd | ||
|
|
ed614d3938 | ||
|
|
d32f21f9ca | ||
|
|
e0150feda6 | ||
|
|
56ccc592a6 | ||
|
|
04e183f5e3 | ||
|
|
adc1273b08 | ||
|
|
93a72013b8 | ||
|
|
c5d28a9bbc | ||
|
|
7dc283f649 | ||
|
|
9645ad0877 | ||
|
|
45f325a0fa | ||
|
|
37652ce011 | ||
|
|
594b2269bd | ||
|
|
55a554ca06 | ||
|
|
a0198ae5f4 | ||
|
|
3bbd7f97da | ||
|
|
761da59ee9 | ||
|
|
09d2013012 | ||
|
|
4f0d045ff4 | ||
|
|
e2e23c430a | ||
|
|
9609c93f8c | ||
|
|
35dc835c62 | ||
|
|
808bbcc2fd | ||
|
|
c5e9762830 | ||
|
|
b13f3af03e | ||
|
|
000a3208c0 | ||
|
|
efd68bdb5f | ||
|
|
d0b7fa9ef5 | ||
|
|
9dcb0b3a15 | ||
|
|
2518e4730b | ||
|
|
74308da407 | ||
|
|
bb9e6a36dd | ||
|
|
c448207724 | ||
|
|
81335ad6dc | ||
|
|
d46a78b3cb | ||
|
|
492b7cd3c4 | ||
|
|
c19691033a | ||
|
|
164cdc234c | ||
|
|
394a2699d8 | ||
|
|
e50333a518 | ||
|
|
d848d316fe | ||
|
|
fa46aefa27 | ||
|
|
0912248fd5 | ||
|
|
fab71f9325 | ||
|
|
51eda12099 | ||
|
|
bf42973c00 | ||
|
|
431e984f03 | ||
|
|
e973e5e33b | ||
|
|
22d02378ef | ||
|
|
c17cf9c043 | ||
|
|
72c1dacd3f | ||
|
|
bc834245d7 |
22
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
22
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: issue template
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug and how to reproduce it**
|
||||||
|
additionally paste relevant lines from db table `aowow_errors`
|
||||||
|
or your browsers console here.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**System:**
|
||||||
|
- OS: [e.g. Win10]
|
||||||
|
- PHP version:
|
||||||
|
- revision used:
|
||||||
|
- Browser (in case of JavaScript / display errors):
|
||||||
|
- AzerothCore: yes/no
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,6 +12,7 @@
|
|||||||
# generated files
|
# generated files
|
||||||
/static/js/profile_all.js
|
/static/js/profile_all.js
|
||||||
/static/js/locale.js
|
/static/js/locale.js
|
||||||
|
/static/js/Markup.js
|
||||||
/static/widgets/power.js
|
/static/widgets/power.js
|
||||||
/static/widgets/power/demo.html
|
/static/widgets/power/demo.html
|
||||||
/static/widgets/searchbox.js
|
/static/widgets/searchbox.js
|
||||||
|
|||||||
37
README.md
37
README.md
@@ -18,23 +18,26 @@ Also, this project is not meant to be used for commercial puposes of any kind!
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
+ Webserver running PHP ≥ 5.5.0 including extensions:
|
+ Webserver running PHP ≥ 7.4 — 8.0 including extensions:
|
||||||
+ SimpleXML
|
+ [SimpleXML](https://www.php.net/manual/en/book.simplexml.php)
|
||||||
+ GD
|
+ [GD](https://www.php.net/manual/en/book.image)
|
||||||
+ Mysqli
|
+ [MySQL Improved](https://www.php.net/manual/en/book.mysqli.php)
|
||||||
+ mbString
|
+ [Multibyte String](https://www.php.net/manual/en/book.mbstring.php)
|
||||||
|
+ [File Information](https://www.php.net/manual/en/book.fileinfo.php)
|
||||||
|
+ [GNU Multiple Precision](https://www.php.net/manual/en/book.gmp.php) (When using TrinityCore as auth source)
|
||||||
+ MySQL ≥ 5.5.30
|
+ MySQL ≥ 5.5.30
|
||||||
+ [TDB 335.63](https://github.com/TrinityCore/TrinityCore/releases/tag/TDB335.63) - including world updates up to 04.05.2017
|
+ [TDB 335.21101](https://github.com/TrinityCore/TrinityCore/releases/tag/TDB335.21101)
|
||||||
|
+ WIN: php.exe needs to be added to the `PATH` system variable, if it isn't already.
|
||||||
+ Tools require cmake: Please refer to the individual repositories for detailed information
|
+ 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)
|
+ [MPQExtractor](https://github.com/Sarjuuk/MPQExtractor) / [FFmpeg](https://ffmpeg.org/download.html) / (optional: [BLPConverter](https://github.com/Sarjuuk/BLPConverter))
|
||||||
+ WIN users may find it easier to use these alternatives
|
+ 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)
|
+ [MPQEditor](http://www.zezula.net/en/mpq/download.html) / [FFmpeg](http://ffmpeg.zeranoe.com/builds/) / (optional: [BLPConverter](https://github.com/PatrickCyr/BLPConverter))
|
||||||
|
|
||||||
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))
|
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
|
#### Highly Recommended
|
||||||
+ setting the following configuration values on your TrintyCore server will greatly increase the accuracy of spawn points
|
+ setting the following configuration values on your TrinityCore server will greatly increase the accuracy of spawn points
|
||||||
> Calculate.Creature.Zone.Area.Data = 1
|
> Calculate.Creature.Zone.Area.Data = 1
|
||||||
> Calculate.Gameoject.Zone.Area.Data = 1
|
> Calculate.Gameoject.Zone.Area.Data = 1
|
||||||
|
|
||||||
@@ -89,7 +92,7 @@ WAV-files need to be reencoded as `ogg/vorbis` and some MP3s may identify themse
|
|||||||
* [example for \*nix](https://gist.github.com/Sarjuuk/1f05ef2affe49a7e7ca0fad7b01c081d)
|
* [example for \*nix](https://gist.github.com/Sarjuuk/1f05ef2affe49a7e7ca0fad7b01c081d)
|
||||||
|
|
||||||
#### 6. Run the initial setup from the CLI
|
#### 6. Run the initial setup from the CLI
|
||||||
`php aowow --firstrun`.
|
`php aowow --setup`.
|
||||||
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.
|
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.
|
When you've created your admin account you are done.
|
||||||
|
|
||||||
@@ -113,15 +116,21 @@ A: You can't anymore. Wowhead switched from Flash to WebGL (as they should) and
|
|||||||
Q: I'm getting random javascript errors!
|
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.
|
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?
|
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.
|
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.
|
||||||
|
|
||||||
|
Q: Screenshot upload fails, because the file size is too large and/or the subdirectories are visible from the web!
|
||||||
|
A: That's a web server configuration issue. If you are using Apache you may need to [enable the use of .htaccess](http://httpd.apache.org/docs/2.4/de/mod/core.html#allowoverride). Other servers require individual configuration.
|
||||||
|
|
||||||
|
Q: An Item, Quest or NPC i added or edited can't be searched. Why?
|
||||||
|
A: A search is only conducted against the currently used locale. You may have only edited the name field in the base table instead of adding multiple strings into the appropriate \*_locale tables. In this case searches in a non-english locale are run against an empty name field.
|
||||||
|
|
||||||
## Thanks
|
## Thanks
|
||||||
|
|
||||||
@mix: for providing the php-script to parse .blp and .dbc into usable images and tables
|
@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
|
@LordJZ: the wrapper-class for DBSimple; the basic idea for the user-class
|
||||||
@kliver: basic implementation of screenshot uploads
|
@kliver: basic implementation of screenshot uploads
|
||||||
|
@Sarjuuk: maintainer of the project
|
||||||
|
|
||||||
|
|
||||||
## Special Thanks
|
## Special Thanks
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
if (!defined('AOWOW_REVISION'))
|
|
||||||
die('illegal access');
|
|
||||||
|
|
||||||
|
|
||||||
// use as example. File is generated from setup.
|
|
||||||
|
|
||||||
// -- Aowow Database --
|
|
||||||
// contains world-data, user-data and logs
|
|
||||||
$AoWoWconf['aowow'] = array(
|
|
||||||
'host' => '127.0.0.1',
|
|
||||||
'user' => '<user>',
|
|
||||||
'pass' => '<pass>',
|
|
||||||
'db' => 'world',
|
|
||||||
'prefix' => 'aowow_'
|
|
||||||
);
|
|
||||||
|
|
||||||
// -- World Database --
|
|
||||||
// used to generate data-tables
|
|
||||||
$AoWoWconf['world'] = array(
|
|
||||||
'host' => '127.0.0.1',
|
|
||||||
'user' => '<user>',
|
|
||||||
'pass' => '<pass>',
|
|
||||||
'db' => 'world',
|
|
||||||
'prefix' => ''
|
|
||||||
);
|
|
||||||
|
|
||||||
// -- Auth Database --
|
|
||||||
// used to generate user-tables
|
|
||||||
$AoWoWconf['auth'] = array(
|
|
||||||
'host' => '127.0.0.1',
|
|
||||||
'user' => '<user>',
|
|
||||||
'pass' => '<pass>',
|
|
||||||
'db' => 'auth',
|
|
||||||
'prefix' => ''
|
|
||||||
);
|
|
||||||
|
|
||||||
// -- Characters Database --
|
|
||||||
// used to display profiles
|
|
||||||
$AoWoWconf['characters'][<realmId>] = array(
|
|
||||||
'host' => '127.0.0.1',
|
|
||||||
'user' => '<user>',
|
|
||||||
'pass' => '<pass>',
|
|
||||||
'db' => 'characters',
|
|
||||||
'prefix' => ''
|
|
||||||
);
|
|
||||||
|
|
||||||
?>
|
|
||||||
@@ -6,14 +6,13 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class AjaxHandler
|
class AjaxHandler
|
||||||
{
|
{
|
||||||
|
use TrRequestData;
|
||||||
|
|
||||||
protected $validParams = [];
|
protected $validParams = [];
|
||||||
protected $params = [];
|
protected $params = [];
|
||||||
protected $handler;
|
protected $handler;
|
||||||
|
|
||||||
protected $contentType = 'application/x-javascript; charset=utf-8';
|
protected $contentType = MIME_TYPE_JSON;
|
||||||
|
|
||||||
protected $_post = [];
|
|
||||||
protected $_get = [];
|
|
||||||
|
|
||||||
public $doRedirect = false;
|
public $doRedirect = false;
|
||||||
|
|
||||||
@@ -21,14 +20,10 @@ class AjaxHandler
|
|||||||
{
|
{
|
||||||
$this->params = $params;
|
$this->params = $params;
|
||||||
|
|
||||||
foreach ($this->_post as $k => &$v)
|
$this->initRequestData();
|
||||||
$v = isset($_POST[$k]) ? filter_input(INPUT_POST, $k, $v[0], $v[1]) : null;
|
|
||||||
|
|
||||||
foreach ($this->_get as $k => &$v)
|
|
||||||
$v = isset($_GET[$k]) ? filter_input(INPUT_GET, $k, $v[0], $v[1]) : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(&$out)
|
public function handle(string &$out) : bool
|
||||||
{
|
{
|
||||||
if (!$this->handler)
|
if (!$this->handler)
|
||||||
return false;
|
return false;
|
||||||
@@ -43,49 +38,34 @@ class AjaxHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
$h = $this->handler;
|
$h = $this->handler;
|
||||||
$out = (string)$this->$h();
|
$out = $this->$h();
|
||||||
|
if ($out === null)
|
||||||
|
$out = '';
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getContentType()
|
public function getContentType() : string
|
||||||
{
|
{
|
||||||
return $this->contentType;
|
return $this->contentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkEmptySet($val)
|
protected function reqPOST(string ...$keys) : bool
|
||||||
{
|
{
|
||||||
return $val === ''; // parameter is expected to be empty
|
foreach ($keys as $k)
|
||||||
|
if (!isset($this->_post[$k]) || $this->_post[$k] === null || $this->_post[$k] === '')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkLocale($val)
|
protected function reqGET(string ...$keys) : bool
|
||||||
{
|
{
|
||||||
if (preg_match('/^'.implode('|', array_keys(array_filter(Util::$localeStrings))).'$/', $val))
|
foreach ($keys as $k)
|
||||||
return intval($val);
|
if (!isset($this->_get[$k]) || $this->_get[$k] === null || $this->_get[$k] === '')
|
||||||
|
return false;
|
||||||
|
|
||||||
return null;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
protected function checkInt($val)
|
|
||||||
{
|
|
||||||
if (preg_match('/^-?\d+$/', $val))
|
|
||||||
return intval($val);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function checkIdList($val)
|
|
||||||
{
|
|
||||||
if (preg_match('/^-?\d+(,-?\d+)*$/', $val))
|
|
||||||
return array_map('intval', explode(',', $val));
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function checkFulltext($val)
|
|
||||||
{
|
|
||||||
// trim non-printable chars
|
|
||||||
return preg_replace('/[\p{C}]/ui', '', $val);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -5,20 +5,23 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class AjaxAccount extends AjaxHandler
|
class AjaxAccount extends AjaxHandler
|
||||||
{
|
{
|
||||||
protected $validParams = ['exclude', 'weightscales'];
|
protected $validParams = ['exclude', 'weightscales', 'favorites'];
|
||||||
protected $_post = array(
|
protected $_post = array(
|
||||||
'groups' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'groups' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'save' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'save' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'delete' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'delete' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdList']],
|
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdList'],
|
||||||
'name' => [FILTER_CALLBACK, ['options' => 'AjaxAccount::checkName']],
|
'name' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAccount::checkName' ],
|
||||||
'scale' => [FILTER_CALLBACK, ['options' => 'AjaxAccount::checkScale']],
|
'scale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAccount::checkScale' ],
|
||||||
'reset' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'reset' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'mode' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'mode' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'type' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'type' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
|
'add' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
|
'remove' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
|
// 'sessionKey' => ['filter' => FILTER_SANITIZE_NUMBER_INT]
|
||||||
);
|
);
|
||||||
protected $_get = array(
|
protected $_get = array(
|
||||||
'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale']]
|
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale']
|
||||||
);
|
);
|
||||||
|
|
||||||
public function __construct(array $params)
|
public function __construct(array $params)
|
||||||
@@ -36,20 +39,22 @@ class AjaxAccount extends AjaxHandler
|
|||||||
$this->handler = 'handleExclude';
|
$this->handler = 'handleExclude';
|
||||||
else if ($this->params[0] == 'weightscales')
|
else if ($this->params[0] == 'weightscales')
|
||||||
$this->handler = 'handleWeightscales';
|
$this->handler = 'handleWeightscales';
|
||||||
|
else if ($this->params[0] == 'favorites')
|
||||||
|
$this->handler = 'handleFavorites';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleExclude()
|
protected function handleExclude() : void
|
||||||
{
|
{
|
||||||
if (!User::$id)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ($this->_post['mode'] == 1) // directly set exludes
|
if ($this->_post['mode'] == 1) // directly set exludes
|
||||||
{
|
{
|
||||||
$type = $this->_post['type'];
|
$type = $this->_post['type'];
|
||||||
$ids = $this->_post['id'];
|
$ids = $this->_post['id'];
|
||||||
|
|
||||||
if (!isset(Util::$typeStrings[$type]) || empty($ids))
|
if (!Type::exists($type) || empty($ids))
|
||||||
|
{
|
||||||
|
trigger_error('AjaxAccount::handleExclude - invalid type #'.$type.(empty($ids) ? ' or id-list empty' : ''), E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// ready for some bullshit? here it comes!
|
// 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
|
// we don't get signaled whether an id should be added to or removed from either includes or excludes
|
||||||
@@ -73,23 +78,27 @@ class AjaxAccount extends AjaxHandler
|
|||||||
$mask = $this->_post['groups'] & PR_EXCLUDE_GROUP_ANY;
|
$mask = $this->_post['groups'] & PR_EXCLUDE_GROUP_ANY;
|
||||||
|
|
||||||
DB::Aowow()->query('UPDATE ?_account SET excludeGroups = ?d WHERE id = ?d', $mask, User::$id);
|
DB::Aowow()->query('UPDATE ?_account SET excludeGroups = ?d WHERE id = ?d', $mask, User::$id);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleWeightscales()
|
protected function handleWeightscales() : string
|
||||||
{
|
{
|
||||||
if ($this->_post['save'])
|
if ($this->_post['save'])
|
||||||
{
|
{
|
||||||
if (!$this->_post['scale'])
|
if (!$this->_post['scale'])
|
||||||
return 0;
|
{
|
||||||
|
trigger_error('AjaxAccount::handleWeightscales - scaleId empty', E_USER_ERROR);
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
|
||||||
$id = 0;
|
$id = 0;
|
||||||
|
|
||||||
if ($this->_post['id'] && ($id = $this->_post['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))
|
if (!DB::Aowow()->selectCell('SELECT 1 FROM ?_account_weightscales WHERE userId = ?d AND id = ?d', User::$id, $id))
|
||||||
return 0;
|
{
|
||||||
|
trigger_error('AjaxAccount::handleWeightscales - scale #'.$id.' not in db or owned by user #'.User::$id, E_USER_ERROR);
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
|
||||||
DB::Aowow()->query('UPDATE ?_account_weightscales SET `name` = ? WHERE id = ?d', $this->_post['name'], $id);
|
DB::Aowow()->query('UPDATE ?_account_weightscales SET `name` = ? WHERE id = ?d', $this->_post['name'], $id);
|
||||||
}
|
}
|
||||||
@@ -97,7 +106,7 @@ class AjaxAccount extends AjaxHandler
|
|||||||
{
|
{
|
||||||
$nScales = DB::Aowow()->selectCell('SELECT COUNT(id) FROM ?_account_weightscales WHERE userId = ?d', User::$id);
|
$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
|
if ($nScales >= 5) // more or less hard-defined in LANG.message_weightscalesaveerror
|
||||||
return 0;
|
return '0';
|
||||||
|
|
||||||
$id = DB::Aowow()->query('INSERT INTO ?_account_weightscales (`userId`, `name`) VALUES (?d, ?)', User::$id, $this->_post['name']);
|
$id = DB::Aowow()->query('INSERT INTO ?_account_weightscales (`userId`, `name`) VALUES (?d, ?)', User::$id, $this->_post['name']);
|
||||||
}
|
}
|
||||||
@@ -106,33 +115,64 @@ class AjaxAccount extends AjaxHandler
|
|||||||
|
|
||||||
foreach (explode(',', $this->_post['scale']) as $s)
|
foreach (explode(',', $this->_post['scale']) as $s)
|
||||||
{
|
{
|
||||||
list($k, $v) = explode(':', $s);
|
[$k, $v] = explode(':', $s);
|
||||||
if (!in_array($k, Util::$weightScales) || $v < 1)
|
if (!in_array($k, Util::$weightScales) || $v < 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
DB::Aowow()->query('INSERT INTO ?_account_weightscale_data VALUES (?d, ?, ?d)', $id, $k, $v);
|
DB::Aowow()->query('INSERT INTO ?_account_weightscale_data VALUES (?d, ?, ?d)', $id, $k, $v);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $id;
|
return (string)$id;
|
||||||
}
|
}
|
||||||
else if ($this->_post['delete'] && $this->_post['id'] && $this->_post['id'][0])
|
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);
|
DB::Aowow()->query('DELETE FROM ?_account_weightscales WHERE id = ?d AND userId = ?d', $this->_post['id'][0], User::$id);
|
||||||
else
|
else
|
||||||
return 0;
|
{
|
||||||
|
trigger_error('AjaxAccount::handleWeightscales - malformed request received', E_USER_ERROR);
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkScale($val)
|
protected function handleFavorites() : void
|
||||||
|
{
|
||||||
|
// omit usage of sessionKey
|
||||||
|
if (count($this->_post['id']) != 1 || empty($this->_post['id'][0]))
|
||||||
|
{
|
||||||
|
trigger_error('AjaxAccount::handleFavorites - malformed request received', E_USER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$typeId = $this->_post['id'][0];
|
||||||
|
|
||||||
|
if ($type = $this->_post['add'])
|
||||||
|
{
|
||||||
|
$tc = Type::newList($type, [['id', $typeId]]);
|
||||||
|
if (!$tc || $tc->error)
|
||||||
|
{
|
||||||
|
trigger_error('AjaxAccount::handleFavorites - invalid typeId #'.$typeId.' for type #'.$type, E_USER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::Aowow()->query('INSERT INTO ?_account_favorites (`userId`, `type`, `typeId`) VALUES (?d, ?d, ?d)', User::$id, $type, $typeId);
|
||||||
|
}
|
||||||
|
else if ($type = $this->_post['remove'])
|
||||||
|
DB::Aowow()->query('DELETE FROM ?_account_favorites WHERE `userId` = ?d AND `type` = ?d AND `typeId` = ?d', User::$id, $type, $typeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function checkScale(string $val) : string
|
||||||
{
|
{
|
||||||
if (preg_match('/^((\w+:\d+)(,\w+:\d+)*)$/', $val))
|
if (preg_match('/^((\w+:\d+)(,\w+:\d+)*)$/', $val))
|
||||||
return $val;
|
return $val;
|
||||||
|
|
||||||
return null;
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkName($val)
|
protected static function checkName(string $val) : string
|
||||||
{
|
{
|
||||||
$var = trim(urldecode($val));
|
$var = trim(urldecode($val));
|
||||||
|
|
||||||
return filter_var($var, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
|
return filter_var($var, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_AOWOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|||||||
@@ -5,33 +5,37 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class AjaxAdmin extends AjaxHandler
|
class AjaxAdmin extends AjaxHandler
|
||||||
{
|
{
|
||||||
protected $validParams = ['screenshots', 'siteconfig', 'weight-presets'];
|
protected $validParams = ['screenshots', 'siteconfig', 'weight-presets', 'spawn-override', 'guide'];
|
||||||
protected $_get = array(
|
protected $_get = array(
|
||||||
'action' => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
|
'action' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ],
|
||||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkId']],
|
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdListUnsigned'],
|
||||||
'key' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkKey']],
|
'key' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkKey' ],
|
||||||
'all' => [FILTER_UNSAFE_RAW, null],
|
'all' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext' ],
|
||||||
'type' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
|
'type' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ],
|
||||||
'typeid' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
|
'typeid' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ],
|
||||||
'user' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkUser']],
|
'user' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkUser' ],
|
||||||
'val' => [FILTER_UNSAFE_RAW, null]
|
'val' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext' ],
|
||||||
|
'guid' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ],
|
||||||
|
'area' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ],
|
||||||
|
'floor' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ]
|
||||||
);
|
);
|
||||||
protected $_post = array(
|
protected $_post = array(
|
||||||
'alt' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
|
'alt' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
'id' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'],
|
||||||
'scale' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkScale']],
|
'scale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkScale'],
|
||||||
'__icon' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkKey']],
|
'__icon' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkKey' ],
|
||||||
|
'status' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'],
|
||||||
|
'msg' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW]
|
||||||
);
|
);
|
||||||
|
|
||||||
public function __construct(array $params)
|
public function __construct(array $params)
|
||||||
{
|
{
|
||||||
parent::__construct($params);
|
parent::__construct($params);
|
||||||
|
|
||||||
// requires 'action' parameter in any case
|
if (!$this->params)
|
||||||
if (!$this->_get['action'] || !$this->params)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ($this->params[0] == 'screenshots')
|
if ($this->params[0] == 'screenshots' && $this->_get['action'])
|
||||||
{
|
{
|
||||||
if (!User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SCREENSHOT))
|
if (!User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SCREENSHOT))
|
||||||
return;
|
return;
|
||||||
@@ -51,7 +55,7 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
else if ($this->_get['action'] == 'relocate')
|
else if ($this->_get['action'] == 'relocate')
|
||||||
$this->handler = 'ssRelocate';
|
$this->handler = 'ssRelocate';
|
||||||
}
|
}
|
||||||
else if ($this->params[0] == 'siteconfig')
|
else if ($this->params[0] == 'siteconfig' && $this->_get['action'])
|
||||||
{
|
{
|
||||||
if (!User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN))
|
if (!User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN))
|
||||||
return;
|
return;
|
||||||
@@ -63,7 +67,7 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
else if ($this->_get['action'] == 'update')
|
else if ($this->_get['action'] == 'update')
|
||||||
$this->handler = 'confUpdate';
|
$this->handler = 'confUpdate';
|
||||||
}
|
}
|
||||||
else if ($this->params[0] == 'weight-presets')
|
else if ($this->params[0] == 'weight-presets' && $this->_get['action'])
|
||||||
{
|
{
|
||||||
if (!User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN | U_GROUP_BUREAU))
|
if (!User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN | U_GROUP_BUREAU))
|
||||||
return;
|
return;
|
||||||
@@ -71,11 +75,25 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
if ($this->_get['action'] == 'save')
|
if ($this->_get['action'] == 'save')
|
||||||
$this->handler = 'wtSave';
|
$this->handler = 'wtSave';
|
||||||
}
|
}
|
||||||
|
else if ($this->params[0] == 'spawn-override')
|
||||||
|
{
|
||||||
|
if (!User::isInGroup(U_GROUP_MODERATOR))
|
||||||
|
return;
|
||||||
|
|
||||||
|
$this->handler = 'spawnPosFix';
|
||||||
|
}
|
||||||
|
else if ($this->params[0] == 'guide')
|
||||||
|
{
|
||||||
|
if (!User::isInGroup(U_GROUP_STAFF))
|
||||||
|
return;
|
||||||
|
|
||||||
|
$this->handler = 'guideManage';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get all => null (optional)
|
// get all => null (optional)
|
||||||
// evaled response .. UNK
|
// evaled response .. UNK
|
||||||
protected function ssList()
|
protected function ssList() : string
|
||||||
{
|
{
|
||||||
// ssm_screenshotPages
|
// ssm_screenshotPages
|
||||||
// ssm_numPagesFound
|
// ssm_numPagesFound
|
||||||
@@ -89,7 +107,7 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
|
|
||||||
// get: [type => type, typeId => typeId] || [user => username]
|
// get: [type => type, typeId => typeId] || [user => username]
|
||||||
// evaled response .. UNK
|
// evaled response .. UNK
|
||||||
protected function ssManage()
|
protected function ssManage() : string
|
||||||
{
|
{
|
||||||
$res = [];
|
$res = [];
|
||||||
|
|
||||||
@@ -104,21 +122,22 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
|
|
||||||
// get: id => SSid
|
// get: id => SSid
|
||||||
// resp: ''
|
// resp: ''
|
||||||
protected function ssEditAlt()
|
protected function ssEditAlt() : void
|
||||||
{
|
{
|
||||||
// doesn't need to be htmlEscaped, ths javascript does that
|
// doesn't need to be htmlEscaped, ths javascript does that
|
||||||
if ($this->_get['id'] && $this->_post['alt'] !== null)
|
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]);
|
DB::Aowow()->query('UPDATE ?_screenshots SET caption = ? WHERE id = ?d', trim($this->_post['alt']), $this->_get['id'][0]);
|
||||||
|
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get: id => comma-separated SSids
|
// get: id => comma-separated SSids
|
||||||
// resp: ''
|
// resp: ''
|
||||||
protected function ssApprove()
|
protected function ssApprove() : void
|
||||||
{
|
{
|
||||||
if (!$this->_get['id'])
|
if (!$this->reqGET('id'))
|
||||||
return '';
|
{
|
||||||
|
trigger_error('AjaxAdmin::ssApprove - screenshotId empty', E_USER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// create resized and thumb version of screenshot
|
// create resized and thumb version of screenshot
|
||||||
$resized = [772, 618];
|
$resized = [772, 618];
|
||||||
@@ -128,11 +147,14 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
foreach ($this->_get['id'] as $id)
|
foreach ($this->_get['id'] as $id)
|
||||||
{
|
{
|
||||||
// must not be already approved
|
// 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))
|
if ($ssEntry = 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
|
// should also error-log
|
||||||
if (!file_exists(sprintf($path, 'pending', $id)))
|
if (!file_exists(sprintf($path, 'pending', $id)))
|
||||||
|
{
|
||||||
|
trigger_error('AjaxAdmin::ssApprove - screenshot #'.$id.' exists in db but not as file', E_USER_ERROR);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$srcImg = imagecreatefromjpeg(sprintf($path, 'pending', $id));
|
$srcImg = imagecreatefromjpeg(sprintf($path, 'pending', $id));
|
||||||
$srcW = imagesx($srcImg);
|
$srcW = imagesx($srcImg);
|
||||||
@@ -170,22 +192,27 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
|
|
||||||
// set as approved in DB and gain rep (once!)
|
// 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);
|
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']]);
|
Util::gainSiteReputation($ssEntry['userIdOwner'], SITEREP_ACTION_UPLOAD, ['id' => $id, 'what' => 1, 'date' => $ssEntry['date']]);
|
||||||
// flag DB entry as having screenshots
|
// flag DB entry as having screenshots
|
||||||
if (Util::$typeClasses[$_['type']] && ($tbl = get_class_vars(Util::$typeClasses[$_['type']])['dataTable']))
|
if ($tbl = Type::getClassAttrib($ssEntry['type'], 'dataTable'))
|
||||||
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $_['typeId']);
|
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $ssEntry['typeId']);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
trigger_error('AjaxAdmin::ssApprove - screenshot #'.$id.' not in db or already approved', E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get: id => comma-separated SSids
|
// get: id => comma-separated SSids
|
||||||
// resp: ''
|
// resp: ''
|
||||||
protected function ssSticky()
|
protected function ssSticky() : void
|
||||||
{
|
{
|
||||||
if (!$this->_get['id'])
|
if (!$this->reqGET('id'))
|
||||||
return '';
|
{
|
||||||
|
trigger_error('AjaxAdmin::ssSticky - screenshotId empty', E_USER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// approve soon to be sticky screenshots
|
// approve soon to be sticky screenshots
|
||||||
$this->ssApprove();
|
$this->ssApprove();
|
||||||
@@ -201,17 +228,18 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
// toggle sticky status
|
// 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);
|
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
|
// get: id => comma-separated SSids
|
||||||
// resp: ''
|
// resp: ''
|
||||||
// 2 steps: 1) remove from sight, 2) remove from disk
|
// 2 steps: 1) remove from sight, 2) remove from disk
|
||||||
protected function ssDelete()
|
protected function ssDelete() : void
|
||||||
{
|
{
|
||||||
if (!$this->_get['id'])
|
if (!$this->reqGET('id'))
|
||||||
return '';
|
{
|
||||||
|
trigger_error('AjaxAdmin::ssDelete - screenshotId empty', E_USER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$path = 'static/uploads/screenshots/%s/%d.jpg';
|
$path = 'static/uploads/screenshots/%s/%d.jpg';
|
||||||
|
|
||||||
@@ -247,26 +275,27 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
{
|
{
|
||||||
$typeIds = explode(',', $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);
|
$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']))
|
if ($toUnflag && ($tbl = Type::getClassAttrib($type, 'dataTable')))
|
||||||
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags & ~?d WHERE id IN (?a)', CUSTOM_HAS_SCREENSHOT, array_keys($toUnflag));
|
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..?)
|
// get: id => ssId, typeid => typeId (but not type..?)
|
||||||
// resp: ''
|
// resp: ''
|
||||||
protected function ssRelocate()
|
protected function ssRelocate() : void
|
||||||
{
|
{
|
||||||
if (!$this->_get['id'] || !$this->_get['typeid'])
|
if (!$this->reqGET('id', 'typeid'))
|
||||||
return '';
|
{
|
||||||
|
trigger_error('AjaxAdmin::ssRelocate - screenshotId or typeId empty', E_USER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$id = $this->_get['id'][0];
|
$id = $this->_get['id'][0];
|
||||||
list($type, $oldTypeId) = array_values(DB::Aowow()->selectRow('SELECT type, typeId FROM ?_screenshots WHERE id = ?d', $id));
|
[$type, $oldTypeId] = array_values(DB::Aowow()->selectRow('SELECT type, typeId FROM ?_screenshots WHERE id = ?d', $id));
|
||||||
$typeId = (int)$this->_get['typeid'];
|
$typeId = (int)$this->_get['typeid'];
|
||||||
|
|
||||||
$tc = new Util::$typeClasses[$type]([['id', $typeId]]);
|
$tc = Type::newList($type, [['id', $typeId]]);
|
||||||
if (!$tc->error)
|
if ($tc && !$tc->error)
|
||||||
{
|
{
|
||||||
// move screenshot
|
// move screenshot
|
||||||
DB::Aowow()->query('UPDATE ?_screenshots SET typeId = ?d WHERE id = ?d', $typeId, $id);
|
DB::Aowow()->query('UPDATE ?_screenshots SET typeId = ?d WHERE id = ?d', $typeId, $id);
|
||||||
@@ -279,11 +308,11 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
if($ssInfo || !$ssInfo['hasMore'])
|
if($ssInfo || !$ssInfo['hasMore'])
|
||||||
DB::Aowow()->query('UPDATE '.$tc::$dataTable.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $oldTypeId);
|
DB::Aowow()->query('UPDATE '.$tc::$dataTable.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $oldTypeId);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
return '';
|
trigger_error('AjaxAdmin::ssRelocate - invalid typeId #'.$typeId.' for type #'.$type, E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function confAdd()
|
protected function confAdd() : string
|
||||||
{
|
{
|
||||||
$key = trim($this->_get['key']);
|
$key = trim($this->_get['key']);
|
||||||
$val = trim(urldecode($this->_get['val']));
|
$val = trim(urldecode($this->_get['val']));
|
||||||
@@ -304,9 +333,9 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function confRemove()
|
protected function confRemove() : string
|
||||||
{
|
{
|
||||||
if (!$this->_get['key'])
|
if (!$this->reqGET('key'))
|
||||||
return 'invalid configuration option given';
|
return 'invalid configuration option given';
|
||||||
|
|
||||||
if (DB::Aowow()->query('DELETE FROM ?_config WHERE `key` = ? AND (`flags` & ?d) = 0', $this->_get['key'], CON_FLAG_PERSISTENT))
|
if (DB::Aowow()->query('DELETE FROM ?_config WHERE `key` = ? AND (`flags` & ?d) = 0', $this->_get['key'], CON_FLAG_PERSISTENT))
|
||||||
@@ -315,7 +344,7 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
return 'option name is either protected or was not found';
|
return 'option name is either protected or was not found';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function confUpdate()
|
protected function confUpdate() : string
|
||||||
{
|
{
|
||||||
$key = trim($this->_get['key']);
|
$key = trim($this->_get['key']);
|
||||||
$val = trim(urldecode($this->_get['val']));
|
$val = trim(urldecode($this->_get['val']));
|
||||||
@@ -334,8 +363,8 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
return "value must be integer";
|
return "value must be integer";
|
||||||
else if ($cfg['flags'] & CON_FLAG_TYPE_FLOAT && !preg_match('/^-?\d*(,|.)?\d+$/i', $val))
|
else if ($cfg['flags'] & CON_FLAG_TYPE_FLOAT && !preg_match('/^-?\d*(,|.)?\d+$/i', $val))
|
||||||
return "value must be float";
|
return "value must be float";
|
||||||
else if ($cfg['flags'] & CON_FLAG_TYPE_BOOL)
|
else if ($cfg['flags'] & CON_FLAG_TYPE_BOOL && $val != '1')
|
||||||
$val = (int)!!$val; // *snort* bwahahaa
|
$val = '0';
|
||||||
|
|
||||||
DB::Aowow()->query('UPDATE ?_config SET `value` = ? WHERE `key` = ?', $val, $key);
|
DB::Aowow()->query('UPDATE ?_config SET `value` = ? WHERE `key` = ?', $val, $key);
|
||||||
if (!$this->confOnChange($key, $val, $msg))
|
if (!$this->confOnChange($key, $val, $msg))
|
||||||
@@ -344,84 +373,165 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
return $msg;
|
return $msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function wtSave()
|
protected function wtSave() : string
|
||||||
{
|
{
|
||||||
if (!$this->_post['id'] || !$this->_post['__icon'])
|
if (!$this->reqPOST('id', '__icon'))
|
||||||
return 3;
|
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
|
// save to db
|
||||||
|
|
||||||
DB::Aowow()->query('DELETE FROM ?_account_weightscale_data WHERE id = ?d', $this->_post['id']);
|
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']);
|
DB::Aowow()->query('UPDATE ?_account_weightscales SET `icon`= ? WHERE `id` = ?d', $this->_post['__icon'], $this->_post['id']);
|
||||||
|
|
||||||
foreach (explode(',', $this->_post['scale']) as $s)
|
foreach (explode(',', $this->_post['scale']) as $s)
|
||||||
{
|
{
|
||||||
list($k, $v) = explode(':', $s);
|
[$k, $v] = explode(':', $s);
|
||||||
|
|
||||||
if (!in_array($k, Util::$weightScales) || $v < 1)
|
if (!in_array($k, Util::$weightScales) || $v < 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (DB::Aowow()->query('INSERT INTO ?_account_weightscale_data VALUES (?d, ?, ?d)', $this->_post['id'], $k, $v) === null)
|
if (DB::Aowow()->query('INSERT INTO ?_account_weightscale_data VALUES (?d, ?, ?d)', $this->_post['id'], $k, $v) === null)
|
||||||
return 1;
|
return '1';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// write dataset
|
// write dataset
|
||||||
|
exec('php aowow --build=weightPresets', $out);
|
||||||
$wtPresets = [];
|
foreach ($out as $o)
|
||||||
$scales = DB::Aowow()->select('SELECT id, name, icon, class FROM ?_account_weightscales WHERE userId = 0 ORDER BY class, id ASC');
|
if (strstr($o, 'ERR'))
|
||||||
|
return '2';
|
||||||
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
|
// all done
|
||||||
|
return '0';
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkId($val)
|
protected function spawnPosFix() : string
|
||||||
{
|
{
|
||||||
// expecting id-list
|
if (!$this->reqGET('type', 'guid', 'area', 'floor'))
|
||||||
if (preg_match('/\d+(,\d+)*/', $val))
|
return '-4';
|
||||||
return array_map('intVal', explode(',', $val));
|
|
||||||
|
|
||||||
return null;
|
$guid = $this->_get['guid'];
|
||||||
|
$type = $this->_get['type'];
|
||||||
|
$area = $this->_get['area'];
|
||||||
|
$floor = $this->_get['floor'];
|
||||||
|
|
||||||
|
if (!in_array($type, [Type::NPC, Type::OBJECT, Type::SOUND, Type::AREATRIGGER]))
|
||||||
|
return '-3';
|
||||||
|
|
||||||
|
DB::Aowow()->query('REPLACE INTO ?_spawns_override VALUES (?d, ?d, ?d, ?d, ?d)', $type, $guid, $area, $floor, AOWOW_REVISION);
|
||||||
|
|
||||||
|
if ($wPos = Game::getWorldPosForGUID($type, $guid))
|
||||||
|
{
|
||||||
|
if ($point = Game::worldPosToZonePos($wPos[$guid]['mapId'], $wPos[$guid]['posX'], $wPos[$guid]['posY'], $area, $floor))
|
||||||
|
{
|
||||||
|
$updGUIDs = [$guid];
|
||||||
|
$newPos = array(
|
||||||
|
'posX' => $point[0]['posX'],
|
||||||
|
'posY' => $point[0]['posY'],
|
||||||
|
'areaId' => $point[0]['areaId'],
|
||||||
|
'floor' => $point[0]['floor']
|
||||||
|
);
|
||||||
|
|
||||||
|
// if creature try for waypoints
|
||||||
|
if ($type == Type::NPC)
|
||||||
|
{
|
||||||
|
$jobs = array(
|
||||||
|
'SELECT -w.id AS `entry`, w.point AS `pointId`, w.position_y AS `posX`, w.position_x AS `posY` FROM creature_addon ca JOIN waypoint_data w ON w.id = ca.path_id WHERE ca.guid = ?d AND ca.path_id <> 0',
|
||||||
|
'SELECT `entry`, `pointId`, `location_y` AS `posX`, `location_x` AS `posY` FROM `script_waypoint` WHERE `entry` = ?d',
|
||||||
|
'SELECT `entry`, `pointId`, `position_y` AS `posX`, `position_x` AS `posY` FROM `waypoints` WHERE `entry` = ?d'
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($jobs as $idx => $job)
|
||||||
|
{
|
||||||
|
if ($swp = DB::World()->select($job, $idx ? $wPos[$guid]['id'] : $guid))
|
||||||
|
{
|
||||||
|
foreach ($swp as $w)
|
||||||
|
{
|
||||||
|
if ($point = Game::worldPosToZonePos($wPos[$guid]['mapId'], $w['posX'], $w['posY'], $area, $floor))
|
||||||
|
{
|
||||||
|
$p = array(
|
||||||
|
'posX' => $point[0]['posX'],
|
||||||
|
'posY' => $point[0]['posY'],
|
||||||
|
'areaId' => $point[0]['areaId'],
|
||||||
|
'floor' => $point[0]['floor']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
DB::Aowow()->query('UPDATE ?_creature_waypoints SET ?a WHERE `creatureOrPath` = ?d AND `point` = ?d', $p, $w['entry'], $w['pointId']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// also move linked vehicle accessories (on the very same position)
|
||||||
|
$updGUIDs = array_merge($updGUIDs, DB::Aowow()->selectCol('SELECT s2.guid FROM ?_spawns s1 JOIN ?_spawns s2 ON s1.posX = s2.posX AND s1.posY = s2.posY AND
|
||||||
|
s1.areaId = s2.areaId AND s1.floor = s2.floor AND s2.guid < 0 WHERE s1.guid = ?d', $guid));
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::Aowow()->query('UPDATE ?_spawns SET ?a WHERE `type` = ?d AND `guid` IN (?a)', $newPos, $type, $updGUIDs);
|
||||||
|
|
||||||
|
return '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '-2';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '-1';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkKey($val)
|
protected function guideManage() : string
|
||||||
|
{
|
||||||
|
$update = function (int $id, int $status, ?string $msg = null) : bool
|
||||||
|
{
|
||||||
|
if (!DB::Aowow()->query('UPDATE ?_guides SET `status` = ?d WHERE `id` = ?d', $status, $id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// set display rev to latest
|
||||||
|
if ($status == GUIDE_STATUS_APPROVED)
|
||||||
|
DB::Aowow()->query('UPDATE ?_guides SET `rev` = (SELECT `rev` FROM ?_articles WHERE `type` = ?d AND `typeId` = ?d ORDER BY `rev` DESC LIMIT 1) WHERE `id` = ?d', Type::GUIDE, $id, $id);
|
||||||
|
|
||||||
|
DB::Aowow()->query('INSERT INTO ?_guides_changelog (`id`, `date`, `userId`, `status`) VALUES (?d, ?d, ?d, ?d)', $id, time(), User::$id, $status);
|
||||||
|
if ($msg)
|
||||||
|
DB::Aowow()->query('INSERT INTO ?_guides_changelog (`id`, `date`, `userId`, `msg`) VALUES (?d, ?d, ?d, ?)' , $id, time(), User::$id, $msg);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!$this->_post['id'])
|
||||||
|
trigger_error('AjaxHander::guideManage - malformed request: id: '.$this->_post['id'].', status: '.$this->_post['status']);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$guide = DB::Aowow()->selectRow('SELECT `userId`, `status` FROM ?_guides WHERE `id` = ?d', $this->_post['id']);
|
||||||
|
if (!$guide)
|
||||||
|
trigger_error('AjaxHander::guideManage - guide #'.$this->_post['id'].' not found');
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($this->_post['status'] == $guide['status'])
|
||||||
|
trigger_error('AjaxHander::guideManage - guide #'.$this->_post['id'].' already has status #'.$this->_post['status']);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($this->_post['status'] == GUIDE_STATUS_APPROVED)
|
||||||
|
{
|
||||||
|
if ($update($this->_post['id'], GUIDE_STATUS_APPROVED, $this->_post['msg']))
|
||||||
|
{
|
||||||
|
Util::gainSiteReputation($guide['userId'], SITEREP_ACTION_ARTICLE, ['id' => $this->_post['id']]);
|
||||||
|
return '1';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return '-2';
|
||||||
|
}
|
||||||
|
else if ($this->_post['status'] == GUIDE_STATUS_REJECTED)
|
||||||
|
return $update($this->_post['id'], GUIDE_STATUS_REJECTED, $this->_post['msg']) ? '1' : '-2';
|
||||||
|
else
|
||||||
|
trigger_error('AjaxHander::guideManage - unhandled status change request');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return '-1';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************/
|
||||||
|
/* additional input filter */
|
||||||
|
/***************************/
|
||||||
|
|
||||||
|
protected static function checkKey(string $val) : string
|
||||||
{
|
{
|
||||||
// expecting string
|
// expecting string
|
||||||
if (preg_match('/[^a-z0-9_\.\-]/i', $val))
|
if (preg_match('/[^a-z0-9_\.\-]/i', $val))
|
||||||
@@ -430,25 +540,30 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
return strtolower($val);
|
return strtolower($val);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkUser($val)
|
protected static function checkUser($val) : string
|
||||||
{
|
{
|
||||||
$n = Util::lower(trim(urldecode($val)));
|
$n = Util::lower(trim(urldecode($val)));
|
||||||
|
|
||||||
if (User::isValidName($n))
|
if (User::isValidName($n))
|
||||||
return $n;
|
return $n;
|
||||||
|
|
||||||
return null;
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkScale($val)
|
protected static function checkScale($val) : string
|
||||||
{
|
{
|
||||||
if (preg_match('/^((\w+:\d+)(,\w+:\d+)*)$/', $val))
|
if (preg_match('/^((\w+:\d+)(,\w+:\d+)*)$/', $val))
|
||||||
return $val;
|
return $val;
|
||||||
|
|
||||||
return null;
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function confOnChange($key, $val, &$msg)
|
|
||||||
|
/**********/
|
||||||
|
/* helper */
|
||||||
|
/**********/
|
||||||
|
|
||||||
|
private static function confOnChange(string $key, string $val, string &$msg) : bool
|
||||||
{
|
{
|
||||||
$fn = $buildList = null;
|
$fn = $buildList = null;
|
||||||
|
|
||||||
@@ -466,12 +581,16 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
case 'static_host':
|
case 'static_host':
|
||||||
$buildList = 'searchplugin,power,searchboxBody,searchboxScript';
|
$buildList = 'searchplugin,power,searchboxBody,searchboxScript';
|
||||||
break;
|
break;
|
||||||
|
case 'contact_email':
|
||||||
|
$buildList = 'markup';
|
||||||
|
break;
|
||||||
case 'locales':
|
case 'locales':
|
||||||
$buildList = 'locales';
|
$buildList = 'locales';
|
||||||
$msg .= ' * remember to rebuild all static files for the language you just added.<br />';
|
$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>';
|
$msg .= ' * you can speed this up by supplying the regionCode to the setup: <pre class="q1">--locales=<regionCodes,> -f</pre>';
|
||||||
break;
|
break;
|
||||||
case 'profiler_queue':
|
case 'profiler_enable':
|
||||||
|
$buildList = 'realms,realmMenu';
|
||||||
$fn = function($x) use (&$msg) {
|
$fn = function($x) use (&$msg) {
|
||||||
if (!$x)
|
if (!$x)
|
||||||
return true;
|
return true;
|
||||||
@@ -479,6 +598,17 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
return Profiler::queueStart($msg);
|
return Profiler::queueStart($msg);
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case 'acc_auth_mode':
|
||||||
|
$fn = function($x) use (&$msg) {
|
||||||
|
if ($x == 1 && !extension_loaded('gmp'))
|
||||||
|
{
|
||||||
|
$msg .= 'PHP extension GMP is required to use TrinityCore as auth source, but is not currently enabled.<br />';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
break;
|
||||||
default: // nothing to do, everything is fine
|
default: // nothing to do, everything is fine
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -495,3 +625,5 @@ class AjaxAdmin extends AjaxHandler
|
|||||||
return $fn ? $fn($val) : true;
|
return $fn ? $fn($val) : true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ class AjaxArenaTeam extends AjaxHandler
|
|||||||
{
|
{
|
||||||
protected $validParams = ['resync', 'status'];
|
protected $validParams = ['resync', 'status'];
|
||||||
protected $_get = array(
|
protected $_get = array(
|
||||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdList']],
|
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdList' ],
|
||||||
'profile' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkEmptySet']],
|
'profile' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkEmptySet'],
|
||||||
);
|
);
|
||||||
|
|
||||||
public function __construct(array $params)
|
public function __construct(array $params)
|
||||||
@@ -35,16 +35,16 @@ class AjaxArenaTeam extends AjaxHandler
|
|||||||
profile: <empty> [optional, also get related chars]
|
profile: <empty> [optional, also get related chars]
|
||||||
return: 1
|
return: 1
|
||||||
*/
|
*/
|
||||||
protected function handleResync()
|
protected function handleResync() : string
|
||||||
{
|
{
|
||||||
if ($teams = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_arena_team WHERE id IN (?a)', $this->_get['id']))
|
if ($teams = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_arena_team WHERE id IN (?a)', $this->_get['id']))
|
||||||
foreach ($teams as $t)
|
foreach ($teams as $t)
|
||||||
Profiler::scheduleResync(TYPE_ARENA_TEAM, $t['realm'], $t['realmGUID']);
|
Profiler::scheduleResync(Type::ARENA_TEAM, $t['realm'], $t['realmGUID']);
|
||||||
|
|
||||||
if ($this->_get['profile'])
|
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']))
|
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)
|
foreach ($chars as $c)
|
||||||
Profiler::scheduleResync(TYPE_PROFILE, $c['realm'], $c['realmGUID']);
|
Profiler::scheduleResync(Type::PROFILE, $c['realm'], $c['realmGUID']);
|
||||||
|
|
||||||
return '1';
|
return '1';
|
||||||
}
|
}
|
||||||
@@ -72,9 +72,9 @@ class AjaxArenaTeam extends AjaxHandler
|
|||||||
1: char does not exist
|
1: char does not exist
|
||||||
2: armory gone
|
2: armory gone
|
||||||
*/
|
*/
|
||||||
protected function handleStatus()
|
protected function handleStatus() : string
|
||||||
{
|
{
|
||||||
$response = Profiler::resyncStatus(TYPE_ARENA_TEAM, $this->_get['id']);
|
$response = Profiler::resyncStatus(Type::ARENA_TEAM, $this->_get['id']);
|
||||||
return Util::toJSON($response);
|
return Util::toJSON($response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,23 +11,23 @@ class AjaxComment extends AjaxHandler
|
|||||||
const REPLY_LENGTH_MAX = 600;
|
const REPLY_LENGTH_MAX = 600;
|
||||||
|
|
||||||
protected $_post = array(
|
protected $_post = array(
|
||||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxComment::checkId']],
|
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdListUnsigned'],
|
||||||
'body' => [FILTER_UNSAFE_RAW, null],// escaped by json_encode
|
'body' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext' ],
|
||||||
'commentbody' => [FILTER_UNSAFE_RAW, null],// escaped by json_encode
|
'commentbody' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext' ],
|
||||||
'response' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
|
'response' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ],
|
||||||
'reason' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
|
'reason' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ],
|
||||||
'remove' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'remove' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'commentId' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'commentId' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'replyId' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'replyId' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'sticky' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'sticky' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
// 'username' => [FILTER_SANITIZE_STRING, 0xC] // FILTER_FLAG_STRIP_LOW | *_HIGH
|
// 'username' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ]
|
||||||
);
|
);
|
||||||
|
|
||||||
protected $_get = array(
|
protected $_get = array(
|
||||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
|
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'],
|
||||||
'type' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
|
'type' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'],
|
||||||
'typeid' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
|
'typeid' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'],
|
||||||
'rating' => [FILTER_SANITIZE_NUMBER_INT, null]
|
'rating' => ['filter' => FILTER_SANITIZE_NUMBER_INT]
|
||||||
);
|
);
|
||||||
|
|
||||||
public function __construct(array $params)
|
public function __construct(array $params)
|
||||||
@@ -75,49 +75,82 @@ class AjaxComment extends AjaxHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// i .. have problems believing, that everything uses nifty ajax while adding comments requires a brutal header(Loacation: <wherever>), yet, thats how it is
|
// 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()
|
protected function handleCommentAdd() : string
|
||||||
{
|
{
|
||||||
if (!$this->_get['typeid'] || !$this->_get['type'] || !isset(Util::$typeClasses[$this->_get['type']]))
|
if (!$this->_get['typeid'] || !$this->_get['type'] || !Type::exists($this->_get['type']))
|
||||||
return; // whatever, we cant even send him back
|
{
|
||||||
|
trigger_error('AjaxComment::handleCommentAdd - malforemd request received', E_USER_ERROR);
|
||||||
|
return ''; // whatever, we cant even send him back
|
||||||
|
}
|
||||||
|
|
||||||
// this type cannot be commented on
|
// this type cannot be commented on
|
||||||
if (!(get_class_vars(Util::$typeClasses[$this->_get['type']])['contribute'] & CONTRIBUTE_CO))
|
if (!Type::checkClassAttrib($this->_get['type'], 'contribute', CONTRIBUTE_CO))
|
||||||
return;
|
{
|
||||||
|
trigger_error('AjaxComment::handleCommentAdd - tried to comment on unsupported type #'.$this->_get['type'], E_USER_ERROR);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
// trim to max length
|
// trim to max length
|
||||||
if (!User::isInGroup(U_GROUP_MODERATOR) && mb_strlen($this->_post['commentbody']) > (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)))
|
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)));
|
$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 (User::canComment())
|
||||||
{
|
{
|
||||||
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']))
|
if (!empty($this->_post['commentbody']) && mb_strlen($this->_post['commentbody']) >= self::COMMENT_LENGTH_MIN)
|
||||||
{
|
{
|
||||||
Util::gainSiteReputation(User::$id, SITEREP_ACTION_COMMENT, ['id' => $postIdx]);
|
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
|
// 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);
|
DB::Aowow()->query('INSERT INTO ?_user_ratings (`type`, `entry`, `userId`, `value`) VALUES (?d, ?d, 0, 1)', RATING_COMMENT, $postIdx);
|
||||||
|
|
||||||
// flag target with hasComment
|
// flag target with hasComment
|
||||||
if ($tbl = get_class_vars(Util::$typeClasses[$this->_get['type']])['dataTable'])
|
if ($tbl = Type::getClassAttrib($this->_get['type'], 'dataTable'))
|
||||||
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $this->_get['typeid']);
|
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $this->_get['typeid']);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$_SESSION['error']['co'] = Lang::main('intError');
|
||||||
|
trigger_error('AjaxComment::handleCommentAdd - write to db failed', E_USER_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
$_SESSION['error']['co'] = Lang::main('textLength', [mb_strlen($this->_post['commentbody']), self::COMMENT_LENGTH_MIN, self::COMMENT_LENGTH_MAX]);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
$_SESSION['error']['co'] = Lang::main('cannotComment');
|
||||||
|
|
||||||
$this->doRedirect = true;
|
$this->doRedirect = true;
|
||||||
return '?'.Util::$typeStrings[$this->_get['type']].'='.$this->_get['typeid'].'#comments';
|
|
||||||
|
$idOrUrl = $this->_get['typeid'];
|
||||||
|
if ($this->_get['type'] == Type::GUIDE)
|
||||||
|
if ($_ = DB::Aowow()->selectCell('SELECT `url` FROM ?_guides WHERE `id` = ?d', $this->_get['typeid']))
|
||||||
|
$idOrUrl = $_;
|
||||||
|
|
||||||
|
return '?'.Type::getFileString($this->_get['type']).'='.$idOrUrl.'#comments';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleCommentEdit()
|
protected function handleCommentEdit() : void
|
||||||
{
|
{
|
||||||
if ((!User::canComment() && !User::isInGroup(U_GROUP_MODERATOR)) || !$this->_get['id'] || !$this->_post['body'])
|
if (!User::canComment() && !User::isInGroup(U_GROUP_MODERATOR))
|
||||||
|
{
|
||||||
|
trigger_error('AjaxComment::handleCommentEdit - user #'.User::$id.' not allowed to edit', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->_get['id'] || !$this->_post['body'])
|
||||||
|
{
|
||||||
|
trigger_error('AjaxComment::handleCommentEdit - malforemd request received', E_USER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mb_strlen($this->_post['body']) < self::COMMENT_LENGTH_MIN)
|
if (mb_strlen($this->_post['body']) < self::COMMENT_LENGTH_MIN)
|
||||||
return;
|
return; // no point in reporting this trifle
|
||||||
|
|
||||||
// trim to max length
|
// trim to max length
|
||||||
if (!User::isInGroup(U_GROUP_MODERATOR) && mb_strlen($this->_post['body']) > (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)))
|
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)));
|
$this->_post['body'] = mb_substr($this->_post['body'], 0, (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)));
|
||||||
|
|
||||||
$update = array(
|
$update = array(
|
||||||
'body' => $this->_post['body'],
|
'body' => $this->_post['body'],
|
||||||
@@ -135,10 +168,13 @@ class AjaxComment extends AjaxHandler
|
|||||||
DB::Aowow()->query('UPDATE ?_comments SET editCount = editCount + 1, ?a WHERE id = ?d', $update, $this->_get['id']);
|
DB::Aowow()->query('UPDATE ?_comments SET editCount = editCount + 1, ?a WHERE id = ?d', $update, $this->_get['id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleCommentDelete()
|
protected function handleCommentDelete() : void
|
||||||
{
|
{
|
||||||
if (!$this->_post['id'] || !User::$id)
|
if (!$this->_post['id'] || !User::$id)
|
||||||
|
{
|
||||||
|
trigger_error('AjaxComment::handleCommentDelete - commentId empty or user not logged in', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// in theory, there is a username passed alongside... lets just use the current user (see user.js)
|
// 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}',
|
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d, deleteUserId = ?d, deleteDate = UNIX_TIMESTAMP() WHERE id IN (?a){ AND userId = ?d}',
|
||||||
@@ -156,15 +192,20 @@ class AjaxComment extends AjaxHandler
|
|||||||
$this->_post['id']
|
$this->_post['id']
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!$coInfo['hasMore'] && Util::$typeClasses[$coInfo['type']] && ($tbl = get_class_vars(Util::$typeClasses[$coInfo['type']])['dataTable']))
|
if (!$coInfo['hasMore'] && ($tbl = Type::getClassAttrib($coInfo['type'], 'dataTable')))
|
||||||
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']);
|
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
trigger_error('AjaxComment::handleCommentDelete - user #'.User::$id.' could not flag comment #'.$this->_post['id'].' as deleted', E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleCommentUndelete()
|
protected function handleCommentUndelete() : void
|
||||||
{
|
{
|
||||||
if (!$this->_post['id'] || !User::$id)
|
if (!$this->_post['id'] || !User::$id)
|
||||||
|
{
|
||||||
|
trigger_error('AjaxComment::handleCommentUndelete - commentId empty or user not logged in', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// in theory, there is a username passed alongside... lets just use the current user (see user.js)
|
// 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}',
|
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id IN (?a){ AND userId = deleteUserId AND deleteUserId = ?d}',
|
||||||
@@ -177,28 +218,30 @@ class AjaxComment extends AjaxHandler
|
|||||||
if ($ok)
|
if ($ok)
|
||||||
{
|
{
|
||||||
$coInfo = DB::Aowow()->selectRow('SELECT type, typeId FROM ?_comments WHERE id = ?d', $this->_post['id']);
|
$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']))
|
if ($tbl = Type::getClassAttrib($coInfo['type'], 'dataTable'))
|
||||||
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']);
|
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
trigger_error('AjaxComment::handleCommentUndelete - user #'.User::$id.' could not unflag comment #'.$this->_post['id'].' as deleted', E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleCommentRating()
|
protected function handleCommentRating() : string
|
||||||
{
|
{
|
||||||
if (!$this->_get['id'])
|
if (!$this->_get['id'])
|
||||||
return Util::toJSON(['success' => 0]);
|
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']))
|
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 ?_user_ratings WHERE `type` = ?d AND `entry` = ?d AND userId <> 0 GROUP BY `entry`', RATING_COMMENT, $this->_get['id']))
|
||||||
return Util::toJSON($votes);
|
return Util::toJSON($votes);
|
||||||
else
|
else
|
||||||
return Util::toJSON(['success' => 1, 'up' => 0, 'down' => 0]);
|
return Util::toJSON(['success' => 1, 'up' => 0, 'down' => 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleCommentVote()
|
protected function handleCommentVote() : string
|
||||||
{
|
{
|
||||||
if (!User::$id || !$this->_get['id'] || !$this->_get['rating'])
|
if (!User::$id || !$this->_get['id'] || !$this->_get['rating'])
|
||||||
return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
|
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']);
|
$target = DB::Aowow()->selectRow('SELECT c.`userId` AS owner, ur.`value` FROM ?_comments c LEFT JOIN ?_user_ratings ur ON ur.`type` = ?d AND ur.`entry` = c.id AND ur.`userId` = ?d WHERE c.id = ?d', RATING_COMMENT, User::$id, $this->_get['id']);
|
||||||
$val = User::canSupervote() ? 2 : 1;
|
$val = User::canSupervote() ? 2 : 1;
|
||||||
if ($this->_get['rating'] < 0)
|
if ($this->_get['rating'] < 0)
|
||||||
$val *= -1;
|
$val *= -1;
|
||||||
@@ -213,9 +256,9 @@ class AjaxComment extends AjaxHandler
|
|||||||
$ok = false;
|
$ok = false;
|
||||||
// old and new have same sign; undo vote (user may have gained/lost access to superVote in the meantime)
|
// 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))
|
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);
|
$ok = DB::Aowow()->query('DELETE FROM ?_user_ratings WHERE `type` = ?d AND `entry` = ?d AND `userId` = ?d', RATING_COMMENT, $this->_get['id'], User::$id);
|
||||||
else // replace, because we may be overwriting an old, opposing vote
|
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))
|
if ($ok = DB::Aowow()->query('REPLACE INTO ?_user_ratings (`type`, `entry`, `userId`, `value`) VALUES (?d, ?d, ?d, ?d)', RATING_COMMENT, (int)$this->_get['id'], User::$id, $val))
|
||||||
User::decrementDailyVotes(); // do not refund retracted votes!
|
User::decrementDailyVotes(); // do not refund retracted votes!
|
||||||
|
|
||||||
if (!$ok)
|
if (!$ok)
|
||||||
@@ -229,10 +272,13 @@ class AjaxComment extends AjaxHandler
|
|||||||
return Util::toJSON(['error' => 0]);
|
return Util::toJSON(['error' => 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleCommentSticky()
|
protected function handleCommentSticky() : void
|
||||||
{
|
{
|
||||||
if (!$this->_post['id'] || !User::isInGroup(U_GROUP_MODERATOR))
|
if (!$this->_post['id'] || !User::isInGroup(U_GROUP_MODERATOR))
|
||||||
|
{
|
||||||
|
trigger_error('AjaxComment::handleCommentSticky - commentId empty or user #'.User::$id.' not moderator', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->_post['sticky'])
|
if ($this->_post['sticky'])
|
||||||
DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d WHERE id = ?d', CC_FLAG_STICKY, $this->_post['id'][0]);
|
DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d WHERE id = ?d', CC_FLAG_STICKY, $this->_post['id'][0]);
|
||||||
@@ -240,12 +286,15 @@ class AjaxComment extends AjaxHandler
|
|||||||
DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id = ?d', CC_FLAG_STICKY, $this->_post['id'][0]);
|
DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id = ?d', CC_FLAG_STICKY, $this->_post['id'][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleCommentOutOfDate()
|
protected function handleCommentOutOfDate() : string
|
||||||
{
|
{
|
||||||
$this->contentType = 'text/plain';
|
$this->contentType = MIME_TYPE_TEXT;
|
||||||
|
|
||||||
if (!$this->_post['id'])
|
if (!$this->_post['id'])
|
||||||
return 'The comment does not exist.';
|
{
|
||||||
|
trigger_error('AjaxComment::handleCommentOutOfDate - commentId empty', E_USER_ERROR);
|
||||||
|
return Lang::main('intError');
|
||||||
|
}
|
||||||
|
|
||||||
$ok = false;
|
$ok = false;
|
||||||
if (User::isInGroup(U_GROUP_MODERATOR)) // directly mark as outdated
|
if (User::isInGroup(U_GROUP_MODERATOR)) // directly mark as outdated
|
||||||
@@ -255,114 +304,127 @@ class AjaxComment extends AjaxHandler
|
|||||||
else
|
else
|
||||||
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~0x4 WHERE id = ?d', $this->_post['id'][0]);
|
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~0x4 WHERE id = ?d', $this->_post['id'][0]);
|
||||||
}
|
}
|
||||||
|
else if (DB::Aowow()->selectCell('SELECT 1 FROM ?_reports WHERE `mode` = ?d AND `reason`= ?d AND `subject` = ?d AND `userId` = ?d', 1, 17, $this->_post['id'][0], User::$id))
|
||||||
|
return Lang::main('alreadyReport');
|
||||||
else if (User::$id && !$this->_post['reason'] || mb_strlen($this->_post['reason']) < self::REPLY_LENGTH_MIN)
|
else if (User::$id && !$this->_post['reason'] || mb_strlen($this->_post['reason']) < self::REPLY_LENGTH_MIN)
|
||||||
return 'Your message is too short.';
|
return Lang::main('textTooShort');
|
||||||
else if (User::$id) // only report as outdated
|
else if (User::$id) // only report as outdated
|
||||||
{
|
$ok = Util::createReport(1, 17, $this->_post['id'][0], '[Outdated Comment] '.$this->_post['reason']);
|
||||||
$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
|
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 'ok'; // the script expects the actual characters 'ok' not some string like "ok"
|
||||||
|
else
|
||||||
|
trigger_error('AjaxComment::handleCommentOutOfDate - failed to update comment in db', E_USER_ERROR);
|
||||||
|
|
||||||
return Lang::main('genericError');
|
return Lang::main('intError');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleCommentShowReplies()
|
protected function handleCommentShowReplies() : string
|
||||||
{
|
{
|
||||||
return Util::toJSON(!$this->_get['id'] ? [] : CommunityContent::getCommentReplies($this->_get['id']));
|
return Util::toJSON(!$this->_get['id'] ? [] : CommunityContent::getCommentReplies($this->_get['id']));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleReplyAdd()
|
protected function handleReplyAdd() : string
|
||||||
{
|
{
|
||||||
$this->contentType = 'text/plain';
|
$this->contentType = MIME_TYPE_TEXT;
|
||||||
|
|
||||||
if (!User::canComment())
|
if (!User::canComment())
|
||||||
return 'You are not allowed to reply.';
|
return Lang::main('cannotComment');
|
||||||
|
|
||||||
else if (!$this->_post['commentId'] || !DB::Aowow()->selectCell('SELECT 1 FROM ?_comments WHERE id = ?d', $this->_post['commentId']))
|
if (!$this->_post['commentId'] || !DB::Aowow()->selectCell('SELECT 1 FROM ?_comments WHERE id = ?d', $this->_post['commentId']))
|
||||||
return Lang::main('genericError');
|
{
|
||||||
|
trigger_error('AjaxComment::handleReplyAdd - comment #'.$this->_post['commentId'].' does not exist', E_USER_ERROR);
|
||||||
|
return Lang::main('intError');
|
||||||
|
}
|
||||||
|
|
||||||
else if (!$this->_post['body'] || mb_strlen($this->_post['body']) < self::REPLY_LENGTH_MIN || mb_strlen($this->_post['body']) > self::REPLY_LENGTH_MAX)
|
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.'.';
|
return Lang::main('textLength', [mb_strlen($this->_post['body']), self::REPLY_LENGTH_MIN, 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']))
|
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']));
|
return Util::toJSON(CommunityContent::getCommentReplies($this->_post['commentId']));
|
||||||
|
|
||||||
else
|
trigger_error('AjaxComment::handleReplyAdd - write to db failed', E_USER_ERROR);
|
||||||
return Lang::main('genericError');
|
return Lang::main('intError');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleReplyEdit()
|
protected function handleReplyEdit() : string
|
||||||
{
|
{
|
||||||
$this->contentType = 'text/plain';
|
$this->contentType = MIME_TYPE_TEXT;
|
||||||
|
|
||||||
if (!User::canComment())
|
if (!User::canComment())
|
||||||
return 'You are not allowed to reply.';
|
return Lang::main('cannotComment');
|
||||||
|
|
||||||
else if (!$this->_post['replyId'] || !$this->_post['commentId'])
|
if ((!$this->_post['replyId'] || !$this->_post['commentId']) && DB::Aowow()->selectCell('SELECT COUNT(1) FROM ?_comments WHERE id IN (?a)', [$this->_post['replyId'], $this->_post['commentId']]))
|
||||||
return Lang::main('genericError');
|
{
|
||||||
|
trigger_error('AjaxComment::handleReplyEdit - comment #'.$this->_post['commentId'].' or reply #'.$this->_post['replyId'].' does not exist', E_USER_ERROR);
|
||||||
|
return Lang::main('intError');
|
||||||
|
}
|
||||||
|
|
||||||
else if (!$this->_post['body'] || mb_strlen($this->_post['body']) < self::REPLY_LENGTH_MIN || mb_strlen($this->_post['body']) > self::REPLY_LENGTH_MAX)
|
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.'.';
|
return Lang::main('textLength', [mb_strlen($this->_post['body']), self::REPLY_LENGTH_MIN, 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}',
|
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))
|
$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']));
|
return Util::toJSON(CommunityContent::getCommentReplies($this->_post['commentId']));
|
||||||
else
|
|
||||||
return Lang::main('genericError');
|
trigger_error('AjaxComment::handleReplyEdit - write to db failed', E_USER_ERROR);
|
||||||
|
return Lang::main('intError');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleReplyDetach()
|
protected function handleReplyDetach() : void
|
||||||
{
|
{
|
||||||
if (!User::isInGroup(U_GROUP_MODERATOR) || !$this->_post['id'])
|
if (!$this->_post['id'] || !User::isInGroup(U_GROUP_MODERATOR))
|
||||||
|
{
|
||||||
|
trigger_error('AjaxComment::handleReplyDetach - commentId empty or user #'.User::$id.' not moderator', E_USER_ERROR);
|
||||||
return;
|
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]);
|
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()
|
protected function handleReplyDelete() : void
|
||||||
{
|
{
|
||||||
if (!User::$id || !$this->_post['id'])
|
if (!User::$id || !$this->_post['id'])
|
||||||
|
{
|
||||||
|
trigger_error('AjaxComment::handleReplyDelete - commentId empty or user not logged in', E_USER_ERROR);
|
||||||
return;
|
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))
|
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]);
|
DB::Aowow()->query('DELETE FROM ?_user_ratings WHERE `type` = ?d AND `entry` = ?d', RATING_COMMENT, $this->_post['id'][0]);
|
||||||
|
else
|
||||||
|
trigger_error('AjaxComment::handleReplyDelete - deleting comment #'.$this->_post['id'][0].' by user #'.User::$id.' from db failed', E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleReplyFlag()
|
protected function handleReplyFlag() : void
|
||||||
{
|
{
|
||||||
if (!User::$id || !$this->_post['id'])
|
if (!User::$id || !$this->_post['id'])
|
||||||
|
{
|
||||||
|
trigger_error('AjaxComment::handleReplyFlag - commentId empty or user not logged in', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DB::Aowow()->query(
|
Util::createReport(1, 19, $this->_post['id'][0], '[General Reply Report]');
|
||||||
'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()
|
protected function handleReplyUpvote() : void
|
||||||
{
|
{
|
||||||
if (!$this->_post['id'] || !User::canUpvote())
|
if (!$this->_post['id'] || !User::canUpvote())
|
||||||
|
{
|
||||||
|
trigger_error('AjaxComment::handleReplyUpvote - commentId empty or user not allowed to vote', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$owner = DB::Aowow()->selectCell('SELECT userId FROM ?_comments WHERE id = ?d', $this->_post['id'][0]);
|
$owner = DB::Aowow()->selectCell('SELECT userId FROM ?_comments WHERE id = ?d', $this->_post['id'][0]);
|
||||||
if (!$owner)
|
if (!$owner)
|
||||||
|
{
|
||||||
|
trigger_error('AjaxComment::handleReplyUpvote - comment #'.$this->_post['id'][0].' not found in db', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$ok = DB::Aowow()->query(
|
$ok = DB::Aowow()->query(
|
||||||
'INSERT INTO ?_comments_rates (commentId, userId, value) VALUES (?d, ?d, ?d)',
|
'INSERT INTO ?_user_ratings (`type`, `entry`, `userId`, `value`) VALUES (?d, ?d, ?d, ?d)',
|
||||||
|
RATING_COMMENT,
|
||||||
$this->_post['id'][0],
|
$this->_post['id'][0],
|
||||||
User::$id,
|
User::$id,
|
||||||
User::canSupervote() ? 2 : 1
|
User::canSupervote() ? 2 : 1
|
||||||
@@ -373,19 +435,28 @@ class AjaxComment extends AjaxHandler
|
|||||||
Util::gainSiteReputation($owner, SITEREP_ACTION_UPVOTED, ['id' => $this->_post['id'][0], 'voterId' => User::$id]);
|
Util::gainSiteReputation($owner, SITEREP_ACTION_UPVOTED, ['id' => $this->_post['id'][0], 'voterId' => User::$id]);
|
||||||
User::decrementDailyVotes();
|
User::decrementDailyVotes();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
trigger_error('AjaxComment::handleReplyUpvote - write to db failed', E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleReplyDownvote()
|
protected function handleReplyDownvote() : void
|
||||||
{
|
{
|
||||||
if (!$this->_post['id'] || !User::canDownvote())
|
if (!$this->_post['id'] || !User::canDownvote())
|
||||||
|
{
|
||||||
|
trigger_error('AjaxComment::handleReplyDownvote - commentId empty or user not allowed to vote', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$owner = DB::Aowow()->selectCell('SELECT userId FROM ?_comments WHERE id = ?d', $this->_post['id'][0]);
|
$owner = DB::Aowow()->selectCell('SELECT userId FROM ?_comments WHERE id = ?d', $this->_post['id'][0]);
|
||||||
if (!$owner)
|
if (!$owner)
|
||||||
|
{
|
||||||
|
trigger_error('AjaxComment::handleReplyDownvote - comment #'.$this->_post['id'][0].' not found in db', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$ok = DB::Aowow()->query(
|
$ok = DB::Aowow()->query(
|
||||||
'INSERT INTO ?_comments_rates (commentId, userId, value) VALUES (?d, ?d, ?d)',
|
'INSERT INTO ?_user_ratings (`type`, `entry`, `userId`, `value`) VALUES (?d, ?d, ?d, ?d)',
|
||||||
|
RATING_COMMENT,
|
||||||
$this->_post['id'][0],
|
$this->_post['id'][0],
|
||||||
User::$id,
|
User::$id,
|
||||||
User::canSupervote() ? -2 : -1
|
User::canSupervote() ? -2 : -1
|
||||||
@@ -396,15 +467,9 @@ class AjaxComment extends AjaxHandler
|
|||||||
Util::gainSiteReputation($owner, SITEREP_ACTION_DOWNVOTED, ['id' => $this->_post['id'][0], 'voterId' => User::$id]);
|
Util::gainSiteReputation($owner, SITEREP_ACTION_DOWNVOTED, ['id' => $this->_post['id'][0], 'voterId' => User::$id]);
|
||||||
User::decrementDailyVotes();
|
User::decrementDailyVotes();
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
trigger_error('AjaxComment::handleReplyDownvote - write to db failed', E_USER_ERROR);
|
||||||
protected function checkId($val)
|
|
||||||
{
|
|
||||||
// expecting id-list
|
|
||||||
if (preg_match('/\d+(,\d+)*/', $val))
|
|
||||||
return array_map('intVal', explode(',', $val));
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
class AjaxContactus extends AjaxHandler
|
class AjaxContactus extends AjaxHandler
|
||||||
{
|
{
|
||||||
protected $_post = array(
|
protected $_post = array(
|
||||||
'mode' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'mode' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'reason' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'reason' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'ua' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
|
'ua' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
'appname' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
|
'appname' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
'page' => [FILTER_SANITIZE_URL, null],
|
'page' => ['filter' => FILTER_SANITIZE_URL],
|
||||||
'desc' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
|
'desc' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
'id' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'id' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'relatedurl' => [FILTER_SANITIZE_URL, null],
|
'relatedurl' => ['filter' => FILTER_SANITIZE_URL],
|
||||||
'email' => [FILTER_SANITIZE_EMAIL, null]
|
'email' => ['filter' => FILTER_SANITIZE_EMAIL]
|
||||||
);
|
);
|
||||||
|
|
||||||
public function __construct(array $params)
|
public function __construct(array $params)
|
||||||
@@ -33,7 +33,7 @@ class AjaxContactus extends AjaxHandler
|
|||||||
7: already reported
|
7: already reported
|
||||||
$: prints response
|
$: prints response
|
||||||
*/
|
*/
|
||||||
protected function handleContactUs()
|
protected function handleContactUs() : string
|
||||||
{
|
{
|
||||||
$mode = $this->_post['mode'];
|
$mode = $this->_post['mode'];
|
||||||
$rsn = $this->_post['reason'];
|
$rsn = $this->_post['reason'];
|
||||||
@@ -41,6 +41,7 @@ class AjaxContactus extends AjaxHandler
|
|||||||
$app = $this->_post['appname'];
|
$app = $this->_post['appname'];
|
||||||
$url = $this->_post['page'];
|
$url = $this->_post['page'];
|
||||||
$desc = $this->_post['desc'];
|
$desc = $this->_post['desc'];
|
||||||
|
$subj = $this->_post['id'];
|
||||||
|
|
||||||
$contexts = array(
|
$contexts = array(
|
||||||
[1, 2, 3, 4, 5, 6, 7, 8],
|
[1, 2, 3, 4, 5, 6, 7, 8],
|
||||||
@@ -53,10 +54,16 @@ class AjaxContactus extends AjaxHandler
|
|||||||
);
|
);
|
||||||
|
|
||||||
if ($mode === null || $rsn === null || $ua === null || $app === null || $url === null)
|
if ($mode === null || $rsn === null || $ua === null || $app === null || $url === null)
|
||||||
return 'required field missing';
|
{
|
||||||
|
trigger_error('AjaxContactus::handleContactUs - malformed contact request received', E_USER_ERROR);
|
||||||
|
return Lang::main('intError');
|
||||||
|
}
|
||||||
|
|
||||||
if (!isset($contexts[$mode]) || !in_array($rsn, $contexts[$mode]))
|
if (!isset($contexts[$mode]) || !in_array($rsn, $contexts[$mode]))
|
||||||
return 'mode invalid';
|
{
|
||||||
|
trigger_error('AjaxContactus::handleContactUs - report has invalid context (mode:'.$mode.' / reason:'.$rsn.')', E_USER_ERROR);
|
||||||
|
return Lang::main('intError');
|
||||||
|
}
|
||||||
|
|
||||||
if (!$desc)
|
if (!$desc)
|
||||||
return 3;
|
return 3;
|
||||||
@@ -65,36 +72,22 @@ class AjaxContactus extends AjaxHandler
|
|||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
if (!User::$id && !User::$ip)
|
if (!User::$id && !User::$ip)
|
||||||
return 'your ip could not be determined';
|
{
|
||||||
|
trigger_error('AjaxContactus::handleContactUs - could not determine IP for anonymous user', E_USER_ERROR);
|
||||||
|
return Lang::main('intError');
|
||||||
|
}
|
||||||
|
|
||||||
// check already reported
|
// check already reported
|
||||||
$field = User::$id ? 'userId' : 'ip';
|
$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))
|
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_reports WHERE `mode` = ?d AND `reason`= ?d AND `subject` = ?d AND ?# = ?', $mode, $rsn, $subj, $field, User::$id ?: User::$ip))
|
||||||
return 7;
|
return 7;
|
||||||
|
|
||||||
$update = array(
|
if (Util::createReport($mode, $rsn, $subj, $desc, $ua, $app, $url, $this->_post['relatedurl'], $this->_post['email']))
|
||||||
'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 0;
|
||||||
|
|
||||||
return 'save to db unsuccessful';
|
trigger_error('AjaxContactus::handleContactUs - write to db failed', E_USER_ERROR);
|
||||||
|
return Lang::main('intError');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class AjaxCookie extends AjaxHandler
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
$this->_get = array(
|
$this->_get = array(
|
||||||
$this->params[0] => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
|
$params[0] => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
);
|
);
|
||||||
|
|
||||||
// NOW we know, what to expect and sanitize
|
// NOW we know, what to expect and sanitize
|
||||||
@@ -26,12 +26,20 @@ class AjaxCookie extends AjaxHandler
|
|||||||
0: success
|
0: success
|
||||||
$: silent error
|
$: silent error
|
||||||
*/
|
*/
|
||||||
protected function handleCookie()
|
protected function handleCookie() : string
|
||||||
{
|
{
|
||||||
if (User::$id && $this->params && $this->_get[$this->params[0]])
|
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]]))
|
if (DB::Aowow()->query('REPLACE INTO ?_account_cookies VALUES (?d, ?, ?)', User::$id, $this->params[0], $this->_get[$this->params[0]]))
|
||||||
return 0;
|
return '0';
|
||||||
|
else
|
||||||
|
trigger_error('AjaxCookie::handleCookie - write to db failed', E_USER_ERROR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
trigger_error('AjaxCookie::handleCookie - malformed request received', E_USER_ERROR);
|
||||||
|
|
||||||
return null;
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
class AjaxData extends AjaxHandler
|
class AjaxData extends AjaxHandler
|
||||||
{
|
{
|
||||||
protected $_get = array(
|
protected $_get = array(
|
||||||
'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale']],
|
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale'],
|
||||||
't' => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
|
't' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ],
|
||||||
'catg' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'catg' => ['filter' => FILTER_SANITIZE_NUMBER_INT ],
|
||||||
'skill' => [FILTER_CALLBACK, ['options' => 'AjaxData::checkSkill']],
|
'skill' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxData::checkSkill' ],
|
||||||
'class' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'class' => ['filter' => FILTER_SANITIZE_NUMBER_INT ],
|
||||||
'callback' => [FILTER_CALLBACK, ['options' => 'AjaxData::checkCallback']]
|
'callback' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxData::checkCallback' ]
|
||||||
);
|
);
|
||||||
|
|
||||||
public function __construct(array $params)
|
public function __construct(array $params)
|
||||||
@@ -28,7 +28,7 @@ class AjaxData extends AjaxHandler
|
|||||||
/* responses
|
/* responses
|
||||||
<string>
|
<string>
|
||||||
*/
|
*/
|
||||||
protected function handleData()
|
protected function handleData() : string
|
||||||
{
|
{
|
||||||
$result = '';
|
$result = '';
|
||||||
|
|
||||||
@@ -36,9 +36,11 @@ class AjaxData extends AjaxHandler
|
|||||||
foreach ($this->params as $set)
|
foreach ($this->params as $set)
|
||||||
{
|
{
|
||||||
// requires valid token to hinder automated access
|
// requires valid token to hinder automated access
|
||||||
if ($set != 'item-scaling')
|
if ($set != 'item-scaling' && (!$this->_get['t'] || empty($_SESSION['dataKey']) || $this->_get['t'] != $_SESSION['dataKey']))
|
||||||
if (!$this->_get['t'] || empty($_SESSION['dataKey']) || $this->_get['t'] != $_SESSION['dataKey'])
|
{
|
||||||
continue;
|
trigger_error('AjaxData::handleData - session data key empty or expired', E_USER_ERROR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch ($set)
|
switch ($set)
|
||||||
{
|
{
|
||||||
@@ -107,6 +109,7 @@ class AjaxData extends AjaxHandler
|
|||||||
$result .= "\n\n";
|
$result .= "\n\n";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
trigger_error('AjaxData::handleData - invalid file "'.$set.'" in request', E_USER_ERROR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,17 +117,17 @@ class AjaxData extends AjaxHandler
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkSkill($val)
|
protected static function checkSkill(string $val) : array
|
||||||
{
|
{
|
||||||
return array_intersect([171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356], explode(',', $val));
|
return array_intersect([171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356], explode(',', $val));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkCallback($val)
|
protected static function checkCallback(string $val) : bool
|
||||||
{
|
{
|
||||||
return substr($val, 0, 29) == '$WowheadProfiler.loadOnDemand';
|
return substr($val, 0, 29) === '$WowheadProfiler.loadOnDemand';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadProfilerData($file, $catg = 'null')
|
private function loadProfilerData(string $file, string $catg = 'null') : string
|
||||||
{
|
{
|
||||||
$result = '';
|
$result = '';
|
||||||
if ($this->_get['callback'])
|
if ($this->_get['callback'])
|
||||||
|
|||||||
80
includes/ajaxHandler/edit.class.php
Normal file
80
includes/ajaxHandler/edit.class.php
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
class AjaxEdit extends AjaxHandler
|
||||||
|
{
|
||||||
|
protected $_get = array(
|
||||||
|
'qqfile' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
|
'guide' => ['filter' => FILTER_SANITIZE_NUMBER_INT]
|
||||||
|
);
|
||||||
|
|
||||||
|
public function __construct(array $params)
|
||||||
|
{
|
||||||
|
parent::__construct($params);
|
||||||
|
|
||||||
|
if (!$params)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ($params[0] == 'image')
|
||||||
|
$this->handler = 'handleUpload';
|
||||||
|
else if ($params[0] == 'article') // has it's own editor page
|
||||||
|
$this->handler = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
success: bool
|
||||||
|
id: image enumerator
|
||||||
|
type: 3 ? png : jpg
|
||||||
|
name: old filename
|
||||||
|
error: errString
|
||||||
|
*/
|
||||||
|
protected function handleUpload() : string
|
||||||
|
{
|
||||||
|
if (!User::$id || $this->_get['guide'] != 1)
|
||||||
|
return Util::toJSON(['success' => false, 'error' => '']);
|
||||||
|
|
||||||
|
require_once('includes/libs/qqFileUploader.class.php');
|
||||||
|
|
||||||
|
$targetPath = 'static/uploads/guide/images/';
|
||||||
|
$tmpPath = 'static/uploads/temp/';
|
||||||
|
$tmpFile = User::$displayName.'-'.Type::GUIDE.'-0-'.Util::createHash(16);
|
||||||
|
|
||||||
|
$uploader = new qqFileUploader(['jpg', 'jpeg', 'png'], 10 * 1024 * 1024);
|
||||||
|
$result = $uploader->handleUpload($tmpPath, $tmpFile, true);
|
||||||
|
|
||||||
|
if (isset($result['success']))
|
||||||
|
{
|
||||||
|
$finfo = new finfo(FILEINFO_MIME);
|
||||||
|
$mime = $finfo->file($tmpPath.$result['newFilename']);
|
||||||
|
if (preg_match('/^image\/(png|jpe?g)/i', $mime, $m))
|
||||||
|
{
|
||||||
|
$i = 1; // image index
|
||||||
|
if ($files = scandir($targetPath, SCANDIR_SORT_DESCENDING))
|
||||||
|
if (rsort($files, SORT_NATURAL) && $files[0] != '.' && $files[0] != '..')
|
||||||
|
$i = explode('.', $files[0])[0] + 1;
|
||||||
|
|
||||||
|
$targetFile = $i . ($m[1] == 'png' ? '.png' : '.jpg');
|
||||||
|
|
||||||
|
// move to final location
|
||||||
|
if (!rename($tmpPath.$result['newFilename'], $targetPath.$targetFile))
|
||||||
|
return Util::toJSON(['error' => Lang::main('intError')]);
|
||||||
|
|
||||||
|
// send success
|
||||||
|
return Util::toJSON(array(
|
||||||
|
'success' => true,
|
||||||
|
'id' => $i,
|
||||||
|
'type' => $m[1] == 'png' ? 3 : 2,
|
||||||
|
'name' => $this->_get['qqfile']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Util::toJSON(['error' => Lang::screenshot('error', 'unkFormat')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Util::toJSON($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -35,6 +35,9 @@ class AjaxFilter extends AjaxHandler
|
|||||||
case 'achievements':
|
case 'achievements':
|
||||||
$this->filter = (new AchievementListFilter(true, $opts));
|
$this->filter = (new AchievementListFilter(true, $opts));
|
||||||
break;
|
break;
|
||||||
|
case 'areatriggers':
|
||||||
|
$this->filter = (new AreaTriggerListFilter(true, $opts));
|
||||||
|
break;
|
||||||
case 'enchantments':
|
case 'enchantments':
|
||||||
$this->filter = (new EnchantmentListFilter(true, $opts));
|
$this->filter = (new EnchantmentListFilter(true, $opts));
|
||||||
break;
|
break;
|
||||||
@@ -81,7 +84,7 @@ class AjaxFilter extends AjaxHandler
|
|||||||
$this->handler = 'handleFilter';
|
$this->handler = 'handleFilter';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleFilter()
|
protected function handleFilter() : string
|
||||||
{
|
{
|
||||||
$url = '?'.$this->page;
|
$url = '?'.$this->page;
|
||||||
|
|
||||||
@@ -103,5 +106,6 @@ class AjaxFilter extends AjaxHandler
|
|||||||
// do get request
|
// do get request
|
||||||
return $url;
|
return $url;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
?>
|
||||||
|
|||||||
35
includes/ajaxHandler/getdescription.class.php
Normal file
35
includes/ajaxHandler/getdescription.class.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
class AjaxGetdescription extends AjaxHandler
|
||||||
|
{
|
||||||
|
protected $_post = array(
|
||||||
|
'description' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkFulltext']]
|
||||||
|
);
|
||||||
|
|
||||||
|
public function __construct(array $params)
|
||||||
|
{
|
||||||
|
parent::__construct($params);
|
||||||
|
|
||||||
|
if (!$params || $params[0]) // should be empty
|
||||||
|
return;
|
||||||
|
|
||||||
|
$this->handler = 'handleDescription';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function handleDescription() : string
|
||||||
|
{
|
||||||
|
$this->contentType = MIME_TYPE_TEXT;
|
||||||
|
|
||||||
|
if (!User::$id)
|
||||||
|
return '';
|
||||||
|
|
||||||
|
$desc = (new Markup($this->_post['description']))->stripTags();
|
||||||
|
|
||||||
|
return Lang::trimTextClean($desc, 120);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
class AjaxGotocomment extends AjaxHandler
|
class AjaxGotocomment extends AjaxHandler
|
||||||
{
|
{
|
||||||
protected $_get = array(
|
protected $_get = array(
|
||||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']]
|
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt']
|
||||||
);
|
);
|
||||||
|
|
||||||
public function __construct(array $params)
|
public function __construct(array $params)
|
||||||
@@ -21,16 +21,18 @@ class AjaxGotocomment extends AjaxHandler
|
|||||||
/* responses
|
/* responses
|
||||||
header()
|
header()
|
||||||
*/
|
*/
|
||||||
protected function handleGoToComment()
|
protected function handleGoToComment() : string
|
||||||
{
|
{
|
||||||
if (!$this->_get['id'])
|
if (!$this->_get['id'])
|
||||||
exit; // just be blank
|
return '.'; // go home
|
||||||
|
|
||||||
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']))
|
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);
|
return '?'.Type::getFileString(intVal($_['type'])).'='.$_['typeId'].'#comments:id='.$_['id'].($_['id'] != $this->_get['id'] ? ':reply='.$this->_get['id'] : null);
|
||||||
else
|
else
|
||||||
exit;
|
trigger_error('AjaxGotocomment::handleGoToComment - could not find comment #'.$this->get['id'], E_USER_ERROR);
|
||||||
|
|
||||||
|
return '.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
61
includes/ajaxHandler/guide.class.php
Normal file
61
includes/ajaxHandler/guide.class.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
class AjaxGuide extends AjaxHandler
|
||||||
|
{
|
||||||
|
protected $_post = array(
|
||||||
|
'id' => [FILTER_SANITIZE_NUMBER_INT, null],
|
||||||
|
'rating' => [FILTER_SANITIZE_NUMBER_INT, null]
|
||||||
|
);
|
||||||
|
|
||||||
|
public function __construct(array $params)
|
||||||
|
{
|
||||||
|
parent::__construct($params);
|
||||||
|
|
||||||
|
if (!$this->params || count($this->params) != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
$this->contentType = MIME_TYPE_TEXT;
|
||||||
|
|
||||||
|
// select handler
|
||||||
|
if ($this->params[0] == 'vote')
|
||||||
|
$this->handler = 'voteGuide';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function voteGuide() : string
|
||||||
|
{
|
||||||
|
if (!$this->_post['id'] || $this->_post['rating'] < 0 || $this->_post['rating'] > 5)
|
||||||
|
{
|
||||||
|
header('HTTP/1.0 404 Not Found', true, 404);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
else if (!User::canUpvote() || !User::canDownvote()) // same logic as comments?
|
||||||
|
{
|
||||||
|
header('HTTP/1.0 403 Forbidden', true, 403);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
// by id, not own, published
|
||||||
|
if ($g = DB::Aowow()->selectRow('SELECT `userId`, `cuFlags` FROM ?_guides WHERE `id` = ?d AND (`status` = ?d OR `rev` > 0)', $this->_post['id'], GUIDE_STATUS_APPROVED))
|
||||||
|
{
|
||||||
|
if ($g['cuFlags'] & GUIDE_CU_NO_RATING || $g['userId'] == User::$id)
|
||||||
|
{
|
||||||
|
header('HTTP/1.0 403 Forbidden', true, 403);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->_post['rating'])
|
||||||
|
DB::Aowow()->query('DELETE FROM ?_user_ratings WHERE `type` = ?d AND `entry` = ?d AND `userId` = ?d', RATING_GUIDE, $this->_post['id'], User::$id);
|
||||||
|
else
|
||||||
|
DB::Aowow()->query('REPLACE INTO ?_user_ratings VALUES (?d, ?d, ?d, ?d)', RATING_GUIDE, $this->_post['id'], User::$id, $this->_post['rating']);
|
||||||
|
|
||||||
|
$res = DB::Aowow()->selectRow('SELECT IFNULL(SUM(`value`), 0) AS `t`, IFNULL(COUNT(*), 0) AS `n` FROM ?_user_ratings WHERE `type` = ?d AND `entry` = ?d', RATING_GUIDE, $this->_post['id']);
|
||||||
|
return Util::toJSON($res['n'] ? ['rating' => $res['t'] / $res['n'], 'nvotes' => $res['n']] : ['rating' => 0, 'nvotes' => 0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Util::toJSON(['rating' => 0, 'nvotes' => 0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -7,8 +7,8 @@ class AjaxGuild extends AjaxHandler
|
|||||||
{
|
{
|
||||||
protected $validParams = ['resync', 'status'];
|
protected $validParams = ['resync', 'status'];
|
||||||
protected $_get = array(
|
protected $_get = array(
|
||||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdList']],
|
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdList' ],
|
||||||
'profile' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkEmptySet']],
|
'profile' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkEmptySet'],
|
||||||
);
|
);
|
||||||
|
|
||||||
public function __construct(array $params)
|
public function __construct(array $params)
|
||||||
@@ -35,16 +35,16 @@ class AjaxGuild extends AjaxHandler
|
|||||||
profile: <empty> [optional, also get related chars]
|
profile: <empty> [optional, also get related chars]
|
||||||
return: 1
|
return: 1
|
||||||
*/
|
*/
|
||||||
protected function handleResync()
|
protected function handleResync() : string
|
||||||
{
|
{
|
||||||
if ($guilds = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_guild WHERE id IN (?a)', $this->_get['id']))
|
if ($guilds = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_guild WHERE id IN (?a)', $this->_get['id']))
|
||||||
foreach ($guilds as $g)
|
foreach ($guilds as $g)
|
||||||
Profiler::scheduleResync(TYPE_GUILD, $g['realm'], $g['realmGUID']);
|
Profiler::scheduleResync(Type::GUILD, $g['realm'], $g['realmGUID']);
|
||||||
|
|
||||||
if ($this->_get['profile'])
|
if ($this->_get['profile'])
|
||||||
if ($chars = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_profiles WHERE guild IN (?a)', $this->_get['id']))
|
if ($chars = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_profiles WHERE guild IN (?a)', $this->_get['id']))
|
||||||
foreach ($chars as $c)
|
foreach ($chars as $c)
|
||||||
Profiler::scheduleResync(TYPE_PROFILE, $c['realm'], $c['realmGUID']);
|
Profiler::scheduleResync(Type::PROFILE, $c['realm'], $c['realmGUID']);
|
||||||
|
|
||||||
return '1';
|
return '1';
|
||||||
}
|
}
|
||||||
@@ -72,9 +72,9 @@ class AjaxGuild extends AjaxHandler
|
|||||||
1: char does not exist
|
1: char does not exist
|
||||||
2: armory gone
|
2: armory gone
|
||||||
*/
|
*/
|
||||||
protected function handleStatus()
|
protected function handleStatus() : string
|
||||||
{
|
{
|
||||||
$response = Profiler::resyncStatus(TYPE_GUILD, $this->_get['id']);
|
$response = Profiler::resyncStatus(Type::GUILD, $this->_get['id']);
|
||||||
return Util::toJSON($response);
|
return Util::toJSON($response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
class AjaxLocale extends AjaxHandler
|
class AjaxLocale extends AjaxHandler
|
||||||
{
|
{
|
||||||
protected $_get = array(
|
protected $_get = array(
|
||||||
'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale']]
|
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale']
|
||||||
);
|
);
|
||||||
|
|
||||||
public function __construct(array $params)
|
public function __construct(array $params)
|
||||||
@@ -21,7 +21,7 @@ class AjaxLocale extends AjaxHandler
|
|||||||
/* responses
|
/* responses
|
||||||
header()
|
header()
|
||||||
*/
|
*/
|
||||||
protected function handleLocale()
|
protected function handleLocale() : string
|
||||||
{
|
{
|
||||||
User::setLocale($this->_get['locale']);
|
User::setLocale($this->_get['locale']);
|
||||||
User::save();
|
User::save();
|
||||||
|
|||||||
@@ -9,35 +9,36 @@ class AjaxProfile extends AjaxHandler
|
|||||||
|
|
||||||
protected $validParams = ['link', 'unlink', 'pin', 'unpin', 'public', 'private', 'avatar', 'resync', 'status', 'save', 'delete', 'purge', 'summary', 'load'];
|
protected $validParams = ['link', 'unlink', 'pin', 'unpin', 'public', 'private', 'avatar', 'resync', 'status', 'save', 'delete', 'purge', 'summary', 'load'];
|
||||||
protected $_get = array(
|
protected $_get = array(
|
||||||
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkIdList']],
|
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdList' ],
|
||||||
'items' => [FILTER_CALLBACK, ['options' => 'AjaxProfile::checkItemList']],
|
'items' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxProfile::checkItemList'],
|
||||||
'size' => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
|
'size' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ],
|
||||||
'guild' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkEmptySet']],
|
'guild' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkEmptySet'],
|
||||||
'arena-team' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkEmptySet']],
|
'arena-team' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkEmptySet'],
|
||||||
|
'user' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxProfile::checkUser' ]
|
||||||
);
|
);
|
||||||
|
|
||||||
protected $_post = array(
|
protected $_post = array(
|
||||||
'name' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkFulltext']],
|
'name' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext'],
|
||||||
'level' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'level' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'class' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'class' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'race' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'race' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'gender' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'gender' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'nomodel' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'nomodel' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'talenttree1' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'talenttree1' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'talenttree2' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'talenttree2' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'talenttree3' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'talenttree3' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'activespec' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'activespec' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'talentbuild1' => [FILTER_SANITIZE_STRING, 0xC],// FILTER_FLAG_STRIP_LOW | *_HIGH
|
'talentbuild1' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
'glyphs1' => [FILTER_SANITIZE_STRING, 0xC],
|
'glyphs1' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
'talentbuild2' => [FILTER_SANITIZE_STRING, 0xC],
|
'talentbuild2' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
'glyphs2' => [FILTER_SANITIZE_STRING, 0xC],
|
'glyphs2' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
'icon' => [FILTER_SANITIZE_STRING, 0xC],
|
'icon' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
'description' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkFulltext']],
|
'description' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext'],
|
||||||
'source' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'source' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'copy' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'copy' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'public' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'public' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'gearscore' => [FILTER_SANITIZE_NUMBER_INT, null],
|
'gearscore' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||||
'inv' => [FILTER_CALLBACK, ['options' => 'AjaxProfile::checkItemString', 'flags' => FILTER_REQUIRE_ARRAY]],
|
'inv' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdListUnsigned', 'flags' => FILTER_REQUIRE_ARRAY],
|
||||||
);
|
);
|
||||||
|
|
||||||
public function __construct(array $params)
|
public function __construct(array $params)
|
||||||
@@ -47,6 +48,9 @@ class AjaxProfile extends AjaxHandler
|
|||||||
if (!$this->params)
|
if (!$this->params)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!CFG_PROFILER_ENABLE)
|
||||||
|
return;
|
||||||
|
|
||||||
switch ($this->params[0])
|
switch ($this->params[0])
|
||||||
{
|
{
|
||||||
case 'unlink':
|
case 'unlink':
|
||||||
@@ -95,23 +99,39 @@ class AjaxProfile extends AjaxHandler
|
|||||||
user: <string> [optional]
|
user: <string> [optional]
|
||||||
return: null
|
return: null
|
||||||
*/
|
*/
|
||||||
protected function handleLink() // links char with account
|
protected function handleLink() : void // links char with account
|
||||||
{
|
{
|
||||||
if (!User::$id || empty($this->_get['id']))
|
if (!User::$id || empty($this->_get['id']))
|
||||||
|
{
|
||||||
|
trigger_error('AjaxProfile::handleLink - profileId empty or user not logged in', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$uid = User::$id;
|
$uid = User::$id;
|
||||||
if ($this->_get['user'] && User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
|
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'])
|
if (!($uid = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE user = ?', $this->_get['user'])))
|
||||||
return;
|
{
|
||||||
|
trigger_error('AjaxProfile::handleLink - user "'.$this->_get['user'].'" does not exist', E_USER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->undo)
|
if ($this->undo)
|
||||||
DB::Aowow()->query('DELETE FROM ?_account_profiles WHERE accountId = ?d AND profileId IN (?a)', $uid, $this->_get['id']);
|
DB::Aowow()->query('DELETE FROM ?_account_profiles WHERE accountId = ?d AND profileId IN (?a)', $uid, $this->_get['id']);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
foreach ($this->_get['id'] as $prId) // only link characters, not custom profiles
|
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))
|
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);
|
DB::Aowow()->query('INSERT IGNORE INTO ?_account_profiles VALUES (?d, ?d, 0)', $uid, $prId);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trigger_error('AjaxProfile::handleLink - profile #'.$prId.' is custom or does not exist', E_USER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* params
|
/* params
|
||||||
@@ -119,20 +139,27 @@ class AjaxProfile extends AjaxHandler
|
|||||||
user: <string> [optional]
|
user: <string> [optional]
|
||||||
return: null
|
return: null
|
||||||
*/
|
*/
|
||||||
protected function handlePin() // (un)favorite
|
protected function handlePin() : void // (un)favorite
|
||||||
{
|
{
|
||||||
if (!User::$id || empty($this->_get['id'][0]))
|
if (!User::$id || empty($this->_get['id'][0]))
|
||||||
|
{
|
||||||
|
trigger_error('AjaxProfile::handlePin - profileId empty or user not logged in', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$uid = User::$id;
|
$uid = User::$id;
|
||||||
if ($this->_get['user'] && User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
|
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'])
|
if (!($uid = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE user = ?', $this->_get['user'])))
|
||||||
return;
|
{
|
||||||
|
trigger_error('AjaxProfile::handlePin - user "'.$this->_get['user'].'" does not exist', E_USER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// since only one character can be pinned at a time we can reset everything
|
// 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);
|
DB::Aowow()->query('UPDATE ?_account_profiles SET extraFlags = extraFlags & ?d WHERE accountId = ?d', ~PROFILER_CU_PINNED, $uid);
|
||||||
// and set a single char if nesecary
|
// and set a single char if necessary
|
||||||
if (!$this->undo)
|
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);
|
DB::Aowow()->query('UPDATE ?_account_profiles SET extraFlags = extraFlags | ?d WHERE profileId = ?d AND accountId = ?d', PROFILER_CU_PINNED, $this->_get['id'][0], $uid);
|
||||||
}
|
}
|
||||||
@@ -142,16 +169,23 @@ class AjaxProfile extends AjaxHandler
|
|||||||
user: <string> [optional]
|
user: <string> [optional]
|
||||||
return: null
|
return: null
|
||||||
*/
|
*/
|
||||||
protected function handlePrivacy() // public visibility
|
protected function handlePrivacy() : void // public visibility
|
||||||
{
|
{
|
||||||
if (!User::$id || empty($this->_get['id'][0]))
|
if (!User::$id || empty($this->_get['id'][0]))
|
||||||
|
{
|
||||||
|
trigger_error('AjaxProfile::handlePrivacy - profileId empty or user not logged in', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$uid = User::$id;
|
$uid = User::$id;
|
||||||
if ($this->_get['user'] && User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
|
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'])
|
if (!($uid = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE user = ?', $this->_get['user'])))
|
||||||
return;
|
{
|
||||||
|
trigger_error('AjaxProfile::handlePrivacy - user "'.$this->_get['user'].'" does not exist', E_USER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->undo)
|
if ($this->undo)
|
||||||
{
|
{
|
||||||
@@ -170,7 +204,7 @@ class AjaxProfile extends AjaxHandler
|
|||||||
size: <string> [optional]
|
size: <string> [optional]
|
||||||
return: image-header
|
return: image-header
|
||||||
*/
|
*/
|
||||||
protected function handleAvatar() // image
|
protected function handleAvatar() : void // image
|
||||||
{
|
{
|
||||||
// something happened in the last years: those textures do not include tiny icons
|
// something happened in the last years: those textures do not include tiny icons
|
||||||
$sizes = [/* 'tiny' => 15, */'small' => 18, 'medium' => 36, 'large' => 56];
|
$sizes = [/* 'tiny' => 15, */'small' => 18, 'medium' => 36, 'large' => 56];
|
||||||
@@ -178,9 +212,12 @@ class AjaxProfile extends AjaxHandler
|
|||||||
$s = $this->_get['size'] ?: 'medium';
|
$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)))
|
if (!$this->_get['id'] || !preg_match('/^([0-9]+)\.(jpg|gif)$/', $this->_get['id'][0], $matches) || !in_array($s, array_keys($sizes)))
|
||||||
|
{
|
||||||
|
trigger_error('AjaxProfile::handleAvatar - malformed request received', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$this->contentType = 'image/'.$matches[2];
|
$this->contentType = $matches[2] == 'png' ? MIME_TYPE_PNG : MIME_TYPE_JPEG;
|
||||||
|
|
||||||
$id = $matches[1];
|
$id = $matches[1];
|
||||||
$dest = imageCreateTruecolor($sizes[$s], $sizes[$s]);
|
$dest = imageCreateTruecolor($sizes[$s], $sizes[$s]);
|
||||||
@@ -202,13 +239,13 @@ class AjaxProfile extends AjaxHandler
|
|||||||
$src = imageCreateFromJpeg(printf($aPath, $id));
|
$src = imageCreateFromJpeg(printf($aPath, $id));
|
||||||
imagecopymerge($dest, $src, 0, 0, $offsetX, $offsetY, $sizes[$s], $sizes[$s], 100);
|
imagecopymerge($dest, $src, 0, 0, $offsetX, $offsetY, $sizes[$s], $sizes[$s], 100);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
trigger_error('AjaxProfile::handleAvatar - avatar file #'.$id.' not found', E_USER_ERROR);
|
||||||
|
|
||||||
if ($matches[2] == 'gif')
|
if ($matches[2] == 'gif')
|
||||||
imageGif($dest);
|
imageGif($dest);
|
||||||
else
|
else
|
||||||
imageJpeg($dest);
|
imageJpeg($dest);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* params
|
/* params
|
||||||
@@ -216,11 +253,15 @@ class AjaxProfile extends AjaxHandler
|
|||||||
user: <string> [optional, not used]
|
user: <string> [optional, not used]
|
||||||
return: 1
|
return: 1
|
||||||
*/
|
*/
|
||||||
protected function handleResync()
|
protected function handleResync() : string
|
||||||
{
|
{
|
||||||
if ($chars = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_profiles WHERE id IN (?a)', $this->_get['id']))
|
if ($chars = DB::Aowow()->select('SELECT realm, realmGUID FROM ?_profiler_profiles WHERE id IN (?a)', $this->_get['id']))
|
||||||
|
{
|
||||||
foreach ($chars as $c)
|
foreach ($chars as $c)
|
||||||
Profiler::scheduleResync(TYPE_PROFILE, $c['realm'], $c['realmGUID']);
|
Profiler::scheduleResync(Type::PROFILE, $c['realm'], $c['realmGUID']);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
trigger_error('AjaxProfile::handleResync - profiles '.implode(', ', $this->_get['id']).' not found in db', E_USER_ERROR);
|
||||||
|
|
||||||
return '1';
|
return '1';
|
||||||
}
|
}
|
||||||
@@ -248,7 +289,7 @@ class AjaxProfile extends AjaxHandler
|
|||||||
1: char does not exist
|
1: char does not exist
|
||||||
2: armory gone
|
2: armory gone
|
||||||
*/
|
*/
|
||||||
protected function handleStatus()
|
protected function handleStatus() : string
|
||||||
{
|
{
|
||||||
// roster resync for this guild was requested -> get char list
|
// roster resync for this guild was requested -> get char list
|
||||||
if ($this->_get['guild'])
|
if ($this->_get['guild'])
|
||||||
@@ -258,7 +299,13 @@ class AjaxProfile extends AjaxHandler
|
|||||||
else
|
else
|
||||||
$ids = $this->_get['id'];
|
$ids = $this->_get['id'];
|
||||||
|
|
||||||
$response = Profiler::resyncStatus(TYPE_PROFILE, $ids);
|
if (!$ids)
|
||||||
|
{
|
||||||
|
trigger_error('AjaxProfile::handleStatus - no profileIds to resync'.($this->_get['guild'] ? ' for guild #'.$this->_get['guild'] : ($this->_get['arena-team'] ? ' for areana team #'.$this->_get['arena-team'] : '')), E_USER_ERROR);
|
||||||
|
return Util::toJSON([1, [PR_QUEUE_STATUS_ERROR, 0, 0, PR_QUEUE_ERROR_CHAR]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = Profiler::resyncStatus(Type::PROFILE, $ids);
|
||||||
return Util::toJSON($response);
|
return Util::toJSON($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,12 +317,12 @@ class AjaxProfile extends AjaxHandler
|
|||||||
proileId [onSuccess]
|
proileId [onSuccess]
|
||||||
-1 [onError]
|
-1 [onError]
|
||||||
*/
|
*/
|
||||||
protected function handleSave() // unKill a profile
|
protected function handleSave() : string // unKill a profile
|
||||||
{
|
{
|
||||||
// todo (med): detail check this post-data
|
// todo (med): detail check this post-data
|
||||||
$cuProfile = array(
|
$cuProfile = array(
|
||||||
'user' => User::$id,
|
'user' => User::$id,
|
||||||
// 'userName' => User::$displayName,
|
// 'userName' => User::$displayName,
|
||||||
'name' => $this->_post['name'],
|
'name' => $this->_post['name'],
|
||||||
'level' => $this->_post['level'],
|
'level' => $this->_post['level'],
|
||||||
'class' => $this->_post['class'],
|
'class' => $this->_post['class'],
|
||||||
@@ -324,7 +371,7 @@ class AjaxProfile extends AjaxHandler
|
|||||||
}
|
}
|
||||||
else // new
|
else // new
|
||||||
{
|
{
|
||||||
$nProfiles = DB::Aowow()->selectCell('SELECT COUNT(*) FROM ?_profiler_profiles WHERE user = ?d AND realmGUID IS NULL', User::$id);
|
$nProfiles = DB::Aowow()->selectCell('SELECT COUNT(*) FROM ?_profiler_profiles WHERE user = ?d AND (cuFlags & ?d) = 0 AND realmGUID IS NULL', User::$id, PROFILER_CU_DELETED);
|
||||||
if ($nProfiles < 10 || User::isPremium())
|
if ($nProfiles < 10 || User::isPremium())
|
||||||
if ($newId = DB::Aowow()->query('INSERT INTO ?_profiler_profiles (?#) VALUES (?a)', array_keys($cuProfile), array_values($cuProfile)))
|
if ($newId = DB::Aowow()->query('INSERT INTO ?_profiler_profiles (?#) VALUES (?a)', array_keys($cuProfile), array_values($cuProfile)))
|
||||||
$charId = $newId;
|
$charId = $newId;
|
||||||
@@ -393,7 +440,7 @@ class AjaxProfile extends AjaxHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $charId;
|
return (string)$charId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* params
|
/* params
|
||||||
@@ -401,10 +448,13 @@ class AjaxProfile extends AjaxHandler
|
|||||||
return
|
return
|
||||||
null
|
null
|
||||||
*/
|
*/
|
||||||
protected function handleDelete() // kill a profile
|
protected function handleDelete() : void // kill a profile
|
||||||
{
|
{
|
||||||
if (!$this->_get['id'])
|
if (!User::$id || !$this->_get['id'])
|
||||||
|
{
|
||||||
|
trigger_error('AjaxProfile::handleDelete - profileId empty or user not logged in', E_USER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// only flag as deleted; only custom profiles
|
// only flag as deleted; only custom profiles
|
||||||
DB::Aowow()->query(
|
DB::Aowow()->query(
|
||||||
@@ -423,24 +473,27 @@ class AjaxProfile extends AjaxHandler
|
|||||||
return
|
return
|
||||||
lots...
|
lots...
|
||||||
*/
|
*/
|
||||||
protected function handleLoad()
|
protected function handleLoad() : string
|
||||||
{
|
{
|
||||||
// titles, achievements, characterData, talents, pets
|
// titles, achievements, characterData, talents, pets
|
||||||
// and some onLoad-hook to .. load it registerProfile($data)
|
// and some onLoad-hook to .. load it registerProfile($data)
|
||||||
// everything else goes through data.php .. strangely enough
|
// everything else goes through data.php .. strangely enough
|
||||||
|
|
||||||
if (!$this->_get['id'])
|
if (!$this->_get['id'])
|
||||||
return;
|
{
|
||||||
|
trigger_error('AjaxProfile::handleLoad - profileId empty', E_USER_ERROR);
|
||||||
|
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]);
|
$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)
|
if (!$pBase)
|
||||||
{
|
{
|
||||||
trigger_error('Profiler::handleLoad() - called with invalid profileId #'.$this->_get['id'][0], E_USER_WARNING);
|
trigger_error('Profiler::handleLoad - called with invalid profileId #'.$this->_get['id'][0], E_USER_WARNING);
|
||||||
return;
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($pBase['cuFlags'] & PROFILER_CU_DELETED) && !User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
|
if (($pBase['cuFlags'] & PROFILER_CU_DELETED) && !User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
|
||||||
return;
|
return '';
|
||||||
|
|
||||||
|
|
||||||
$rData = [];
|
$rData = [];
|
||||||
@@ -508,7 +561,7 @@ class AjaxProfile extends AjaxHandler
|
|||||||
{
|
{
|
||||||
$profile['region'] = [$rData['region'], Lang::profiler('regions', $rData['region'])];
|
$profile['region'] = [$rData['region'], Lang::profiler('regions', $rData['region'])];
|
||||||
$profile['battlegroup'] = [Profiler::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP];
|
$profile['battlegroup'] = [Profiler::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP];
|
||||||
$profile['realm'] = [Profiler::urlize($rData['name']), $rData['name']];
|
$profile['realm'] = [Profiler::urlize($rData['name'], true), $rData['name']];
|
||||||
}
|
}
|
||||||
|
|
||||||
// bookmarks
|
// bookmarks
|
||||||
@@ -524,7 +577,7 @@ class AjaxProfile extends AjaxHandler
|
|||||||
$profile['pets'] = $pets;
|
$profile['pets'] = $pets;
|
||||||
|
|
||||||
// source for custom profiles; profileId => [name, ownerId, iconString(optional)]
|
// 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']))
|
if ($customs = DB::Aowow()->select('SELECT id AS ARRAY_KEY, name, user, icon FROM ?_profiler_profiles WHERE sourceId = ?d AND sourceId <> id {AND (cuFlags & ?d) = 0}', $pBase['id'], User::isInGroup(U_GROUP_STAFF) ? DBSIMPLE_SKIP : PROFILER_CU_DELETED))
|
||||||
{
|
{
|
||||||
foreach ($customs as $id => $cu)
|
foreach ($customs as $id => $cu)
|
||||||
{
|
{
|
||||||
@@ -550,28 +603,28 @@ class AjaxProfile extends AjaxHandler
|
|||||||
{
|
{
|
||||||
switch ($type)
|
switch ($type)
|
||||||
{
|
{
|
||||||
case TYPE_FACTION: // factionId => amount
|
case Type::FACTION: // factionId => amount
|
||||||
$profile['reputation'] = array_combine(array_keys($data), array_column($data, 'cur'));
|
$profile['reputation'] = array_combine(array_keys($data), array_column($data, 'cur'));
|
||||||
break;
|
break;
|
||||||
case TYPE_TITLE:
|
case Type::TITLE:
|
||||||
foreach ($data as &$d)
|
foreach ($data as &$d)
|
||||||
$d = 1;
|
$d = 1;
|
||||||
|
|
||||||
$profile['titles'] = $data;
|
$profile['titles'] = $data;
|
||||||
break;
|
break;
|
||||||
case TYPE_QUEST:
|
case Type::QUEST:
|
||||||
foreach ($data as &$d)
|
foreach ($data as &$d)
|
||||||
$d = 1;
|
$d = 1;
|
||||||
|
|
||||||
$profile['quests'] = $data;
|
$profile['quests'] = $data;
|
||||||
break;
|
break;
|
||||||
case TYPE_SPELL:
|
case Type::SPELL:
|
||||||
foreach ($data as &$d)
|
foreach ($data as &$d)
|
||||||
$d = 1;
|
$d = 1;
|
||||||
|
|
||||||
$profile['spells'] = $data;
|
$profile['spells'] = $data;
|
||||||
break;
|
break;
|
||||||
case TYPE_ACHIEVEMENT:
|
case Type::ACHIEVEMENT:
|
||||||
$achievements = array_filter($data, function ($x) { return $x['max'] === null; });
|
$achievements = array_filter($data, function ($x) { return $x['max'] === null; });
|
||||||
$statistics = array_filter($data, function ($x) { return $x['max'] !== null; });
|
$statistics = array_filter($data, function ($x) { return $x['max'] !== null; });
|
||||||
|
|
||||||
@@ -589,7 +642,7 @@ class AjaxProfile extends AjaxHandler
|
|||||||
$profile['statistics'] = array_combine(array_keys($statistics), array_column($statistics, 'max'));
|
$profile['statistics'] = array_combine(array_keys($statistics), array_column($statistics, 'max'));
|
||||||
$profile['activity'] = $activity;
|
$profile['activity'] = $activity;
|
||||||
break;
|
break;
|
||||||
case TYPE_SKILL:
|
case Type::SKILL:
|
||||||
foreach ($data as &$d)
|
foreach ($data as &$d)
|
||||||
$d = [$d['cur'], $d['max']];
|
$d = [$d['cur'], $d['max']];
|
||||||
|
|
||||||
@@ -691,26 +744,24 @@ class AjaxProfile extends AjaxHandler
|
|||||||
return
|
return
|
||||||
null
|
null
|
||||||
*/
|
*/
|
||||||
protected function handlePurge() { } // removes completion data (as uploaded by the wowhead client) Just fail silently if someone triggers this manually
|
protected function handlePurge() : void { } // removes completion data (as uploaded by the wowhead client) Just fail silently if someone triggers this manually
|
||||||
|
|
||||||
protected function checkItemList($val)
|
protected static function checkItemList($val) : array
|
||||||
{
|
{
|
||||||
// expecting item-list
|
// expecting item-list
|
||||||
if (preg_match('/\d+(:\d+)*/', $val))
|
if (preg_match('/\d+(:\d+)*/', $val))
|
||||||
return array_map('intval', explode(':', $val));
|
return array_map('intVal', explode(':', $val));
|
||||||
|
|
||||||
return null;
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkItemString($val)
|
protected static function checkUser(string $val) : string
|
||||||
{
|
{
|
||||||
// expecting item-list
|
if (User::isValidName($val))
|
||||||
if (preg_match('/\d+(,\d+)*/', $val))
|
return $val;
|
||||||
return array_map('intval', explode(',', $val));
|
|
||||||
|
|
||||||
return null;
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -10,13 +10,15 @@ abstract class BaseType
|
|||||||
public $error = true;
|
public $error = true;
|
||||||
|
|
||||||
protected $templates = [];
|
protected $templates = [];
|
||||||
protected $curTpl = []; // lets iterate!
|
protected $curTpl = [];
|
||||||
protected $matches = 0; // total matches unaffected by sqlLimit in config
|
protected $matches = 0; // total matches unaffected by sqlLimit in config
|
||||||
|
|
||||||
protected $dbNames = ['Aowow']; // multiple DBs in profiler
|
protected $dbNames = ['Aowow']; // multiple DBs in profiler
|
||||||
protected $queryBase = '';
|
protected $queryBase = '';
|
||||||
protected $queryOpts = [];
|
protected $queryOpts = [];
|
||||||
|
|
||||||
|
private $itrStack = [];
|
||||||
|
|
||||||
public static $contribute = CONTRIBUTE_ANY;
|
public static $contribute = CONTRIBUTE_ANY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -57,7 +59,6 @@ abstract class BaseType
|
|||||||
$where = [];
|
$where = [];
|
||||||
$linking = ' AND ';
|
$linking = ' AND ';
|
||||||
$limit = CFG_SQL_LIMIT_DEFAULT;
|
$limit = CFG_SQL_LIMIT_DEFAULT;
|
||||||
$className = get_class($this);
|
|
||||||
|
|
||||||
if (!$this->queryBase || $conditions === null)
|
if (!$this->queryBase || $conditions === null)
|
||||||
return;
|
return;
|
||||||
@@ -257,18 +258,18 @@ abstract class BaseType
|
|||||||
|
|
||||||
// execute query (finally)
|
// execute query (finally)
|
||||||
$mtch = 0;
|
$mtch = 0;
|
||||||
|
$rows = [];
|
||||||
// this is purely because of multiple realms per server
|
// this is purely because of multiple realms per server
|
||||||
foreach ($this->dbNames as $dbIdx => $n)
|
foreach ($this->dbNames as $dbIdx => $n)
|
||||||
{
|
{
|
||||||
$query = str_replace('DB_IDX', $dbIdx, $this->queryBase);
|
$query = str_replace('DB_IDX', $dbIdx, $this->queryBase);
|
||||||
|
if ($rows = DB::{$n}($dbIdx)->SelectPage($mtch, $query))
|
||||||
if ($rows = DB::{$n}($dbIdx)->SelectPage($mtch, $query))
|
|
||||||
{
|
{
|
||||||
$this->matches += $mtch;
|
$this->matches += $mtch;
|
||||||
foreach ($rows as $id => $row)
|
foreach ($rows as $id => $row)
|
||||||
{
|
{
|
||||||
if (isset($this->templates[$id]))
|
if (isset($this->templates[$id]))
|
||||||
trigger_error('guid for List already in use #'.$id, E_USER_WARNING);
|
trigger_error('GUID for List already in use #'.$id.'. Additional occurrence omitted!', E_USER_ERROR);
|
||||||
else
|
else
|
||||||
$this->templates[$id] = $row;
|
$this->templates[$id] = $row;
|
||||||
}
|
}
|
||||||
@@ -287,12 +288,12 @@ abstract class BaseType
|
|||||||
|
|
||||||
public function &iterate()
|
public function &iterate()
|
||||||
{
|
{
|
||||||
$oldIdx = $this->id;
|
$this->itrStack[] = $this->id;
|
||||||
|
|
||||||
// reset on __construct
|
// reset on __construct
|
||||||
$this->reset();
|
$this->reset();
|
||||||
|
|
||||||
while (list($id, $_) = each($this->templates))
|
foreach ($this->templates as $id => $__)
|
||||||
{
|
{
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
$this->curTpl = &$this->templates[$id]; // do not use $tpl from each(), as we want to be referenceable
|
$this->curTpl = &$this->templates[$id]; // do not use $tpl from each(), as we want to be referenceable
|
||||||
@@ -304,6 +305,7 @@ abstract class BaseType
|
|||||||
|
|
||||||
// fforward to old index
|
// fforward to old index
|
||||||
$this->reset();
|
$this->reset();
|
||||||
|
$oldIdx = array_pop($this->itrStack);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (key($this->templates) != $oldIdx)
|
if (key($this->templates) != $oldIdx)
|
||||||
@@ -311,6 +313,7 @@ abstract class BaseType
|
|||||||
|
|
||||||
$this->curTpl = current($this->templates);
|
$this->curTpl = current($this->templates);
|
||||||
$this->id = key($this->templates);
|
$this->id = key($this->templates);
|
||||||
|
next($this->templates);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while (next($this->templates));
|
while (next($this->templates));
|
||||||
@@ -328,6 +331,7 @@ abstract class BaseType
|
|||||||
{
|
{
|
||||||
if (isset($this->templates[$id]))
|
if (isset($this->templates[$id]))
|
||||||
{
|
{
|
||||||
|
unset($this->curTpl); // kill reference or strange stuff will happen
|
||||||
$this->curTpl = $this->templates[$id];
|
$this->curTpl = $this->templates[$id];
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
return $this->templates[$id];
|
return $this->templates[$id];
|
||||||
@@ -436,7 +440,7 @@ abstract class BaseType
|
|||||||
'q': cssQuality [Items]
|
'q': cssQuality [Items]
|
||||||
'z': zone [set when all happens in here]
|
'z': zone [set when all happens in here]
|
||||||
'p': PvP [pvpSourceId]
|
'p': PvP [pvpSourceId]
|
||||||
's': TYPE_TITLE: side; TYPE_SPELL: skillId (yeah, double use. Ain't life just grand)
|
's': Type::TITLE: side; Type::SPELL: skillId (yeah, double use. Ain't life just grand)
|
||||||
'c': category [Spells / Quests]
|
'c': category [Spells / Quests]
|
||||||
'c2': subCat [Quests]
|
'c2': subCat [Quests]
|
||||||
'icon': iconString
|
'icon': iconString
|
||||||
@@ -552,33 +556,41 @@ trait spawnHelper
|
|||||||
|
|
||||||
private function createShortSpawns() // [zoneId, floor, [[x1, y1], [x2, y2], ..]] as tooltip2 if enabled by <a rel="map" ...> or anchor #map (one area, one floor, one creature, no survivors)
|
private function createShortSpawns() // [zoneId, floor, [[x1, y1], [x2, y2], ..]] as tooltip2 if enabled by <a rel="map" ...> or anchor #map (one area, one floor, one creature, no survivors)
|
||||||
{
|
{
|
||||||
|
$this->spawnResult[SPAWNINFO_SHORT] = new StdClass;
|
||||||
|
|
||||||
// first get zone/floor with the most spawns
|
// first get zone/floor with the most spawns
|
||||||
if ($res = DB::Aowow()->selectRow('SELECT areaId, floor FROM ?_spawns WHERE type = ?d && typeId = ?d GROUP BY areaId, floor ORDER BY count(1) DESC LIMIT 1', self::$type, $this->id))
|
if ($res = DB::Aowow()->selectRow('SELECT areaId, floor FROM ?_spawns WHERE type = ?d AND typeId = ?d AND posX > 0 AND posY > 0 GROUP BY areaId, floor ORDER BY count(1) DESC LIMIT 1', self::$type, $this->id))
|
||||||
{
|
{
|
||||||
// get relevant spawn points
|
// get relevant spawn points
|
||||||
$points = DB::Aowow()->select('SELECT posX, posY FROM ?_spawns WHERE type = ?d && typeId = ?d && areaId = ?d && floor = ?d', self::$type, $this->id, $res['areaId'], $res['floor']);
|
$points = DB::Aowow()->select('SELECT posX, posY FROM ?_spawns WHERE type = ?d AND typeId = ?d AND areaId = ?d AND floor = ?d AND posX > 0 AND posY > 0', self::$type, $this->id, $res['areaId'], $res['floor']);
|
||||||
$spawns = [];
|
$spawns = [];
|
||||||
foreach ($points as $p)
|
foreach ($points as $p)
|
||||||
$spawns[] = [$p['posX'], $p['posY']];
|
$spawns[] = [$p['posX'], $p['posY']];
|
||||||
|
|
||||||
$this->spawnResult[SPAWNINFO_SHORT] = [$res['areaId'], $res['floor'], $spawns];
|
$this->spawnResult[SPAWNINFO_SHORT]->zone = $res['areaId'];
|
||||||
|
$this->spawnResult[SPAWNINFO_SHORT]->coords = [$res['floor'] => $spawns];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFullSpawns() // for display on map (objsct/npc detail page)
|
private function createFullSpawns() // for display on map (object/npc detail page)
|
||||||
{
|
{
|
||||||
$data = [];
|
$data = [];
|
||||||
$wpSum = [];
|
$wpSum = [];
|
||||||
$wpIdx = 0;
|
$wpIdx = 0;
|
||||||
$spawns = DB::Aowow()->select("SELECT * FROM ?_spawns WHERE type = ?d AND typeId = ?d", self::$type, $this->id);
|
$worldPos = [];
|
||||||
|
$spawns = DB::Aowow()->select("SELECT * FROM ?_spawns WHERE type = ?d AND typeId = ?d AND posX > 0 AND posY > 0", self::$type, $this->id);
|
||||||
|
|
||||||
if (!$spawns)
|
if (!$spawns)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (User::isInGroup(U_GROUP_MODERATOR))
|
||||||
|
$worldPos = Game::getWorldPosForGUID(self::$type, ...array_column($spawns, 'guid'));
|
||||||
|
|
||||||
foreach ($spawns as $s)
|
foreach ($spawns as $s)
|
||||||
{
|
{
|
||||||
// check, if we can attach waypoints to creature
|
// check, if we can attach waypoints to creature
|
||||||
// we will get a nice clusterfuck of dots if we do this for more GUIDs, than we have colors though
|
// we will get a nice clusterfuck of dots if we do this for more GUIDs, than we have colors though
|
||||||
if (count($spawns) < 6 && self::$type == TYPE_NPC)
|
if (count($spawns) < 6 && self::$type == Type::NPC)
|
||||||
{
|
{
|
||||||
if ($wPoints = DB::Aowow()->select('SELECT * FROM ?_creature_waypoints WHERE creatureOrPath = ?d AND floor = ?d', $s['pathId'] ? -$s['pathId'] : $this->id, $s['floor']))
|
if ($wPoints = DB::Aowow()->select('SELECT * FROM ?_creature_waypoints WHERE creatureOrPath = ?d AND floor = ?d', $s['pathId'] ? -$s['pathId'] : $this->id, $s['floor']))
|
||||||
{
|
{
|
||||||
@@ -633,7 +645,62 @@ trait spawnHelper
|
|||||||
$info[4] = Lang::game('mode').Lang::main('colon').implode(', ', $_);
|
$info[4] = Lang::game('mode').Lang::main('colon').implode(', ', $_);
|
||||||
}
|
}
|
||||||
|
|
||||||
$footer = '<span class="q2">Click to move to different floor</span>';
|
if (self::$type == Type::AREATRIGGER)
|
||||||
|
{
|
||||||
|
$o = Util::O2Deg($this->getField('orientation'));
|
||||||
|
$info[5] = 'Orientation'.Lang::main('colon').$o[0].'° ('.$o[1].')';
|
||||||
|
}
|
||||||
|
|
||||||
|
// guid < 0 are vehicle accessories. those are moved by moving the vehicle
|
||||||
|
if (User::isInGroup(U_GROUP_MODERATOR) && $worldPos && $s['guid'] > 0)
|
||||||
|
{
|
||||||
|
if ($points = Game::worldPosToZonePos($worldPos[$s['guid']]['mapId'], $worldPos[$s['guid']]['posX'], $worldPos[$s['guid']]['posY']))
|
||||||
|
{
|
||||||
|
$floors = [];
|
||||||
|
foreach ($points as $p)
|
||||||
|
{
|
||||||
|
if (isset(Game::$areaFloors[$p['areaId']]))
|
||||||
|
$floors[$p['areaId']][] = $p['floor'];
|
||||||
|
|
||||||
|
if (isset($menu[$p['areaId']]))
|
||||||
|
continue;
|
||||||
|
else if ($p['areaId'] == $s['areaId'])
|
||||||
|
$menu[$p['areaId']] = [$p['areaId'], '$g_zones['.$p['areaId'].']', '', null, ['class' => 'checked q0']];
|
||||||
|
else
|
||||||
|
$menu[$p['areaId']] = [$p['areaId'], '$g_zones['.$p['areaId'].']', '$spawnposfix.bind(null, '.self::$type.', '.$s['guid'].', '.$p['areaId'].', -1)', null, null];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($floors as $area => $f)
|
||||||
|
{
|
||||||
|
$menu[$area][2] = '';
|
||||||
|
$menu[$area][3] = [];
|
||||||
|
if ($menu[$area][4])
|
||||||
|
$menu[$area][4]['class'] = 'checked';
|
||||||
|
|
||||||
|
foreach ($f as $n)
|
||||||
|
{
|
||||||
|
$jsRef = $n;
|
||||||
|
if ($area != 4273) // Ulduar is weird maaaan.....
|
||||||
|
$jsRef--;
|
||||||
|
|
||||||
|
// todo: 3959 (BT) and 4075 (Sunwell) start at level 0 or something
|
||||||
|
|
||||||
|
if ($n == $s['floor'])
|
||||||
|
$menu[$area][3][] = [$jsRef, '$g_zone_areas['.$area.']['.$jsRef.']', '', null, ['class' => 'checked q0']];
|
||||||
|
else
|
||||||
|
$menu[$area][3][] = [$jsRef, '$g_zone_areas['.$area.']['.$jsRef.']', '$spawnposfix.bind(null, '.self::$type.', '.$s['guid'].', '.$area.', '.$n.')'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$menu = array_values($menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($menu)
|
||||||
|
{
|
||||||
|
$footer = '<br /><span class="q2">Click to move displayed spawn point</span>';
|
||||||
|
array_unshift($menu, [null, "Move to..."]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($info)
|
if ($info)
|
||||||
@@ -654,9 +721,22 @@ trait spawnHelper
|
|||||||
foreach ($areas as $f => &$floor)
|
foreach ($areas as $f => &$floor)
|
||||||
$floor['count'] = count($floor['coords']) - (!empty($wpSum[$a][$f]) ? $wpSum[$a][$f] : 0);
|
$floor['count'] = count($floor['coords']) - (!empty($wpSum[$a][$f]) ? $wpSum[$a][$f] : 0);
|
||||||
|
|
||||||
|
uasort($data, array($this, 'sortBySpawnCount'));
|
||||||
$this->spawnResult[SPAWNINFO_FULL] = $data;
|
$this->spawnResult[SPAWNINFO_FULL] = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function sortBySpawnCount($a, $b)
|
||||||
|
{
|
||||||
|
$aCount = current($a)['count'];
|
||||||
|
$bCount = current($b)['count'];
|
||||||
|
|
||||||
|
if ($aCount == $bCount) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($aCount < $bCount) ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
private function createZoneSpawns() // [zoneId1, zoneId2, ..] for locations-column in listview
|
private function createZoneSpawns() // [zoneId1, zoneId2, ..] for locations-column in listview
|
||||||
{
|
{
|
||||||
$res = DB::Aowow()->selectCol("SELECT typeId AS ARRAY_KEY, GROUP_CONCAT(DISTINCT areaId) FROM ?_spawns WHERE type = ?d AND typeId IN (?a) GROUP BY typeId", self::$type, $this->getfoundIDs());
|
$res = DB::Aowow()->selectCol("SELECT typeId AS ARRAY_KEY, GROUP_CONCAT(DISTINCT areaId) FROM ?_spawns WHERE type = ?d AND typeId IN (?a) GROUP BY typeId", self::$type, $this->getfoundIDs());
|
||||||
@@ -670,12 +750,12 @@ trait spawnHelper
|
|||||||
$this->spawnResult[SPAWNINFO_ZONES] = $res;
|
$this->spawnResult[SPAWNINFO_ZONES] = $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createQuestSpawns() // [zoneId => [floor => [[x1, y1], [x2, y2], ..]]]
|
private function createQuestSpawns() // [zoneId => [floor => [[x1, y1], [x2, y2], ..]]] mapper on quest detail page
|
||||||
{
|
{
|
||||||
if (self::$type == TYPE_SOUND)
|
if (self::$type == Type::SOUND)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$res = DB::Aowow()->select('SELECT areaId, floor, typeId, posX, posY FROM ?_spawns WHERE type = ?d && typeId IN (?a)', self::$type, $this->getFoundIDs());
|
$res = DB::Aowow()->select('SELECT areaId, floor, typeId, posX, posY FROM ?_spawns WHERE type = ?d AND typeId IN (?a) AND posX > 0 AND posY > 0', self::$type, $this->getFoundIDs());
|
||||||
$spawns = [];
|
$spawns = [];
|
||||||
foreach ($res as $data)
|
foreach ($res as $data)
|
||||||
{
|
{
|
||||||
@@ -705,13 +785,13 @@ trait spawnHelper
|
|||||||
public function getSpawns($mode)
|
public function getSpawns($mode)
|
||||||
{
|
{
|
||||||
// only Creatures, GOs and SoundEmitters can be spawned
|
// only Creatures, GOs and SoundEmitters can be spawned
|
||||||
if (!self::$type || !$this->getfoundIDs() || (self::$type != TYPE_NPC && self::$type != TYPE_OBJECT && self::$type != TYPE_SOUND))
|
if (!self::$type || !$this->getfoundIDs() || (self::$type != Type::NPC && self::$type != Type::OBJECT && self::$type != Type::SOUND && self::$type != Type::AREATRIGGER))
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
switch ($mode)
|
switch ($mode)
|
||||||
{
|
{
|
||||||
case SPAWNINFO_SHORT:
|
case SPAWNINFO_SHORT:
|
||||||
if (empty($this->spawnResult[SPAWNINFO_SHORT]))
|
if ($this->spawnResult[SPAWNINFO_SHORT] === null)
|
||||||
$this->createShortSpawns();
|
$this->createShortSpawns();
|
||||||
|
|
||||||
return $this->spawnResult[SPAWNINFO_SHORT];
|
return $this->spawnResult[SPAWNINFO_SHORT];
|
||||||
@@ -762,14 +842,6 @@ trait profilerHelper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
roight!
|
|
||||||
just noticed, that the filters on pages originally pointed to ?filter=<pageName>
|
|
||||||
wich probably checked for correctness of inputs and redirected the correct values as a get-request
|
|
||||||
..
|
|
||||||
well, as it is now, its working .. and you never change a running system ..
|
|
||||||
*/
|
|
||||||
|
|
||||||
abstract class Filter
|
abstract class Filter
|
||||||
{
|
{
|
||||||
private static $wCards = ['*' => '%', '?' => '_'];
|
private static $wCards = ['*' => '%', '?' => '_'];
|
||||||
@@ -920,7 +992,7 @@ abstract class Filter
|
|||||||
{
|
{
|
||||||
// doesn't need to set formData['form']; this happens in GET-step
|
// doesn't need to set formData['form']; this happens in GET-step
|
||||||
|
|
||||||
foreach ($this->inputFields as $inp => list($type, $valid, $asArray))
|
foreach ($this->inputFields as $inp => [$type, $valid, $asArray])
|
||||||
{
|
{
|
||||||
if (!isset($_POST[$inp]) || $_POST[$inp] === '')
|
if (!isset($_POST[$inp]) || $_POST[$inp] === '')
|
||||||
continue;
|
continue;
|
||||||
@@ -966,7 +1038,7 @@ abstract class Filter
|
|||||||
}
|
}
|
||||||
|
|
||||||
$cr = $crs = $crv = [];
|
$cr = $crs = $crv = [];
|
||||||
foreach ($this->inputFields as $inp => list($type, $valid, $asArray))
|
foreach ($this->inputFields as $inp => [$type, $valid, $asArray])
|
||||||
{
|
{
|
||||||
if (!isset($post[$inp]) || $post[$inp] === '')
|
if (!isset($post[$inp]) || $post[$inp] === '')
|
||||||
continue;
|
continue;
|
||||||
@@ -1131,7 +1203,7 @@ abstract class Filter
|
|||||||
else if (gettype($valid) == 'double')
|
else if (gettype($valid) == 'double')
|
||||||
$val = floatval($val);
|
$val = floatval($val);
|
||||||
else /* if (gettype($valid) == 'string') */
|
else /* if (gettype($valid) == 'string') */
|
||||||
$var = strval($val);
|
$val = strval($val);
|
||||||
|
|
||||||
if ($valid == $val)
|
if ($valid == $val)
|
||||||
return true;
|
return true;
|
||||||
@@ -1193,9 +1265,9 @@ abstract class Filter
|
|||||||
foreach ($parts as $p)
|
foreach ($parts as $p)
|
||||||
{
|
{
|
||||||
if ($p[0] == '-' && (mb_strlen($p) > 3 || $shortStr))
|
if ($p[0] == '-' && (mb_strlen($p) > 3 || $shortStr))
|
||||||
$sub[] = [$f, sprintf($exPH, mb_substr($p, 1)), '!'];
|
$sub[] = [$f, sprintf($exPH, str_replace('_', '\\_', mb_substr($p, 1))), '!'];
|
||||||
else if ($p[0] != '-' && (mb_strlen($p) > 2 || $shortStr))
|
else if ($p[0] != '-' && (mb_strlen($p) > 2 || $shortStr))
|
||||||
$sub[] = [$f, sprintf($exPH, $p)];
|
$sub[] = [$f, sprintf($exPH, str_replace('_', '\\_', $p))];
|
||||||
}
|
}
|
||||||
|
|
||||||
// single cnd?
|
// single cnd?
|
||||||
@@ -1274,12 +1346,17 @@ abstract class Filter
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function genericBooleanFlags($field, $value, $op)
|
private function genericBooleanFlags($field, $value, $op, $matchAny = false)
|
||||||
{
|
{
|
||||||
if ($this->int2Bool($op))
|
if (!$this->int2Bool($op))
|
||||||
return [[$field, $value, '&'], $op ? $value : 0];
|
return null;
|
||||||
|
|
||||||
return null;
|
if (!$op)
|
||||||
|
return [[$field, $value, '&'], 0];
|
||||||
|
else if ($matchAny)
|
||||||
|
return [[$field, $value, '&'], 0, '!'];
|
||||||
|
else
|
||||||
|
return [[$field, $value, '&'], $value];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function genericString($field, $value, $strFlags)
|
private function genericString($field, $value, $strFlags)
|
||||||
@@ -1317,19 +1394,16 @@ abstract class Filter
|
|||||||
|
|
||||||
protected function genericCriterion(&$cr)
|
protected function genericCriterion(&$cr)
|
||||||
{
|
{
|
||||||
$gen = $this->genericFilter[$cr[0]];
|
$gen = array_pad($this->genericFilter[$cr[0]], 4, null);
|
||||||
$result = null;
|
$result = null;
|
||||||
|
|
||||||
if(!isset($gen[2]))
|
|
||||||
$gen[2] = 0;
|
|
||||||
|
|
||||||
switch ($gen[0])
|
switch ($gen[0])
|
||||||
{
|
{
|
||||||
case FILTER_CR_NUMERIC:
|
case FILTER_CR_NUMERIC:
|
||||||
$result = $this->genericNumeric($gen[1], $cr[2], $cr[1], $gen[2]);
|
$result = $this->genericNumeric($gen[1], $cr[2], $cr[1], $gen[2]);
|
||||||
break;
|
break;
|
||||||
case FILTER_CR_FLAG:
|
case FILTER_CR_FLAG:
|
||||||
$result = $this->genericBooleanFlags($gen[1], $gen[2], $cr[1]);
|
$result = $this->genericBooleanFlags($gen[1], $gen[2], $cr[1], $gen[3]);
|
||||||
break;
|
break;
|
||||||
case FILTER_CR_STAFFFLAG:
|
case FILTER_CR_STAFFFLAG:
|
||||||
if (User::isInGroup(U_GROUP_EMPLOYEE) && $cr[1] >= 0)
|
if (User::isInGroup(U_GROUP_EMPLOYEE) && $cr[1] >= 0)
|
||||||
|
|||||||
@@ -18,18 +18,18 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class CommunityContent
|
class CommunityContent
|
||||||
{
|
{
|
||||||
private static $jsGlobals = [];
|
private static array $jsGlobals = [];
|
||||||
private static $subjCache = [];
|
private static array $subjCache = [];
|
||||||
|
|
||||||
private static $commentQuery = '
|
private static string $coQuery = '
|
||||||
SELECT
|
SELECT
|
||||||
c.*,
|
c.*,
|
||||||
a1.displayName AS user,
|
a1.displayName AS user,
|
||||||
a2.displayName AS editUser,
|
a2.displayName AS editUser,
|
||||||
a3.displayName AS deleteUser,
|
a3.displayName AS deleteUser,
|
||||||
a4.displayName AS responseUser,
|
a4.displayName AS responseUser,
|
||||||
IFNULL(SUM(cr.value), 0) AS rating,
|
IFNULL(SUM(ur.value), 0) AS rating,
|
||||||
SUM(IF(cr.userId > 0 AND cr.userId = ?d, cr.value, 0)) AS userRating,
|
SUM(IF(ur.userId > 0 AND ur.userId = ?d, ur.value, 0)) AS userRating,
|
||||||
SUM(IF( r.userId > 0 AND r.userId = ?d, 1, 0)) AS userReported
|
SUM(IF( r.userId > 0 AND r.userId = ?d, 1, 0)) AS userReported
|
||||||
FROM
|
FROM
|
||||||
?_comments c
|
?_comments c
|
||||||
@@ -42,7 +42,7 @@ class CommunityContent
|
|||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
?_account a4 ON c.responseUserId = a4.id
|
?_account a4 ON c.responseUserId = a4.id
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
?_comments_rates cr ON c.id = cr.commentId
|
?_user_ratings ur ON c.id = ur.entry AND ur.type = ?d
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
?_reports r ON r.subject = c.id AND r.mode = 1 AND r.reason = 19
|
?_reports r ON r.subject = c.id AND r.mode = 1 AND r.reason = 19
|
||||||
WHERE
|
WHERE
|
||||||
@@ -54,24 +54,41 @@ class CommunityContent
|
|||||||
rating ASC
|
rating ASC
|
||||||
';
|
';
|
||||||
|
|
||||||
private static $previewQuery = '
|
private static string $ssQuery = '
|
||||||
|
SELECT s.id AS ARRAY_KEY, 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 AND }{s.type = ? AND }{s.typeId = ? AND }s.status & ?d AND (s.status & ?d) = 0
|
||||||
|
{ORDER BY ?# DESC}
|
||||||
|
{LIMIT ?d}
|
||||||
|
';
|
||||||
|
|
||||||
|
private static string $viQuery = '
|
||||||
|
SELECT v.id AS ARRAY_KEY, 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 AND }{v.type = ? AND }{v.typeId = ? AND }v.status & ?d AND (v.status & ?d) = 0
|
||||||
|
{ORDER BY ?# DESC}
|
||||||
|
{LIMIT ?d}
|
||||||
|
';
|
||||||
|
|
||||||
|
private static string $previewQuery = '
|
||||||
SELECT
|
SELECT
|
||||||
c.id,
|
c.id,
|
||||||
c.body AS preview,
|
c.body AS preview,
|
||||||
c.date,
|
c.date,
|
||||||
c.replyTo AS commentid,
|
c.replyTo AS commentid,
|
||||||
UNIX_TIMESTAMP() - c.date AS elapsed,
|
|
||||||
IF(c.flags & ?d, 1, 0) AS deleted,
|
IF(c.flags & ?d, 1, 0) AS deleted,
|
||||||
IF(c.type <> 0, c.type, c2.type) AS type,
|
IF(c.type <> 0, c.type, c2.type) AS type,
|
||||||
IF(c.typeId <> 0, c.typeId, c2.typeId) AS typeId,
|
IF(c.typeId <> 0, c.typeId, c2.typeId) AS typeId,
|
||||||
IFNULL(SUM(cr.value), 0) AS rating,
|
IFNULL(SUM(ur.value), 0) AS rating,
|
||||||
a.displayName AS user
|
a.displayName AS user
|
||||||
FROM
|
FROM
|
||||||
?_comments c
|
?_comments c
|
||||||
JOIN
|
JOIN
|
||||||
?_account a ON c.userId = a.id
|
?_account a ON c.userId = a.id
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
?_comments_rates cr ON cr.commentId = c.id AND cr.userId <> 0
|
?_user_ratings ur ON ur.entry = c.id AND ur.userId <> 0 AND ur.`type` = 1
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
?_comments c2 ON c.replyTo = c2.id
|
?_comments c2 ON c.replyTo = c2.id
|
||||||
WHERE
|
WHERE
|
||||||
@@ -87,13 +104,13 @@ class CommunityContent
|
|||||||
?d
|
?d
|
||||||
';
|
';
|
||||||
|
|
||||||
private static function addSubject($type, $typeId)
|
private static function addSubject(int $type, int $typeId) : void
|
||||||
{
|
{
|
||||||
if (!isset(self::$subjCache[$type][$typeId]))
|
if (!isset(self::$subjCache[$type][$typeId]))
|
||||||
self::$subjCache[$type][$typeId] = 0;
|
self::$subjCache[$type][$typeId] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getSubjects()
|
private static function getSubjects() : void
|
||||||
{
|
{
|
||||||
foreach (self::$subjCache as $type => $ids)
|
foreach (self::$subjCache as $type => $ids)
|
||||||
{
|
{
|
||||||
@@ -101,39 +118,16 @@ class CommunityContent
|
|||||||
if (!$_)
|
if (!$_)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$cnd = [CFG_SQL_LIMIT_NONE, ['id', $_]];
|
$obj = Type::newList($type, [CFG_SQL_LIMIT_NONE, ['id', $_]]);
|
||||||
|
if (!$obj)
|
||||||
switch ($type)
|
continue;
|
||||||
{
|
|
||||||
case TYPE_NPC: $obj = new CreatureList($cnd); break;
|
|
||||||
case TYPE_OBJECT: $obj = new GameobjectList($cnd); break;
|
|
||||||
case TYPE_ITEM: $obj = new ItemList($cnd); break;
|
|
||||||
case TYPE_ITEMSET: $obj = new ItemsetList($cnd); break;
|
|
||||||
case TYPE_QUEST: $obj = new QuestList($cnd); break;
|
|
||||||
case TYPE_SPELL: $obj = new SpellList($cnd); break;
|
|
||||||
case TYPE_ZONE: $obj = new ZoneList($cnd); break;
|
|
||||||
case TYPE_FACTION: $obj = new FactionList($cnd); break;
|
|
||||||
case TYPE_PET: $obj = new PetList($cnd); break;
|
|
||||||
case TYPE_ACHIEVEMENT: $obj = new AchievementList($cnd); break;
|
|
||||||
case TYPE_TITLE: $obj = new TitleList($cnd); break;
|
|
||||||
case TYPE_WORLDEVENT: $obj = new WorldEventList($cnd); break;
|
|
||||||
case TYPE_CLASS: $obj = new CharClassList($cnd); break;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($obj->iterate() as $id => $__)
|
foreach ($obj->iterate() as $id => $__)
|
||||||
self::$subjCache[$type][$id] = $obj->getField('name', true);
|
self::$subjCache[$type][$id] = $obj->getField('name', true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getCommentPreviews($params = [], &$nFound = 0)
|
public static function getCommentPreviews(array $params = [], ?int &$nFound = 0, bool $dateFmt = true) : array
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
purged:0, <- doesnt seem to be used anymore
|
purged:0, <- doesnt seem to be used anymore
|
||||||
@@ -166,31 +160,14 @@ class CommunityContent
|
|||||||
$c['subject'] = self::$subjCache[$c['type']][$c['typeId']];
|
$c['subject'] = self::$subjCache[$c['type']][$c['typeId']];
|
||||||
|
|
||||||
// format date
|
// format date
|
||||||
$c['date'] = date(Util::$dateFormatInternal, $c['date']);
|
$c['date'] = $dateFmt ? date(Util::$dateFormatInternal, $c['date']) : intVal($c['date']);
|
||||||
|
|
||||||
// remove commentid if not looking for replies
|
// remove commentid if not looking for replies
|
||||||
if (empty($params['replies']))
|
if (empty($params['replies']))
|
||||||
unset($c['commentid']);
|
unset($c['commentid']);
|
||||||
|
|
||||||
// remove line breaks
|
// format text for listview
|
||||||
$c['preview'] = strtr($c['preview'], ["\n" => ' ', "\r" => ' ']);
|
$c['preview'] = Lang::trimTextClean($c['preview']);
|
||||||
// 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 (mb_strlen($c['preview']) > 100)
|
|
||||||
{
|
|
||||||
$n = 0;
|
|
||||||
$b = [];
|
|
||||||
$parts = explode(' ', $c['preview']);
|
|
||||||
while ($n < 100 && $parts)
|
|
||||||
{
|
|
||||||
$_ = array_shift($parts);
|
|
||||||
$n += mb_strlen($_);
|
|
||||||
$b[] = $_;
|
|
||||||
}
|
|
||||||
|
|
||||||
$c['preview'] = implode(' ', $b).'…';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -202,13 +179,13 @@ class CommunityContent
|
|||||||
return $comments;
|
return $comments;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getCommentReplies($commentId, $limit = 0, &$nFound = 0)
|
public static function getCommentReplies(int $commentId, int $limit = 0, ?int &$nFound = 0) : array
|
||||||
{
|
{
|
||||||
$replies = [];
|
$replies = [];
|
||||||
$query = $limit > 0 ? self::$commentQuery.' LIMIT '.$limit : self::$commentQuery;
|
$query = $limit > 0 ? self::$coQuery.' LIMIT '.$limit : self::$coQuery;
|
||||||
|
|
||||||
// get replies
|
// get replies
|
||||||
$results = DB::Aowow()->selectPage($nFound, $query, User::$id, User::$id, $commentId, 0, 0, CC_FLAG_DELETED, User::$id, User::isInGroup(U_GROUP_COMMENTS_MODERATOR));
|
$results = DB::Aowow()->selectPage($nFound, $query, User::$id, User::$id, RATING_COMMENT, $commentId, 0, 0, CC_FLAG_DELETED, User::$id, User::isInGroup(U_GROUP_COMMENTS_MODERATOR));
|
||||||
foreach ($results as $r)
|
foreach ($results as $r)
|
||||||
{
|
{
|
||||||
(new Markup($r['body']))->parseGlobalsFromText(self::$jsGlobals);
|
(new Markup($r['body']))->parseGlobalsFromText(self::$jsGlobals);
|
||||||
@@ -323,8 +300,7 @@ class CommunityContent
|
|||||||
if ($pages)
|
if ($pages)
|
||||||
{
|
{
|
||||||
// limit to one actually existing type each
|
// limit to one actually existing type each
|
||||||
$types = array_intersect(array_unique(array_column($pages, 'type')), array_keys(Util::$typeClasses));
|
foreach (array_unique(array_column($pages, 'type')) as $t)
|
||||||
foreach ($types as $t)
|
|
||||||
{
|
{
|
||||||
$ids = [];
|
$ids = [];
|
||||||
foreach ($pages as $row)
|
foreach ($pages as $row)
|
||||||
@@ -334,11 +310,14 @@ class CommunityContent
|
|||||||
if (!$ids)
|
if (!$ids)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$tClass = new Util::$typeClasses[$t](array(['id', $ids], CFG_SQL_LIMIT_NONE));
|
$obj = Type::newList($t, [CFG_SQL_LIMIT_NONE, ['id', $ids]]);
|
||||||
|
if (!$obj || $obj->error)
|
||||||
|
continue;
|
||||||
|
|
||||||
foreach ($pages as &$p)
|
foreach ($pages as &$p)
|
||||||
if ($p['type'] == $t)
|
if ($p['type'] == $t)
|
||||||
if ($tClass->getEntry($p['typeId']))
|
if ($obj->getEntry($p['typeId']))
|
||||||
$p['name'] = $tClass->getField('name', true);
|
$p['name'] = $obj->getField('name', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($pages as &$p)
|
foreach ($pages as &$p)
|
||||||
@@ -359,10 +338,10 @@ class CommunityContent
|
|||||||
return $pages;
|
return $pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getComments($type, $typeId)
|
public static function getComments(int $type, int $typeId) : array
|
||||||
{
|
{
|
||||||
|
|
||||||
$results = DB::Aowow()->query(self::$commentQuery, User::$id, User::$id, 0, $type, $typeId, CC_FLAG_DELETED, User::$id, (int)User::isInGroup(U_GROUP_COMMENTS_MODERATOR));
|
$results = DB::Aowow()->query(self::$coQuery, User::$id, User::$id, RATING_COMMENT, 0, $type, $typeId, CC_FLAG_DELETED, User::$id, (int)User::isInGroup(U_GROUP_COMMENTS_MODERATOR));
|
||||||
$comments = [];
|
$comments = [];
|
||||||
|
|
||||||
// additional informations
|
// additional informations
|
||||||
@@ -371,7 +350,7 @@ class CommunityContent
|
|||||||
{
|
{
|
||||||
(new Markup($r['body']))->parseGlobalsFromText(self::$jsGlobals);
|
(new Markup($r['body']))->parseGlobalsFromText(self::$jsGlobals);
|
||||||
|
|
||||||
self::$jsGlobals[TYPE_USER][$r['userId']] = $r['userId'];
|
self::$jsGlobals[Type::USER][$r['userId']] = $r['userId'];
|
||||||
|
|
||||||
$c = array(
|
$c = array(
|
||||||
'commentv2' => 1, // always 1.. enables some features i guess..?
|
'commentv2' => 1, // always 1.. enables some features i guess..?
|
||||||
@@ -417,15 +396,9 @@ class CommunityContent
|
|||||||
return $comments;
|
return $comments;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getVideos($typeOrUser = 0, $typeId = 0, &$nFound = 0)
|
public static function getVideos(int $typeOrUser = 0, int $typeId = 0, int &$nFound = 0, bool $dateFmt = true) : array
|
||||||
{
|
{
|
||||||
$videos = DB::Aowow()->selectPage($nFound, "
|
$videos = DB::Aowow()->selectPage($nFound, self::$viQuery,
|
||||||
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 AND }{v.type = ? AND }{v.typeId = ? AND }v.status & ?d AND (v.status & ?d) = 0
|
|
||||||
{ORDER BY ?# DESC}
|
|
||||||
{LIMIT ?d}",
|
|
||||||
CC_FLAG_STICKY,
|
CC_FLAG_STICKY,
|
||||||
$typeOrUser < 0 ? -$typeOrUser : DBSIMPLE_SKIP,
|
$typeOrUser < 0 ? -$typeOrUser : DBSIMPLE_SKIP,
|
||||||
$typeOrUser > 0 ? $typeOrUser : DBSIMPLE_SKIP,
|
$typeOrUser > 0 ? $typeOrUser : DBSIMPLE_SKIP,
|
||||||
@@ -455,7 +428,7 @@ class CommunityContent
|
|||||||
$v['subject'] = Lang::user('removed');
|
$v['subject'] = Lang::user('removed');
|
||||||
}
|
}
|
||||||
|
|
||||||
$v['date'] = date(Util::$dateFormatInternal, $v['date']);
|
$v['date'] = $dateFmt ? date(Util::$dateFormatInternal, $v['date']) : intVal($v['date']);
|
||||||
$v['videoType'] = 1; // always youtube
|
$v['videoType'] = 1; // always youtube
|
||||||
|
|
||||||
if (!$v['sticky'])
|
if (!$v['sticky'])
|
||||||
@@ -468,15 +441,9 @@ class CommunityContent
|
|||||||
return $videos;
|
return $videos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getScreenshots($typeOrUser = 0, $typeId = 0, &$nFound = 0)
|
public static function getScreenshots(int $typeOrUser = 0, int $typeId = 0, int &$nFound = 0, bool $dateFmt = true) : array
|
||||||
{
|
{
|
||||||
$screenshots = DB::Aowow()->selectPage($nFound, "
|
$screenshots = DB::Aowow()->selectPage($nFound, self::$ssQuery,
|
||||||
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 AND }{s.type = ? AND }{s.typeId = ? AND }s.status & ?d AND (s.status & ?d) = 0
|
|
||||||
{ORDER BY ?# DESC}
|
|
||||||
{LIMIT ?d}",
|
|
||||||
CC_FLAG_STICKY,
|
CC_FLAG_STICKY,
|
||||||
$typeOrUser < 0 ? -$typeOrUser : DBSIMPLE_SKIP,
|
$typeOrUser < 0 ? -$typeOrUser : DBSIMPLE_SKIP,
|
||||||
$typeOrUser > 0 ? $typeOrUser : DBSIMPLE_SKIP,
|
$typeOrUser > 0 ? $typeOrUser : DBSIMPLE_SKIP,
|
||||||
@@ -506,7 +473,7 @@ class CommunityContent
|
|||||||
$s['subject'] = Lang::user('removed');
|
$s['subject'] = Lang::user('removed');
|
||||||
}
|
}
|
||||||
|
|
||||||
$s['date'] = date(Util::$dateFormatInternal, $s['date']);
|
$s['date'] = $dateFmt ? date(Util::$dateFormatInternal, $s['date']) : intVal($s['date']);
|
||||||
|
|
||||||
if (!$s['sticky'])
|
if (!$s['sticky'])
|
||||||
unset($s['sticky']);
|
unset($s['sticky']);
|
||||||
@@ -518,11 +485,11 @@ class CommunityContent
|
|||||||
return $screenshots;
|
return $screenshots;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getAll($type, $typeId, &$jsg)
|
public static function getAll(int $type, int $typeId, array &$jsg) : array
|
||||||
{
|
{
|
||||||
$result = array(
|
$result = array(
|
||||||
'vi' => self::getVideos($type, $typeId),
|
'vi' => self::getVideos($type, $typeId),
|
||||||
'sc' => self::getScreenshots($type, $typeId),
|
'ss' => self::getScreenshots($type, $typeId),
|
||||||
'co' => self::getComments($type, $typeId)
|
'co' => self::getComments($type, $typeId)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -530,5 +497,10 @@ class CommunityContent
|
|||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getJSGlobals() : array
|
||||||
|
{
|
||||||
|
return self::$jsGlobals;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ class DB
|
|||||||
private static $optionsCache = [];
|
private static $optionsCache = [];
|
||||||
private static $connectionCache = [];
|
private static $connectionCache = [];
|
||||||
|
|
||||||
|
private static $logs = [];
|
||||||
|
|
||||||
private static function createConnectSyntax(&$options)
|
private static function createConnectSyntax(&$options)
|
||||||
{
|
{
|
||||||
return 'mysqli://'.$options['user'].':'.$options['pass'].'@'.$options['host'].'/'.$options['db'];
|
return 'mysqli://'.$options['user'].':'.$options['pass'].'@'.$options['host'].'/'.$options['db'];
|
||||||
@@ -29,10 +31,10 @@ class DB
|
|||||||
$interface = DbSimple_Generic::connect(self::createConnectSyntax($options));
|
$interface = DbSimple_Generic::connect(self::createConnectSyntax($options));
|
||||||
|
|
||||||
if (!$interface || $interface->error)
|
if (!$interface || $interface->error)
|
||||||
die('Failed to connect to database.');
|
die('Failed to connect to database on index #'.$idx.".\n");
|
||||||
|
|
||||||
$interface->setErrorHandler(['DB', 'errorHandler']);
|
$interface->setErrorHandler(['DB', 'errorHandler']);
|
||||||
$interface->query('SET NAMES ?', 'utf8');
|
$interface->query('SET NAMES ?', 'utf8mb4');
|
||||||
if ($options['prefix'])
|
if ($options['prefix'])
|
||||||
$interface->setIdentPrefix($options['prefix']);
|
$interface->setIdentPrefix($options['prefix']);
|
||||||
|
|
||||||
@@ -47,6 +49,25 @@ class DB
|
|||||||
self::$connectionCache[$idx] = true;
|
self::$connectionCache[$idx] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function test(array $options, ?string &$err = '') : bool
|
||||||
|
{
|
||||||
|
$defPort = ini_get('mysqli.default_port');
|
||||||
|
$port = 0;
|
||||||
|
if (strstr($options['host'], ':'))
|
||||||
|
[$options['host'], $port] = explode(':', $options['host']);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$link = @mysqli_connect($options['host'], $options['user'], $options['pass'], $options['db'], $port ?: $defPort);
|
||||||
|
mysqli_close($link);
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
$err = '['.mysqli_connect_errno().'] '.mysqli_connect_error();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static function errorHandler($message, $data)
|
public static function errorHandler($message, $data)
|
||||||
{
|
{
|
||||||
if (!error_reporting())
|
if (!error_reporting())
|
||||||
@@ -58,6 +79,35 @@ class DB
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function logger($self, $query, $trace)
|
||||||
|
{
|
||||||
|
if ($trace) // actual query
|
||||||
|
self::$logs[] = [substr(str_replace("\n", ' ', $query), 0, 200)];
|
||||||
|
else // the statistics
|
||||||
|
{
|
||||||
|
end(self::$logs);
|
||||||
|
self::$logs[key(self::$logs)][] = substr(explode(';', $query)[0], 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getLogs()
|
||||||
|
{
|
||||||
|
$out = '<pre><table style="font-size:12;"><tr><th></th><th>Time</th><th>Query</th></tr>';
|
||||||
|
foreach (self::$logs as $i => [$l, $t])
|
||||||
|
{
|
||||||
|
$c = 'inherit';
|
||||||
|
preg_match('/(\d+)/', $t, $m);
|
||||||
|
if ($m[1] > 100)
|
||||||
|
$c = '#FFA0A0';
|
||||||
|
else if ($m[1] > 20)
|
||||||
|
$c = '#FFFFA0';
|
||||||
|
|
||||||
|
$out .= '<tr><td>'.$i.'.</td><td style="background-color:'.$c.';">'.$t.'</td><td>'.$l.'</td></tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return Util::jsEscape($out).'</table></pre>';
|
||||||
|
}
|
||||||
|
|
||||||
public static function getDB($idx)
|
public static function getDB($idx)
|
||||||
{
|
{
|
||||||
return self::$interfaceCache[$idx];
|
return self::$interfaceCache[$idx];
|
||||||
|
|||||||
@@ -7,35 +7,24 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
* Page
|
* Page
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('E_AOWOW', E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT));
|
define('E_AOWOW', E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT));
|
||||||
|
define('JSON_AOWOW_POWER', JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
define('FILTER_FLAG_STRIP_AOWOW', FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_BACKTICK);
|
||||||
|
|
||||||
// TypeIds
|
define('MIME_TYPE_TEXT', 'Content-Type: text/plain; charset=utf-8');
|
||||||
define('TYPE_NPC', 1);
|
define('MIME_TYPE_XML', 'Content-Type: text/xml; charset=utf-8');
|
||||||
define('TYPE_OBJECT', 2);
|
define('MIME_TYPE_JSON', 'Content-Type: application/x-javascript; charset=utf-8');
|
||||||
define('TYPE_ITEM', 3);
|
define('MIME_TYPE_RSS', 'Content-Type: application/rss+xml; charset=utf-8');
|
||||||
define('TYPE_ITEMSET', 4);
|
define('MIME_TYPE_JPEG', 'Content-Type: image/jpeg');
|
||||||
define('TYPE_QUEST', 5);
|
define('MIME_TYPE_PNG', 'Content-Type: image/png');
|
||||||
define('TYPE_SPELL', 6);
|
|
||||||
define('TYPE_ZONE', 7);
|
// shared setup strings
|
||||||
define('TYPE_FACTION', 8);
|
define('ERR_CREATE_FILE', 'could not create file at destination %s');
|
||||||
define('TYPE_PET', 9);
|
define('ERR_WRITE_FILE', 'could not write to file at destination %s');
|
||||||
define('TYPE_ACHIEVEMENT', 10);
|
define('ERR_READ_FILE', 'file %s could not be read');
|
||||||
define('TYPE_TITLE', 11);
|
define('ERR_MISSING_FILE', 'file %s not found');
|
||||||
define('TYPE_WORLDEVENT', 12);
|
define('ERR_NONE', 'created file %s');
|
||||||
define('TYPE_CLASS', 13);
|
define('ERR_MISSING_INCL', 'required function %s() could not be found at %s');
|
||||||
define('TYPE_RACE', 14);
|
|
||||||
define('TYPE_SKILL', 15);
|
|
||||||
define('TYPE_CURRENCY', 17);
|
|
||||||
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_NONE', 0); // page will not be cached
|
||||||
define('CACHE_TYPE_PAGE', 1);
|
define('CACHE_TYPE_PAGE', 1);
|
||||||
@@ -46,6 +35,11 @@ define('CACHE_TYPE_XML', 4); // only used by item
|
|||||||
define('CACHE_MODE_FILECACHE', 0x1);
|
define('CACHE_MODE_FILECACHE', 0x1);
|
||||||
define('CACHE_MODE_MEMCACHED', 0x2);
|
define('CACHE_MODE_MEMCACHED', 0x2);
|
||||||
|
|
||||||
|
define ('CSS_FILE', 1);
|
||||||
|
define ('CSS_STRING', 2);
|
||||||
|
define ('JS_FILE', 3);
|
||||||
|
define ('JS_STRING', 4);
|
||||||
|
|
||||||
define('SEARCH_TYPE_REGULAR', 0x10000000);
|
define('SEARCH_TYPE_REGULAR', 0x10000000);
|
||||||
define('SEARCH_TYPE_OPEN', 0x20000000);
|
define('SEARCH_TYPE_OPEN', 0x20000000);
|
||||||
define('SEARCH_TYPE_JSON', 0x40000000);
|
define('SEARCH_TYPE_JSON', 0x40000000);
|
||||||
@@ -72,7 +66,7 @@ define('ACC_BAN_COMMENT', 0x08); // cannot comment an
|
|||||||
define('ACC_BAN_UPLOAD', 0x10); // cannot upload avatar / signature files [originally: ban from data upload]
|
define('ACC_BAN_UPLOAD', 0x10); // cannot upload avatar / signature files [originally: ban from data upload]
|
||||||
define('ACC_BAN_SCREENSHOT', 0x20); // cannot upload screenshots
|
define('ACC_BAN_SCREENSHOT', 0x20); // cannot upload screenshots
|
||||||
define('ACC_BAN_VIDEO', 0x40); // cannot suggest videos
|
define('ACC_BAN_VIDEO', 0x40); // cannot suggest videos
|
||||||
// define('ACC_BAN_FORUM', 0x80); // cannot use forums [not used here]
|
define('ACC_BAN_GUIDE', 0x80); // cannot write a guide
|
||||||
|
|
||||||
// Site Reputation/Privileges
|
// Site Reputation/Privileges
|
||||||
define('SITEREP_ACTION_REGISTER', 1); // Registered account
|
define('SITEREP_ACTION_REGISTER', 1); // Registered account
|
||||||
@@ -155,6 +149,7 @@ define('U_GROUP_PREMIUM_PERMISSIONS', (U_GROUP_PREMIUM|U_GROUP_STAFF|U_GRO
|
|||||||
define('LOCALE_EN', 0);
|
define('LOCALE_EN', 0);
|
||||||
define('LOCALE_FR', 2);
|
define('LOCALE_FR', 2);
|
||||||
define('LOCALE_DE', 3);
|
define('LOCALE_DE', 3);
|
||||||
|
define('LOCALE_CN', 4);
|
||||||
define('LOCALE_ES', 6);
|
define('LOCALE_ES', 6);
|
||||||
define('LOCALE_RU', 8);
|
define('LOCALE_RU', 8);
|
||||||
|
|
||||||
@@ -169,6 +164,10 @@ define('BUTTON_TALENT', 6);
|
|||||||
define('BUTTON_EQUIP', 7);
|
define('BUTTON_EQUIP', 7);
|
||||||
define('BUTTON_PLAYLIST', 8);
|
define('BUTTON_PLAYLIST', 8);
|
||||||
define('BUTTON_RESYNC', 9);
|
define('BUTTON_RESYNC', 9);
|
||||||
|
define('BUTTON_GUIDE_REPORT', 10);
|
||||||
|
define('BUTTON_GUIDE_NEW', 11);
|
||||||
|
define('BUTTON_GUIDE_EDIT', 12);
|
||||||
|
define('BUTTON_GUIDE_LOG', 13);
|
||||||
|
|
||||||
// generic filter handler
|
// generic filter handler
|
||||||
define('FILTER_CR_BOOLEAN', 1);
|
define('FILTER_CR_BOOLEAN', 1);
|
||||||
@@ -212,6 +211,7 @@ define('PROFILEINFO_PROFILE', 0x1);
|
|||||||
define('PROFILEINFO_CHARACTER', 0x2);
|
define('PROFILEINFO_CHARACTER', 0x2);
|
||||||
define('PROFILEINFO_GUILD', 0x10); // like &roster
|
define('PROFILEINFO_GUILD', 0x10); // like &roster
|
||||||
define('PROFILEINFO_ARENA', 0x20);
|
define('PROFILEINFO_ARENA', 0x20);
|
||||||
|
define('PROFILEINFO_USER', 0x40);
|
||||||
|
|
||||||
define('SPAWNINFO_ZONES', 1); // not a mask, mutually exclusive
|
define('SPAWNINFO_ZONES', 1); // not a mask, mutually exclusive
|
||||||
define('SPAWNINFO_SHORT', 2);
|
define('SPAWNINFO_SHORT', 2);
|
||||||
@@ -244,6 +244,16 @@ define('STR_LOCALIZED', 0x1);
|
|||||||
define('STR_MATCH_EXACT', 0x2);
|
define('STR_MATCH_EXACT', 0x2);
|
||||||
define('STR_ALLOW_SHORT', 0x4);
|
define('STR_ALLOW_SHORT', 0x4);
|
||||||
|
|
||||||
|
define('RATING_COMMENT', 1);
|
||||||
|
define('RATING_GUIDE', 2);
|
||||||
|
|
||||||
|
define('GUIDE_STATUS_NONE', 0);
|
||||||
|
define('GUIDE_STATUS_DRAFT', 1);
|
||||||
|
define('GUIDE_STATUS_REVIEW', 2);
|
||||||
|
define('GUIDE_STATUS_APPROVED', 3);
|
||||||
|
define('GUIDE_STATUS_REJECTED', 4);
|
||||||
|
define('GUIDE_STATUS_ARCHIVED', 5);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Game
|
* Game
|
||||||
*/
|
*/
|
||||||
@@ -303,7 +313,12 @@ define('PROFILER_CU_DELETED', 0x04);
|
|||||||
define('PROFILER_CU_PROFILE', 0x08);
|
define('PROFILER_CU_PROFILE', 0x08);
|
||||||
define('PROFILER_CU_NEEDS_RESYNC', 0x10);
|
define('PROFILER_CU_NEEDS_RESYNC', 0x10);
|
||||||
|
|
||||||
|
define('GUIDE_CU_NO_QUICKFACTS', 0x100); // merge with CC_FLAG_*
|
||||||
|
define('GUIDE_CU_NO_RATING', 0x200);
|
||||||
|
|
||||||
define('MAX_LEVEL', 80);
|
define('MAX_LEVEL', 80);
|
||||||
|
define('MAX_SKILL', 450);
|
||||||
|
define('MAX_LOCALES', 16); // technical limitation, 6 in use here
|
||||||
define('WOW_BUILD', 12340);
|
define('WOW_BUILD', 12340);
|
||||||
|
|
||||||
// Loot handles
|
// Loot handles
|
||||||
@@ -460,6 +475,10 @@ define('TEAM_ALLIANCE', 0);
|
|||||||
define('TEAM_HORDE', 1);
|
define('TEAM_HORDE', 1);
|
||||||
define('TEAM_NEUTRAL', 2);
|
define('TEAM_NEUTRAL', 2);
|
||||||
|
|
||||||
|
// Lock Types
|
||||||
|
define('LOCK_TYPE_ITEM', 1);
|
||||||
|
define('LOCK_TYPE_SKILL', 2);
|
||||||
|
|
||||||
// Lock-Properties (also categorizes GOs)
|
// Lock-Properties (also categorizes GOs)
|
||||||
define('LOCK_PROPERTY_FOOTLOCKER', 1);
|
define('LOCK_PROPERTY_FOOTLOCKER', 1);
|
||||||
define('LOCK_PROPERTY_HERBALISM', 2);
|
define('LOCK_PROPERTY_HERBALISM', 2);
|
||||||
@@ -477,19 +496,115 @@ define('NPC_RANK_RARE_ELITE', 2);
|
|||||||
define('NPC_RANK_BOSS', 3);
|
define('NPC_RANK_BOSS', 3);
|
||||||
define('NPC_RANK_RARE', 4);
|
define('NPC_RANK_RARE', 4);
|
||||||
|
|
||||||
|
define('NPC_FLAG_GOSSIP', 0x00000001);
|
||||||
|
define('NPC_FLAG_QUEST_GIVER', 0x00000002);
|
||||||
define('NPC_FLAG_TRAINER', 0x00000010);
|
define('NPC_FLAG_TRAINER', 0x00000010);
|
||||||
define('NPC_FLAG_CLASS_TRAINER', 0x00000020);
|
define('NPC_FLAG_CLASS_TRAINER', 0x00000020);
|
||||||
|
define('NPC_PROFESSION_TRAINER', 0x00000040);
|
||||||
define('NPC_FLAG_VENDOR', 0x00000080);
|
define('NPC_FLAG_VENDOR', 0x00000080);
|
||||||
|
define('NPC_FLAG_VENDOR_AMMO', 0x00000100);
|
||||||
|
define('NPC_FLAG_VENDOR_FOOD', 0x00000200);
|
||||||
|
define('NPC_FLAG_VENDOR_POISON', 0x00000400);
|
||||||
|
define('NPC_FLAG_VENDOR_REAGENT', 0x00000800);
|
||||||
define('NPC_FLAG_REPAIRER', 0x00001000);
|
define('NPC_FLAG_REPAIRER', 0x00001000);
|
||||||
define('NPC_FLAG_FLIGHT_MASTER', 0x00002000);
|
define('NPC_FLAG_FLIGHT_MASTER', 0x00002000);
|
||||||
define('NPC_FLAG_SPIRIT_HEALER', 0x00004000); // civil
|
define('NPC_FLAG_SPIRIT_HEALER', 0x00004000); // civil
|
||||||
define('NPC_FLAG_SPIRIT_GUIDE', 0x00008000); // battleground
|
define('NPC_FLAG_SPIRIT_GUIDE', 0x00008000); // battleground
|
||||||
define('NPC_FLAG_INNKEEPER', 0x00010000);
|
define('NPC_FLAG_INNKEEPER', 0x00010000);
|
||||||
define('NPC_FLAG_BANKER', 0x00020000);
|
define('NPC_FLAG_BANKER', 0x00020000);
|
||||||
|
define('NPC_FLAG_PETITIONER', 0x00040000);
|
||||||
define('NPC_FLAG_GUILD_MASTER', 0x00080000);
|
define('NPC_FLAG_GUILD_MASTER', 0x00080000);
|
||||||
define('NPC_FLAG_BATTLEMASTER', 0x00100000);
|
define('NPC_FLAG_BATTLEMASTER', 0x00100000);
|
||||||
define('NPC_FLAG_AUCTIONEER', 0x00200000);
|
define('NPC_FLAG_AUCTIONEER', 0x00200000);
|
||||||
define('NPC_FLAG_STABLE_MASTER', 0x00400000);
|
define('NPC_FLAG_STABLE_MASTER', 0x00400000);
|
||||||
|
define('NPC_FLAG_GUILD_BANK', 0x00800000);
|
||||||
|
define('NPC_FLAG_SPELLCLICK', 0x01000000);
|
||||||
|
define('NPC_FLAG_MAILBOX', 0x04000000);
|
||||||
|
|
||||||
|
define('UNIT_FLAG_SERVER_CONTROLLED', 0x00000001); //
|
||||||
|
define('UNIT_FLAG_NON_ATTACKABLE', 0x00000002); //
|
||||||
|
define('UNIT_FLAG_REMOVE_CLIENT_CONTROL', 0x00000004); //
|
||||||
|
define('UNIT_FLAG_PVP_ATTACKABLE', 0x00000008); // Allows to apply PvP rules to attackable state in addition to faction dependent state
|
||||||
|
define('UNIT_FLAG_RENAME', 0x00000010); //
|
||||||
|
define('UNIT_FLAG_PREPARATION', 0x00000020); // Don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP
|
||||||
|
define('UNIT_FLAG_UNK_6', 0x00000040); // not sure what it does, but it is needed to cast nontriggered spells in smart_scripts
|
||||||
|
define('UNIT_FLAG_NOT_ATTACKABLE_1', 0x00000080); // UNIT_FLAG_PVP_ATTACKABLE| UNIT_FLAG_NOT_ATTACKABLE_1 is NON_PVP_ATTACKABLE
|
||||||
|
define('UNIT_FLAG_IMMUNE_TO_PC', 0x00000100); // disables combat/assistance with PlayerCharacters (PC)
|
||||||
|
define('UNIT_FLAG_IMMUNE_TO_NPC', 0x00000200); // disables combat/assistance with NonPlayerCharacters (NPC)
|
||||||
|
define('UNIT_FLAG_LOOTING', 0x00000400); // Loot animation
|
||||||
|
define('UNIT_FLAG_PET_IN_COMBAT', 0x00000800); // In combat? 2.0.8
|
||||||
|
define('UNIT_FLAG_PVP', 0x00001000); // Changed in 3.0.3
|
||||||
|
define('UNIT_FLAG_SILENCED', 0x00002000); // Can't cast spells
|
||||||
|
define('UNIT_FLAG_CANNOT_SWIM', 0x00004000); // 2.0.8
|
||||||
|
define('UNIT_FLAG_UNK_15', 0x00008000); // Only Swim ('OnlySwim' from UnitFlags.cs in WPP)
|
||||||
|
define('UNIT_FLAG_UNK_16', 0x00010000); // No Attack 2 ('NoAttack2' from UnitFlags.cs in WPP)
|
||||||
|
define('UNIT_FLAG_PACIFIED', 0x00020000); // Creature will not attack
|
||||||
|
define('UNIT_FLAG_STUNNED', 0x00040000); // 3.0.3 ok
|
||||||
|
define('UNIT_FLAG_IN_COMBAT', 0x00080000); // ('AffectingCombat' from UnitFlags.cs in WPP)
|
||||||
|
define('UNIT_FLAG_TAXI_FLIGHT', 0x00100000); // Disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag
|
||||||
|
define('UNIT_FLAG_DISARMED', 0x00200000); // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip.
|
||||||
|
define('UNIT_FLAG_CONFUSED', 0x00400000); // Confused.
|
||||||
|
define('UNIT_FLAG_FLEEING', 0x00800000); // ('Feared' from UnitFlags.cs in WPP)
|
||||||
|
define('UNIT_FLAG_PLAYER_CONTROLLED', 0x01000000); // Used in spell Eyes of the Beast for pet... let attack by controlled creature. Also used by Vehicles (PCV).
|
||||||
|
define('UNIT_FLAG_NOT_SELECTABLE', 0x02000000); // Can't be selected by mouse or with /target {name} command.
|
||||||
|
define('UNIT_FLAG_SKINNABLE', 0x04000000); // Skinnable
|
||||||
|
define('UNIT_FLAG_MOUNT', 0x08000000); // The client seems to handle it perfectly. Also used when making custom mounts.
|
||||||
|
define('UNIT_FLAG_UNK_28', 0x10000000); // (PreventKneelingWhenLooting from UnitFlags.cs in WPP)
|
||||||
|
define('UNIT_FLAG_UNK_29', 0x20000000); // Used in Feign Death spell or NPC will play dead. (PreventEmotes)
|
||||||
|
define('UNIT_FLAG_SHEATHE', 0x40000000); //
|
||||||
|
define('UNIT_FLAG_UNK_31', 0x80000000); //
|
||||||
|
|
||||||
|
define('UNIT_FLAG2_FEIGN_DEATH', 0x00000001); //
|
||||||
|
define('UNIT_FLAG2_UNK1', 0x00000002); // Hide unit model (show only player equip)
|
||||||
|
define('UNIT_FLAG2_IGNORE_REPUTATION', 0x00000004); //
|
||||||
|
define('UNIT_FLAG2_COMPREHEND_LANG', 0x00000008); //
|
||||||
|
define('UNIT_FLAG2_MIRROR_IMAGE', 0x00000010); //
|
||||||
|
define('UNIT_FLAG2_INSTANTLY_APPEAR_MODEL', 0x00000020); // Unit model instantly appears when summoned (does not fade in)
|
||||||
|
define('UNIT_FLAG2_FORCE_MOVEMENT', 0x00000040); //
|
||||||
|
define('UNIT_FLAG2_DISARM_OFFHAND', 0x00000080); //
|
||||||
|
define('UNIT_FLAG2_DISABLE_PRED_STATS', 0x00000100); // Player has disabled predicted stats (Used by raid frames)
|
||||||
|
define('UNIT_FLAG2_DISARM_RANGED', 0x00000400); // this does not disable ranged weapon display (maybe additional flag needed?)
|
||||||
|
define('UNIT_FLAG2_REGENERATE_POWER', 0x00000800); //
|
||||||
|
define('UNIT_FLAG2_RESTRICT_PARTY_INTERACTION', 0x1000); // Restrict interaction to party or raid
|
||||||
|
define('UNIT_FLAG2_PREVENT_SPELL_CLICK', 0x00002000); // Prevent spellclick
|
||||||
|
define('UNIT_FLAG2_ALLOW_ENEMY_INTERACT', 0x00004000); //
|
||||||
|
define('UNIT_FLAG2_DISABLE_TURN', 0x00008000); //
|
||||||
|
define('UNIT_FLAG2_UNK2', 0x00010000); //
|
||||||
|
define('UNIT_FLAG2_PLAY_DEATH_ANIM', 0x00020000); // Plays special death animation upon death
|
||||||
|
define('UNIT_FLAG2_ALLOW_CHEAT_SPELLS', 0x00040000); // allows casting spells with AttributesEx7 & SPELL_ATTR7_IS_CHEAT_SPELL
|
||||||
|
|
||||||
|
// UNIT_FIELD_BYTES_1 - idx 0 (UnitStandStateType)
|
||||||
|
define('UNIT_STAND_STATE_STAND', 0);
|
||||||
|
define('UNIT_STAND_STATE_SIT', 1);
|
||||||
|
define('UNIT_STAND_STATE_SIT_CHAIR', 2);
|
||||||
|
define('UNIT_STAND_STATE_SLEEP', 3);
|
||||||
|
define('UNIT_STAND_STATE_SIT_LOW_CHAIR', 4);
|
||||||
|
define('UNIT_STAND_STATE_SIT_MEDIUM_CHAIR', 5);
|
||||||
|
define('UNIT_STAND_STATE_SIT_HIGH_CHAIR', 6);
|
||||||
|
define('UNIT_STAND_STATE_DEAD', 7);
|
||||||
|
define('UNIT_STAND_STATE_KNEEL', 8);
|
||||||
|
define('UNIT_STAND_STATE_SUBMERGED', 9);
|
||||||
|
|
||||||
|
// UNIT_FIELD_BYTES_1 - idx 2 (UnitStandFlags)
|
||||||
|
define('UNIT_STAND_FLAGS_UNK1', 0x01);
|
||||||
|
define('UNIT_STAND_FLAGS_CREEP', 0x02);
|
||||||
|
define('UNIT_STAND_FLAGS_UNTRACKABLE', 0x04);
|
||||||
|
define('UNIT_STAND_FLAGS_UNK4', 0x08);
|
||||||
|
define('UNIT_STAND_FLAGS_UNK5', 0x10);
|
||||||
|
|
||||||
|
// UNIT_FIELD_BYTES_1 - idx 3 (UnitBytes1_Flags)
|
||||||
|
define('UNIT_BYTE1_FLAG_ALWAYS_STAND', 0x01);
|
||||||
|
define('UNIT_BYTE1_FLAG_HOVER', 0x02);
|
||||||
|
define('UNIT_BYTE1_FLAG_UNK_3', 0x04);
|
||||||
|
|
||||||
|
define('UNIT_DYNFLAG_LOOTABLE', 0x01); //
|
||||||
|
define('UNIT_DYNFLAG_TRACK_UNIT', 0x02); // Creature's location will be seen as a small dot in the minimap
|
||||||
|
define('UNIT_DYNFLAG_TAPPED', 0x04); // Makes creatures name appear grey (Lua_UnitIsTapped)
|
||||||
|
define('UNIT_DYNFLAG_TAPPED_BY_PLAYER', 0x08); // Lua_UnitIsTappedByPlayer usually used by PCVs (Player Controlled Vehicles)
|
||||||
|
define('UNIT_DYNFLAG_SPECIALINFO', 0x10); //
|
||||||
|
define('UNIT_DYNFLAG_DEAD', 0x20); // Makes the creature appear dead (this DOES NOT make the creature's name grey or not attack players).
|
||||||
|
define('UNIT_DYNFLAG_REFER_A_FRIEND', 0x40); //
|
||||||
|
define('UNIT_DYNFLAG_TAPPED_BY_ALL_THREAT_LIST', 0x80); // Lua_UnitIsTappedByAllThreatList
|
||||||
|
|
||||||
// quest
|
// quest
|
||||||
define('QUEST_FLAG_STAY_ALIVE', 0x00001);
|
define('QUEST_FLAG_STAY_ALIVE', 0x00001);
|
||||||
@@ -549,6 +664,20 @@ define('OBJECT_DESTRUCTIBLE_BUILDING', 33);
|
|||||||
define('OBJECT_GUILD_BANK', 34);
|
define('OBJECT_GUILD_BANK', 34);
|
||||||
define('OBJECT_TRAPDOOR', 35);
|
define('OBJECT_TRAPDOOR', 35);
|
||||||
|
|
||||||
|
define('GO_FLAG_IN_USE', 0x0001); // Gameobject in use - Disables interaction while being animated
|
||||||
|
define('GO_FLAG_LOCKED', 0x0002); // Makes the Gameobject Locked. Requires a key, spell, or event to be opened. "Locked" appears in tooltip
|
||||||
|
define('GO_FLAG_INTERACT_COND', 0x0004); // Untargetable, cannot interact
|
||||||
|
define('GO_FLAG_TRANSPORT', 0x0008); // Gameobject can transport (boat, elevator, car)
|
||||||
|
define('GO_FLAG_NOT_SELECTABLE', 0x0010); // Not selectable (Not even in GM-mode)
|
||||||
|
define('GO_FLAG_NODESPAWN', 0x0020); // Never despawns. Typical for gameobjects with on/off state (doors for example)
|
||||||
|
define('GO_FLAG_TRIGGERED', 0x0040); // typically, summoned objects. Triggered by spell or other events
|
||||||
|
define('GO_FLAG_DAMAGED', 0x0200); // Gameobject has been siege damaged
|
||||||
|
define('GO_FLAG_DESTROYED', 0x0400); // Gameobject has been destroyed
|
||||||
|
|
||||||
|
define('GO_STATE_ACTIVE', 0); // show in world as used and not reset (closed door open)
|
||||||
|
define('GO_STATE_READY', 1); // show in world as ready (closed door close)
|
||||||
|
define('GO_STATE_ACTIVE_ALTERNATIVE', 2); // show in world as used in alt way and not reset (closed door open by cannon fire)
|
||||||
|
|
||||||
// InventoryType
|
// InventoryType
|
||||||
define('INVTYPE_NON_EQUIP', 0);
|
define('INVTYPE_NON_EQUIP', 0);
|
||||||
define('INVTYPE_HEAD', 1);
|
define('INVTYPE_HEAD', 1);
|
||||||
@@ -683,7 +812,7 @@ define('ITEM_MOD_SPELL_POWER', 45);
|
|||||||
define('ITEM_MOD_HEALTH_REGEN', 46);
|
define('ITEM_MOD_HEALTH_REGEN', 46);
|
||||||
define('ITEM_MOD_SPELL_PENETRATION', 47);
|
define('ITEM_MOD_SPELL_PENETRATION', 47);
|
||||||
define('ITEM_MOD_BLOCK_VALUE', 48);
|
define('ITEM_MOD_BLOCK_VALUE', 48);
|
||||||
// ITEM_MOD_MASTERY_RATING, 49
|
// define('ITEM_MOD_MASTERY_RATING', 49);
|
||||||
define('ITEM_MOD_ARMOR', 50); // resistances v
|
define('ITEM_MOD_ARMOR', 50); // resistances v
|
||||||
define('ITEM_MOD_FIRE_RESISTANCE', 51);
|
define('ITEM_MOD_FIRE_RESISTANCE', 51);
|
||||||
define('ITEM_MOD_FROST_RESISTANCE', 52);
|
define('ITEM_MOD_FROST_RESISTANCE', 52);
|
||||||
@@ -698,6 +827,312 @@ define('ITEM_MOD_SHADOW_POWER', 60);
|
|||||||
define('ITEM_MOD_NATURE_POWER', 61);
|
define('ITEM_MOD_NATURE_POWER', 61);
|
||||||
define('ITEM_MOD_ARCANE_POWER', 62);
|
define('ITEM_MOD_ARCANE_POWER', 62);
|
||||||
|
|
||||||
|
// Spell Attributes definitions
|
||||||
|
define('SPELL_ATTR0_CU_ENCHANT_PROC', 0x00000001); //
|
||||||
|
define('SPELL_ATTR0_CU_CONE_BACK', 0x00000002); //
|
||||||
|
define('SPELL_ATTR0_CU_CONE_LINE', 0x00000004); //
|
||||||
|
define('SPELL_ATTR0_CU_SHARE_DAMAGE', 0x00000008); //
|
||||||
|
define('SPELL_ATTR0_CU_NO_INITIAL_THREAT', 0x00000010); //
|
||||||
|
define('SPELL_ATTR0_CU_AURA_CC', 0x00000020); //
|
||||||
|
define('SPELL_ATTR0_CU_DONT_BREAK_STEALTH', 0x00000040); //
|
||||||
|
define('SPELL_ATTR0_CU_CAN_CRIT', 0x00000080); //
|
||||||
|
define('SPELL_ATTR0_CU_DIRECT_DAMAGE', 0x00000100); //
|
||||||
|
define('SPELL_ATTR0_CU_CHARGE', 0x00000200); //
|
||||||
|
define('SPELL_ATTR0_CU_PICKPOCKET', 0x00000400); //
|
||||||
|
define('SPELL_ATTR0_CU_ROLLING_PERIODIC', 0x00000800); //
|
||||||
|
define('SPELL_ATTR0_CU_NEGATIVE_EFF0', 0x00001000); //
|
||||||
|
define('SPELL_ATTR0_CU_NEGATIVE_EFF1', 0x00002000); //
|
||||||
|
define('SPELL_ATTR0_CU_NEGATIVE_EFF2', 0x00004000); //
|
||||||
|
define('SPELL_ATTR0_CU_IGNORE_ARMOR', 0x00008000); //
|
||||||
|
define('SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER', 0x00010000); //
|
||||||
|
define('SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET', 0x00020000); //
|
||||||
|
define('SPELL_ATTR0_CU_ALLOW_INFLIGHT_TARGET', 0x00040000); //
|
||||||
|
define('SPELL_ATTR0_CU_NEEDS_AMMO_DATA', 0x00080000); //
|
||||||
|
define('SPELL_ATTR0_CU_BINARY_SPELL', 0x00100000); //
|
||||||
|
define('SPELL_ATTR0_CU_SCHOOLMASK_NORMAL_WITH_MAGIC', 0x00200000); //
|
||||||
|
define('SPELL_ATTR0_CU_LIQUID_AURA', 0x00400000); //
|
||||||
|
define('SPELL_ATTR0_CU_NEGATIVE', SPELL_ATTR0_CU_NEGATIVE_EFF0 | SPELL_ATTR0_CU_NEGATIVE_EFF1 | SPELL_ATTR0_CU_NEGATIVE_EFF2); //
|
||||||
|
|
||||||
|
define('SPELL_ATTR0_UNK0', 0x00000001); // Unknown attribute 0@Attr0
|
||||||
|
define('SPELL_ATTR0_REQ_AMMO', 0x00000002); // Treat as ranged attack DESCRIPTION Use ammo, ranged attack range modifiers, ranged haste, etc.
|
||||||
|
define('SPELL_ATTR0_ON_NEXT_SWING', 0x00000004); // On next melee (type 1) DESCRIPTION Both "on next swing" attributes have identical handling in server & client
|
||||||
|
define('SPELL_ATTR0_IS_REPLENISHMENT', 0x00000008); // Replenishment (client only)
|
||||||
|
define('SPELL_ATTR0_ABILITY', 0x00000010); // Treat as ability DESCRIPTION Cannot be reflected, not affected by cast speed modifiers, etc.
|
||||||
|
define('SPELL_ATTR0_TRADESPELL', 0x00000020); // Trade skill recipe DESCRIPTION Displayed in recipe list, not affected by cast speed modifiers
|
||||||
|
define('SPELL_ATTR0_PASSIVE', 0x00000040); // Passive spell DESCRIPTION Spell is automatically cast on self by core
|
||||||
|
define('SPELL_ATTR0_HIDDEN_CLIENTSIDE', 0x00000080); // Hidden in UI (client only) DESCRIPTION Not visible in spellbook or aura bar
|
||||||
|
define('SPELL_ATTR0_HIDE_IN_COMBAT_LOG', 0x00000100); // Hidden in combat log (client only) DESCRIPTION Spell will not appear in combat logs
|
||||||
|
define('SPELL_ATTR0_TARGET_MAINHAND_ITEM', 0x00000200); // Auto-target mainhand item (client only) DESCRIPTION Client will automatically select main-hand item as cast target
|
||||||
|
define('SPELL_ATTR0_ON_NEXT_SWING_2', 0x00000400); // On next melee (type 2) DESCRIPTION Both "on next swing" attributes have identical handling in server & client
|
||||||
|
define('SPELL_ATTR0_UNK11', 0x00000800); // Unknown attribute 11@Attr0
|
||||||
|
define('SPELL_ATTR0_DAYTIME_ONLY', 0x00001000); // Only usable during daytime (unused)
|
||||||
|
define('SPELL_ATTR0_NIGHT_ONLY', 0x00002000); // Only usable during nighttime (unused)
|
||||||
|
define('SPELL_ATTR0_INDOORS_ONLY', 0x00004000); // Only usable indoors
|
||||||
|
define('SPELL_ATTR0_OUTDOORS_ONLY', 0x00008000); // Only usable outdoors
|
||||||
|
define('SPELL_ATTR0_NOT_SHAPESHIFT', 0x00010000); // Not usable while shapeshifted
|
||||||
|
define('SPELL_ATTR0_ONLY_STEALTHED', 0x00020000); // Only usable in stealth
|
||||||
|
define('SPELL_ATTR0_DONT_AFFECT_SHEATH_STATE', 0x00040000); // Don't shealthe weapons (client only)
|
||||||
|
define('SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION', 0x00080000); // Scale with caster level DESCRIPTION For non-player casts, scale impact and power cost with caster's level
|
||||||
|
define('SPELL_ATTR0_STOP_ATTACK_TARGET', 0x00100000); // Stop attacking after cast DESCRIPTION After casting this, the current auto-attack will be interrupted
|
||||||
|
define('SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK', 0x00200000); // Prevent physical avoidance DESCRIPTION Spell cannot be dodged, parried or blocked
|
||||||
|
define('SPELL_ATTR0_CAST_TRACK_TARGET', 0x00400000); // Automatically face target during cast (client only)
|
||||||
|
define('SPELL_ATTR0_CASTABLE_WHILE_DEAD', 0x00800000); // Can be cast while dead DESCRIPTION Spells without this flag cannot be cast by dead units in non-triggered contexts
|
||||||
|
define('SPELL_ATTR0_CASTABLE_WHILE_MOUNTED', 0x01000000); // Can be cast while mounted
|
||||||
|
define('SPELL_ATTR0_DISABLED_WHILE_ACTIVE', 0x02000000); // Cooldown starts on expiry DESCRIPTION Spell is unusable while already active, and cooldown does not begin until the effects have worn off
|
||||||
|
define('SPELL_ATTR0_NEGATIVE_1', 0x04000000); // Is negative spell DESCRIPTION Forces the spell to be treated as a negative spell
|
||||||
|
define('SPELL_ATTR0_CASTABLE_WHILE_SITTING', 0x08000000); // Can be cast while sitting
|
||||||
|
define('SPELL_ATTR0_CANT_USED_IN_COMBAT', 0x10000000); // Cannot be used in combat
|
||||||
|
define('SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY', 0x20000000); // Pierce invulnerability DESCRIPTION Allows spell to pierce invulnerability, unless the invulnerability spell also has this attribute
|
||||||
|
define('SPELL_ATTR0_HEARTBEAT_RESIST_CHECK', 0x40000000); // Periodic resistance checks DESCRIPTION Periodically re-rolls against resistance to potentially expire aura early
|
||||||
|
define('SPELL_ATTR0_CANT_CANCEL', 0x80000000); // Aura cannot be cancelled DESCRIPTION Prevents the player from voluntarily canceling a positive aura
|
||||||
|
|
||||||
|
define('SPELL_ATTR1_DISMISS_PET', 0x00000001); // Dismiss Pet on cast DESCRIPTION Without this attribute, summoning spells will fail if caster already has a pet
|
||||||
|
define('SPELL_ATTR1_DRAIN_ALL_POWER', 0x00000002); // Drain all power DESCRIPTION Ignores listed power cost and drains entire pool instead
|
||||||
|
define('SPELL_ATTR1_CHANNELED_1', 0x00000004); // Channeled (type 1) DESCRIPTION Both "channeled" attributes have identical handling in server & client
|
||||||
|
define('SPELL_ATTR1_CANT_BE_REDIRECTED', 0x00000008); // Ignore redirection effects DESCRIPTION Spell will not be attracted by SPELL_MAGNET auras (Grounding Totem)
|
||||||
|
define('SPELL_ATTR1_UNK4', 0x00000010); // Unknown attribute 4@Attr1
|
||||||
|
define('SPELL_ATTR1_NOT_BREAK_STEALTH', 0x00000020); // Does not break stealth
|
||||||
|
define('SPELL_ATTR1_CHANNELED_2', 0x00000040); // Channeled (type 2) DESCRIPTION Both "channeled" attributes have identical handling in server & client
|
||||||
|
define('SPELL_ATTR1_CANT_BE_REFLECTED', 0x00000080); // Ignore reflection effects DESCRIPTION Spell will pierce through Spell Reflection and similar
|
||||||
|
define('SPELL_ATTR1_CANT_TARGET_IN_COMBAT', 0x00000100); // Target cannot be in combat
|
||||||
|
define('SPELL_ATTR1_MELEE_COMBAT_START', 0x00000200); // Starts auto-attack (client only) DESCRIPTION Caster will begin auto-attacking the target on cast
|
||||||
|
define('SPELL_ATTR1_NO_THREAT', 0x00000400); // Does not generate threat DESCRIPTION Also does not cause target to engage
|
||||||
|
define('SPELL_ATTR1_UNK11', 0x00000800); // Unknown attribute 11@Attr1 DESCRIPTION Aura?
|
||||||
|
define('SPELL_ATTR1_IS_PICKPOCKET', 0x00001000); // Pickpocket (client only)
|
||||||
|
define('SPELL_ATTR1_FARSIGHT', 0x00002000); // Farsight aura (client only)
|
||||||
|
define('SPELL_ATTR1_CHANNEL_TRACK_TARGET', 0x00004000); // Track target while channeling DESCRIPTION While channeling, adjust facing to face target
|
||||||
|
define('SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY', 0x00008000); // Immunity cancels preapplied auras DESCRIPTION For immunity spells, cancel all auras that this spell would make you immune to when the spell is applied
|
||||||
|
define('SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE', 0x00010000); // Unaffected by school immunities DESCRIPTION Will not pierce Divine Shield, Ice Block and other full invulnerabilities
|
||||||
|
define('SPELL_ATTR1_UNAUTOCASTABLE_BY_PET', 0x00020000); // Cannot be autocast by pet
|
||||||
|
define('SPELL_ATTR1_UNK18', 0x00040000); // Unknown attribute 18@Attr1 DESCRIPTION Stun, Polymorph, Daze, Hex - CC?
|
||||||
|
define('SPELL_ATTR1_CANT_TARGET_SELF', 0x00080000); // Cannot be self-cast
|
||||||
|
define('SPELL_ATTR1_REQ_COMBO_POINTS1', 0x00100000); // Requires combo points (type 1)
|
||||||
|
define('SPELL_ATTR1_UNK21', 0x00200000); // Unknown attribute 21@Attr1
|
||||||
|
define('SPELL_ATTR1_REQ_COMBO_POINTS2', 0x00400000); // Requires combo points (type 2)
|
||||||
|
define('SPELL_ATTR1_UNK23', 0x00800000); // Unknwon attribute 23@Attr1
|
||||||
|
define('SPELL_ATTR1_IS_FISHING', 0x01000000); // Fishing (client only)
|
||||||
|
define('SPELL_ATTR1_UNK25', 0x02000000); // Unknown attribute 25@Attr1
|
||||||
|
define('SPELL_ATTR1_UNK26', 0x04000000); // Unknown attribute 26@Attr1 DESCRIPTION Related to [target=focus] and [target=mouseover] macros?
|
||||||
|
define('SPELL_ATTR1_UNK27', 0x08000000); // Unknown attribute 27@Attr1 DESCRIPTION Melee spell?
|
||||||
|
define('SPELL_ATTR1_DONT_DISPLAY_IN_AURA_BAR', 0x10000000); // Hide in aura bar (client only)
|
||||||
|
define('SPELL_ATTR1_CHANNEL_DISPLAY_SPELL_NAME', 0x20000000); // Show spell name during channel (client only)
|
||||||
|
define('SPELL_ATTR1_ENABLE_AT_DODGE', 0x40000000); // Enable at dodge
|
||||||
|
define('SPELL_ATTR1_UNK31', 0x80000000); // Unknown attribute 31@Attr1
|
||||||
|
|
||||||
|
define('SPELL_ATTR2_CAN_TARGET_DEAD', 0x00000001); // Can target dead players or corpses
|
||||||
|
define('SPELL_ATTR2_UNK1', 0x00000002); // Unknown attribute 1@Attr2
|
||||||
|
define('SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS', 0x00000004); // Ignore Line of Sight
|
||||||
|
define('SPELL_ATTR2_UNK3', 0x00000008); // Ignore aura scaling
|
||||||
|
define('SPELL_ATTR2_DISPLAY_IN_STANCE_BAR', 0x00000010); // Show in stance bar (client only)
|
||||||
|
define('SPELL_ATTR2_AUTOREPEAT_FLAG', 0x00000020); // Ranged auto-attack spell
|
||||||
|
define('SPELL_ATTR2_CANT_TARGET_TAPPED', 0x00000040); // Cannot target others' tapped units DESCRIPTION Can only target untapped units, or those tapped by caster
|
||||||
|
define('SPELL_ATTR2_UNK7', 0x00000080); // Unknown attribute 7@Attr2
|
||||||
|
define('SPELL_ATTR2_UNK8', 0x00000100); // Unknown attribute 8@Attr2
|
||||||
|
define('SPELL_ATTR2_UNK9', 0x00000200); // Unknown attribute 9@Attr2
|
||||||
|
define('SPELL_ATTR2_UNK10', 0x00000400); // Unknown attribute 10@Attr2 DESCRIPTION Related to taming?
|
||||||
|
define('SPELL_ATTR2_HEALTH_FUNNEL', 0x00000800); // Health Funnel
|
||||||
|
define('SPELL_ATTR2_UNK12', 0x00001000); // Unknown attribute 12@Attr2
|
||||||
|
define('SPELL_ATTR2_PRESERVE_ENCHANT_IN_ARENA', 0x00002000); // Enchant persists when entering arena
|
||||||
|
define('SPELL_ATTR2_UNK14', 0x00004000); // Unknown attribute 14@Attr2
|
||||||
|
define('SPELL_ATTR2_UNK15', 0x00008000); // Unknown attribute 15@Attr2
|
||||||
|
define('SPELL_ATTR2_TAME_BEAST', 0x00010000); // Tame Beast
|
||||||
|
define('SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS', 0x00020000); // Don't reset swing timer DESCRIPTION Does not reset melee/ranged autoattack timer on cast
|
||||||
|
define('SPELL_ATTR2_REQ_DEAD_PET', 0x00040000); // Requires dead pet
|
||||||
|
define('SPELL_ATTR2_NOT_NEED_SHAPESHIFT', 0x00080000); // Also allow outside shapeshift DESCRIPTION Even if Stances are nonzero, allow spell to be cast outside of shapeshift (though not in a different shapeshift)
|
||||||
|
define('SPELL_ATTR2_UNK20', 0x00100000); // Unknown attribute 20@Attr2
|
||||||
|
define('SPELL_ATTR2_DAMAGE_REDUCED_SHIELD', 0x00200000); // Damage reduction ability DESCRIPTION Causes BG flags to be dropped if combined with ATTR1_DISPEL_AURAS_ON_IMMUNITY
|
||||||
|
define('SPELL_ATTR2_UNK22', 0x00400000); // Unknown attribute 22@Attr2
|
||||||
|
define('SPELL_ATTR2_IS_ARCANE_CONCENTRATION', 0x00800000); // Arcane Concentration
|
||||||
|
define('SPELL_ATTR2_UNK24', 0x01000000); // Unknown attribute 24@Attr2
|
||||||
|
define('SPELL_ATTR2_UNK25', 0x02000000); // Unknown attribute 25@Attr2
|
||||||
|
define('SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE', 0x04000000); // Pierce aura application immunities DESCRIPTION Allow aura to be applied despite target being immune to new aura applications
|
||||||
|
define('SPELL_ATTR2_UNK27', 0x08000000); // Unknown attribute 27@Attr2
|
||||||
|
define('SPELL_ATTR2_UNK28', 0x10000000); // Unknown attribute 28@Attr2
|
||||||
|
define('SPELL_ATTR2_CANT_CRIT', 0x20000000); // Cannot critically strike
|
||||||
|
define('SPELL_ATTR2_TRIGGERED_CAN_TRIGGER_PROC', 0x40000000); // Allow triggered spell to trigger (type 1) DESCRIPTION Without this attribute, any triggered spell will be unable to trigger other auras' procs
|
||||||
|
define('SPELL_ATTR2_FOOD_BUFF', 0x80000000); // Food buff (client only)
|
||||||
|
|
||||||
|
define('SPELL_ATTR3_UNK0', 0x00000001); // Unknown attribute 0@Attr3
|
||||||
|
define('SPELL_ATTR3_IGNORE_PROC_SUBCLASS_MASK', 0x00000002); // 1 Ignores subclass mask check when checking proc
|
||||||
|
define('SPELL_ATTR3_UNK2', 0x00000004); // Unknown attribute 2@Attr3
|
||||||
|
define('SPELL_ATTR3_BLOCKABLE_SPELL', 0x00000008); // Blockable spell
|
||||||
|
define('SPELL_ATTR3_IGNORE_RESURRECTION_TIMER', 0x00000010); // Ignore resurrection timer
|
||||||
|
define('SPELL_ATTR3_UNK5', 0x00000020); // Unknown attribute 5@Attr3
|
||||||
|
define('SPELL_ATTR3_UNK6', 0x00000040); // Unknown attribute 6@Attr3
|
||||||
|
define('SPELL_ATTR3_STACK_FOR_DIFF_CASTERS', 0x00000080); // Stack separately for each caster
|
||||||
|
define('SPELL_ATTR3_ONLY_TARGET_PLAYERS', 0x00000100); // Can only target players
|
||||||
|
define('SPELL_ATTR3_TRIGGERED_CAN_TRIGGER_PROC_2', 0x00000200); // Allow triggered spell to trigger (type 2) DESCRIPTION Without this attribute, any triggered spell will be unable to trigger other auras' procs
|
||||||
|
define('SPELL_ATTR3_MAIN_HAND', 0x00000400); // Require main hand weapon
|
||||||
|
define('SPELL_ATTR3_BATTLEGROUND', 0x00000800); // Can only be cast in battleground
|
||||||
|
define('SPELL_ATTR3_ONLY_TARGET_GHOSTS', 0x00001000); // Can only target ghost players
|
||||||
|
define('SPELL_ATTR3_DONT_DISPLAY_CHANNEL_BAR', 0x00002000); // Do not display channel bar (client only)
|
||||||
|
define('SPELL_ATTR3_IS_HONORLESS_TARGET', 0x00004000); // Honorless Target
|
||||||
|
define('SPELL_ATTR3_UNK15', 0x00008000); // Unknown attribute 15@Attr3 DESCRIPTION Auto Shoot, Shoot, Throw - ranged normal attack attribute?
|
||||||
|
define('SPELL_ATTR3_CANT_TRIGGER_PROC', 0x00010000); // Cannot trigger procs
|
||||||
|
define('SPELL_ATTR3_NO_INITIAL_AGGRO', 0x00020000); // No initial aggro
|
||||||
|
define('SPELL_ATTR3_IGNORE_HIT_RESULT', 0x00040000); // Ignore hit result DESCRIPTION Spell cannot miss, or be dodged/parried/blocked
|
||||||
|
define('SPELL_ATTR3_DISABLE_PROC', 0x00080000); // Cannot trigger spells during aura proc
|
||||||
|
define('SPELL_ATTR3_DEATH_PERSISTENT', 0x00100000); // Persists through death
|
||||||
|
define('SPELL_ATTR3_UNK21', 0x00200000); // Unknown attribute 21@Attr3
|
||||||
|
define('SPELL_ATTR3_REQ_WAND', 0x00400000); // Requires equipped Wand
|
||||||
|
define('SPELL_ATTR3_UNK23', 0x00800000); // Unknown attribute 23@Attr3
|
||||||
|
define('SPELL_ATTR3_REQ_OFFHAND', 0x01000000); // Requires offhand weapon
|
||||||
|
define('SPELL_ATTR3_TREAT_AS_PERIODIC', 0x02000000); // Treat as periodic effect
|
||||||
|
define('SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED', 0x04000000); // Can trigger from triggered spells
|
||||||
|
define('SPELL_ATTR3_DRAIN_SOUL', 0x08000000); // Drain Soul
|
||||||
|
define('SPELL_ATTR3_UNK28', 0x10000000); // Unknown attribute 28@Attr3
|
||||||
|
define('SPELL_ATTR3_NO_DONE_BONUS', 0x20000000); // Damage dealt is unaffected by modifiers
|
||||||
|
define('SPELL_ATTR3_DONT_DISPLAY_RANGE', 0x40000000); // Do not show range in tooltip (client only)
|
||||||
|
define('SPELL_ATTR3_UNK31', 0x80000000); // Unknown attribute 31@Attr3
|
||||||
|
|
||||||
|
define('SPELL_ATTR4_IGNORE_RESISTANCES', 0x00000001); // Cannot be resisted
|
||||||
|
define('SPELL_ATTR4_PROC_ONLY_ON_CASTER', 0x00000002); // Only proc on self-cast
|
||||||
|
define('SPELL_ATTR4_FADES_WHILE_LOGGED_OUT', 0x00000004); // Buff expires while offline DESCRIPTION Debuffs (except Resurrection Sickness) will automatically do this
|
||||||
|
define('SPELL_ATTR4_UNK3', 0x00000008); // Unknown attribute 3@Attr4
|
||||||
|
define('SPELL_ATTR4_UNK4', 0x00000010); // Treat as delayed spell
|
||||||
|
define('SPELL_ATTR4_UNK5', 0x00000020); // Unknown attribute 5@Attr4
|
||||||
|
define('SPELL_ATTR4_NOT_STEALABLE', 0x00000040); // Aura cannot be stolen
|
||||||
|
define('SPELL_ATTR4_CAN_CAST_WHILE_CASTING', 0x00000080); // Can be cast while casting DESCRIPTION Ignores already in-progress cast and still casts
|
||||||
|
define('SPELL_ATTR4_FIXED_DAMAGE', 0x00000100); // Deals fixed damage
|
||||||
|
define('SPELL_ATTR4_TRIGGER_ACTIVATE', 0x00000200); // Spell is initially disabled (client only)
|
||||||
|
define('SPELL_ATTR4_SPELL_VS_EXTEND_COST', 0x00000400); // Attack speed modifies cost DESCRIPTION Adds 10 to power cost for each 1s of weapon speed
|
||||||
|
define('SPELL_ATTR4_UNK11', 0x00000800); // Unknown attribute 11@Attr4
|
||||||
|
define('SPELL_ATTR4_UNK12', 0x00001000); // Unknown attribute 12@Attr4
|
||||||
|
define('SPELL_ATTR4_UNK13', 0x00002000); // Unknown attribute 13@Attr4
|
||||||
|
define('SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS', 0x00004000); // Damage does not break auras
|
||||||
|
define('SPELL_ATTR4_UNK15', 0x00008000); // Unknown attribute 15@Attr4
|
||||||
|
define('SPELL_ATTR4_NOT_USABLE_IN_ARENA', 0x00010000); // Not usable in arena DESCRIPTION Makes spell unusable despite CD <= 10min
|
||||||
|
define('SPELL_ATTR4_USABLE_IN_ARENA', 0x00020000); // Usable in arena DESCRIPTION Makes spell usable despite CD > 10min
|
||||||
|
define('SPELL_ATTR4_AREA_TARGET_CHAIN', 0x00040000); // Chain area targets DESCRIPTION [NYI] Hits area targets over time instead of all at once
|
||||||
|
define('SPELL_ATTR4_UNK19', 0x00080000); // Unknown attribute 19@Attr4
|
||||||
|
define('SPELL_ATTR4_NOT_CHECK_SELFCAST_POWER', 0x00100000); // Allow self-cast to override stronger aura (client only)
|
||||||
|
define('SPELL_ATTR4_UNK21', 0x00200000); // Keep when entering arena
|
||||||
|
define('SPELL_ATTR4_UNK22', 0x00400000); // Unknown attribute 22@Attr4
|
||||||
|
define('SPELL_ATTR4_CANT_TRIGGER_ITEM_SPELLS', 0x00800000); // Cannot trigger item spells
|
||||||
|
define('SPELL_ATTR4_UNK24', 0x01000000); // Unknown attribute 24@Attr4 DESCRIPTION Shoot-type spell?
|
||||||
|
define('SPELL_ATTR4_IS_PET_SCALING', 0x02000000); // Pet Scaling aura
|
||||||
|
define('SPELL_ATTR4_CAST_ONLY_IN_OUTLAND', 0x04000000); // Only in Outland/Northrend
|
||||||
|
define('SPELL_ATTR4_INHERIT_CRIT_FROM_AURA', 0x08000000); // Inherit critical chance from triggering aura
|
||||||
|
define('SPELL_ATTR4_UNK28', 0x10000000); // Unknown attribute 28@Attr4
|
||||||
|
define('SPELL_ATTR4_UNK29', 0x20000000); // Unknown attribute 29@Attr4
|
||||||
|
define('SPELL_ATTR4_UNK30', 0x40000000); // Unknown attribute 30@Attr4
|
||||||
|
define('SPELL_ATTR4_UNK31', 0x80000000); // Unknown attribute 31@Attr4
|
||||||
|
|
||||||
|
define('SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING', 0x00000001); // Can be channeled while moving
|
||||||
|
define('SPELL_ATTR5_NO_REAGENT_WHILE_PREP', 0x00000002); // No reagents during arena preparation
|
||||||
|
define('SPELL_ATTR5_REMOVE_ON_ARENA_ENTER', 0x00000004); // Remove when entering arena DESCRIPTION Force this aura to be removed on entering arena, regardless of other properties
|
||||||
|
define('SPELL_ATTR5_USABLE_WHILE_STUNNED', 0x00000008); // Usable while stunned
|
||||||
|
define('SPELL_ATTR5_UNK4', 0x00000010); // Unknown attribute 4@Attr5
|
||||||
|
define('SPELL_ATTR5_SINGLE_TARGET_SPELL', 0x00000020); // Single-target aura DESCRIPTION Remove previous application to another unit if applied
|
||||||
|
define('SPELL_ATTR5_UNK6', 0x00000040); // Unknown attribute 6@Attr5
|
||||||
|
define('SPELL_ATTR5_UNK7', 0x00000080); // Unknown attribute 7@Attr5
|
||||||
|
define('SPELL_ATTR5_UNK8', 0x00000100); // Unknown attribute 8@Attr5
|
||||||
|
define('SPELL_ATTR5_START_PERIODIC_AT_APPLY', 0x00000200); // Immediately do periodic tick on apply
|
||||||
|
define('SPELL_ATTR5_HIDE_DURATION', 0x00000400); // Do not send aura duration to client
|
||||||
|
define('SPELL_ATTR5_ALLOW_TARGET_OF_TARGET_AS_TARGET', 0x00000800); // Auto-target target of target (client only)
|
||||||
|
define('SPELL_ATTR5_UNK12', 0x00001000); // Unknown attribute 12@Attr5 DESCRIPTION Cleave related?
|
||||||
|
define('SPELL_ATTR5_HASTE_AFFECT_DURATION', 0x00002000); // Duration scales with Haste Rating
|
||||||
|
define('SPELL_ATTR5_UNK14', 0x00004000); // Unknown attribute 14@Attr5
|
||||||
|
define('SPELL_ATTR5_UNK15', 0x00008000); // Unknown attribute 15@Attr5 DESCRIPTION Related to multi-target spells?
|
||||||
|
define('SPELL_ATTR5_UNK16', 0x00010000); // Unknown attribute 16@Attr5
|
||||||
|
define('SPELL_ATTR5_USABLE_WHILE_FEARED', 0x00020000); // Usable while feared
|
||||||
|
define('SPELL_ATTR5_USABLE_WHILE_CONFUSED', 0x00040000); // Usable while confused
|
||||||
|
define('SPELL_ATTR5_DONT_TURN_DURING_CAST', 0x00080000); // Do not auto-turn while casting
|
||||||
|
define('SPELL_ATTR5_UNK20', 0x00100000); // Unknown attribute 20@Attr5
|
||||||
|
define('SPELL_ATTR5_UNK21', 0x00200000); // Unknown attribute 21@Attr5
|
||||||
|
define('SPELL_ATTR5_UNK22', 0x00400000); // Unknown attribute 22@Attr5
|
||||||
|
define('SPELL_ATTR5_UNK23', 0x00800000); // Unknown attribute 23@Attr5
|
||||||
|
define('SPELL_ATTR5_UNK24', 0x01000000); // Unknown attribute 24@Attr5
|
||||||
|
define('SPELL_ATTR5_UNK25', 0x02000000); // Unknown attribute 25@Attr5
|
||||||
|
define('SPELL_ATTR5_SKIP_CHECKCAST_LOS_CHECK', 0x04000000); // Ignore line of sight checks
|
||||||
|
define('SPELL_ATTR5_DONT_SHOW_AURA_IF_SELF_CAST', 0x08000000); // Don't show aura if self-cast (client only)
|
||||||
|
define('SPELL_ATTR5_DONT_SHOW_AURA_IF_NOT_SELF_CAST', 0x10000000); // Don't show aura unless self-cast (client only)
|
||||||
|
define('SPELL_ATTR5_UNK29', 0x20000000); // Unknown attribute 29@Attr5
|
||||||
|
define('SPELL_ATTR5_UNK30', 0x40000000); // Unknown attribute 30@Attr5
|
||||||
|
define('SPELL_ATTR5_UNK31', 0x80000000); // Unknown attribute 31@Attr5 DESCRIPTION Forces nearby enemies to attack caster?
|
||||||
|
|
||||||
|
define('SPELL_ATTR6_DONT_DISPLAY_COOLDOWN', 0x00000001); // Don't display cooldown (client only)
|
||||||
|
define('SPELL_ATTR6_ONLY_IN_ARENA', 0x00000002); // Only usable in arena
|
||||||
|
define('SPELL_ATTR6_IGNORE_CASTER_AURAS', 0x00000004); // Ignore all preventing caster auras
|
||||||
|
define('SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG', 0x00000008); // Ignore immunity flags when assisting
|
||||||
|
define('SPELL_ATTR6_UNK4', 0x00000010); // Unknown attribute 4@Attr6
|
||||||
|
define('SPELL_ATTR6_DONT_CONSUME_PROC_CHARGES', 0x00000020); // Don't consume proc charges
|
||||||
|
define('SPELL_ATTR6_USE_SPELL_CAST_EVENT', 0x00000040); // Generate spell_cast event instead of aura_start (client only)
|
||||||
|
define('SPELL_ATTR6_UNK7', 0x00000080); // Unknown attribute 7@Attr6
|
||||||
|
define('SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED', 0x00000100); // Do not implicitly target in CC DESCRIPTION Implicit targeting (chaining and area targeting) will not impact crowd controlled targets
|
||||||
|
define('SPELL_ATTR6_UNK9', 0x00000200); // Unknown attribute 9@Attr6
|
||||||
|
define('SPELL_ATTR6_CAN_TARGET_POSSESSED_FRIENDS', 0x00000400); // Can target possessed friends DESCRIPTION [NYI]
|
||||||
|
define('SPELL_ATTR6_NOT_IN_RAID_INSTANCE', 0x00000800); // Unusable in raid instances
|
||||||
|
define('SPELL_ATTR6_CASTABLE_WHILE_ON_VEHICLE', 0x00001000); // Castable while caster is on vehicle
|
||||||
|
define('SPELL_ATTR6_CAN_TARGET_INVISIBLE', 0x00002000); // Can target invisible units
|
||||||
|
define('SPELL_ATTR6_UNK14', 0x00004000); // Unknown attribute 14@Attr6
|
||||||
|
define('SPELL_ATTR6_UNK15', 0x00008000); // Unknown attribute 15@Attr6
|
||||||
|
define('SPELL_ATTR6_UNK16', 0x00010000); // Unknown attribute 16@Attr6
|
||||||
|
define('SPELL_ATTR6_UNK17', 0x00020000); // Unknown attribute 17@Attr6 DESCRIPTION Mount related?
|
||||||
|
define('SPELL_ATTR6_CAST_BY_CHARMER', 0x00040000); // Spell is cast by charmer DESCRIPTION Client will prevent casting if not possessed, charmer will be caster for all intents and purposes
|
||||||
|
define('SPELL_ATTR6_UNK19', 0x00080000); // Unknown attribute 19@Attr6
|
||||||
|
define('SPELL_ATTR6_ONLY_VISIBLE_TO_CASTER', 0x00100000); // Only visible to caster (client only)
|
||||||
|
define('SPELL_ATTR6_CLIENT_UI_TARGET_EFFECTS', 0x00200000); // Client UI target effects (client only)
|
||||||
|
define('SPELL_ATTR6_UNK22', 0x00400000); // Unknown attribute 22@Attr6
|
||||||
|
define('SPELL_ATTR6_UNK23', 0x00800000); // Unknown attribute 23@Attr6
|
||||||
|
define('SPELL_ATTR6_CAN_TARGET_UNTARGETABLE', 0x01000000); // Can target untargetable units
|
||||||
|
define('SPELL_ATTR6_NOT_RESET_SWING_IF_INSTANT', 0x02000000); // Do not reset swing timer if cast time is instant
|
||||||
|
define('SPELL_ATTR6_UNK26', 0x04000000); // Unknown attribute 26@Attr6 DESCRIPTION Player castable buff?
|
||||||
|
define('SPELL_ATTR6_LIMIT_PCT_HEALING_MODS', 0x08000000); // Limit applicable %healing modifiers DESCRIPTION This prevents certain healing modifiers from applying - see implementation if you really care about details
|
||||||
|
define('SPELL_ATTR6_UNK28', 0x10000000); // Unknown attribute 28@Attr6 DESCRIPTION Death grip?
|
||||||
|
define('SPELL_ATTR6_LIMIT_PCT_DAMAGE_MODS', 0x20000000); // Limit applicable %damage modifiers DESCRIPTION This prevents certain damage modifiers from applying - see implementation if you really care about details
|
||||||
|
define('SPELL_ATTR6_UNK30', 0x40000000); // Unknown attribute 30@Attr6
|
||||||
|
define('SPELL_ATTR6_IGNORE_CATEGORY_COOLDOWN_MODS', 0x80000000); // Ignore cooldown modifiers for category cooldown
|
||||||
|
|
||||||
|
define('SPELL_ATTR7_UNK0', 0x00000001); // Unknown attribute 0@Attr7
|
||||||
|
define('SPELL_ATTR7_IGNORE_DURATION_MODS', 0x00000002); // Ignore duration modifiers
|
||||||
|
define('SPELL_ATTR7_REACTIVATE_AT_RESURRECT', 0x00000004); // Reactivate at resurrect (client only)
|
||||||
|
define('SPELL_ATTR7_IS_CHEAT_SPELL', 0x00000008); // Is cheat spell DESCRIPTION Cannot cast if caster doesn't have UnitFlag2 & UNIT_FLAG2_ALLOW_CHEAT_SPELLS
|
||||||
|
define('SPELL_ATTR7_UNK4', 0x00000010); // Unknown attribute 4@Attr7 DESCRIPTION Soulstone related?
|
||||||
|
define('SPELL_ATTR7_SUMMON_PLAYER_TOTEM', 0x00000020); // Summons player-owned totem
|
||||||
|
define('SPELL_ATTR7_NO_PUSHBACK_ON_DAMAGE', 0x00000040); // Damage dealt by this does not cause spell pushback
|
||||||
|
define('SPELL_ATTR7_UNK7', 0x00000080); // Unknown attribute 7@Attr7
|
||||||
|
define('SPELL_ATTR7_HORDE_ONLY', 0x00000100); // Horde only
|
||||||
|
define('SPELL_ATTR7_ALLIANCE_ONLY', 0x00000200); // Alliance only
|
||||||
|
define('SPELL_ATTR7_DISPEL_CHARGES', 0x00000400); // Dispel/Spellsteal remove individual charges
|
||||||
|
define('SPELL_ATTR7_INTERRUPT_ONLY_NONPLAYER', 0x00000800); // Only interrupt non-player casting
|
||||||
|
define('SPELL_ATTR7_UNK12', 0x00001000); // Unknown attribute 12@Attr7
|
||||||
|
define('SPELL_ATTR7_UNK13', 0x00002000); // Unknown attribute 13@Attr7
|
||||||
|
define('SPELL_ATTR7_UNK14', 0x00004000); // Unknown attribute 14@Attr7
|
||||||
|
define('SPELL_ATTR7_UNK15', 0x00008000); // Unknown attribute 15@Attr7 DESCRIPTION Exorcism - guaranteed crit vs families?
|
||||||
|
define('SPELL_ATTR7_CAN_RESTORE_SECONDARY_POWER', 0x00010000); // Can restore secondary power DESCRIPTION Only spells with this attribute can replenish a non-active power type
|
||||||
|
define('SPELL_ATTR7_UNK17', 0x00020000); // Unknown attribute 17@Attr7
|
||||||
|
define('SPELL_ATTR7_HAS_CHARGE_EFFECT', 0x00040000); // Has charge effect
|
||||||
|
define('SPELL_ATTR7_ZONE_TELEPORT', 0x00080000); // Is zone teleport
|
||||||
|
define('SPELL_ATTR7_UNK20', 0x00100000); // Unknown attribute 20@Attr7 DESCRIPTION Invulnerability related?
|
||||||
|
define('SPELL_ATTR7_UNK21', 0x00200000); // Unknown attribute 21@Attr7
|
||||||
|
define('SPELL_ATTR7_IGNORE_COLD_WEATHER_FLYING', 0x00400000); // Ignore cold weather flying restriction DESCRIPTION Set for loaner mounts, allows them to be used despite lacking required flight skill
|
||||||
|
define('SPELL_ATTR7_UNK23', 0x00800000); // Unknown attribute 23@Attr7
|
||||||
|
define('SPELL_ATTR7_UNK24', 0x01000000); // Unknown attribute 24@Attr7
|
||||||
|
define('SPELL_ATTR7_UNK25', 0x02000000); // Unknown attribute 25@Attr7
|
||||||
|
define('SPELL_ATTR7_UNK26', 0x04000000); // Unknown attribute 26@Attr7
|
||||||
|
define('SPELL_ATTR7_UNK27', 0x08000000); // Unknown attribute 27@Attr7
|
||||||
|
define('SPELL_ATTR7_CONSOLIDATED_RAID_BUFF', 0x10000000); // Consolidate in raid buff frame (client only)
|
||||||
|
define('SPELL_ATTR7_UNK29', 0x20000000); // Unknown attribute 29@Attr7
|
||||||
|
define('SPELL_ATTR7_UNK30', 0x40000000); // Unknown attribute 30@Attr7
|
||||||
|
define('SPELL_ATTR7_CLIENT_INDICATOR', 0x80000000); // Client indicator (client only)
|
||||||
|
|
||||||
|
|
||||||
|
// (some) Skill ids
|
||||||
|
define('SKILL_BLACKSMITHING', 164);
|
||||||
|
define('SKILL_LEATHERWORKING', 165);
|
||||||
|
define('SKILL_ALCHEMY', 171);
|
||||||
|
define('SKILL_HERBALISM', 182);
|
||||||
|
define('SKILL_MINING', 186);
|
||||||
|
define('SKILL_TAILORING', 197);
|
||||||
|
define('SKILL_ENGINEERING', 202);
|
||||||
|
define('SKILL_ENCHANTING', 333);
|
||||||
|
define('SKILL_SKINNING', 393);
|
||||||
|
define('SKILL_JEWELCRAFTING', 755);
|
||||||
|
define('SKILL_INSCRIPTION', 773);
|
||||||
|
define('SKILL_LOCKPICKING', 633);
|
||||||
|
|
||||||
|
|
||||||
// AchievementCriteriaCondition
|
// AchievementCriteriaCondition
|
||||||
define('ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH', 1); // reset progress on death
|
define('ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH', 1); // reset progress on death
|
||||||
define('ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP', 3); // requires you to be on specific map, reset at change
|
define('ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP', 3); // requires you to be on specific map, reset at change
|
||||||
@@ -886,6 +1321,314 @@ define('CND_ALIVE', 36); // target is alive:
|
|||||||
define('CND_HP_VAL', 37); // targets absolute health: amount, operator, NULL
|
define('CND_HP_VAL', 37); // targets absolute health: amount, operator, NULL
|
||||||
define('CND_HP_PCT', 38); // targets relative health: amount, operator, NULL
|
define('CND_HP_PCT', 38); // targets relative health: amount, operator, NULL
|
||||||
|
|
||||||
|
// TrinityCore - SmartAI
|
||||||
|
define('SAI_SRC_TYPE_CREATURE', 0);
|
||||||
|
define('SAI_SRC_TYPE_OBJECT', 1);
|
||||||
|
define('SAI_SRC_TYPE_AREATRIGGER', 2);
|
||||||
|
define('SAI_SRC_TYPE_ACTIONLIST', 9);
|
||||||
|
|
||||||
|
define('SAI_EVENT_FLAG_NO_REPEAT', 0x0001);
|
||||||
|
define('SAI_EVENT_FLAG_DIFFICULTY_0', 0x0002);
|
||||||
|
define('SAI_EVENT_FLAG_DIFFICULTY_1', 0x0004);
|
||||||
|
define('SAI_EVENT_FLAG_DIFFICULTY_2', 0x0008);
|
||||||
|
define('SAI_EVENT_FLAG_DIFFICULTY_3', 0x0010);
|
||||||
|
define('SAI_EVENT_FLAG_NO_RESET', 0x0100);
|
||||||
|
define('SAI_EVENT_FLAG_WHILE_CHARMED', 0x0200);
|
||||||
|
|
||||||
|
define('SAI_EVENT_UPDATE_IC', 0); // In combat.
|
||||||
|
define('SAI_EVENT_UPDATE_OOC', 1); // Out of combat.
|
||||||
|
define('SAI_EVENT_HEALTH_PCT', 2); // Health Percentage
|
||||||
|
define('SAI_EVENT_MANA_PCT', 3); // Mana Percentage
|
||||||
|
define('SAI_EVENT_AGGRO', 4); // On Creature Aggro
|
||||||
|
define('SAI_EVENT_KILL', 5); // On Creature Kill
|
||||||
|
define('SAI_EVENT_DEATH', 6); // On Creature Death
|
||||||
|
define('SAI_EVENT_EVADE', 7); // On Creature Evade Attack
|
||||||
|
define('SAI_EVENT_SPELLHIT', 8); // On Creature/Gameobject Spell Hit
|
||||||
|
define('SAI_EVENT_RANGE', 9); // On Target In Range
|
||||||
|
define('SAI_EVENT_OOC_LOS', 10); // On Target In Distance Out of Combat
|
||||||
|
define('SAI_EVENT_RESPAWN', 11); // On Creature/Gameobject Respawn
|
||||||
|
define('SAI_EVENT_TARGET_HEALTH_PCT', 12); // On Target Health Percentage
|
||||||
|
define('SAI_EVENT_VICTIM_CASTING', 13); // On Target Casting Spell
|
||||||
|
define('SAI_EVENT_FRIENDLY_HEALTH', 14); // On Friendly Health Deficit
|
||||||
|
define('SAI_EVENT_FRIENDLY_IS_CC', 15); //
|
||||||
|
define('SAI_EVENT_FRIENDLY_MISSING_BUFF', 16); // On Friendly Lost Buff
|
||||||
|
define('SAI_EVENT_SUMMONED_UNIT', 17); // On Creature/Gameobject Summoned Unit
|
||||||
|
define('SAI_EVENT_TARGET_MANA_PCT', 18); // On Target Mana Percentage
|
||||||
|
define('SAI_EVENT_ACCEPTED_QUEST', 19); // On Target Accepted Quest
|
||||||
|
define('SAI_EVENT_REWARD_QUEST', 20); // On Target Rewarded Quest
|
||||||
|
define('SAI_EVENT_REACHED_HOME', 21); // On Creature Reached Home
|
||||||
|
define('SAI_EVENT_RECEIVE_EMOTE', 22); // On Receive Emote.
|
||||||
|
define('SAI_EVENT_HAS_AURA', 23); // On Creature Has Aura
|
||||||
|
define('SAI_EVENT_TARGET_BUFFED', 24); // On Target Buffed With Spell
|
||||||
|
define('SAI_EVENT_RESET', 25); // After Combat, On Respawn or Spawn
|
||||||
|
define('SAI_EVENT_IC_LOS', 26); // On Target In Distance In Combat
|
||||||
|
define('SAI_EVENT_PASSENGER_BOARDED', 27); //
|
||||||
|
define('SAI_EVENT_PASSENGER_REMOVED', 28); //
|
||||||
|
define('SAI_EVENT_CHARMED', 29); // On Creature Charmed
|
||||||
|
define('SAI_EVENT_CHARMED_TARGET', 30); // On Target Charmed
|
||||||
|
define('SAI_EVENT_SPELLHIT_TARGET', 31); // On Target Spell Hit
|
||||||
|
define('SAI_EVENT_DAMAGED', 32); // On Creature Damaged
|
||||||
|
define('SAI_EVENT_DAMAGED_TARGET', 33); // On Target Damaged
|
||||||
|
define('SAI_EVENT_MOVEMENTINFORM', 34); // WAYPOINT_MOTION_TYPE = 2, POINT_MOTION_TYPE = 8
|
||||||
|
define('SAI_EVENT_SUMMON_DESPAWNED', 35); // On Summoned Unit Despawned
|
||||||
|
define('SAI_EVENT_CORPSE_REMOVED', 36); // On Creature Corpse Removed
|
||||||
|
define('SAI_EVENT_AI_INIT', 37); //
|
||||||
|
define('SAI_EVENT_DATA_SET', 38); // On Creature/Gameobject Data Set, Can be used with SMART_ACTION_SET_DATA
|
||||||
|
define('SAI_EVENT_WAYPOINT_START', 39); // On Creature Waypoint ID Started
|
||||||
|
define('SAI_EVENT_WAYPOINT_REACHED', 40); // On Creature Waypoint ID Reached
|
||||||
|
// define('SAI_EVENT_TRANSPORT_ADDPLAYER', 41); //
|
||||||
|
// define('SAI_EVENT_TRANSPORT_ADDCREATURE', 42); //
|
||||||
|
// define('SAI_EVENT_TRANSPORT_REMOVE_PLAYER', 43); //
|
||||||
|
// define('SAI_EVENT_TRANSPORT_RELOCATE', 44); //
|
||||||
|
// define('SAI_EVENT_INSTANCE_PLAYER_ENTER', 45); //
|
||||||
|
define('SAI_EVENT_AREATRIGGER_ONTRIGGER', 46); //
|
||||||
|
// define('SAI_EVENT_QUEST_ACCEPTED', 47); // On Target Quest Accepted
|
||||||
|
// define('SAI_EVENT_QUEST_OBJ_COMPLETION', 48); // On Target Quest Objective Completed
|
||||||
|
// define('SAI_EVENT_QUEST_COMPLETION', 49); // On Target Quest Completed
|
||||||
|
// define('SAI_EVENT_QUEST_REWARDED', 50); // On Target Quest Rewarded
|
||||||
|
// define('SAI_EVENT_QUEST_FAIL', 51); // On Target Quest Field
|
||||||
|
define('SAI_EVENT_TEXT_OVER', 52); // On TEXT_OVER Event Triggered After SMART_ACTION_TALK
|
||||||
|
define('SAI_EVENT_RECEIVE_HEAL', 53); // On Creature Received Healing
|
||||||
|
define('SAI_EVENT_JUST_SUMMONED', 54); // On Creature Just spawned
|
||||||
|
define('SAI_EVENT_WAYPOINT_PAUSED', 55); // On Creature Paused at Waypoint ID
|
||||||
|
define('SAI_EVENT_WAYPOINT_RESUMED', 56); // On Creature Resumed after Waypoint ID
|
||||||
|
define('SAI_EVENT_WAYPOINT_STOPPED', 57); // On Creature Stopped On Waypoint ID
|
||||||
|
define('SAI_EVENT_WAYPOINT_ENDED', 58); // On Creature Waypoint Path Ended
|
||||||
|
define('SAI_EVENT_TIMED_EVENT_TRIGGERED', 59); //
|
||||||
|
define('SAI_EVENT_UPDATE', 60); //
|
||||||
|
define('SAI_EVENT_LINK', 61); // Used to link together multiple events as a chain of events.
|
||||||
|
define('SAI_EVENT_GOSSIP_SELECT', 62); // On gossip clicked (gossip_menu_option335).
|
||||||
|
define('SAI_EVENT_JUST_CREATED', 63); //
|
||||||
|
define('SAI_EVENT_GOSSIP_HELLO', 64); // On Right-Click Creature/Gameobject that have gossip enabled.
|
||||||
|
define('SAI_EVENT_FOLLOW_COMPLETED', 65); //
|
||||||
|
define('SAI_EVENT_EVENT_PHASE_CHANGE', 66); // On event phase mask set
|
||||||
|
define('SAI_EVENT_IS_BEHIND_TARGET', 67); // On Creature is behind target.
|
||||||
|
define('SAI_EVENT_GAME_EVENT_START', 68); // On game_event started.
|
||||||
|
define('SAI_EVENT_GAME_EVENT_END', 69); // On game_event ended.
|
||||||
|
define('SAI_EVENT_GO_STATE_CHANGED', 70); //
|
||||||
|
define('SAI_EVENT_GO_EVENT_INFORM', 71); //
|
||||||
|
define('SAI_EVENT_ACTION_DONE', 72); //
|
||||||
|
define('SAI_EVENT_ON_SPELLCLICK', 73); //
|
||||||
|
define('SAI_EVENT_FRIENDLY_HEALTH_PCT', 74); //
|
||||||
|
define('SAI_EVENT_DISTANCE_CREATURE', 75); // On creature guid OR any instance of creature entry is within distance.
|
||||||
|
define('SAI_EVENT_DISTANCE_GAMEOBJECT', 76); // On gameobject guid OR any instance of gameobject entry is within distance.
|
||||||
|
define('SAI_EVENT_COUNTER_SET', 77); // If the value of specified counterID is equal to a specified value
|
||||||
|
// define('SAI_EVENT_SCENE_START', 78); // don't use on 3.3.5a
|
||||||
|
// define('SAI_EVENT_SCENE_TRIGGER', 79); // don't use on 3.3.5a
|
||||||
|
// define('SAI_EVENT_SCENE_CANCEL', 80); // don't use on 3.3.5a
|
||||||
|
// define('SAI_EVENT_SCENE_COMPLETE', 81); // don't use on 3.3.5a
|
||||||
|
define('SAI_EVENT_SUMMONED_UNIT_DIES', 82); // CreatureId(0 all), CooldownMin, CooldownMax
|
||||||
|
|
||||||
|
define('SAI_ACTION_NONE', 0); // Do nothing
|
||||||
|
define('SAI_ACTION_TALK', 1); // Param2 in Milliseconds.
|
||||||
|
define('SAI_ACTION_SET_FACTION', 2); // Sets faction to creature.
|
||||||
|
define('SAI_ACTION_MORPH_TO_ENTRY_OR_MODEL', 3); // Take DisplayID of creature (param1) OR Turn to DisplayID (param2) OR Both = 0 for Demorph
|
||||||
|
define('SAI_ACTION_SOUND', 4); // TextRange = 0 only sends sound to self, TextRange = 1 sends sound to everyone in visibility range
|
||||||
|
define('SAI_ACTION_PLAY_EMOTE', 5); // Play Emote
|
||||||
|
define('SAI_ACTION_FAIL_QUEST', 6); // Fail Quest of Target
|
||||||
|
define('SAI_ACTION_OFFER_QUEST', 7); // Add Quest to Target
|
||||||
|
define('SAI_ACTION_SET_REACT_STATE', 8); // React State. Can be Passive (0), Defensive (1), Aggressive (2), Assist (3).
|
||||||
|
define('SAI_ACTION_ACTIVATE_GOBJECT', 9); // Activate Object
|
||||||
|
define('SAI_ACTION_RANDOM_EMOTE', 10); // Play Random Emote
|
||||||
|
define('SAI_ACTION_CAST', 11); // Cast Spell ID at Target
|
||||||
|
define('SAI_ACTION_SUMMON_CREATURE', 12); // Summon Unit
|
||||||
|
define('SAI_ACTION_THREAT_SINGLE_PCT', 13); // Change Threat Percentage for Single Target
|
||||||
|
define('SAI_ACTION_THREAT_ALL_PCT', 14); // Change Threat Percentage for All Enemies
|
||||||
|
define('SAI_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS', 15); //
|
||||||
|
// define('SAI_ACTION_SET_INGAME_PHASE_ID', 16); // For 4.3.4 + only
|
||||||
|
define('SAI_ACTION_SET_EMOTE_STATE', 17); // Play Emote Continuously
|
||||||
|
define('SAI_ACTION_SET_UNIT_FLAG', 18); // Can set Multi-able flags at once
|
||||||
|
define('SAI_ACTION_REMOVE_UNIT_FLAG', 19); // Can Remove Multi-able flags at once
|
||||||
|
define('SAI_ACTION_AUTO_ATTACK', 20); // Stop or Continue Automatic Attack.
|
||||||
|
define('SAI_ACTION_ALLOW_COMBAT_MOVEMENT', 21); // Allow or Disable Combat Movement
|
||||||
|
define('SAI_ACTION_SET_EVENT_PHASE', 22); //
|
||||||
|
define('SAI_ACTION_INC_EVENT_PHASE', 23); // Set param1 OR param2 (not both). Value 0 has no effect.
|
||||||
|
define('SAI_ACTION_EVADE', 24); // Evade Incoming Attack
|
||||||
|
define('SAI_ACTION_FLEE_FOR_ASSIST', 25); // If you want the fleeing NPC to say '%s attempts to run away in fear' on flee, use 1 on param1. 0 for no message.
|
||||||
|
define('SAI_ACTION_CALL_GROUPEVENTHAPPENS', 26); //
|
||||||
|
define('SAI_ACTION_COMBAT_STOP', 27); //
|
||||||
|
define('SAI_ACTION_REMOVEAURASFROMSPELL', 28); // 0 removes all auras
|
||||||
|
define('SAI_ACTION_FOLLOW', 29); // Follow Target
|
||||||
|
define('SAI_ACTION_RANDOM_PHASE', 30); //
|
||||||
|
define('SAI_ACTION_RANDOM_PHASE_RANGE', 31); //
|
||||||
|
define('SAI_ACTION_RESET_GOBJECT', 32); // Reset Gameobject
|
||||||
|
define('SAI_ACTION_CALL_KILLEDMONSTER', 33); // This is the ID from quest_template.RequiredNpcOrGo
|
||||||
|
define('SAI_ACTION_SET_INST_DATA', 34); // Set Instance Data
|
||||||
|
// define('SAI_ACTION_SET_INST_DATA64', 35); // Set Instance Data uint64
|
||||||
|
define('SAI_ACTION_UPDATE_TEMPLATE', 36); // Updates creature_template to given entry
|
||||||
|
define('SAI_ACTION_DIE', 37); // Kill Target
|
||||||
|
define('SAI_ACTION_SET_IN_COMBAT_WITH_ZONE', 38); //
|
||||||
|
define('SAI_ACTION_CALL_FOR_HELP', 39); // If you want the NPC to say '%s calls for help!'. Use 1 on param1, 0 for no message.
|
||||||
|
define('SAI_ACTION_SET_SHEATH', 40); //
|
||||||
|
define('SAI_ACTION_FORCE_DESPAWN', 41); // Despawn Target after param1 in Milliseconds. If you want to set respawn time set param2 in seconds.
|
||||||
|
define('SAI_ACTION_SET_INVINCIBILITY_HP_LEVEL', 42); // If you use both params, only percent will be used.
|
||||||
|
define('SAI_ACTION_MOUNT_TO_ENTRY_OR_MODEL', 43); // Mount to Creature Entry (param1) OR Mount to Creature Display (param2) Or both = 0 for Unmount
|
||||||
|
define('SAI_ACTION_SET_INGAME_PHASE_MASK', 44); //
|
||||||
|
define('SAI_ACTION_SET_DATA', 45); // Set Data For Target, can be used with SMART_EVENT_DATA_SET
|
||||||
|
define('SAI_ACTION_ATTACK_STOP', 46); //
|
||||||
|
define('SAI_ACTION_SET_VISIBILITY', 47); // Makes creature Visible = 1 or Invisible = 0
|
||||||
|
define('SAI_ACTION_SET_ACTIVE', 48); //
|
||||||
|
define('SAI_ACTION_ATTACK_START', 49); // Allows basic melee swings to creature.
|
||||||
|
define('SAI_ACTION_SUMMON_GO', 50); // Spawns Gameobject, use target_type to set spawn position.
|
||||||
|
define('SAI_ACTION_KILL_UNIT', 51); // Kills Creature.
|
||||||
|
define('SAI_ACTION_ACTIVATE_TAXI', 52); // Sends player to flight path. You have to be close to Flight Master, which gives Taxi ID you need.
|
||||||
|
define('SAI_ACTION_WP_START', 53); // Creature starts Waypoint Movement. Use waypoints table to create movement.
|
||||||
|
define('SAI_ACTION_WP_PAUSE', 54); // Creature pauses its Waypoint Movement for given time.
|
||||||
|
define('SAI_ACTION_WP_STOP', 55); // Creature stops its Waypoint Movement.
|
||||||
|
define('SAI_ACTION_ADD_ITEM', 56); // Adds item(s) to player.
|
||||||
|
define('SAI_ACTION_REMOVE_ITEM', 57); // Removes item(s) from player.
|
||||||
|
define('SAI_ACTION_INSTALL_AI_TEMPLATE', 58); //
|
||||||
|
define('SAI_ACTION_SET_RUN', 59); //
|
||||||
|
define('SAI_ACTION_SET_DISABLE_GRAVITY', 60); // Only works for creatures with inhabit air.
|
||||||
|
define('SAI_ACTION_SET_SWIM', 61); //
|
||||||
|
define('SAI_ACTION_TELEPORT', 62); // Continue this action with the TARGET_TYPE column. Use any target_type (except 0), and use target_x, target_y, target_z, target_o as the coordinates
|
||||||
|
define('SAI_ACTION_SET_COUNTER', 63); //
|
||||||
|
define('SAI_ACTION_STORE_TARGET_LIST', 64); //
|
||||||
|
define('SAI_ACTION_WP_RESUME', 65); // Creature continues in its Waypoint Movement.
|
||||||
|
define('SAI_ACTION_SET_ORIENTATION', 66); //
|
||||||
|
define('SAI_ACTION_CREATE_TIMED_EVENT', 67); //
|
||||||
|
define('SAI_ACTION_PLAYMOVIE', 68); //
|
||||||
|
define('SAI_ACTION_MOVE_TO_POS', 69); // PointId is called by SMART_EVENT_MOVEMENTINFORM. Continue this action with the TARGET_TYPE column. Use any target_type, and use target_x, target_y, target_z, target_o as the coordinates
|
||||||
|
define('SAI_ACTION_ENABLE_TEMP_GOBJ', 70); // param1 = duration
|
||||||
|
define('SAI_ACTION_EQUIP', 71); // only slots with mask set will be sent to client, bits are 1, 2, 4, leaving mask 0 is defaulted to mask 7 (send all), Slots1-3 are only used if no Param1 is set
|
||||||
|
define('SAI_ACTION_CLOSE_GOSSIP', 72); // Closes gossip window.
|
||||||
|
define('SAI_ACTION_TRIGGER_TIMED_EVENT', 73); //
|
||||||
|
define('SAI_ACTION_REMOVE_TIMED_EVENT', 74); //
|
||||||
|
define('SAI_ACTION_ADD_AURA', 75); // Adds aura to player(s). Use target_type 17 to make AoE aura.
|
||||||
|
define('SAI_ACTION_OVERRIDE_SCRIPT_BASE_OBJECT', 76); // WARNING: CAN CRASH CORE, do not use if you dont know what you are doing
|
||||||
|
define('SAI_ACTION_RESET_SCRIPT_BASE_OBJECT', 77); //
|
||||||
|
define('SAI_ACTION_CALL_SCRIPT_RESET', 78); //
|
||||||
|
define('SAI_ACTION_SET_RANGED_MOVEMENT', 79); // Sets movement to follow at a specific range to the target.
|
||||||
|
define('SAI_ACTION_CALL_TIMED_ACTIONLIST', 80); //
|
||||||
|
define('SAI_ACTION_SET_NPC_FLAG', 81); //
|
||||||
|
define('SAI_ACTION_ADD_NPC_FLAG', 82); //
|
||||||
|
define('SAI_ACTION_REMOVE_NPC_FLAG', 83); //
|
||||||
|
define('SAI_ACTION_SIMPLE_TALK', 84); // Makes a player say text. SMART_EVENT_TEXT_OVER is not triggered and whispers can not be used.
|
||||||
|
define('SAI_ACTION_SELF_CAST', 85); // spellID, castFlags
|
||||||
|
define('SAI_ACTION_CROSS_CAST', 86); // This action is used to make selected caster (in CasterTargetType) to cast spell. Actual target is entered in target_type as normally.
|
||||||
|
define('SAI_ACTION_CALL_RANDOM_TIMED_ACTIONLIST', 87); // Will select one entry from the ones provided. 0 is ignored.
|
||||||
|
define('SAI_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST', 88); // 0 is ignored.
|
||||||
|
define('SAI_ACTION_RANDOM_MOVE', 89); // Creature moves to random position in given radius.
|
||||||
|
define('SAI_ACTION_SET_UNIT_FIELD_BYTES_1', 90); //
|
||||||
|
define('SAI_ACTION_REMOVE_UNIT_FIELD_BYTES_1', 91); //
|
||||||
|
define('SAI_ACTION_INTERRUPT_SPELL', 92); // This action allows you to interrupt the current spell being cast. If you do not set the spellId, the core will find the current spell depending on the withDelay and the withInstant values.
|
||||||
|
define('SAI_ACTION_SEND_GO_CUSTOM_ANIM', 93); //
|
||||||
|
define('SAI_ACTION_SET_DYNAMIC_FLAG', 94); //
|
||||||
|
define('SAI_ACTION_ADD_DYNAMIC_FLAG', 95); //
|
||||||
|
define('SAI_ACTION_REMOVE_DYNAMIC_FLAG', 96); //
|
||||||
|
define('SAI_ACTION_JUMP_TO_POS', 97); //
|
||||||
|
define('SAI_ACTION_SEND_GOSSIP_MENU', 98); // Can be used together with 'SMART_EVENT_GOSSIP_HELLO' to set custom gossip.
|
||||||
|
define('SAI_ACTION_GO_SET_LOOT_STATE', 99); //
|
||||||
|
define('SAI_ACTION_SEND_TARGET_TO_TARGET', 100); // Send targets previously stored with SMART_ACTION_STORE_TARGET, to another npc/go, the other npc/go can then access them as if it was its own stored list
|
||||||
|
define('SAI_ACTION_SET_HOME_POS', 101); // Use with SMART_TARGET_SELF or SMART_TARGET_POSITION
|
||||||
|
define('SAI_ACTION_SET_HEALTH_REGEN', 102); // Sets the current creatures health regen on or off.
|
||||||
|
define('SAI_ACTION_SET_ROOT', 103); // Enables or disables creature movement
|
||||||
|
define('SAI_ACTION_SET_GO_FLAG', 104); // oldFlag = newFlag
|
||||||
|
define('SAI_ACTION_ADD_GO_FLAG', 105); // oldFlag |= newFlag
|
||||||
|
define('SAI_ACTION_REMOVE_GO_FLAG', 106); // oldFlag &= ~newFlag
|
||||||
|
define('SAI_ACTION_SUMMON_CREATURE_GROUP', 107); // Use creature_summon_groups table. SAI target has no effect, use 0
|
||||||
|
define('SAI_ACTION_SET_POWER', 108); //
|
||||||
|
define('SAI_ACTION_ADD_POWER', 109); //
|
||||||
|
define('SAI_ACTION_REMOVE_POWER', 110); //
|
||||||
|
define('SAI_ACTION_GAME_EVENT_STOP', 111); //
|
||||||
|
define('SAI_ACTION_GAME_EVENT_START', 112); //
|
||||||
|
define('SAI_ACTION_START_CLOSEST_WAYPOINT', 113); // Make target follow closest waypoint to its location
|
||||||
|
define('SAI_ACTION_MOVE_OFFSET', 114); // Use target_x, target_y, target_z With target_type=1
|
||||||
|
define('SAI_ACTION_RANDOM_SOUND', 115); //
|
||||||
|
define('SAI_ACTION_SET_CORPSE_DELAY', 116); //
|
||||||
|
define('SAI_ACTION_DISABLE_EVADE', 117); //
|
||||||
|
define('SAI_ACTION_GO_SET_GO_STATE', 118); //
|
||||||
|
define('SAI_ACTION_SET_CAN_FLY', 119); //
|
||||||
|
define('SAI_ACTION_REMOVE_AURAS_BY_TYPE', 120); //
|
||||||
|
define('SAI_ACTION_SET_SIGHT_DIST', 121); //
|
||||||
|
define('SAI_ACTION_FLEE', 122); //
|
||||||
|
define('SAI_ACTION_ADD_THREAT', 123); //
|
||||||
|
define('SAI_ACTION_LOAD_EQUIPMENT', 124); //
|
||||||
|
define('SAI_ACTION_TRIGGER_RANDOM_TIMED_EVENT', 125); //
|
||||||
|
define('SAI_ACTION_REMOVE_ALL_GAMEOBJECTS', 126); //
|
||||||
|
define('SAI_ACTION_PAUSE_MOVEMENT', 127); // MovementSlot (default = 0, active = 1, controlled = 2), PauseTime (ms), Force
|
||||||
|
// define('SAI_ACTION_PLAY_ANIMKIT', 128); // don't use on 3.3.5a
|
||||||
|
// define('SAI_ACTION_SCENE_PLAY', 129); // don't use on 3.3.5a
|
||||||
|
// define('SAI_ACTION_SCENE_CANCEL', 130); // don't use on 3.3.5a
|
||||||
|
define('SAI_ACTION_SPAWN_SPAWNGROUP', 131); //
|
||||||
|
define('SAI_ACTION_DESPAWN_SPAWNGROUP', 132); //
|
||||||
|
define('SAI_ACTION_RESPAWN_BY_SPAWNID', 133); // type, typeGuid - Use to respawn npcs and gobs, the target in this case is always=1 and only a single unit could be a target via the spawnId (action_param1, action_param2)
|
||||||
|
define('SAI_ACTION_INVOKER_CAST', 134); // spellID, castFlags
|
||||||
|
define('SAI_ACTION_PLAY_CINEMATIC', 135); // cinematic
|
||||||
|
define('SAI_ACTION_SET_MOVEMENT_SPEED', 136); // movementType, speedInteger, speedFraction
|
||||||
|
define('SAI_ACTION_PLAY_SPELL_VISUAL_KIT', 137); // spellVisualKitId (RESERVED, PENDING CHERRYPICK)
|
||||||
|
define('SAI_ACTION_OVERRIDE_LIGHT', 138); // zoneId, areaLightId, overrideLightID, transitionMilliseconds
|
||||||
|
define('SAI_ACTION_OVERRIDE_WEATHER', 139); // zoneId, weatherId, intensity
|
||||||
|
|
||||||
|
define('SAI_ACTION_ALL_SPELLCASTS', [SAI_ACTION_CAST, SAI_ACTION_ADD_AURA, SAI_ACTION_INVOKER_CAST, SAI_ACTION_SELF_CAST, SAI_ACTION_CROSS_CAST]);
|
||||||
|
define('SAI_ACTION_ALL_TIMED_ACTION_LISTS', [SAI_ACTION_CALL_TIMED_ACTIONLIST, SAI_ACTION_CALL_RANDOM_TIMED_ACTIONLIST, SAI_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST]);
|
||||||
|
|
||||||
|
define('SAI_CAST_FLAG_INTERRUPT_PREV', 0x01);
|
||||||
|
define('SAI_CAST_FLAG_TRIGGERED', 0x02);
|
||||||
|
// define('SAI_CAST_FORCE_CAST', 0x04); // Forces cast even if creature is out of mana or out of range
|
||||||
|
// define('SAI_CAST_NO_MELEE_IF_OOM', 0x08); // Prevents creature from entering melee if out of mana or out of range
|
||||||
|
// define('SAI_CAST_FORCE_TARGET_SELF', 0x10); // the target to cast this spell on itself
|
||||||
|
define('SAI_CAST_FLAG_AURA_MISSING', 0x20);
|
||||||
|
define('SAI_CAST_FLAG_COMBAT_MOVE', 0x40);
|
||||||
|
|
||||||
|
define('SAI_REACT_PASSIVE', 0);
|
||||||
|
define('SAI_REACT_DEFENSIVE', 1);
|
||||||
|
define('SAI_REACT_AGGRESSIVE', 2);
|
||||||
|
define('SAI_REACT_ASSIST', 3);
|
||||||
|
|
||||||
|
define('SAI_SUMMON_TIMED_OR_DEAD_DESPAWN', 1);
|
||||||
|
define('SAI_SUMMON_TIMED_OR_CORPSE_DESPAWN', 2);
|
||||||
|
define('SAI_SUMMON_TIMED_DESPAWN', 3);
|
||||||
|
define('SAI_SUMMON_TIMED_DESPAWN_OOC', 4);
|
||||||
|
define('SAI_SUMMON_CORPSE_DESPAWN', 5);
|
||||||
|
define('SAI_SUMMON_CORPSE_TIMED_DESPAWN', 6);
|
||||||
|
define('SAI_SUMMON_DEAD_DESPAWN', 7);
|
||||||
|
define('SAI_SUMMON_MANUAL_DESPAWN', 8);
|
||||||
|
|
||||||
|
define('SAI_TARGET_NONE', 0); // None.
|
||||||
|
define('SAI_TARGET_SELF', 1); // Self cast.
|
||||||
|
define('SAI_TARGET_VICTIM', 2); // Our current target. (ie: highest aggro)
|
||||||
|
define('SAI_TARGET_HOSTILE_SECOND_AGGRO', 3); // Second highest aggro.
|
||||||
|
define('SAI_TARGET_HOSTILE_LAST_AGGRO', 4); // Dead last on aggro.
|
||||||
|
define('SAI_TARGET_HOSTILE_RANDOM', 5); // Just any random target on our threat list.
|
||||||
|
define('SAI_TARGET_HOSTILE_RANDOM_NOT_TOP', 6); // Any random target except top threat.
|
||||||
|
define('SAI_TARGET_ACTION_INVOKER', 7); // Unit who caused this Event to occur.
|
||||||
|
define('SAI_TARGET_POSITION', 8); // Use xyz from event params.
|
||||||
|
define('SAI_TARGET_CREATURE_RANGE', 9); // (Random?) creature with specified ID within specified range.
|
||||||
|
define('SAI_TARGET_CREATURE_GUID', 10); // Creature with specified GUID.
|
||||||
|
define('SAI_TARGET_CREATURE_DISTANCE', 11); // Creature with specified ID within distance. (Different from #9?)
|
||||||
|
define('SAI_TARGET_STORED', 12); // Uses pre-stored target(list)
|
||||||
|
define('SAI_TARGET_GAMEOBJECT_RANGE', 13); // (Random?) object with specified ID within specified range.
|
||||||
|
define('SAI_TARGET_GAMEOBJECT_GUID', 14); // Object with specified GUID.
|
||||||
|
define('SAI_TARGET_GAMEOBJECT_DISTANCE', 15); // Object with specified ID within distance. (Different from #13?)
|
||||||
|
define('SAI_TARGET_INVOKER_PARTY', 16); // Invoker's party members
|
||||||
|
define('SAI_TARGET_PLAYER_RANGE', 17); // (Random?) player within specified range.
|
||||||
|
define('SAI_TARGET_PLAYER_DISTANCE', 18); // (Random?) player within specified distance. (Different from #17?)
|
||||||
|
define('SAI_TARGET_CLOSEST_CREATURE', 19); // Closest creature with specified ID within specified range.
|
||||||
|
define('SAI_TARGET_CLOSEST_GAMEOBJECT', 20); // Closest object with specified ID within specified range.
|
||||||
|
define('SAI_TARGET_CLOSEST_PLAYER', 21); // Closest player within specified range.
|
||||||
|
define('SAI_TARGET_ACTION_INVOKER_VEHICLE', 22); // Unit's vehicle who caused this Event to occur
|
||||||
|
define('SAI_TARGET_OWNER_OR_SUMMONER', 23); // Unit's owner or summoner
|
||||||
|
define('SAI_TARGET_THREAT_LIST', 24); // All units on creature's threat list
|
||||||
|
define('SAI_TARGET_CLOSEST_ENEMY', 25); // Any attackable target (creature or player) within maxDist
|
||||||
|
define('SAI_TARGET_CLOSEST_FRIENDLY', 26); // Any friendly unit (creature, player or pet) within maxDist
|
||||||
|
define('SAI_TARGET_LOOT_RECIPIENTS', 27); // All tagging players
|
||||||
|
define('SAI_TARGET_FARTHEST', 28); // Farthest unit on the threat list
|
||||||
|
define('SAI_TARGET_VEHICLE_PASSENGER', 29); // Vehicle can target unit in given seat
|
||||||
|
define('SAI_TARGET_CLOSEST_UNSPAWNED_GO', 30); // entry(0any), maxDist
|
||||||
|
|
||||||
|
define('SAI_TEMPLATE_BASIC', 0); //
|
||||||
|
define('SAI_TEMPLATE_CASTER', 1); // +JOIN: target_param1 as castFlag
|
||||||
|
define('SAI_TEMPLATE_TURRET', 2); // +JOIN: target_param1 as castflag
|
||||||
|
define('SAI_TEMPLATE_PASSIVE', 3); //
|
||||||
|
define('SAI_TEMPLATE_CAGED_GO_PART', 4); //
|
||||||
|
define('SAI_TEMPLATE_CAGED_NPC_PART', 5); //
|
||||||
|
|
||||||
|
define('SAI_SPAWN_FLAG_NONE', 0x00);
|
||||||
|
define('SAI_SPAWN_FLAG_IGNORE_RESPAWN', 0x01); // onSpawnIn - ignore & reset respawn timer
|
||||||
|
define('SAI_SPAWN_FLAG_FORCE_SPAWN', 0x02); // onSpawnIn - force additional spawn if already in world
|
||||||
|
define('SAI_SPAWN_FLAG_NOSAVE_RESPAWN', 0x04); // onDespawn - remove respawn time
|
||||||
|
|
||||||
// profiler queue interactions
|
// profiler queue interactions
|
||||||
define('PR_QUEUE_STATUS_ENDED', 0);
|
define('PR_QUEUE_STATUS_ENDED', 0);
|
||||||
define('PR_QUEUE_STATUS_WAITING', 1);
|
define('PR_QUEUE_STATUS_WAITING', 1);
|
||||||
@@ -912,4 +1655,12 @@ define('PR_EXCLUDE_GROUP_WRONG_PROFESSION', PR_EXCLUDE_GROUP_REQ_FISHING | PR
|
|||||||
define('PR_EXCLUDE_GROUP_REQ_CANT_BE_EXALTED', 0x400);
|
define('PR_EXCLUDE_GROUP_REQ_CANT_BE_EXALTED', 0x400);
|
||||||
define('PR_EXCLUDE_GROUP_ANY', 0x7FF);
|
define('PR_EXCLUDE_GROUP_ANY', 0x7FF);
|
||||||
|
|
||||||
|
// Areatrigger types
|
||||||
|
define('AT_TYPE_NONE', 0);
|
||||||
|
define('AT_TYPE_TAVERN', 1);
|
||||||
|
define('AT_TYPE_TELEPORT', 2);
|
||||||
|
define('AT_TYPE_OBJECTIVE', 3);
|
||||||
|
define('AT_TYPE_SMART', 4);
|
||||||
|
define('AT_TYPE_SCRIPT', 5);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -14,6 +14,25 @@ class Game
|
|||||||
'9d9d9d', 'ffffff', '1eff00', '0070dd', 'a335ee', 'ff8000', 'e5cc80', 'e6cc80'
|
'9d9d9d', 'ffffff', '1eff00', '0070dd', 'a335ee', 'ff8000', 'e5cc80', 'e6cc80'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static $specIconStrings = array(
|
||||||
|
-1 => 'inv_misc_questionmark',
|
||||||
|
0 => 'spell_nature_elementalabsorption',
|
||||||
|
6 => ['spell_deathknight_bloodpresence', 'spell_deathknight_frostpresence', 'spell_deathknight_unholypresence' ],
|
||||||
|
11 => ['spell_nature_starfall', 'ability_racial_bearform', 'spell_nature_healingtouch' ],
|
||||||
|
3 => ['ability_hunter_beasttaming', 'ability_marksmanship', 'ability_hunter_swiftstrike' ],
|
||||||
|
8 => ['spell_holy_magicalsentry', 'spell_fire_firebolt02', 'spell_frost_frostbolt02' ],
|
||||||
|
2 => ['spell_holy_holybolt', 'spell_holy_devotionaura', 'spell_holy_auraoflight' ],
|
||||||
|
5 => ['spell_holy_wordfortitude', 'spell_holy_holybolt', 'spell_shadow_shadowwordpain' ],
|
||||||
|
4 => ['ability_rogue_eviscerate', 'ability_backstab', 'ability_stealth' ],
|
||||||
|
7 => ['spell_nature_lightning', 'spell_nature_lightningshield', 'spell_nature_magicimmunity' ],
|
||||||
|
9 => ['spell_shadow_deathcoil', 'spell_shadow_metamorphosis', 'spell_shadow_rainoffire' ],
|
||||||
|
1 => ['ability_rogue_eviscerate', 'ability_warrior_innerrage', 'ability_warrior_defensivestance' ]
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $classFileStrings = array(
|
||||||
|
null, 'warrior', 'paladin', 'hunter', 'rogue', 'priest', 'deathknight', 'shaman', 'mage', 'warlock', null, 'druid'
|
||||||
|
);
|
||||||
|
|
||||||
private static $combatRatingToItemMod = array( // zero-indexed idx:CR; val:Mod
|
private static $combatRatingToItemMod = array( // zero-indexed idx:CR; val:Mod
|
||||||
null, 12, 13, 14, 15, 16, 17, 18, 19,
|
null, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||||
20, 21, 22, 23, 24, 25, 26, 27, 28,
|
20, 21, 22, 23, 24, 25, 26, 27, 28,
|
||||||
@@ -25,19 +44,19 @@ class Game
|
|||||||
ITEM_MOD_HEALTH_REGEN, ITEM_MOD_SPELL_PENETRATION, ITEM_MOD_BLOCK_VALUE
|
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
|
public static $questClasses = array(
|
||||||
-2 => [ 0],
|
-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],
|
0 => [ 1, 3, 4, 8, 9, 10, 11, 12, 25, 28, 33, 36, 38, 40, 41, 44, 45, 46, 47, 51, 85, 130, 132, 139, 154, 267, 1497, 1519, 1537, 2257, 3430, 3431, 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],
|
1 => [ 14, 15, 16, 17, 141, 148, 188, 215, 220, 331, 357, 361, 363, 400, 405, 406, 440, 490, 493, 618, 1377, 1637, 1638, 1657, 1769, 3524, 3525, 3526, 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],
|
2 => [ 206, 209, 491, 717, 718, 719, 721, 722, 796, 1176, 1196, 1337, 1417, 1581, 1583, 1584, 1941, 2017, 2057, 2100, 2366, 2367, 2437, 2557, 3535, 3562, 3688, 3713, 3714, 3715, 3716, 3717, 3789, 3790, 3791, 3792, 3842, 3847, 3848, 3849, 3905, 4100, 4131, 4196, 4228, 4264, 4265, 4272, 4277, 4415, 4416, 4494, 4522, 4723, 4809, 4813, 4820],
|
||||||
/*todo*/ 3 => [ 1977, 2159, 2562, 2677, 2717, 3428, 3429, 3456, 3606, 3805, 3836, 3840, 3842, 4273, 4500, 4722, 4812],
|
3 => [ 1977, 2159, 2677, 2717, 3428, 3429, 3456, 3457, 3606, 3607, 3805, 3836, 3845, 3923, 3959, 4075, 4273, 4493, 4500, 4603, 4722, 4812, 4987],
|
||||||
4 => [ -372, -263, -262, -261, -162, -161, -141, -82, -81, -61],
|
4 => [ -372, -263, -262, -261, -162, -161, -141, -82, -81, -61],
|
||||||
5 => [ -373, -371, -324, -304, -264, -201, -182, -181, -121, -101, -24],
|
5 => [ -373, -371, -324, -304, -264, -201, -182, -181, -121, -101, -24],
|
||||||
6 => [ -25, 2597, 3277, 3358, 3820, 4384, 4710],
|
6 => [ -25, 2597, 3277, 3358, 3820, 4384, 4710],
|
||||||
7 => [-1010, -368, -367, -365, -344, -241, -1],
|
7 => [-1010, -368, -367, -365, -344, -241, -1],
|
||||||
8 => [ 3483, 3518, 3519, 3520, 3521, 3522, 3523, 3679, 3703], // Skettis is no parent
|
8 => [ 3483, 3518, 3519, 3520, 3521, 3522, 3523, 3679, 3703],
|
||||||
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
|
9 => [-1005, -1003, -1002, -1001, -376, -375, -374, -370, -369, -366, -364, -41, -22], // 22: seasonal
|
||||||
10 => [ 65, 66, 67, 210, 394, 495, 3537, 3711, 4024, 4197, 4395, 4742] // Coldara is no parent
|
10 => [ 65, 66, 67, 210, 394, 495, 2817, 3537, 3711, 4024, 4197, 4395, 4742]
|
||||||
);
|
);
|
||||||
|
|
||||||
/* why:
|
/* why:
|
||||||
@@ -61,38 +80,6 @@ class Game
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
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
|
public static $sockets = array( // jsStyle Strings
|
||||||
'meta', 'red', 'yellow', 'blue'
|
'meta', 'red', 'yellow', 'blue'
|
||||||
);
|
);
|
||||||
@@ -115,6 +102,13 @@ class Game
|
|||||||
null, 4, 10, 9, 8, 6, 15, 11, 3, 5, null, 7
|
null, 4, 10, 9, 8, 6, 15, 11, 3, 5, null, 7
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static $areaFloors = array(
|
||||||
|
206 => 3, 209 => 7, 719 => 3, 721 => 4, 796 => 4, 1196 => 2, 1337 => 2, 1581 => 2, 1583 => 7, 1584 => 2,
|
||||||
|
2017 => 2, 2057 => 4, 2100 => 2, 2557 => 6, 2677 => 4, 3428 => 3, 3457 => 17, 3790 => 2, 3791 => 2, 3959 => 8,
|
||||||
|
3456 => 6, 3715 => 2, 3848 => 3, 3849 => 2, 4075 => 2, 4100 => 2, 4131 => 2, 4196 => 2, 4228 => 4, 4272 => 2,
|
||||||
|
4273 => 6, 4277 => 3, 4395 => 2, 4494 => 2, 4722 => 2, 4812 => 8
|
||||||
|
);
|
||||||
|
|
||||||
public static function itemModByRatingMask($mask)
|
public static function itemModByRatingMask($mask)
|
||||||
{
|
{
|
||||||
if (($mask & 0x1C000) == 0x1C000) // special case resilience
|
if (($mask & 0x1C000) == 0x1C000) // special case resilience
|
||||||
@@ -210,9 +204,7 @@ class Game
|
|||||||
);
|
);
|
||||||
|
|
||||||
// return list of integers, not strings
|
// return list of integers, not strings
|
||||||
array_walk($data, function (&$v, $k) {
|
$data = array_map('intVal', $data);
|
||||||
$v = intVal($v);
|
|
||||||
});
|
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
@@ -237,6 +229,262 @@ class Game
|
|||||||
return $pages;
|
return $pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*********************/
|
||||||
|
/* World Pos. Checks */
|
||||||
|
/*********************/
|
||||||
|
|
||||||
|
private static $alphaMapCache = [];
|
||||||
|
|
||||||
|
private static function alphaMapCheck(int $areaId, array &$set) : bool
|
||||||
|
{
|
||||||
|
$file = 'setup/generated/alphaMaps/'.$areaId.'.png';
|
||||||
|
if (!file_exists($file)) // file does not exist (probably instanced area)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// invalid and corner cases (literally)
|
||||||
|
if (!is_array($set) || empty($set['posX']) || empty($set['posY']) || $set['posX'] >= 100 || $set['posY'] >= 100)
|
||||||
|
{
|
||||||
|
$set = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty(self::$alphaMapCache[$areaId]))
|
||||||
|
self::$alphaMapCache[$areaId] = imagecreatefrompng($file);
|
||||||
|
|
||||||
|
// alphaMaps are 1000 x 1000, adapt points [black => valid point]
|
||||||
|
if (!imagecolorat(self::$alphaMapCache[$areaId], $set['posX'] * 10, $set['posY'] * 10))
|
||||||
|
$set = null;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function checkCoords(array $points) : array
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
$capitals = array( // capitals take precedence over their surroundings
|
||||||
|
1497, 1637, 1638, 3487, // Undercity, Ogrimmar, Thunder Bluff, Silvermoon City
|
||||||
|
1519, 1537, 1657, 3557, // Stormwind City, Ironforge, Darnassus, The Exodar
|
||||||
|
3703, 4395 // Shattrath City, Dalaran
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($points as $res)
|
||||||
|
{
|
||||||
|
if (self::alphaMapCheck($res['areaId'], $res))
|
||||||
|
{
|
||||||
|
if (!$res)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// some rough measure how central the spawn is on the map (the lower the number, the better)
|
||||||
|
// 0: perfect center; 1: touches a border
|
||||||
|
$q = abs( (($res['posX'] - 50) / 50) * (($res['posY'] - 50) / 50) );
|
||||||
|
|
||||||
|
if (empty($result) || $result[0] > $q)
|
||||||
|
$result = [$q, $res];
|
||||||
|
}
|
||||||
|
else if (in_array($res['areaId'], $capitals)) // capitals (auto-discovered) and no hand-made alphaMap available
|
||||||
|
return $res;
|
||||||
|
else if (empty($result)) // add with lowest quality if alpha map is missing
|
||||||
|
$result = [1.0, $res];
|
||||||
|
}
|
||||||
|
|
||||||
|
// spawn does not really match on a map, but we need at least one result
|
||||||
|
if (!$result)
|
||||||
|
{
|
||||||
|
usort($points, function ($a, $b) { return ($a['dist'] < $b['dist']) ? -1 : 1; });
|
||||||
|
$result = [1.0, $points[0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getWorldPosForGUID(int $type, int ...$guids) : array
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
switch ($type)
|
||||||
|
{
|
||||||
|
case Type::NPC:
|
||||||
|
$result = DB::World()->select('SELECT `guid` AS ARRAY_KEY, `id`, `map` AS `mapId`, `position_y` AS `posX`, `position_x` AS `posY` FROM creature WHERE `guid` IN (?a)', $guids);
|
||||||
|
break;
|
||||||
|
case Type::OBJECT:
|
||||||
|
$result = DB::World()->select('SELECT `guid` AS ARRAY_KEY, `id`, `map` AS `mapId`, `position_y` AS `posX`, `position_x` AS `posY` FROM gameobject WHERE `guid` IN (?a)', $guids);
|
||||||
|
break;
|
||||||
|
case Type::SOUND:
|
||||||
|
$result = DB::AoWoW()->select('SELECT `soundId` AS ARRAY_KEY, `soundId` AS `id`, `mapId`, `posX`, `posY` FROM dbc_soundemitters WHERE `soundId` IN (?a)', $guids);
|
||||||
|
break;
|
||||||
|
case Type::AREATRIGGER:
|
||||||
|
$result = DB::AoWoW()->select('SELECT `id` AS ARRAY_KEY, `id`, `mapId`, `posX`, `posY` FROM dbc_areatrigger WHERE `id` IN (?a)', $guids);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
trigger_error('Game::getWorldPosForGUID - instanced with unsupported TYPE '.$type, E_USER_WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function worldPosToZonePos(int $mapId, float $posX, float $posY, int $areaId = 0, int $floor = -1) : array
|
||||||
|
{
|
||||||
|
if (!$mapId < 0)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
$query = 'SELECT
|
||||||
|
dm.id,
|
||||||
|
wma.areaId,
|
||||||
|
IFNULL(dm.floor, 0) AS floor,
|
||||||
|
100 - ROUND(IF(dm.id IS NOT NULL, (?f - dm.minY) * 100 / (dm.maxY - dm.minY), (?f - wma.right) * 100 / (wma.left - wma.right)), 1) AS `posX`,
|
||||||
|
100 - ROUND(IF(dm.id IS NOT NULL, (?f - dm.minX) * 100 / (dm.maxX - dm.minX), (?f - wma.bottom) * 100 / (wma.top - wma.bottom)), 1) AS `posY`,
|
||||||
|
SQRT(POWER(abs(IF(dm.id IS NOT NULL, (?f - dm.minY) * 100 / (dm.maxY - dm.minY), (?f - wma.right) * 100 / (wma.left - wma.right)) - 50), 2) +
|
||||||
|
POWER(abs(IF(dm.id IS NOT NULL, (?f - dm.minX) * 100 / (dm.maxX - dm.minX), (?f - wma.bottom) * 100 / (wma.top - wma.bottom)) - 50), 2)) AS `dist`
|
||||||
|
FROM
|
||||||
|
dbc_worldmaparea wma
|
||||||
|
LEFT JOIN
|
||||||
|
dbc_dungeonmap dm ON dm.mapId = IF(?d AND (wma.mapId NOT IN (0, 1, 530, 571) OR wma.areaId = 4395), wma.mapId, -1)
|
||||||
|
WHERE
|
||||||
|
wma.mapId = ?d AND IF(?d, wma.areaId = ?d, wma.areaId <> 0){ AND IF(dm.floor IS NULL, 1, dm.floor = ?d)}
|
||||||
|
HAVING
|
||||||
|
(`posX` BETWEEN 0.1 AND 99.9 AND `posY` BETWEEN 0.1 AND 99.9)
|
||||||
|
ORDER BY
|
||||||
|
`dist` ASC';
|
||||||
|
|
||||||
|
// dist BETWEEN 0 (center) AND 70.7 (corner)
|
||||||
|
$points = DB::Aowow()->select($query, $posX, $posX, $posY, $posY, $posX, $posX, $posY, $posY, 1, $mapId, $areaId, $areaId, $floor < 0 ? DBSIMPLE_SKIP : $floor);
|
||||||
|
if (!$points) // retry: TC counts pre-instance subareas as instance-maps .. which have no map file
|
||||||
|
$points = DB::Aowow()->select($query, $posX, $posX, $posY, $posY, $posX, $posX, $posY, $posY, 0, $mapId, 0, 0, DBSIMPLE_SKIP);
|
||||||
|
|
||||||
|
if (!is_array($points))
|
||||||
|
{
|
||||||
|
trigger_error('Game::worldPosToZonePos - dbc query failed', E_USER_ERROR);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $points;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getQuotesForCreature(int $creatureId, bool $asHTML = false, string $talkSource = '') : array
|
||||||
|
{
|
||||||
|
$nQuotes = 0;
|
||||||
|
$quotes = [];
|
||||||
|
$soundIds = [];
|
||||||
|
|
||||||
|
$quoteSrc = DB::World()->select('
|
||||||
|
SELECT
|
||||||
|
ct.GroupID AS ARRAY_KEY, ct.ID as ARRAY_KEY2,
|
||||||
|
ct.`Type` AS `talkType`,
|
||||||
|
ct.TextRange AS `range`,
|
||||||
|
IFNULL(bct.`LanguageID`, ct.`Language`) AS lang,
|
||||||
|
IFNULL(NULLIF(bct.Text, ""), IFNULL(NULLIF(bct.Text1, ""), IFNULL(ct.`Text`, ""))) AS text_loc0,
|
||||||
|
{IFNULL(NULLIF(bctl.Text, ""), IFNULL(NULLIF(bctl.Text1, ""), IFNULL(ctl.Text, ""))) AS text_loc?d,}
|
||||||
|
IF(bct.SoundEntriesID > 0, bct.SoundEntriesID, ct.Sound) AS soundId
|
||||||
|
FROM
|
||||||
|
creature_text ct
|
||||||
|
{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
|
||||||
|
broadcast_text_locale bctl ON ct.BroadcastTextId = bctl.ID AND bctl.locale = ?}
|
||||||
|
WHERE
|
||||||
|
ct.CreatureID = ?d',
|
||||||
|
User::$localeId ?: DBSIMPLE_SKIP,
|
||||||
|
User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP,
|
||||||
|
User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP,
|
||||||
|
$creatureId
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($quoteSrc as $grp => $text)
|
||||||
|
{
|
||||||
|
$group = [];
|
||||||
|
foreach ($text as $t)
|
||||||
|
{
|
||||||
|
if ($t['soundId'])
|
||||||
|
$soundIds[] = $t['soundId'];
|
||||||
|
|
||||||
|
$msg = Util::localizedString($t, 'text');
|
||||||
|
if (!$msg)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// fixup .. either set %s for emotes or dont >.<
|
||||||
|
if (in_array($t['talkType'], [2, 16]) && strpos($msg, '%s') === false)
|
||||||
|
$msg = '%s '.$msg;
|
||||||
|
|
||||||
|
// fixup: bad case-insensivity
|
||||||
|
$msg = Util::parseHtmlText(str_replace('%S', '%s', htmlentities($msg)), !$asHTML);
|
||||||
|
|
||||||
|
if ($talkSource)
|
||||||
|
$msg = sprintf($msg, $talkSource);
|
||||||
|
|
||||||
|
// make type css compatible
|
||||||
|
switch ($t['talkType'])
|
||||||
|
{
|
||||||
|
case 1: // yell:
|
||||||
|
case 14: $t['talkType'] = 1; break; // - dark red
|
||||||
|
case 2: // emote:
|
||||||
|
case 16: // "
|
||||||
|
case 3: // boss emote:
|
||||||
|
case 41: $t['talkType'] = 4; break; // - orange
|
||||||
|
case 4: // whisper:
|
||||||
|
case 15: // "
|
||||||
|
case 5: // boss whisper:
|
||||||
|
case 42: $t['talkType'] = 3; break; // - pink-ish
|
||||||
|
default: $t['talkType'] = 2; // [type: 0, 12] say: yellow-ish
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// prefix
|
||||||
|
$pre = '';
|
||||||
|
if ($t['talkType'] != 4)
|
||||||
|
$pre = ($talkSource ?: '%s').' '.Lang::npc('textTypes', $t['talkType']).Lang::main('colon').($t['lang'] ? '['.Lang::game('languages', $t['lang']).'] ' : null);
|
||||||
|
|
||||||
|
if ($asHTML)
|
||||||
|
$msg = '<div><span class="s'.$t['talkType'].'">%s'.($t['range'] ? sprintf(Util::$dfnString, Lang::npc('textRanges', $t['range']), $msg) : $msg).'</span></div>';
|
||||||
|
else
|
||||||
|
$msg = '[div][span class=s'.$t['talkType'].']%s'.html_entity_decode($msg).'[/span][/div]';
|
||||||
|
|
||||||
|
$line = array(
|
||||||
|
'range' => $t['range'],
|
||||||
|
'text' => $msg,
|
||||||
|
'prefix' => $pre
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
$nQuotes++;
|
||||||
|
$group[] = $line;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($group)
|
||||||
|
$quotes[$grp] = $group;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$quotes, $nQuotes, $soundIds];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getBreakpointsForSkill(int $skillId, int $reqLevel) : array
|
||||||
|
{
|
||||||
|
switch ($skillId)
|
||||||
|
{
|
||||||
|
case SKILL_HERBALISM:
|
||||||
|
case SKILL_LOCKPICKING:
|
||||||
|
case SKILL_JEWELCRAFTING:
|
||||||
|
case SKILL_INSCRIPTION:
|
||||||
|
case SKILL_SKINNING:
|
||||||
|
case SKILL_MINING:
|
||||||
|
$points = [$reqLevel]; // red/orange
|
||||||
|
|
||||||
|
if ($reqLevel + 25 <= MAX_SKILL) // orange/yellow
|
||||||
|
$points[] = $reqLevel + 25;
|
||||||
|
|
||||||
|
if ($reqLevel + 50 <= MAX_SKILL) // yellow/green
|
||||||
|
$points[] = $reqLevel + 50;
|
||||||
|
|
||||||
|
if ($reqLevel + 100 <= MAX_SKILL) // green/grey
|
||||||
|
$points[] = $reqLevel + 100;
|
||||||
|
|
||||||
|
return $points;
|
||||||
|
default:
|
||||||
|
return [$reqLevel];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ require_once 'includes/markup.class.php'; // manipulate markup
|
|||||||
require_once 'includes/database.class.php'; // wrap DBSimple
|
require_once 'includes/database.class.php'; // wrap DBSimple
|
||||||
require_once 'includes/community.class.php'; // handle comments, screenshots and videos
|
require_once 'includes/community.class.php'; // handle comments, screenshots and videos
|
||||||
require_once 'includes/loot.class.php'; // build lv-tabs containing loot-information
|
require_once 'includes/loot.class.php'; // build lv-tabs containing loot-information
|
||||||
|
require_once 'includes/smartAI.class.php';
|
||||||
require_once 'localization/lang.class.php';
|
require_once 'localization/lang.class.php';
|
||||||
require_once 'pages/genericPage.class.php';
|
require_once 'pages/genericPage.class.php';
|
||||||
|
|
||||||
@@ -92,43 +93,48 @@ if (!empty($AoWoWconf['characters']))
|
|||||||
|
|
||||||
|
|
||||||
// load config to constants
|
// load config to constants
|
||||||
$sets = DB::isConnectable(DB_AOWOW) ? DB::Aowow()->select('SELECT `key` AS ARRAY_KEY, `value`, `flags` FROM ?_config') : [];
|
function loadConfig(bool $noPHP = false) : void
|
||||||
foreach ($sets as $k => $v)
|
|
||||||
{
|
{
|
||||||
$php = $v['flags'] & CON_FLAG_PHP;
|
$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']) && !($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);
|
$php = $v['flags'] & CON_FLAG_PHP;
|
||||||
continue;
|
if ($php && $noPHP)
|
||||||
}
|
continue;
|
||||||
|
|
||||||
if ($v['flags'] & CON_FLAG_TYPE_INT)
|
// this should not have been possible
|
||||||
$val = intVal($v['value']);
|
if (!strlen($v['value']) && !($v['flags'] & CON_FLAG_TYPE_STRING) && !$php)
|
||||||
else if ($v['flags'] & CON_FLAG_TYPE_FLOAT)
|
{
|
||||||
$val = floatVal($v['value']);
|
trigger_error('Aowow config value CFG_'.strtoupper($k).' is empty - config will not be used!', E_USER_ERROR);
|
||||||
else if ($v['flags'] & CON_FLAG_TYPE_BOOL)
|
continue;
|
||||||
$val = (bool)$v['value'];
|
}
|
||||||
else if ($v['flags'] & CON_FLAG_TYPE_STRING)
|
|
||||||
$val = preg_replace("/[\p{C}]/ui", '', $v['value']);
|
|
||||||
else if ($php)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($php)
|
if ($v['flags'] & CON_FLAG_TYPE_INT)
|
||||||
ini_set(strtolower($k), $val);
|
$val = intVal($v['value']);
|
||||||
else
|
else if ($v['flags'] & CON_FLAG_TYPE_FLOAT)
|
||||||
define('CFG_'.strtoupper($k), $val);
|
$val = floatVal($v['value']);
|
||||||
|
else if ($v['flags'] & CON_FLAG_TYPE_BOOL)
|
||||||
|
$val = (bool)$v['value'];
|
||||||
|
else if ($v['flags'] & CON_FLAG_TYPE_STRING)
|
||||||
|
$val = preg_replace("/[\p{C}]/ui", '', $v['value']);
|
||||||
|
else if ($php)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($php)
|
||||||
|
ini_set(strtolower($k), $val);
|
||||||
|
else if (!defined('CFG_'.strtoupper($k)))
|
||||||
|
define('CFG_'.strtoupper($k), $val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
loadConfig();
|
||||||
|
|
||||||
// handle non-fatal errors and notices
|
// handle non-fatal errors and notices
|
||||||
error_reporting(!empty($AoWoWconf['aowow']) && CFG_DEBUG ? E_AOWOW : 0);
|
error_reporting(!empty($AoWoWconf['aowow']) && CFG_DEBUG ? E_AOWOW : 0);
|
||||||
@@ -156,10 +162,12 @@ set_error_handler(function($errNo, $errStr, $errFile, $errLine)
|
|||||||
$errName = 'E_RECOVERABLE_ERROR';
|
$errName = 'E_RECOVERABLE_ERROR';
|
||||||
|
|
||||||
Util::addNote($uGroup, $errName.' - '.$errStr.' @ '.$errFile. ':'.$errLine);
|
Util::addNote($uGroup, $errName.' - '.$errStr.' @ '.$errFile. ':'.$errLine);
|
||||||
|
if (CLI)
|
||||||
|
CLI::write($errName.' - '.$errStr.' @ '.$errFile. ':'.$errLine, $errNo & 0x40A ? CLI::LOG_WARN : CLI::LOG_ERROR);
|
||||||
|
|
||||||
if (DB::isConnectable(DB_AOWOW))
|
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()',
|
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
|
AOWOW_REVISION, $errNo, $errFile, $errLine, CLI ? 'CLI' : ($_SERVER['QUERY_STRING'] ?? ''), User::$groups, $errStr
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -172,11 +180,11 @@ set_exception_handler(function ($ex)
|
|||||||
|
|
||||||
if (DB::isConnectable(DB_AOWOW))
|
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()',
|
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()
|
AOWOW_REVISION, $ex->getCode(), $ex->getFile(), $ex->getLine(), CLI ? 'CLI' : ($_SERVER['QUERY_STRING'] ?? ''), User::$groups, $ex->getMessage()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!CLI)
|
if (!CLI)
|
||||||
(new GenericPage(null))->error();
|
(new GenericPage())->error();
|
||||||
else
|
else
|
||||||
echo 'Exception - '.$ex->getMessage()."\n ".$ex->getFile(). '('.$ex->getLine().")\n".$ex->getTraceAsString()."\n";
|
echo 'Exception - '.$ex->getMessage()."\n ".$ex->getFile(). '('.$ex->getLine().")\n".$ex->getTraceAsString()."\n";
|
||||||
});
|
});
|
||||||
@@ -190,7 +198,7 @@ register_shutdown_function(function()
|
|||||||
|
|
||||||
if (DB::isConnectable(DB_AOWOW))
|
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()',
|
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']
|
AOWOW_REVISION, $e['type'], $e['file'], $e['line'], CLI ? 'CLI' : ($_SERVER['QUERY_STRING'] ?? ''), User::$groups, $e['message']
|
||||||
);
|
);
|
||||||
|
|
||||||
if (CLI)
|
if (CLI)
|
||||||
@@ -220,25 +228,45 @@ if (!CLI)
|
|||||||
|
|
||||||
session_set_cookie_params(15 * YEAR, '/', '', $secure, true);
|
session_set_cookie_params(15 * YEAR, '/', '', $secure, true);
|
||||||
session_cache_limiter('private');
|
session_cache_limiter('private');
|
||||||
session_start();
|
if (!session_start())
|
||||||
|
{
|
||||||
|
trigger_error('failed to start session', E_USER_ERROR);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (!empty($AoWoWconf['aowow']) && User::init())
|
if (!empty($AoWoWconf['aowow']) && User::init())
|
||||||
User::save(); // save user-variables in session
|
User::save(); // save user-variables in session
|
||||||
|
|
||||||
|
// set up some logging (~10 queries will execute before we init the user and load the config)
|
||||||
|
if (CFG_DEBUG && User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN))
|
||||||
|
{
|
||||||
|
DB::Aowow()->setLogger(['DB', 'logger']);
|
||||||
|
DB::World()->setLogger(['DB', 'logger']);
|
||||||
|
if (DB::isConnected(DB_AUTH))
|
||||||
|
DB::Auth()->setLogger(['DB', 'logger']);
|
||||||
|
|
||||||
|
if (!empty($AoWoWconf['characters']))
|
||||||
|
foreach ($AoWoWconf['characters'] as $idx => $__)
|
||||||
|
if (DB::isConnected(DB_CHARACTERS . $idx))
|
||||||
|
DB::Characters($idx)->setLogger(['DB', 'logger']);
|
||||||
|
}
|
||||||
|
|
||||||
// hard-override locale for this call (should this be here..?)
|
// hard-override locale for this call (should this be here..?)
|
||||||
// all strings attached..
|
// all strings attached..
|
||||||
if (!empty($AoWoWconf['aowow']))
|
if (!empty($AoWoWconf['aowow']))
|
||||||
{
|
{
|
||||||
if (isset($_GET['locale']) && (CFG_LOCALES & (1 << (int)$_GET['locale'])))
|
if (isset($_GET['locale']) && (int)$_GET['locale'] <= MAX_LOCALES && (int)$_GET['locale'] >= 0)
|
||||||
User::useLocale($_GET['locale']);
|
if (CFG_LOCALES & (1 << $_GET['locale']))
|
||||||
|
User::useLocale($_GET['locale']);
|
||||||
|
|
||||||
Lang::load(User::$localeString);
|
Lang::load(User::$localeString);
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse page-parameters .. sanitize before use!
|
// parse page-parameters .. sanitize before use!
|
||||||
$str = explode('&', $_SERVER['QUERY_STRING'], 2)[0];
|
$str = explode('&', mb_strtolower($_SERVER['QUERY_STRING'] ?? ''), 2)[0];
|
||||||
$_ = explode('=', $str, 2);
|
$_ = explode('=', $str, 2);
|
||||||
$pageCall = $_[0];
|
$pageCall = $_[0];
|
||||||
$pageParam = isset($_[1]) ? $_[1] : null;
|
$pageParam = $_[1] ?? '';
|
||||||
|
|
||||||
Util::$wowheadLink = 'http://'.Util::$subDomains[User::$localeId].'.wowhead.com/'.$str;
|
Util::$wowheadLink = 'http://'.Util::$subDomains[User::$localeId].'.wowhead.com/'.$str;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,9 +159,8 @@ class DbSimple_Connect
|
|||||||
*
|
*
|
||||||
* @param string $query запрос
|
* @param string $query запрос
|
||||||
*/
|
*/
|
||||||
public function addInit($query)
|
public function addInit(...$args)
|
||||||
{
|
{
|
||||||
$args = func_get_args();
|
|
||||||
if ($this->DbSimple !== null)
|
if ($this->DbSimple !== null)
|
||||||
return call_user_func_array(array(&$this->DbSimple, 'query'), $args);
|
return call_user_func_array(array(&$this->DbSimple, 'query'), $args);
|
||||||
$this->init[] = $args;
|
$this->init[] = $args;
|
||||||
|
|||||||
@@ -144,9 +144,8 @@ abstract class DbSimple_Database extends DbSimple_LastError
|
|||||||
* mixed select(string $query [, $arg1] [,$arg2] ...)
|
* mixed select(string $query [, $arg1] [,$arg2] ...)
|
||||||
* Execute query and return the result.
|
* Execute query and return the result.
|
||||||
*/
|
*/
|
||||||
public function select($query)
|
public function select(...$args)
|
||||||
{
|
{
|
||||||
$args = func_get_args();
|
|
||||||
$total = false;
|
$total = false;
|
||||||
return $this->_query($args, $total);
|
return $this->_query($args, $total);
|
||||||
}
|
}
|
||||||
@@ -157,10 +156,8 @@ abstract class DbSimple_Database extends DbSimple_LastError
|
|||||||
* Total number of found rows (independent to LIMIT) is returned in $total
|
* Total number of found rows (independent to LIMIT) is returned in $total
|
||||||
* (in most cases second query is performed to calculate $total).
|
* (in most cases second query is performed to calculate $total).
|
||||||
*/
|
*/
|
||||||
public function selectPage(&$total, $query)
|
public function selectPage(&$total, ...$args)
|
||||||
{
|
{
|
||||||
$args = func_get_args();
|
|
||||||
array_shift($args);
|
|
||||||
$total = true;
|
$total = true;
|
||||||
return $this->_query($args, $total);
|
return $this->_query($args, $total);
|
||||||
}
|
}
|
||||||
@@ -173,9 +170,8 @@ abstract class DbSimple_Database extends DbSimple_LastError
|
|||||||
* because PHP DOES NOT generates notice on $row['abc'] if $row === null
|
* because PHP DOES NOT generates notice on $row['abc'] if $row === null
|
||||||
* or $row === false (but, if $row is empty array, notice is generated).
|
* or $row === false (but, if $row is empty array, notice is generated).
|
||||||
*/
|
*/
|
||||||
public function selectRow()
|
public function selectRow(...$args)
|
||||||
{
|
{
|
||||||
$args = func_get_args();
|
|
||||||
$total = false;
|
$total = false;
|
||||||
$rows = $this->_query($args, $total);
|
$rows = $this->_query($args, $total);
|
||||||
if (!is_array($rows)) return $rows;
|
if (!is_array($rows)) return $rows;
|
||||||
@@ -188,9 +184,8 @@ abstract class DbSimple_Database extends DbSimple_LastError
|
|||||||
* array selectCol(string $query [, $arg1] [,$arg2] ...)
|
* array selectCol(string $query [, $arg1] [,$arg2] ...)
|
||||||
* Return the first column of query result as array.
|
* Return the first column of query result as array.
|
||||||
*/
|
*/
|
||||||
public function selectCol()
|
public function selectCol(...$args)
|
||||||
{
|
{
|
||||||
$args = func_get_args();
|
|
||||||
$total = false;
|
$total = false;
|
||||||
$rows = $this->_query($args, $total);
|
$rows = $this->_query($args, $total);
|
||||||
if (!is_array($rows)) return $rows;
|
if (!is_array($rows)) return $rows;
|
||||||
@@ -203,9 +198,8 @@ abstract class DbSimple_Database extends DbSimple_LastError
|
|||||||
* Return the first cell of the first column of query result.
|
* Return the first cell of the first column of query result.
|
||||||
* If no one row selected, return null.
|
* If no one row selected, return null.
|
||||||
*/
|
*/
|
||||||
public function selectCell()
|
public function selectCell(...$args)
|
||||||
{
|
{
|
||||||
$args = func_get_args();
|
|
||||||
$total = false;
|
$total = false;
|
||||||
$rows = $this->_query($args, $total);
|
$rows = $this->_query($args, $total);
|
||||||
if (!is_array($rows)) return $rows;
|
if (!is_array($rows)) return $rows;
|
||||||
@@ -221,9 +215,8 @@ abstract class DbSimple_Database extends DbSimple_LastError
|
|||||||
* mixed query(string $query [, $arg1] [,$arg2] ...)
|
* mixed query(string $query [, $arg1] [,$arg2] ...)
|
||||||
* Alias for select(). May be used for INSERT or UPDATE queries.
|
* Alias for select(). May be used for INSERT or UPDATE queries.
|
||||||
*/
|
*/
|
||||||
public function query()
|
public function query(...$args)
|
||||||
{
|
{
|
||||||
$args = func_get_args();
|
|
||||||
$total = false;
|
$total = false;
|
||||||
return $this->_query($args, $total);
|
return $this->_query($args, $total);
|
||||||
}
|
}
|
||||||
@@ -246,9 +239,8 @@ abstract class DbSimple_Database extends DbSimple_LastError
|
|||||||
* Нужно для сложных запросов, состоящих из кусков, которые полезно сохранить
|
* Нужно для сложных запросов, состоящих из кусков, которые полезно сохранить
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function subquery()
|
public function subquery(...$args)
|
||||||
{
|
{
|
||||||
$args = func_get_args();
|
|
||||||
$this->_expandPlaceholders($args,$this->_placeholderNativeArgs !== null);
|
$this->_expandPlaceholders($args,$this->_placeholderNativeArgs !== null);
|
||||||
return new DbSimple_SubQuery($args);
|
return new DbSimple_SubQuery($args);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ class DbSimple_Mysqli extends DbSimple_Database
|
|||||||
{
|
{
|
||||||
$this->_lastQuery = $queryMain;
|
$this->_lastQuery = $queryMain;
|
||||||
$this->_expandPlaceholders($queryMain, false);
|
$this->_expandPlaceholders($queryMain, false);
|
||||||
|
mysqli_ping($this->link);
|
||||||
$result = mysqli_query($this->link, $queryMain[0]);
|
$result = mysqli_query($this->link, $queryMain[0]);
|
||||||
if ($result === false)
|
if ($result === false)
|
||||||
return $this->_setDbError($queryMain[0]);
|
return $this->_setDbError($queryMain[0]);
|
||||||
|
|||||||
187
includes/libs/qqFileUploader.class.php
Normal file
187
includes/libs/qqFileUploader.class.php
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/****************************************
|
||||||
|
Example of how to use this uploader class...
|
||||||
|
You can uncomment the following lines (minus the require) to use these as your defaults.
|
||||||
|
|
||||||
|
// list of valid extensions, ex. array("jpeg", "xml", "bmp")
|
||||||
|
$allowedExtensions = array();
|
||||||
|
// max file size in bytes
|
||||||
|
$sizeLimit = 10 * 1024 * 1024;
|
||||||
|
|
||||||
|
require('valums-file-uploader/server/php.php');
|
||||||
|
$uploader = new qqFileUploader($allowedExtensions, $sizeLimit);
|
||||||
|
|
||||||
|
// Call handleUpload() with the name of the folder, relative to PHP's getcwd()
|
||||||
|
$result = $uploader->handleUpload('uploads/');
|
||||||
|
|
||||||
|
// to pass data through iframe you will need to encode all html tags
|
||||||
|
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
|
||||||
|
|
||||||
|
/******************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle file uploads via XMLHttpRequest
|
||||||
|
*/
|
||||||
|
class qqUploadedFileXhr
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Save the file to the specified path
|
||||||
|
* @return boolean TRUE on success
|
||||||
|
*/
|
||||||
|
function save(string $path) : bool
|
||||||
|
{
|
||||||
|
$input = fopen("php://input", "r");
|
||||||
|
$temp = tmpfile();
|
||||||
|
$realSize = stream_copy_to_stream($input, $temp);
|
||||||
|
fclose($input);
|
||||||
|
|
||||||
|
if ($realSize != $this->getSize())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$target = fopen($path, "w");
|
||||||
|
fseek($temp, 0, SEEK_SET);
|
||||||
|
stream_copy_to_stream($temp, $target);
|
||||||
|
fclose($target);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getName() : string
|
||||||
|
{
|
||||||
|
return $_GET['qqfile'];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSize(): int
|
||||||
|
{
|
||||||
|
if (isset($_SERVER["CONTENT_LENGTH"]))
|
||||||
|
return (int)$_SERVER["CONTENT_LENGTH"];
|
||||||
|
|
||||||
|
throw new Exception('Getting content length is not supported.');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle file uploads via regular form post (uses the $_FILES array)
|
||||||
|
*/
|
||||||
|
class qqUploadedFileForm
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Save the file to the specified path
|
||||||
|
* @return boolean TRUE on success
|
||||||
|
*/
|
||||||
|
function save(string $path) : bool
|
||||||
|
{
|
||||||
|
if(!move_uploaded_file($_FILES['qqfile']['tmp_name'], $path))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getName() : string
|
||||||
|
{
|
||||||
|
return $_FILES['qqfile']['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSize() : int
|
||||||
|
{
|
||||||
|
return $_FILES['qqfile']['size'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class qqFileUploader
|
||||||
|
{
|
||||||
|
private $allowedExtensions = array();
|
||||||
|
private $sizeLimit = 10485760;
|
||||||
|
private $file;
|
||||||
|
|
||||||
|
public function __construct(array $allowedExtensions = array(), $sizeLimit = 10485760)
|
||||||
|
{
|
||||||
|
$this->allowedExtensions = array_map("strtolower", $allowedExtensions);
|
||||||
|
$this->sizeLimit = $sizeLimit;
|
||||||
|
|
||||||
|
$this->checkServerSettings();
|
||||||
|
|
||||||
|
if (isset($_GET['qqfile']))
|
||||||
|
$this->file = new qqUploadedFileXhr();
|
||||||
|
else if (isset($_FILES['qqfile']))
|
||||||
|
$this->file = new qqUploadedFileForm();
|
||||||
|
else
|
||||||
|
$this->file = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName() : string
|
||||||
|
{
|
||||||
|
return $this->file?->getName() ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkServerSettings() : void
|
||||||
|
{
|
||||||
|
$postSize = $this->toBytes(ini_get('post_max_size'));
|
||||||
|
$uploadSize = $this->toBytes(ini_get('upload_max_filesize'));
|
||||||
|
|
||||||
|
if ($postSize < $this->sizeLimit || $uploadSize < $this->sizeLimit)
|
||||||
|
{
|
||||||
|
$size = max(1, $this->sizeLimit / 1024 / 1024) . 'M';
|
||||||
|
die("{'error':'increase post_max_size and upload_max_filesize to $size'}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function toBytes(string $str) : int
|
||||||
|
{
|
||||||
|
$val = trim($str);
|
||||||
|
$last = strtolower(substr($str, -1, 1));
|
||||||
|
switch ($last)
|
||||||
|
{
|
||||||
|
case 'g': $val *= 1024;
|
||||||
|
case 'm': $val *= 1024;
|
||||||
|
case 'k': $val *= 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns array('success' => true, 'newFilename' => 'myDoc123.doc') or array('error' => 'error message')
|
||||||
|
*/
|
||||||
|
function handleUpload(string $uploadDirectory, string $newName = '', bool $replaceOldFile = FALSE) : array
|
||||||
|
{
|
||||||
|
if (!is_writable($uploadDirectory))
|
||||||
|
return ['error' => "Server error. Upload directory isn't writable."];
|
||||||
|
|
||||||
|
if (!$this->file)
|
||||||
|
return ['error' => 'No files were uploaded.'];
|
||||||
|
|
||||||
|
$size = $this->file->getSize();
|
||||||
|
|
||||||
|
if ($size == 0)
|
||||||
|
return ['error' => 'File is empty'];
|
||||||
|
|
||||||
|
if ($size > $this->sizeLimit)
|
||||||
|
return ['error' => 'File is too large'];
|
||||||
|
|
||||||
|
$pathinfo = pathinfo($this->getName());
|
||||||
|
$filename = $newName ?: $pathinfo['filename'];
|
||||||
|
//$filename = md5(uniqid());
|
||||||
|
$ext = @$pathinfo['extension']; // hide notices if extension is empty
|
||||||
|
|
||||||
|
if ($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions))
|
||||||
|
{
|
||||||
|
$these = implode(', ', $this->allowedExtensions);
|
||||||
|
return ['error' => 'File has an invalid extension, it should be one of '. $these . '.'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't overwrite previous files that were uploaded
|
||||||
|
if (!$replaceOldFile)
|
||||||
|
while (file_exists($uploadDirectory . $filename . '.' . $ext))
|
||||||
|
$filename .= rand(10, 99);
|
||||||
|
|
||||||
|
if ($this->file->save($uploadDirectory . $filename . '.' . $ext))
|
||||||
|
return ['success' => true, 'newFilename' => $filename . '.' . $ext];
|
||||||
|
else
|
||||||
|
return ['error' => 'Could not save uploaded file. The upload was cancelled, or server error encountered'];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ class Loot
|
|||||||
|
|
||||||
private $entry = 0; // depending on the lookup itemId oder templateId
|
private $entry = 0; // depending on the lookup itemId oder templateId
|
||||||
private $results = [];
|
private $results = [];
|
||||||
|
private $chanceMods = [];
|
||||||
private $lootTemplates = array(
|
private $lootTemplates = array(
|
||||||
LOOT_REFERENCE, // internal
|
LOOT_REFERENCE, // internal
|
||||||
LOOT_ITEM, // item
|
LOOT_ITEM, // item
|
||||||
@@ -40,23 +41,23 @@ class Loot
|
|||||||
LOOT_SPELL // spell
|
LOOT_SPELL // spell
|
||||||
);
|
);
|
||||||
|
|
||||||
public function &iterate()
|
public function &iterate() : iterable
|
||||||
{
|
{
|
||||||
reset($this->results);
|
reset($this->results);
|
||||||
|
|
||||||
while (list($k, $__) = each($this->results))
|
foreach ($this->results as $k => $__)
|
||||||
yield $k => $this->results[$k];
|
yield $k => $this->results[$k];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getResult()
|
public function getResult() : array
|
||||||
{
|
{
|
||||||
return $this->results;
|
return $this->results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createStack($l) // issue: TC always has an equal distribution between min/max
|
private function createStack(array $l) : string // issue: TC always has an equal distribution between min/max
|
||||||
{
|
{
|
||||||
if (empty($l['min']) || empty($l['max']) || $l['max'] <= $l['min'])
|
if (empty($l['min']) || empty($l['max']) || $l['max'] <= $l['min'])
|
||||||
return null;
|
return '';
|
||||||
|
|
||||||
$stack = [];
|
$stack = [];
|
||||||
for ($i = $l['min']; $i <= $l['max']; $i++)
|
for ($i = $l['min']; $i <= $l['max']; $i++)
|
||||||
@@ -66,7 +67,7 @@ class Loot
|
|||||||
return json_encode($stack, JSON_NUMERIC_CHECK); // do not replace with Util::toJSON !
|
return json_encode($stack, JSON_NUMERIC_CHECK); // do not replace with Util::toJSON !
|
||||||
}
|
}
|
||||||
|
|
||||||
private function storeJSGlobals($data)
|
private function storeJSGlobals(array $data) : void
|
||||||
{
|
{
|
||||||
foreach ($data as $type => $jsData)
|
foreach ($data as $type => $jsData)
|
||||||
{
|
{
|
||||||
@@ -81,7 +82,62 @@ class Loot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getByContainerRecursive($tableName, $lootId, &$handledRefs, $groupId = 0, $baseChance = 1.0)
|
private function calcChance(array $refs, array $parents = []) : array
|
||||||
|
{
|
||||||
|
$retData = [];
|
||||||
|
$retKeys = [];
|
||||||
|
|
||||||
|
foreach ($refs as $rId => $ref)
|
||||||
|
{
|
||||||
|
// check for possible database inconsistencies
|
||||||
|
if (!$ref['chance'] && !$ref['isGrouped'])
|
||||||
|
trigger_error('Loot by Item: Ungrouped Item/Ref '.$ref['item'].' has 0% chance assigned!', E_USER_WARNING);
|
||||||
|
|
||||||
|
if ($ref['isGrouped'] && $ref['sumChance'] > 100)
|
||||||
|
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'])
|
||||||
|
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;
|
||||||
|
|
||||||
|
// apply inherited chanceMods
|
||||||
|
if (isset($this->chanceMods[$ref['item']]))
|
||||||
|
{
|
||||||
|
$chance *= $this->chanceMods[$ref['item']][0];
|
||||||
|
$chance = 1 - pow(1 - $chance, $this->chanceMods[$ref['item']][1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save chance for parent-ref
|
||||||
|
$this->chanceMods[$rId] = [$chance, $ref['multiplier']];
|
||||||
|
|
||||||
|
// refTemplate doesn't point to a new ref -> we are done
|
||||||
|
if (!in_array($rId, $parents))
|
||||||
|
{
|
||||||
|
$data = array(
|
||||||
|
'percent' => $chance,
|
||||||
|
'stack' => [$ref['min'], $ref['max']],
|
||||||
|
'count' => 1 // ..and one for the sort script
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($_ = self::createStack($ref))
|
||||||
|
$data['pctstack'] = $_;
|
||||||
|
|
||||||
|
// sort highest chances first
|
||||||
|
$i = 0;
|
||||||
|
for (; $i < count($retData); $i++)
|
||||||
|
if ($retData[$i]['percent'] < $data['percent'])
|
||||||
|
break;
|
||||||
|
|
||||||
|
array_splice($retData, $i, 0, [$data]);
|
||||||
|
array_splice($retKeys, $i, 0, [$rId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_combine($retKeys, $retData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getByContainerRecursive(string $tableName, int $lootId, array &$handledRefs, int $groupId = 0, float $baseChance = 1.0) : ?array
|
||||||
{
|
{
|
||||||
$loot = [];
|
$loot = [];
|
||||||
$rawItems = [];
|
$rawItems = [];
|
||||||
@@ -101,7 +157,8 @@ class Loot
|
|||||||
'quest' => $entry['QuestRequired'],
|
'quest' => $entry['QuestRequired'],
|
||||||
'group' => $entry['GroupId'],
|
'group' => $entry['GroupId'],
|
||||||
'parentRef' => $tableName == LOOT_REFERENCE ? $lootId : 0,
|
'parentRef' => $tableName == LOOT_REFERENCE ? $lootId : 0,
|
||||||
'realChanceMod' => $baseChance
|
'realChanceMod' => $baseChance,
|
||||||
|
'groupChance' => 0
|
||||||
);
|
);
|
||||||
|
|
||||||
// if ($entry['LootMode'] > 1)
|
// if ($entry['LootMode'] > 1)
|
||||||
@@ -134,7 +191,7 @@ class Loot
|
|||||||
// bandaid.. remove when propperly handling lootmodes
|
// bandaid.. remove when propperly handling lootmodes
|
||||||
if (!in_array($entry['Reference'], $handledRefs))
|
if (!in_array($entry['Reference'], $handledRefs))
|
||||||
{ // todo (high): find out, why i used this in the first place. (don't do drugs, kids)
|
{ // todo (high): find out, why i used this in the first place. (don't do drugs, kids)
|
||||||
list($data, $raw) = self::getByContainerRecursive(LOOT_REFERENCE, $entry['Reference'], $handledRefs, /*$entry['GroupId'],*/ 0, $entry['Chance'] / 100);
|
[$data, $raw] = self::getByContainerRecursive(LOOT_REFERENCE, $entry['Reference'], $handledRefs, /*$entry['GroupId'],*/ 0, $entry['Chance'] / 100);
|
||||||
|
|
||||||
$handledRefs[] = $entry['Reference'];
|
$handledRefs[] = $entry['Reference'];
|
||||||
|
|
||||||
@@ -167,11 +224,15 @@ class Loot
|
|||||||
}
|
}
|
||||||
else if ($entry['GroupId'] && $entry['Chance'])
|
else if ($entry['GroupId'] && $entry['Chance'])
|
||||||
{
|
{
|
||||||
if (empty($groupChances[$entry['GroupId']]))
|
|
||||||
$groupChances[$entry['GroupId']] = 0;
|
|
||||||
|
|
||||||
$groupChances[$entry['GroupId']] += $entry['Chance'];
|
|
||||||
$set['groupChance'] = $entry['Chance'];
|
$set['groupChance'] = $entry['Chance'];
|
||||||
|
|
||||||
|
if (!$entry['Reference'])
|
||||||
|
{
|
||||||
|
if (empty($groupChances[$entry['GroupId']]))
|
||||||
|
$groupChances[$entry['GroupId']] = 0;
|
||||||
|
|
||||||
|
$groupChances[$entry['GroupId']] += $entry['Chance'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else // shouldn't have happened
|
else // shouldn't have happened
|
||||||
{
|
{
|
||||||
@@ -192,21 +253,19 @@ class Loot
|
|||||||
trigger_error('Loot entry '.$lootId.' / group '.$k.' has a total chance of '.number_format($sum, 2).'%. Some items cannot drop!', E_USER_WARNING);
|
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;
|
$sum = 100;
|
||||||
}
|
}
|
||||||
|
// is applied as backReference to items with 0-chance
|
||||||
$cnt = empty($nGroupEquals[$k]) ? 1 : $nGroupEquals[$k];
|
$groupChances[$k] = (100 - $sum) / ($nGroupEquals[$k] ?: 1);
|
||||||
|
|
||||||
$groupChances[$k] = (100 - $sum) / $cnt; // is applied as backReference to items with 0-chance
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [$loot, array_unique($rawItems)];
|
return [$loot, array_unique($rawItems)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getByContainer($table, $entry)
|
public function getByContainer(string $table, int $entry): bool
|
||||||
{
|
{
|
||||||
$this->entry = intVal($entry);
|
$this->entry = intVal($entry);
|
||||||
|
|
||||||
if (!in_array($table, $this->lootTemplates) || !$this->entry)
|
if (!in_array($table, $this->lootTemplates) || !$this->entry)
|
||||||
return null;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
todo (high): implement conditions on loot (and conditions in general)
|
todo (high): implement conditions on loot (and conditions in general)
|
||||||
@@ -269,7 +328,7 @@ class Loot
|
|||||||
);
|
);
|
||||||
$this->results[] = array_merge($base, $data);
|
$this->results[] = array_merge($base, $data);
|
||||||
|
|
||||||
$this->jsGlobals[TYPE_ITEM][$loot['reference']] = $data;
|
$this->jsGlobals[Type::ITEM][$loot['reference']] = $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +380,7 @@ class Loot
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getByItem($entry, $maxResults = CFG_SQL_LIMIT_DEFAULT, $lootTableList = [])
|
public function getByItem(int $entry, int $maxResults = CFG_SQL_LIMIT_DEFAULT, array $lootTableList = []) : bool
|
||||||
{
|
{
|
||||||
$this->entry = intVal($entry);
|
$this->entry = intVal($entry);
|
||||||
|
|
||||||
@@ -350,13 +409,12 @@ class Loot
|
|||||||
['achievement', [], '$LANG.tab_rewardfrom', 'reward-from-achievement', [], [], []]
|
['achievement', [], '$LANG.tab_rewardfrom', 'reward-from-achievement', [], [], []]
|
||||||
);
|
);
|
||||||
$refResults = [];
|
$refResults = [];
|
||||||
$chanceMods = [];
|
|
||||||
$query = 'SELECT
|
$query = 'SELECT
|
||||||
lt1.entry AS ARRAY_KEY,
|
lt1.entry AS ARRAY_KEY,
|
||||||
IF(lt1.reference = 0, lt1.item, lt1.reference) AS item,
|
IF(lt1.reference = 0, lt1.item, lt1.reference) AS item,
|
||||||
lt1.chance,
|
lt1.chance,
|
||||||
SUM(IF(lt2.chance = 0, 1, 0)) AS nZeroItems,
|
SUM(IF(lt2.chance = 0, 1, 0)) AS nZeroItems,
|
||||||
SUM(lt2.chance) AS sumChance,
|
SUM(IF(lt2.reference = 0, lt2.chance, 0)) AS sumChance,
|
||||||
IF(lt1.groupid > 0, 1, 0) AS isGrouped,
|
IF(lt1.groupid > 0, 1, 0) AS isGrouped,
|
||||||
IF(lt1.reference = 0, lt1.mincount, 1) AS min,
|
IF(lt1.reference = 0, lt1.mincount, 1) AS min,
|
||||||
IF(lt1.reference = 0, lt1.maxcount, 1) AS max,
|
IF(lt1.reference = 0, lt1.maxcount, 1) AS max,
|
||||||
@@ -369,61 +427,6 @@ class Loot
|
|||||||
%s
|
%s
|
||||||
GROUP BY lt2.entry, lt2.groupid';
|
GROUP BY lt2.entry, lt2.groupid';
|
||||||
|
|
||||||
$calcChance = function ($refs, $parents = []) use (&$chanceMods)
|
|
||||||
{
|
|
||||||
$retData = [];
|
|
||||||
$retKeys = [];
|
|
||||||
|
|
||||||
foreach ($refs as $rId => $ref)
|
|
||||||
{
|
|
||||||
// check for possible database inconsistencies
|
|
||||||
if (!$ref['chance'] && !$ref['isGrouped'])
|
|
||||||
trigger_error('Loot by Item: Ungrouped Item/Ref '.$ref['item'].' has 0% chance assigned!', E_USER_WARNING);
|
|
||||||
|
|
||||||
if ($ref['isGrouped'] && $ref['sumChance'] > 100)
|
|
||||||
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'])
|
|
||||||
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;
|
|
||||||
|
|
||||||
// apply inherited chanceMods
|
|
||||||
if (isset($chanceMods[$ref['item']]))
|
|
||||||
{
|
|
||||||
$chance *= $chanceMods[$ref['item']][0];
|
|
||||||
$chance = 1 - pow(1 - $chance, $chanceMods[$ref['item']][1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// save chance for parent-ref
|
|
||||||
$chanceMods[$rId] = [$chance, $ref['multiplier']];
|
|
||||||
|
|
||||||
// refTemplate doesn't point to a new ref -> we are done
|
|
||||||
if (!in_array($rId, $parents))
|
|
||||||
{
|
|
||||||
$data = array(
|
|
||||||
'percent' => $chance,
|
|
||||||
'stack' => [$ref['min'], $ref['max']],
|
|
||||||
'count' => 1 // ..and one for the sort script
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($_ = self::createStack($ref))
|
|
||||||
$data['pctstack'] = $_;
|
|
||||||
|
|
||||||
// sort highest chances first
|
|
||||||
$i = 0;
|
|
||||||
for (; $i < count($retData); $i++)
|
|
||||||
if ($retData[$i]['percent'] < $data['percent'])
|
|
||||||
break;
|
|
||||||
|
|
||||||
array_splice($retData, $i, 0, [$data]);
|
|
||||||
array_splice($retKeys, $i, 0, [$rId]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_combine($retKeys, $retData);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
get references containing the item
|
get references containing the item
|
||||||
*/
|
*/
|
||||||
@@ -442,7 +445,7 @@ class Loot
|
|||||||
array_keys($curRefs)
|
array_keys($curRefs)
|
||||||
);
|
);
|
||||||
|
|
||||||
$refResults += $calcChance($curRefs, array_column($newRefs, 'item'));
|
$refResults += $this->calcChance($curRefs, array_column($newRefs, 'item'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -453,7 +456,7 @@ class Loot
|
|||||||
if ($lootTableList && !in_array($this->lootTemplates[$i], $lootTableList))
|
if ($lootTableList && !in_array($this->lootTemplates[$i], $lootTableList))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$result = $calcChance(DB::World()->select(
|
$result = $this->calcChance(DB::World()->select(
|
||||||
sprintf($query, '{lt1.reference IN (?a) OR }(lt1.reference = 0 AND lt1.item = ?d)'),
|
sprintf($query, '{lt1.reference IN (?a) OR }(lt1.reference = 0 AND lt1.item = ?d)'),
|
||||||
$this->lootTemplates[$i], $this->lootTemplates[$i],
|
$this->lootTemplates[$i], $this->lootTemplates[$i],
|
||||||
$refResults ? array_keys($refResults) : DBSIMPLE_SKIP,
|
$refResults ? array_keys($refResults) : DBSIMPLE_SKIP,
|
||||||
@@ -494,7 +497,7 @@ class Loot
|
|||||||
|
|
||||||
$srcData = $srcObj->getListviewData();
|
$srcData = $srcObj->getListviewData();
|
||||||
|
|
||||||
foreach ($srcObj->iterate() as $__id => $curTpl)
|
foreach ($srcObj->iterate() as $curTpl)
|
||||||
{
|
{
|
||||||
switch ($curTpl['typeCat'])
|
switch ($curTpl['typeCat'])
|
||||||
{
|
{
|
||||||
@@ -628,9 +631,8 @@ class Loot
|
|||||||
$this->results[$tabId] = [$data[0], $tabData];
|
$this->results[$tabId] = [$data[0], $tabData];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ class Markup
|
|||||||
$match[1] = 'achievement';
|
$match[1] = 'achievement';
|
||||||
else if ($match[1] == 'icondb')
|
else if ($match[1] == 'icondb')
|
||||||
$match[1] = 'icon';
|
$match[1] = 'icon';
|
||||||
else if ($match[1] == 'money')
|
|
||||||
|
if ($match[1] == 'money')
|
||||||
{
|
{
|
||||||
if (stripos($match[0], 'items'))
|
if (stripos($match[0], 'items'))
|
||||||
{
|
{
|
||||||
@@ -39,7 +40,7 @@ class Markup
|
|||||||
{
|
{
|
||||||
$sm = explode(',', $submatch[1]);
|
$sm = explode(',', $submatch[1]);
|
||||||
for ($i = 0; $i < count($sm); $i+=2)
|
for ($i = 0; $i < count($sm); $i+=2)
|
||||||
$this->jsGlobals[TYPE_ITEM][$sm[$i]] = $sm[$i];
|
$this->jsGlobals[Type::ITEM][$sm[$i]] = $sm[$i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,11 +50,11 @@ class Markup
|
|||||||
{
|
{
|
||||||
$sm = explode(',', $submatch[1]);
|
$sm = explode(',', $submatch[1]);
|
||||||
for ($i = 0; $i < count($sm); $i+=2)
|
for ($i = 0; $i < count($sm); $i+=2)
|
||||||
$this->jsGlobals[TYPE_CURRENCY][$sm[$i]] = $sm[$i];
|
$this->jsGlobals[Type::CURRENCY][$sm[$i]] = $sm[$i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ($type = array_search($match[1], Util::$typeStrings))
|
else if ($type = Type::getIndexFrom(Type::IDX_FILE_STR, $match[1]))
|
||||||
$this->jsGlobals[$type][$match[2]] = $match[2];
|
$this->jsGlobals[$type][$match[2]] = $match[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,8 +82,8 @@ class Markup
|
|||||||
$sm = explode(',', $submatch[1]);
|
$sm = explode(',', $submatch[1]);
|
||||||
for ($i = 0; $i < count($sm); $i += 2)
|
for ($i = 0; $i < count($sm); $i += 2)
|
||||||
{
|
{
|
||||||
if (!empty($globals[TYPE_ITEM][1][$sm[$i]]))
|
if (!empty($globals[Type::ITEM][1][$sm[$i]]))
|
||||||
$moneys[] = $globals[TYPE_ITEM][1][$sm[$i]]['name'];
|
$moneys[] = $globals[Type::ITEM][1][$sm[$i]]['name'];
|
||||||
else
|
else
|
||||||
$moneys[] = Util::ucFirst(Lang::game('item')).' #'.$sm[$i];
|
$moneys[] = Util::ucFirst(Lang::game('item')).' #'.$sm[$i];
|
||||||
}
|
}
|
||||||
@@ -96,8 +97,8 @@ class Markup
|
|||||||
$sm = explode(',', $submatch[1]);
|
$sm = explode(',', $submatch[1]);
|
||||||
for ($i = 0; $i < count($sm); $i += 2)
|
for ($i = 0; $i < count($sm); $i += 2)
|
||||||
{
|
{
|
||||||
if (!empty($globals[TYPE_CURRENCY][1][$sm[$i]]))
|
if (!empty($globals[Type::CURRENCY][1][$sm[$i]]))
|
||||||
$moneys[] = $globals[TYPE_CURRENCY][1][$sm[$i]]['name'];
|
$moneys[] = $globals[Type::CURRENCY][1][$sm[$i]]['name'];
|
||||||
else
|
else
|
||||||
$moneys[] = Util::ucFirst(Lang::game('curency')).' #'.$sm[$i];
|
$moneys[] = Util::ucFirst(Lang::game('curency')).' #'.$sm[$i];
|
||||||
}
|
}
|
||||||
@@ -106,8 +107,7 @@ class Markup
|
|||||||
|
|
||||||
return Lang::concat($moneys);
|
return Lang::concat($moneys);
|
||||||
}
|
}
|
||||||
|
if ($type = Type::getIndexFrom(Type::IDX_FILE_STR, $match[1]))
|
||||||
if ($type = array_search($match[1], Util::$typeStrings))
|
|
||||||
{
|
{
|
||||||
if (!empty($globals[$type][1][$match[2]]))
|
if (!empty($globals[$type][1][$match[2]]))
|
||||||
return $globals[$type][1][$match[2]]['name'];
|
return $globals[$type][1][$match[2]]['name'];
|
||||||
|
|||||||
@@ -33,7 +33,11 @@ class Profiler
|
|||||||
19 => [INVTYPE_TABARD], // tabard
|
19 => [INVTYPE_TABARD], // tabard
|
||||||
);
|
);
|
||||||
|
|
||||||
public static $raidProgression = array( // statisticAchievement => relevantCriterium
|
public static $raidProgression = array( // statisticAchievement => relevantCriterium ; don't forget to enable this in /js/Profiler.js as well
|
||||||
|
1361 => 5100, 1362 => 5101, 1363 => 5102, 1365 => 5104, 1366 => 5108, 1364 => 5110, 1369 => 5112, 1370 => 5113, 1371 => 5114, 1372 => 5117, 1373 => 5119, 1374 => 5120, 1375 => 7805, 1376 => 5122, 1377 => 5123, // Naxxramas 10
|
||||||
|
1367 => 5103, 1368 => 5111, 1378 => 5124, 1379 => 5125, 1380 => 5126, 1381 => 5127, 1382 => 5128, 1383 => 7806, 1384 => 5130, 1385 => 5131, 1386 => 5132, 1387 => 5133, 1388 => 5134, 1389 => 5135, 1390 => 5136, // Naxxramas 25
|
||||||
|
2856 => 9938, 2857 => 9939, 2858 => 9940, 2859 => 9941, 2861 => 9943, 2865 => 9947, 2866 => 9948, 2868 => 9950, 2869 => 9951, 2870 => 9952, 2863 => 10558, 2864 => 10559, 2862 => 10560, 2867 => 10565, 2860 => 10580, // Ulduar 10
|
||||||
|
2872 => 9954, 2873 => 9955, 2874 => 9956, 2884 => 9957, 2875 => 9959, 2879 => 9963, 2880 => 9964, 2882 => 9966, 2883 => 9967, 3236 => 10542, 3257 => 10561, 3256 => 10562, 3258 => 10563, 2881 => 10566, 2885 => 10581, // Ulduar 25
|
||||||
1098 => 3271, // Onyxia's Lair 10
|
1098 => 3271, // Onyxia's Lair 10
|
||||||
1756 => 13345, // Onyxia's Lair 25
|
1756 => 13345, // Onyxia's Lair 25
|
||||||
4031 => 12230, 4034 => 12234, 4038 => 12238, 4042 => 12242, 4046 => 12246, // Trial of the Crusader 25 nh
|
4031 => 12230, 4034 => 12234, 4038 => 12238, 4042 => 12242, 4046 => 12246, // Trial of the Crusader 25 nh
|
||||||
@@ -44,10 +48,10 @@ class Profiler
|
|||||||
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
|
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
|
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
|
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
|
4823 => 13467, // Ruby Sanctum 25 hc
|
||||||
// 4820 => 13465, // Ruby Sanctum 25 nh
|
4820 => 13465, // Ruby Sanctum 25 nh
|
||||||
// 4822 => 13468, // Ruby Sanctum 10 hc
|
4822 => 13468, // Ruby Sanctum 10 hc
|
||||||
// 4821 => 13466, // Ruby Sanctum 10 nh
|
4821 => 13466, // Ruby Sanctum 10 nh
|
||||||
);
|
);
|
||||||
|
|
||||||
public static function getBuyoutForItem($itemId)
|
public static function getBuyoutForItem($itemId)
|
||||||
@@ -108,7 +112,6 @@ class Profiler
|
|||||||
if ($queuePID && $queuePID != $pid)
|
if ($queuePID && $queuePID != $pid)
|
||||||
{
|
{
|
||||||
trigger_error('pSync - another queue with PID #'.$queuePID.' is already running', E_USER_ERROR);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +182,24 @@ class Profiler
|
|||||||
{
|
{
|
||||||
if (DB::isConnectable(DB_AUTH) && !self::$realms)
|
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);
|
self::$realms = DB::Auth()->select('SELECT
|
||||||
|
id AS ARRAY_KEY,
|
||||||
|
`name`,
|
||||||
|
CASE
|
||||||
|
WHEN timezone IN (2, 3, 4) THEN "us"
|
||||||
|
WHEN timezone IN (8, 9, 10, 11, 12) THEN "eu"
|
||||||
|
WHEN timezone = 6 THEN "kr"
|
||||||
|
WHEN timezone = 14 THEN "tw"
|
||||||
|
WHEN timezone = 16 THEN "cn"
|
||||||
|
END AS region
|
||||||
|
FROM
|
||||||
|
realmlist
|
||||||
|
WHERE
|
||||||
|
allowedSecurityLevel = 0 AND
|
||||||
|
gamebuild = ?d',
|
||||||
|
WOW_BUILD
|
||||||
|
);
|
||||||
|
|
||||||
foreach (self::$realms as $rId => $rData)
|
foreach (self::$realms as $rId => $rData)
|
||||||
{
|
{
|
||||||
if (DB::isConnectable(DB_CHARACTERS . $rId))
|
if (DB::isConnectable(DB_CHARACTERS . $rId))
|
||||||
@@ -214,19 +234,19 @@ class Profiler
|
|||||||
|
|
||||||
switch ($type)
|
switch ($type)
|
||||||
{
|
{
|
||||||
case TYPE_PROFILE:
|
case Type::PROFILE:
|
||||||
if ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d', $realmId, $guid))
|
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);
|
self::queueInsert($realmId, $guid, Type::PROFILE, $newId);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case TYPE_GUILD:
|
case Type::GUILD:
|
||||||
if ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_guild WHERE realm = ?d AND realmGUID = ?d', $realmId, $guid))
|
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);
|
self::queueInsert($realmId, $guid, Type::GUILD, $newId);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case TYPE_ARENA_TEAM:
|
case Type::ARENA_TEAM:
|
||||||
if ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_arena_team WHERE realm = ?d AND realmGUID = ?d', $realmId, $guid))
|
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);
|
self::queueInsert($realmId, $guid, Type::ARENA_TEAM, $newId);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -244,7 +264,7 @@ class Profiler
|
|||||||
|
|
||||||
public static function resyncStatus($type, array $subjectGUIDs)
|
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
|
$response = [CFG_PROFILER_ENABLE ? 2 : 0]; // in theory you could have multiple queues; used as divisor for: (15 / x) + 2
|
||||||
if (!$subjectGUIDs)
|
if (!$subjectGUIDs)
|
||||||
$response[] = [PR_QUEUE_STATUS_ENDED, 0, 0, PR_QUEUE_ERROR_CHAR];
|
$response[] = [PR_QUEUE_STATUS_ENDED, 0, 0, PR_QUEUE_ERROR_CHAR];
|
||||||
else
|
else
|
||||||
@@ -252,14 +272,14 @@ class Profiler
|
|||||||
// error out all profiles with status WORKING, that are older than 60sec
|
// 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);
|
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);
|
$subjectStatus = DB::Aowow()->select('SELECT typeId AS ARRAY_KEY, status, realm, errorCode 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);
|
$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)
|
foreach ($subjectGUIDs as $guid)
|
||||||
{
|
{
|
||||||
if (empty($subjectStatus[$guid])) // whelp, thats some error..
|
if (empty($subjectStatus[$guid])) // whelp, thats some error..
|
||||||
$response[] = [PR_QUEUE_STATUS_ERROR, 0, 0, PR_QUEUE_ERROR_UNK];
|
$response[] = [PR_QUEUE_STATUS_ERROR, 0, 0, PR_QUEUE_ERROR_UNK];
|
||||||
else if ($subjectStatus[$guid]['status'] == PR_QUEUE_STATUS_ERROR)
|
else if ($subjectStatus[$guid]['status'] == PR_QUEUE_STATUS_ERROR)
|
||||||
$response[] = [PR_QUEUE_STATUS_ERROR, 0, 0, $subjectStatus[$guid]['errCode']];
|
$response[] = [PR_QUEUE_STATUS_ERROR, 0, 0, $subjectStatus[$guid]['errorCode']];
|
||||||
else
|
else
|
||||||
$response[] = array(
|
$response[] = array(
|
||||||
$subjectStatus[$guid]['status'],
|
$subjectStatus[$guid]['status'],
|
||||||
@@ -281,11 +301,25 @@ class Profiler
|
|||||||
return false;
|
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
|
// 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']);
|
$profile = DB::Aowow()->selectRow('SELECT id, lastupdated FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d', $realmId, $char['guid']);
|
||||||
|
if (!$profile)
|
||||||
|
return false; // well ... it failed
|
||||||
|
|
||||||
|
$profileId = $profile['id'];
|
||||||
|
|
||||||
|
CLI::write('fetching char '.$char['name'].' (#'.$charGuid.') from realm #'.$realmId);
|
||||||
|
|
||||||
|
if (!$char['online'] && $char['logout_time'] <= $profile['lastupdated'])
|
||||||
|
{
|
||||||
|
DB::Aowow()->query('UPDATE ?_profiler_profiles SET lastupdated = ?d WHERE id = ?d', time(), $profileId);
|
||||||
|
CLI::write('char did not log in since last update. skipping...');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
CLI::write('fetching char #'.$charGuid.' from realm #'.$realmId);
|
|
||||||
CLI::write('writing...');
|
CLI::write('writing...');
|
||||||
|
|
||||||
|
$ra = (1 << ($char['race'] - 1));
|
||||||
|
$cl = (1 << ($char['class'] - 1));
|
||||||
|
|
||||||
/*************/
|
/*************/
|
||||||
/* equipment */
|
/* equipment */
|
||||||
@@ -364,20 +398,21 @@ class Profiler
|
|||||||
/**************/
|
/**************/
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'realm' => $realmId,
|
'realm' => $realmId,
|
||||||
'realmGUID' => $charGuid,
|
'realmGUID' => $charGuid,
|
||||||
'name' => $char['name'],
|
'name' => $char['name'],
|
||||||
'race' => $char['race'],
|
'renameItr' => 0,
|
||||||
'class' => $char['class'],
|
'race' => $char['race'],
|
||||||
'level' => $char['level'],
|
'class' => $char['class'],
|
||||||
'gender' => $char['gender'],
|
'level' => $char['level'],
|
||||||
'skincolor' => $char['playerBytes'] & 0xFF,
|
'gender' => $char['gender'],
|
||||||
'facetype' => ($char['playerBytes'] >> 8) & 0xFF, // maybe features
|
'skincolor' => $char['skin'],
|
||||||
'hairstyle' => ($char['playerBytes'] >> 16) & 0xFF,
|
'facetype' => $char['face'], // maybe features
|
||||||
'haircolor' => ($char['playerBytes'] >> 24) & 0xFF,
|
'hairstyle' => $char['hairStyle'],
|
||||||
'features' => $char['playerBytes2'] & 0xFF, // maybe facetype
|
'haircolor' => $char['hairColor'],
|
||||||
'title' => $char['chosenTitle'] ? DB::Aowow()->selectCell('SELECT id FROM ?_titles WHERE bitIdx = ?d', $char['chosenTitle']) : 0,
|
'features' => $char['facialStyle'], // maybe facetype
|
||||||
'playedtime' => $char['totaltime'],
|
'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),
|
'nomodelMask' => ($char['playerFlags'] & 0x400 ? (1 << SLOT_HEAD) : 0) | ($char['playerFlags'] & 0x800 ? (1 << SLOT_BACK) : 0),
|
||||||
'talenttree1' => 0,
|
'talenttree1' => 0,
|
||||||
'talenttree2' => 0,
|
'talenttree2' => 0,
|
||||||
@@ -386,28 +421,34 @@ class Profiler
|
|||||||
'talentbuild2' => '',
|
'talentbuild2' => '',
|
||||||
'glyphs1' => '',
|
'glyphs1' => '',
|
||||||
'glyphs2' => '',
|
'glyphs2' => '',
|
||||||
'activespec' => $char['activespec'],
|
'activespec' => $char['activeTalentGroup'],
|
||||||
'guild' => null,
|
'guild' => null,
|
||||||
'guildRank' => null,
|
'guildRank' => null,
|
||||||
'gearscore' => 0,
|
'gearscore' => 0,
|
||||||
'achievementpoints' => 0
|
'achievementpoints' => 0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// char is flagged for rename
|
||||||
|
if ($char['at_login'] & 0x1)
|
||||||
|
{
|
||||||
|
$ri = DB::Aowow()->selectCell('SELECT MAX(renameItr) FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d AND name = ?', $realmId, $charGuid, $char['name']);
|
||||||
|
$data['renameItr'] = $ri ? ++$ri : 1;
|
||||||
|
}
|
||||||
|
|
||||||
/********************/
|
/********************/
|
||||||
/* talents + glyphs */
|
/* 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']);
|
$t = DB::Characters($realmId)->selectCol('SELECT talentGroup 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']);
|
$g = DB::Characters($realmId)->select('SELECT talentGroup 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++)
|
for ($i = 0; $i < 2; $i++)
|
||||||
{
|
{
|
||||||
// talents
|
// talents
|
||||||
for ($j = 0; $j < 3; $j++)
|
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);
|
$_ = 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('', $_);
|
$data['talentbuild'.($i + 1)] .= implode('', $_);
|
||||||
if ($char['activespec'] == $i)
|
if ($data['activespec'] == $i)
|
||||||
$data['talenttree'.($j + 1)] = array_sum($_);
|
$data['talenttree'.($j + 1)] = array_sum($_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,7 +484,7 @@ class Profiler
|
|||||||
if ($gemItems)
|
if ($gemItems)
|
||||||
{
|
{
|
||||||
$gemScores = new ItemList(array(['id', array_column($gemItems, 0)]));
|
$gemScores = new ItemList(array(['id', array_column($gemItems, 0)]));
|
||||||
foreach ($gemItems as list($itemId, $mult))
|
foreach ($gemItems as [$itemId, $mult])
|
||||||
if (isset($gemScores->json[$itemId]['gearscore']))
|
if (isset($gemScores->json[$itemId]['gearscore']))
|
||||||
$data['gearscore'] += $gemScores->json[$itemId]['gearscore'] * $mult;
|
$data['gearscore'] += $gemScores->json[$itemId]['gearscore'] * $mult;
|
||||||
}
|
}
|
||||||
@@ -472,7 +513,7 @@ class Profiler
|
|||||||
/* hunter pets */
|
/* hunter pets */
|
||||||
/***************/
|
/***************/
|
||||||
|
|
||||||
if ((1 << ($char['class'] - 1)) == CLASS_HUNTER)
|
if ($cl == CLASS_HUNTER)
|
||||||
{
|
{
|
||||||
DB::Aowow()->query('DELETE FROM ?_profiler_pets WHERE owner = ?d', $profileId);
|
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);
|
$pets = DB::Characters($realmId)->select('SELECT id AS ARRAY_KEY, id, entry, modelId, name FROM character_pet WHERE owner = ?d', $charGuid);
|
||||||
@@ -481,7 +522,7 @@ class Profiler
|
|||||||
$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']);
|
$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);
|
$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']);
|
$_ = 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(
|
$pet = array(
|
||||||
'id' => $petGuid,
|
'id' => $petGuid,
|
||||||
'owner' => $profileId,
|
'owner' => $profileId,
|
||||||
@@ -506,7 +547,7 @@ class Profiler
|
|||||||
DB::Aowow()->query('DELETE FROM ?_profiler_completion WHERE id = ?d', $profileId);
|
DB::Aowow()->query('DELETE FROM ?_profiler_completion WHERE id = ?d', $profileId);
|
||||||
|
|
||||||
// done quests
|
// 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']))
|
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)
|
foreach (Util::createSqlBatchInsert($quests) as $q)
|
||||||
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$q, array_keys($quests[0]));
|
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$q, array_keys($quests[0]));
|
||||||
|
|
||||||
@@ -515,7 +556,7 @@ class Profiler
|
|||||||
|
|
||||||
// known skills (professions only)
|
// 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);
|
$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);
|
$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
|
// manually apply racial profession bonuses
|
||||||
foreach ($skills as &$sk)
|
foreach ($skills as &$sk)
|
||||||
@@ -544,16 +585,68 @@ class Profiler
|
|||||||
unset($sk);
|
unset($sk);
|
||||||
|
|
||||||
if ($skills)
|
if ($skills)
|
||||||
|
{
|
||||||
|
// apply auto-learned trade skills
|
||||||
|
DB::Aowow()->query('
|
||||||
|
INSERT INTO ?_profiler_completion
|
||||||
|
SELECT ?d, ?d, spellId, NULL, NULL
|
||||||
|
FROM dbc_skilllineability
|
||||||
|
WHERE skillLineId IN (?a) AND
|
||||||
|
acquireMethod = 1 AND
|
||||||
|
(reqRaceMask = 0 OR reqRaceMask & ?d) AND
|
||||||
|
(reqClassMask = 0 OR reqClassMask & ?d)',
|
||||||
|
$profileId, Type::SPELL,
|
||||||
|
array_column($skills, 'typeId'),
|
||||||
|
1 << ($char['race'] - 1),
|
||||||
|
1 << ($char['class'] - 1)
|
||||||
|
);
|
||||||
|
|
||||||
foreach (Util::createSqlBatchInsert($skills) as $sk)
|
foreach (Util::createSqlBatchInsert($skills) as $sk)
|
||||||
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$sk, array_keys($skills[0]));
|
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$sk, array_keys($skills[0]));
|
||||||
|
}
|
||||||
|
|
||||||
CLI::write(' ..professions');
|
CLI::write(' ..professions');
|
||||||
|
|
||||||
|
|
||||||
// reputation
|
// 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)
|
// get base values for this race/class
|
||||||
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$rep, array_keys($reputation[0]));
|
$reputation = [];
|
||||||
|
$baseRep = DB::Aowow()->selectCol('
|
||||||
|
SELECT id AS ARRAY_KEY, baseRepValue1 FROM aowow_factions WHERE baseRepValue1 && (baseRepRaceMask1 & ?d || (!baseRepRaceMask1 AND baseRepClassMask1)) &&
|
||||||
|
((baseRepClassMask1 & ?d) || !baseRepClassMask1) UNION
|
||||||
|
SELECT id AS ARRAY_KEY, baseRepValue2 FROM aowow_factions WHERE baseRepValue2 && (baseRepRaceMask2 & ?d || (!baseRepRaceMask2 AND baseRepClassMask2)) &&
|
||||||
|
((baseRepClassMask2 & ?d) || !baseRepClassMask2) UNION
|
||||||
|
SELECT id AS ARRAY_KEY, baseRepValue3 FROM aowow_factions WHERE baseRepValue3 && (baseRepRaceMask3 & ?d || (!baseRepRaceMask3 AND baseRepClassMask3)) &&
|
||||||
|
((baseRepClassMask3 & ?d) || !baseRepClassMask3) UNION
|
||||||
|
SELECT id AS ARRAY_KEY, baseRepValue4 FROM aowow_factions WHERE baseRepValue4 && (baseRepRaceMask4 & ?d || (!baseRepRaceMask4 AND baseRepClassMask4)) &&
|
||||||
|
((baseRepClassMask4 & ?d) || !baseRepClassMask4)
|
||||||
|
', $ra, $cl, $ra, $cl, $ra, $cl, $ra, $cl);
|
||||||
|
|
||||||
|
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 & 0x4) = 0', $profileId, Type::FACTION, $char['guid']))
|
||||||
|
{
|
||||||
|
// merge back base values for encountered factions
|
||||||
|
foreach ($reputation as &$set)
|
||||||
|
{
|
||||||
|
if (empty($baseRep[$set['typeId']]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$set['cur'] += $baseRep[$set['typeId']];
|
||||||
|
unset($baseRep[$set['typeId']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert base values for not yet encountered factions
|
||||||
|
foreach ($baseRep as $id => $val)
|
||||||
|
$reputation[] = array(
|
||||||
|
'id' => $profileId,
|
||||||
|
'type' => Type::FACTION,
|
||||||
|
'typeId' => $id,
|
||||||
|
'cur' => $val
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach (Util::createSqlBatchInsert($reputation) as $rep)
|
||||||
|
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$rep, array_keys($reputation[0]));
|
||||||
|
|
||||||
CLI::write(' ..reputation');
|
CLI::write(' ..reputation');
|
||||||
|
|
||||||
@@ -567,13 +660,13 @@ class Profiler
|
|||||||
$indizes[] = $j + ($i * 32);
|
$indizes[] = $j + ($i * 32);
|
||||||
|
|
||||||
if ($indizes)
|
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);
|
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');
|
CLI::write(' ..titles');
|
||||||
|
|
||||||
|
|
||||||
// achievements
|
// 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']))
|
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)
|
foreach (Util::createSqlBatchInsert($achievements) as $a)
|
||||||
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$a, array_keys($achievements[0]));
|
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$a, array_keys($achievements[0]));
|
||||||
@@ -585,7 +678,7 @@ class Profiler
|
|||||||
|
|
||||||
|
|
||||||
// raid progression
|
// 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))
|
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); });
|
array_walk($progress, function (&$val) { $val['typeId'] = array_search($val['typeId'], self::$raidProgression); });
|
||||||
foreach (Util::createSqlBatchInsert($progress) as $p)
|
foreach (Util::createSqlBatchInsert($progress) as $p)
|
||||||
@@ -596,7 +689,7 @@ class Profiler
|
|||||||
|
|
||||||
|
|
||||||
// known spells
|
// 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']))
|
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)
|
foreach (Util::createSqlBatchInsert($spells) as $s)
|
||||||
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$s, array_keys($spells[0]));
|
DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$s, array_keys($spells[0]));
|
||||||
|
|
||||||
@@ -698,7 +791,7 @@ class Profiler
|
|||||||
|
|
||||||
// ranks
|
// ranks
|
||||||
DB::Aowow()->query('DELETE FROM ?_profiler_guild_rank WHERE guildId = ?d', $guildId);
|
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))
|
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)
|
foreach (Util::createSqlBatchInsert($ranks) as $r)
|
||||||
DB::Aowow()->query('INSERT INTO ?_profiler_guild_rank (?#) VALUES '.$r, array_keys(reset($ranks)));
|
DB::Aowow()->query('INSERT INTO ?_profiler_guild_rank (?#) VALUES '.$r, array_keys(reset($ranks)));
|
||||||
|
|
||||||
@@ -737,7 +830,7 @@ class Profiler
|
|||||||
|
|
||||||
public static function getArenaTeamFromRealm($realmId, $teamGuid)
|
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);
|
$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)
|
if (!$team)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
define('AOWOW_REVISION', 27);
|
define('AOWOW_REVISION', 33);
|
||||||
define('CLI', PHP_SAPI === 'cli');
|
define('CLI', PHP_SAPI === 'cli');
|
||||||
|
|
||||||
|
|
||||||
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo'];
|
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo'/*, 'gmp'*/];
|
||||||
$error = '';
|
$error = '';
|
||||||
foreach ($reqExt as $r)
|
foreach ($reqExt as $r)
|
||||||
if (!extension_loaded($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";
|
$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)
|
if (version_compare(PHP_VERSION, '7.4.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";
|
$error .= 'PHP Version <b>7.4</b> or higher required! Your version is <b>'.PHP_VERSION."</b>.\nCore functions are unavailable!\n";
|
||||||
|
|
||||||
if ($error)
|
if ($error)
|
||||||
{
|
{
|
||||||
|
|||||||
1622
includes/smartAI.class.php
Normal file
1622
includes/smartAI.class.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ class AchievementList extends BaseType
|
|||||||
{
|
{
|
||||||
use listviewHelper;
|
use listviewHelper;
|
||||||
|
|
||||||
public static $type = TYPE_ACHIEVEMENT;
|
public static $type = Type::ACHIEVEMENT;
|
||||||
public static $brickFile = 'achievement';
|
public static $brickFile = 'achievement';
|
||||||
public static $dataTable = '?_achievement';
|
public static $dataTable = '?_achievement';
|
||||||
|
|
||||||
@@ -36,14 +36,16 @@ class AchievementList extends BaseType
|
|||||||
$rewards = DB::World()->select('
|
$rewards = DB::World()->select('
|
||||||
SELECT
|
SELECT
|
||||||
ar.ID AS ARRAY_KEY, ar.TitleA, ar.TitleH, ar.ItemID, ar.Sender AS sender, ar.MailTemplateID,
|
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.Subject AS subject_loc0, IFNULL(arl2.Subject, "") AS subject_loc2, IFNULL(arl3.Subject, "") AS subject_loc3, IFNULL(arl4.Subject, "") AS subject_loc4, 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
|
ar.Body AS text_loc0, IFNULL(arl2.Body, "") AS text_loc2, IFNULL(arl3.Body, "") AS text_loc3, IFNULL(arl4.Body, "") AS text_loc4, IFNULL(arl6.Body, "") AS text_loc6, IFNULL(arl8.Body, "") AS text_loc8
|
||||||
FROM
|
FROM
|
||||||
achievement_reward ar
|
achievement_reward ar
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
achievement_reward_locale arl2 ON arl2.ID = ar.ID AND arl2.Locale = "frFR"
|
achievement_reward_locale arl2 ON arl2.ID = ar.ID AND arl2.Locale = "frFR"
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
achievement_reward_locale arl3 ON arl3.ID = ar.ID AND arl3.Locale = "deDE"
|
achievement_reward_locale arl3 ON arl3.ID = ar.ID AND arl3.Locale = "deDE"
|
||||||
|
LEFT JOIN
|
||||||
|
achievement_reward_locale arl4 ON arl4.ID = ar.ID AND arl4.Locale = "zhCN"
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
achievement_reward_locale arl6 ON arl6.ID = ar.ID AND arl6.Locale = "esES"
|
achievement_reward_locale arl6 ON arl6.ID = ar.ID AND arl6.Locale = "esES"
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
@@ -61,31 +63,33 @@ class AchievementList extends BaseType
|
|||||||
{
|
{
|
||||||
$_curTpl = array_merge($rewards[$_id], $_curTpl);
|
$_curTpl = array_merge($rewards[$_id], $_curTpl);
|
||||||
|
|
||||||
|
$_curTpl['mailTemplate'] = $rewards[$_id]['MailTemplateID'];
|
||||||
|
|
||||||
if ($rewards[$_id]['MailTemplateID'])
|
if ($rewards[$_id]['MailTemplateID'])
|
||||||
{
|
{
|
||||||
// using class Loot creates an inifinite loop cirling between Loot, ItemList and SpellList or something
|
// using class Loot creates an inifinite loop cirling between Loot, ItemList and SpellList or something
|
||||||
// $mailSrc = new Loot();
|
// $mailSrc = new Loot();
|
||||||
// $mailSrc->getByContainer(LOOT_MAIL, $rewards[$_id]['mailTemplate']);
|
// $mailSrc->getByContainer(LOOT_MAIL, $rewards[$_id]['MailTemplateID']);
|
||||||
// foreach ($mailSrc->iterate() as $loot)
|
// foreach ($mailSrc->iterate() as $loot)
|
||||||
// $_curTpl['rewards'][] = [TYPE_ITEM, $loot['id']];
|
// $_curTpl['rewards'][] = [Type::ITEM, $loot['id']];
|
||||||
|
|
||||||
// lets just assume for now, that mailRewards for achievements do not contain references
|
// 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]['MailTemplateID']);
|
$mailRew = DB::World()->selectCol('SELECT Item FROM mail_loot_template WHERE Reference <= 0 AND entry = ?d', $rewards[$_id]['MailTemplateID']);
|
||||||
foreach ($mailRew AS $mr)
|
foreach ($mailRew AS $mr)
|
||||||
$_curTpl['rewards'][] = [TYPE_ITEM, $mr];
|
$_curTpl['rewards'][] = [Type::ITEM, $mr];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//"rewards":[[11,137],[3,138]] [type, typeId]
|
//"rewards":[[11,137],[3,138]] [type, typeId]
|
||||||
if (!empty($_curTpl['ItemID']))
|
if (!empty($_curTpl['ItemID']))
|
||||||
$_curTpl['rewards'][] = [TYPE_ITEM, $_curTpl['ItemID']];
|
$_curTpl['rewards'][] = [Type::ITEM, $_curTpl['ItemID']];
|
||||||
if (!empty($_curTpl['itemExtra']))
|
if (!empty($_curTpl['itemExtra']))
|
||||||
$_curTpl['rewards'][] = [TYPE_ITEM, $_curTpl['itemExtra']];
|
$_curTpl['rewards'][] = [Type::ITEM, $_curTpl['itemExtra']];
|
||||||
if (!empty($_curTpl['TitleA']))
|
if (!empty($_curTpl['TitleA']))
|
||||||
$_curTpl['rewards'][] = [TYPE_TITLE, $_curTpl['TitleA']];
|
$_curTpl['rewards'][] = [Type::TITLE, $_curTpl['TitleA']];
|
||||||
if (!empty($_curTpl['TitleH']))
|
if (!empty($_curTpl['TitleH']))
|
||||||
if (empty($_curTpl['TitleA']) || $_curTpl['TitleA'] != $_curTpl['TitleH'])
|
if (empty($_curTpl['TitleA']) || $_curTpl['TitleA'] != $_curTpl['TitleH'])
|
||||||
$_curTpl['rewards'][] = [TYPE_TITLE, $_curTpl['TitleH']];
|
$_curTpl['rewards'][] = [Type::TITLE, $_curTpl['TitleH']];
|
||||||
|
|
||||||
// icon
|
// icon
|
||||||
$_curTpl['iconString'] = $_curTpl['iconString'] ?: 'trade_engineering';
|
$_curTpl['iconString'] = $_curTpl['iconString'] ?: 'trade_engineering';
|
||||||
@@ -99,7 +103,7 @@ class AchievementList extends BaseType
|
|||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
{
|
{
|
||||||
if ($addMask & GLOBALINFO_SELF)
|
if ($addMask & GLOBALINFO_SELF)
|
||||||
$data[TYPE_ACHIEVEMENT][$this->id] = ['icon' => $this->curTpl['iconString'], 'name' => $this->getField('name', true)];
|
$data[Type::ACHIEVEMENT][$this->id] = ['icon' => $this->curTpl['iconString'], 'name' => $this->getField('name', true)];
|
||||||
|
|
||||||
if ($addMask & GLOBALINFO_REWARDS)
|
if ($addMask & GLOBALINFO_REWARDS)
|
||||||
foreach ($this->curTpl['rewards'] as $_)
|
foreach ($this->curTpl['rewards'] as $_)
|
||||||
@@ -147,7 +151,7 @@ class AchievementList extends BaseType
|
|||||||
if (isset($this->criteria[$this->id]))
|
if (isset($this->criteria[$this->id]))
|
||||||
return $this->criteria[$this->id];
|
return $this->criteria[$this->id];
|
||||||
|
|
||||||
$result = DB::Aowow()->Select('SELECT * FROM ?_achievementcriteria WHERE `refAchievementId` = ?d ORDER BY `order` ASC', $this->id);
|
$result = DB::Aowow()->Select('SELECT * FROM ?_achievementcriteria WHERE `refAchievementId` = ?d ORDER BY `order` ASC', $this->curTpl['refAchievement'] ?: $this->id);
|
||||||
if (!$result)
|
if (!$result)
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
@@ -222,7 +226,7 @@ class AchievementList extends BaseType
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$criteria .= '<!--cr'.$crt['id'].':'.$crt['type'].':'.$crt['value1'].'-->- '.Util::jsEscape($crtName);
|
$criteria .= '<!--cr'.$crt['id'].':'.$crt['type'].':'.$crt['value1'].'-->- '.$crtName;
|
||||||
|
|
||||||
if ($crt['completionFlags'] & ACHIEVEMENT_CRITERIA_FLAG_MONEY_COUNTER)
|
if ($crt['completionFlags'] & ACHIEVEMENT_CRITERIA_FLAG_MONEY_COUNTER)
|
||||||
$criteria .= ' <span class="moneygold">'.Lang::nf($crt['value2' ] / 10000).'</span>';
|
$criteria .= ' <span class="moneygold">'.Lang::nf($crt['value2' ] / 10000).'</span>';
|
||||||
@@ -234,13 +238,13 @@ class AchievementList extends BaseType
|
|||||||
}
|
}
|
||||||
|
|
||||||
$x = '<table><tr><td><b class="q">';
|
$x = '<table><tr><td><b class="q">';
|
||||||
$x .= Util::jsEscape($name);
|
$x .= $name;
|
||||||
$x .= '</b></td></tr></table>';
|
$x .= '</b></td></tr></table>';
|
||||||
if ($description || $criteria)
|
if ($description || $criteria)
|
||||||
$x .= '<table><tr><td>';
|
$x .= '<table><tr><td>';
|
||||||
|
|
||||||
if ($description)
|
if ($description)
|
||||||
$x .= '<br />'.Util::jsEscape($description).'<br />';
|
$x .= '<br />'.$description.'<br />';
|
||||||
|
|
||||||
if ($criteria)
|
if ($criteria)
|
||||||
{
|
{
|
||||||
@@ -262,7 +266,7 @@ class AchievementList extends BaseType
|
|||||||
$data[$this->id] = array(
|
$data[$this->id] = array(
|
||||||
"n" => $this->getField('name', true),
|
"n" => $this->getField('name', true),
|
||||||
"s" => $this->curTpl['faction'],
|
"s" => $this->curTpl['faction'],
|
||||||
"t" => TYPE_ACHIEVEMENT,
|
"t" => Type::ACHIEVEMENT,
|
||||||
"ti" => $this->id
|
"ti" => $this->id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -317,8 +321,8 @@ class AchievementListFilter extends Filter
|
|||||||
protected $inputFields = array(
|
protected $inputFields = array(
|
||||||
'cr' => [FILTER_V_RANGE, [2, 18], true ], // criteria ids
|
'cr' => [FILTER_V_RANGE, [2, 18], true ], // criteria ids
|
||||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 99999]], true ], // criteria operators
|
'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
|
'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
|
'na' => [FILTER_V_REGEX, '/[\p{C};%\\\\]/ui', false], // name / description - only printable chars, no delimiter
|
||||||
'ex' => [FILTER_V_EQUAL, 'on', false], // extended name search
|
'ex' => [FILTER_V_EQUAL, 'on', false], // extended name search
|
||||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||||
'si' => [FILTER_V_LIST, [1, 2, 3, -1, -2], false], // side
|
'si' => [FILTER_V_LIST, [1, 2, 3, -1, -2], false], // side
|
||||||
|
|||||||
102
includes/types/areatrigger.class.php
Normal file
102
includes/types/areatrigger.class.php
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
class AreaTriggerList extends BaseType
|
||||||
|
{
|
||||||
|
use spawnHelper;
|
||||||
|
|
||||||
|
public static $type = Type::AREATRIGGER;
|
||||||
|
public static $brickFile = 'areatrigger';
|
||||||
|
public static $dataTable = '?_areatrigger';
|
||||||
|
|
||||||
|
protected $queryBase = 'SELECT a.*, a.id AS ARRAY_KEY FROM ?_areatrigger a';
|
||||||
|
protected $queryOpts = array(
|
||||||
|
'a' => [['s']],
|
||||||
|
's' => ['j' => ['?_spawns s ON s.type = 503 AND s.typeId = a.id', true], 's' => ', s.areaId']
|
||||||
|
);
|
||||||
|
|
||||||
|
public function __construct($conditions)
|
||||||
|
{
|
||||||
|
parent::__construct($conditions);
|
||||||
|
|
||||||
|
foreach ($this->iterate() as $id => &$_curTpl)
|
||||||
|
if (!$_curTpl['name'])
|
||||||
|
$_curTpl['name'] = 'Unnamed Areatrigger #' . $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getListviewData() : array
|
||||||
|
{
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($this->iterate() as $__)
|
||||||
|
{
|
||||||
|
$data[$this->id] = array(
|
||||||
|
'id' => $this->curTpl['id'],
|
||||||
|
'type' => $this->curTpl['type'],
|
||||||
|
'name' => $this->curTpl['name'],
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($_ = $this->curTpl['areaId'])
|
||||||
|
$data[$this->id]['location'] = [$_];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getJSGlobals($addMask = GLOBALINFO_ANY)
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderTooltip() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class AreaTriggerListFilter extends Filter
|
||||||
|
{
|
||||||
|
protected $genericFilter = array(
|
||||||
|
2 => [FILTER_CR_NUMERIC, 'id', NUM_CAST_INT] // id
|
||||||
|
);
|
||||||
|
|
||||||
|
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||||
|
protected $inputFields = array(
|
||||||
|
'cr' => [FILTER_V_LIST, [2], 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
|
||||||
|
'ty' => [FILTER_V_RANGE, [0, 5], 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'];
|
||||||
|
|
||||||
|
// name [str]
|
||||||
|
if (isset($_v['na']))
|
||||||
|
if ($_ = $this->modularizeString(['name']))
|
||||||
|
$parts[] = $_;
|
||||||
|
|
||||||
|
// type [list]
|
||||||
|
if (isset($_v['ty']))
|
||||||
|
$parts[] = ['type', $_v['ty']];
|
||||||
|
|
||||||
|
return $parts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -17,7 +17,7 @@ class ArenaTeamList extends BaseType
|
|||||||
{
|
{
|
||||||
$data[$this->id] = array(
|
$data[$this->id] = array(
|
||||||
'name' => $this->curTpl['name'],
|
'name' => $this->curTpl['name'],
|
||||||
'realm' => Profiler::urlize($this->curTpl['realmName']),
|
'realm' => Profiler::urlize($this->curTpl['realmName'], true),
|
||||||
'realmname' => $this->curTpl['realmName'],
|
'realmname' => $this->curTpl['realmName'],
|
||||||
// 'battlegroup' => Profiler::urlize($this->curTpl['battlegroup']), // was renamed to subregion somewhere around cata release
|
// 'battlegroup' => Profiler::urlize($this->curTpl['battlegroup']), // was renamed to subregion somewhere around cata release
|
||||||
// 'battlegroupname' => $this->curTpl['battlegroup'],
|
// 'battlegroupname' => $this->curTpl['battlegroup'],
|
||||||
@@ -47,7 +47,7 @@ class ArenaTeamListFilter extends Filter
|
|||||||
|
|
||||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||||
protected $inputFields = array(
|
protected $inputFields = array(
|
||||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name - only printable chars, no delimiter
|
'na' => [FILTER_V_REGEX, '/[\p{C};%\\\\]/ui', false], // name - only printable chars, no delimiter
|
||||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||||
'ex' => [FILTER_V_EQUAL, 'on', false], // only match exact
|
'ex' => [FILTER_V_EQUAL, 'on', false], // only match exact
|
||||||
'si' => [FILTER_V_LIST, [1, 2], false], // side
|
'si' => [FILTER_V_LIST, [1, 2], false], // side
|
||||||
@@ -88,7 +88,7 @@ class ArenaTeamListFilter extends Filter
|
|||||||
|
|
||||||
protected function cbRegionCheck(&$v)
|
protected function cbRegionCheck(&$v)
|
||||||
{
|
{
|
||||||
if ($v == 'eu' || $v == 'us')
|
if (in_array($v, Util::$regions))
|
||||||
{
|
{
|
||||||
$this->parentCats[0] = $v; // directly redirect onto this region
|
$this->parentCats[0] = $v; // directly redirect onto this region
|
||||||
$v = ''; // remove from filter
|
$v = ''; // remove from filter
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class CharClassList extends BaseType
|
class CharClassList extends BaseType
|
||||||
{
|
{
|
||||||
public static $type = TYPE_CLASS;
|
public static $type = Type::CHR_CLASS;
|
||||||
public static $brickFile = 'class';
|
public static $brickFile = 'class';
|
||||||
public static $dataTable = '?_classes';
|
public static $dataTable = '?_classes';
|
||||||
|
|
||||||
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_classes c';
|
protected $queryBase = 'SELECT c.*, id AS ARRAY_KEY FROM ?_classes c';
|
||||||
|
|
||||||
public function __construct($conditions = [])
|
public function __construct($conditions = [])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class CharRaceList extends BaseType
|
class CharRaceList extends BaseType
|
||||||
{
|
{
|
||||||
public static $type = TYPE_RACE;
|
public static $type = Type::CHR_RACE;
|
||||||
public static $brickFile = 'race';
|
public static $brickFile = 'race';
|
||||||
public static $dataTable = '?_races';
|
public static $dataTable = '?_races';
|
||||||
|
|
||||||
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_races r';
|
protected $queryBase = 'SELECT r.*, id AS ARRAY_KEY FROM ?_races r';
|
||||||
|
|
||||||
public function getListviewData()
|
public function getListviewData()
|
||||||
{
|
{
|
||||||
@@ -40,7 +40,7 @@ class CharRaceList extends BaseType
|
|||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
$data[TYPE_RACE][$this->id] = ['name' => $this->getField('name', true)];
|
$data[Type::CHR_RACE][$this->id] = ['name' => $this->getField('name', true)];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ class CreatureList extends BaseType
|
|||||||
{
|
{
|
||||||
use spawnHelper;
|
use spawnHelper;
|
||||||
|
|
||||||
public static $type = TYPE_NPC;
|
public static $type = Type::NPC;
|
||||||
public static $brickFile = 'creature';
|
public static $brickFile = 'creature';
|
||||||
public static $dataTable = '?_creature';
|
public static $dataTable = '?_creature';
|
||||||
|
|
||||||
protected $queryBase = 'SELECT ct.*, ct.id AS ARRAY_KEY FROM ?_creature ct';
|
protected $queryBase = 'SELECT ct.*, ct.id AS ARRAY_KEY FROM ?_creature ct';
|
||||||
public $queryOpts = array(
|
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'],
|
'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_loc4, IFNULL(dct2.name_loc4, IFNULL(dct3.name_loc4, ""))) AS parent_loc4, 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]],
|
'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]],
|
'dct2' => ['j' => ['?_creature dct2 ON ct.cuFlags & 0x02 AND dct2.difficultyEntry2 = ct.id', true]],
|
||||||
'dct3' => ['j' => ['?_creature dct3 ON ct.cuFlags & 0x02 AND dct3.difficultyEntry3 = ct.id', true]],
|
'dct3' => ['j' => ['?_creature dct3 ON ct.cuFlags & 0x02 AND dct3.difficultyEntry3 = ct.id', true]],
|
||||||
@@ -49,7 +49,7 @@ class CreatureList extends BaseType
|
|||||||
|
|
||||||
public static function getName($id)
|
public static function getName($id)
|
||||||
{
|
{
|
||||||
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM ?_creature WHERE id = ?d', $id);
|
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_creature WHERE id = ?d', $id);
|
||||||
return Util::localizedString($n, 'name');
|
return Util::localizedString($n, 'name');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,10 +81,10 @@ class CreatureList extends BaseType
|
|||||||
$row3[] = '('.$_.')';
|
$row3[] = '('.$_.')';
|
||||||
|
|
||||||
$x = '<table>';
|
$x = '<table>';
|
||||||
$x .= '<tr><td><b class="q">'.$this->getField('name', true).'</b></td></tr>';
|
$x .= '<tr><td><b class="q">'.Util::htmlEscape($this->getField('name', true)).'</b></td></tr>';
|
||||||
|
|
||||||
if ($sn = $this->getField('subname', true))
|
if ($sn = $this->getField('subname', true))
|
||||||
$x .= '<tr><td>'.$sn.'</td></tr>';
|
$x .= '<tr><td>'.Util::htmlEscape($sn).'</td></tr>';
|
||||||
|
|
||||||
$x .= '<tr><td>'.implode(' ', $row3).'</td></tr>';
|
$x .= '<tr><td>'.implode(' ', $row3).'</td></tr>';
|
||||||
|
|
||||||
@@ -102,27 +102,22 @@ class CreatureList extends BaseType
|
|||||||
|
|
||||||
public function getRandomModelId()
|
public function getRandomModelId()
|
||||||
{
|
{
|
||||||
|
// dwarf?? [null, 30754, 30753, 30755, 30736]
|
||||||
// totems use hardcoded models, tauren model is base
|
// totems use hardcoded models, tauren model is base
|
||||||
$totems = array( // tauren => [orc, dwarf(?!), troll, tauren, draenei]
|
$totems = [null, 4589, 4588, 4587, 4590]; // slot => modelId
|
||||||
4589 => [30758, 30754, 30762, 4589, 19074], // fire
|
$data = [];
|
||||||
4588 => [30757, 30753, 30761, 4588, 19073], // earth
|
|
||||||
4587 => [30759, 30755, 30763, 4587, 19075], // water
|
|
||||||
4590 => [30756, 30736, 30760, 4590, 19071], // air
|
|
||||||
);
|
|
||||||
|
|
||||||
$data = [];
|
|
||||||
|
|
||||||
for ($i = 1; $i < 5; $i++)
|
for ($i = 1; $i < 5; $i++)
|
||||||
if ($_ = $this->curTpl['displayId'.$i])
|
if ($_ = $this->curTpl['displayId'.$i])
|
||||||
$data[] = $_;
|
$data[] = $_;
|
||||||
|
|
||||||
if (count($data) == 1 && in_array($data[0], array_keys($totems)))
|
if (count($data) == 1 && ($slotId = array_search($data[0], $totems)))
|
||||||
$data = $totems[$data[0]];
|
$data = DB::World()->selectCol('SELECT DisplayId FROM player_totem_model WHERE TotemSlot = ?d', $slotId);
|
||||||
|
|
||||||
return !$data ? 0 : $data[array_rand($data)];
|
return !$data ? 0 : $data[array_rand($data)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBaseStats($type)
|
public function getBaseStats(string $type) : array
|
||||||
{
|
{
|
||||||
// i'm aware of the BaseVariance/RangedVariance fields ... i'm just totaly unsure about the whole damage calculation
|
// i'm aware of the BaseVariance/RangedVariance fields ... i'm just totaly unsure about the whole damage calculation
|
||||||
switch ($type)
|
switch ($type)
|
||||||
@@ -147,8 +142,14 @@ class CreatureList extends BaseType
|
|||||||
$rngMin = ($this->getField('dmgMin') + ($this->getField('rngAtkPwrMin') / 14)) * $this->getField('dmgMultiplier') * $this->getField('rngAtkSpeed');
|
$rngMin = ($this->getField('dmgMin') + ($this->getField('rngAtkPwrMin') / 14)) * $this->getField('dmgMultiplier') * $this->getField('rngAtkSpeed');
|
||||||
$rngMax = ($this->getField('dmgMax') * 1.5 + ($this->getField('rngAtkPwrMax') / 14)) * $this->getField('dmgMultiplier') * $this->getField('rngAtkSpeed');
|
$rngMax = ($this->getField('dmgMax') * 1.5 + ($this->getField('rngAtkPwrMax') / 14)) * $this->getField('dmgMultiplier') * $this->getField('rngAtkSpeed');
|
||||||
return [$rngMin, $rngMax];
|
return [$rngMin, $rngMax];
|
||||||
|
case 'resistance':
|
||||||
|
$r = [];
|
||||||
|
for ($i = SPELL_SCHOOL_HOLY; $i < SPELL_SCHOOL_ARCANE+1; $i++)
|
||||||
|
$r[$i] = $this->getField('resistance'.$i);
|
||||||
|
|
||||||
|
return $r;
|
||||||
default:
|
default:
|
||||||
return [0, 0];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +252,7 @@ class CreatureList extends BaseType
|
|||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
$data[TYPE_NPC][$this->id] = ['name' => $this->getField('name', true)];
|
$data[Type::NPC][$this->id] = ['name' => $this->getField('name', true)];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
@@ -264,7 +265,7 @@ class CreatureList extends BaseType
|
|||||||
{
|
{
|
||||||
$data[$this->id] = array(
|
$data[$this->id] = array(
|
||||||
'n' => $this->getField('parentId') ? $this->getField('parent', true) : $this->getField('name', true),
|
'n' => $this->getField('parentId') ? $this->getField('parent', true) : $this->getField('name', true),
|
||||||
't' => TYPE_NPC,
|
't' => Type::NPC,
|
||||||
'ti' => $this->getField('parentId') ?: $this->id,
|
'ti' => $this->getField('parentId') ?: $this->id,
|
||||||
// 'bd' => (int)($this->curTpl['cuFlags'] & NPC_CU_INSTANCE_BOSS || ($this->curTpl['typeFlags'] & 0x4 && $this->curTpl['rank']))
|
// 'bd' => (int)($this->curTpl['cuFlags'] & NPC_CU_INSTANCE_BOSS || ($this->curTpl['typeFlags'] & 0x4 && $this->curTpl['rank']))
|
||||||
// 'z' where am i spawned
|
// 'z' where am i spawned
|
||||||
@@ -301,11 +302,11 @@ class CreatureListFilter extends Filter
|
|||||||
7 => [FILTER_CR_CALLBACK, 'cbQuestRelation', 'startsQuests', 0x1 ], // startsquest [enum]
|
7 => [FILTER_CR_CALLBACK, 'cbQuestRelation', 'startsQuests', 0x1 ], // startsquest [enum]
|
||||||
8 => [FILTER_CR_CALLBACK, 'cbQuestRelation', 'endsQuests', 0x2 ], // endsquest [enum]
|
8 => [FILTER_CR_CALLBACK, 'cbQuestRelation', 'endsQuests', 0x2 ], // endsquest [enum]
|
||||||
9 => [FILTER_CR_BOOLEAN, 'lootId', ], // lootable
|
9 => [FILTER_CR_BOOLEAN, 'lootId', ], // lootable
|
||||||
10 => [FILTER_CR_BOOLEAN, 'cbRegularSkinLoot', NPC_TYPEFLAG_SPECIALLOOT ], // skinnable [yn]
|
10 => [FILTER_CR_CALLBACK, 'cbRegularSkinLoot', NPC_TYPEFLAG_SPECIALLOOT ], // skinnable [yn]
|
||||||
11 => [FILTER_CR_BOOLEAN, 'pickpocketLootId', ], // pickpocketable
|
11 => [FILTER_CR_BOOLEAN, 'pickpocketLootId', ], // pickpocketable
|
||||||
12 => [FILTER_CR_CALLBACK, 'cbMoneyDrop', null, null ], // averagemoneydropped [op] [int]
|
12 => [FILTER_CR_CALLBACK, 'cbMoneyDrop', null, null ], // averagemoneydropped [op] [int]
|
||||||
15 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_HERBLOOT, null ], // gatherable [yn]
|
15 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_HERBLOOT, null ], // gatherable [yn]
|
||||||
16 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_ENGINEERLOOT, null ], // minable [yn]
|
16 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_MININGLOOT, null ], // minable [yn]
|
||||||
18 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_AUCTIONEER ], // auctioneer
|
18 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_AUCTIONEER ], // auctioneer
|
||||||
19 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BANKER ], // banker
|
19 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BANKER ], // banker
|
||||||
20 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BATTLEMASTER ], // battlemaster
|
20 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BATTLEMASTER ], // battlemaster
|
||||||
@@ -328,15 +329,15 @@ class CreatureListFilter extends Filter
|
|||||||
41 => [FILTER_CR_NYI_PH, 1, null ], // haslocation [yn] [staff]
|
41 => [FILTER_CR_NYI_PH, 1, null ], // haslocation [yn] [staff]
|
||||||
42 => [FILTER_CR_CALLBACK, 'cbReputation', '>', null ], // increasesrepwith [enum]
|
42 => [FILTER_CR_CALLBACK, 'cbReputation', '>', null ], // increasesrepwith [enum]
|
||||||
43 => [FILTER_CR_CALLBACK, 'cbReputation', '<', null ], // decreasesrepwith [enum]
|
43 => [FILTER_CR_CALLBACK, 'cbReputation', '<', null ], // decreasesrepwith [enum]
|
||||||
44 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_MININGLOOT, null ] // salvageable [yn]
|
44 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_ENGINEERLOOT, null ] // salvageable [yn]
|
||||||
);
|
);
|
||||||
|
|
||||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||||
protected $inputFields = array(
|
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
|
'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
|
'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
|
'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
|
'na' => [FILTER_V_REGEX, '/[\p{C};%\\\\]/ui', false], // name / subname - only printable chars, no delimiter
|
||||||
'ex' => [FILTER_V_EQUAL, 'on', false], // also match subname
|
'ex' => [FILTER_V_EQUAL, 'on', false], // also match subname
|
||||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||||
'fa' => [FILTER_V_CALLBACK, 'cbPetFamily', true ], // pet family [list] - cat[0] == 1
|
'fa' => [FILTER_V_CALLBACK, 'cbPetFamily', true ], // pet family [list] - cat[0] == 1
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class CurrencyList extends BaseType
|
class CurrencyList extends BaseType
|
||||||
{
|
{
|
||||||
public static $type = TYPE_CURRENCY;
|
public static $type = Type::CURRENCY;
|
||||||
public static $brickFile = 'currency';
|
public static $brickFile = 'currency';
|
||||||
public static $dataTable = '?_currencies';
|
public static $dataTable = '?_currencies';
|
||||||
|
|
||||||
protected $queryBase = 'SELECT *, c.id AS ARRAY_KEY FROM ?_currencies c';
|
protected $queryBase = 'SELECT c.*, c.id AS ARRAY_KEY FROM ?_currencies c';
|
||||||
protected $queryOpts = array(
|
protected $queryOpts = array(
|
||||||
'c' => [['ic']],
|
'c' => [['ic']],
|
||||||
'ic' => ['j' => ['?_icons ic ON ic.id = c.iconId', true], 's' => ', ic.name AS iconString']
|
'ic' => ['j' => ['?_icons ic ON ic.id = c.iconId', true], 's' => ', ic.name AS iconString']
|
||||||
@@ -57,7 +57,7 @@ class CurrencyList extends BaseType
|
|||||||
else
|
else
|
||||||
$icon = [$this->curTpl['iconString'], $this->curTpl['iconString']];
|
$icon = [$this->curTpl['iconString'], $this->curTpl['iconString']];
|
||||||
|
|
||||||
$data[TYPE_CURRENCY][$this->id] = ['name' => $this->getField('name', true), 'icon' => $icon];
|
$data[Type::CURRENCY][$this->id] = ['name' => $this->getField('name', true), 'icon' => $icon];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
@@ -69,11 +69,11 @@ class CurrencyList extends BaseType
|
|||||||
return array();
|
return array();
|
||||||
|
|
||||||
$x = '<table><tr><td>';
|
$x = '<table><tr><td>';
|
||||||
$x .= '<b>'.Util::jsEscape($this->getField('name', true)).'</b><br>';
|
$x .= '<b>'.$this->getField('name', true).'</b><br>';
|
||||||
|
|
||||||
// cata+ (or go fill it by hand)
|
// cata+ (or go fill it by hand)
|
||||||
if ($_ = $this->getField('description', true))
|
if ($_ = $this->getField('description', true))
|
||||||
$x .= '<div style="max-width: 300px" class="q">'.Util::jsEscape($_).'</div>';
|
$x .= '<div style="max-width: 300px" class="q">'.$_.'</div>';
|
||||||
|
|
||||||
if ($_ = $this->getField('cap'))
|
if ($_ = $this->getField('cap'))
|
||||||
$x .= '<br><span class="q">'.Lang::currency('cap').Lang::main('colon').'</span>'.Lang::nf($_).'<br>';
|
$x .= '<br><span class="q">'.Lang::currency('cap').Lang::main('colon').'</span>'.Lang::nf($_).'<br>';
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class EmoteList extends BaseType
|
class EmoteList extends BaseType
|
||||||
{
|
{
|
||||||
public static $type = TYPE_EMOTE;
|
public static $type = Type::EMOTE;
|
||||||
public static $brickFile = 'emote';
|
public static $brickFile = 'emote';
|
||||||
public static $dataTable = '?_emotes';
|
public static $dataTable = '?_emotes';
|
||||||
|
|
||||||
protected $queryBase = 'SELECT *, e.id AS ARRAY_KEY FROM ?_emotes e';
|
protected $queryBase = 'SELECT e.*, e.id AS ARRAY_KEY FROM ?_emotes e';
|
||||||
|
|
||||||
public function __construct($conditions = [])
|
public function __construct($conditions = [])
|
||||||
{
|
{
|
||||||
@@ -47,7 +47,7 @@ class EmoteList extends BaseType
|
|||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
$data[TYPE_EMOTE][$this->id] = ['name' => $this->getField('cmd')];
|
$data[Type::EMOTE][$this->id] = ['name' => $this->getField('cmd')];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class EnchantmentList extends BaseType
|
|||||||
{
|
{
|
||||||
use listviewHelper;
|
use listviewHelper;
|
||||||
|
|
||||||
public static $type = TYPE_ENCHANTMENT;
|
public static $type = Type::ENCHANTMENT;
|
||||||
public static $brickFile = 'enchantment';
|
public static $brickFile = 'enchantment';
|
||||||
public static $dataTable = '?_itemenchantment';
|
public static $dataTable = '?_itemenchantment';
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ class EnchantmentList extends BaseType
|
|||||||
private $triggerIds = [];
|
private $triggerIds = [];
|
||||||
|
|
||||||
protected $queryBase = 'SELECT ie.*, ie.id AS ARRAY_KEY FROM ?_itemenchantment ie';
|
protected $queryBase = 'SELECT ie.*, ie.id AS ARRAY_KEY FROM ?_itemenchantment ie';
|
||||||
protected $queryOpts = array( // 502 => TYPE_ENCHANTMENT
|
protected $queryOpts = array( // 502 => Type::ENCHANTMENT
|
||||||
'ie' => [['is']],
|
'ie' => [['is']],
|
||||||
'is' => ['j' => ['?_item_stats `is` ON `is`.`type` = 502 AND `is`.`typeId` = `ie`.`id`', true], 's' => ', `is`.*'],
|
'is' => ['j' => ['?_item_stats `is` ON `is`.`type` = 502 AND `is`.`typeId` = `ie`.`id`', true], 's' => ', `is`.*'],
|
||||||
);
|
);
|
||||||
@@ -73,7 +73,7 @@ class EnchantmentList extends BaseType
|
|||||||
// use if you JUST need the name
|
// use if you JUST need the name
|
||||||
public static function getName($id)
|
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 );
|
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_itemenchantment WHERE id = ?d', $id );
|
||||||
return Util::localizedString($n, 'name');
|
return Util::localizedString($n, 'name');
|
||||||
}
|
}
|
||||||
// end static use
|
// end static use
|
||||||
@@ -216,7 +216,7 @@ class EnchantmentList extends BaseType
|
|||||||
|
|
||||||
if ($addMask & GLOBALINFO_SELF)
|
if ($addMask & GLOBALINFO_SELF)
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
$data[TYPE_ENCHANTMENT][$this->id] = ['name' => $this->getField('name', true)];
|
$data[Type::ENCHANTMENT][$this->id] = ['name' => $this->getField('name', true)];
|
||||||
|
|
||||||
if ($addMask & GLOBALINFO_RELATED)
|
if ($addMask & GLOBALINFO_RELATED)
|
||||||
{
|
{
|
||||||
@@ -224,8 +224,8 @@ class EnchantmentList extends BaseType
|
|||||||
$data = $this->relSpells->getJSGlobals(GLOBALINFO_SELF);
|
$data = $this->relSpells->getJSGlobals(GLOBALINFO_SELF);
|
||||||
|
|
||||||
foreach ($this->triggerIds as $tId)
|
foreach ($this->triggerIds as $tId)
|
||||||
if (empty($data[TYPE_SPELL][$tId]))
|
if (empty($data[Type::SPELL][$tId]))
|
||||||
$data[TYPE_SPELL][$tId] = $tId;
|
$data[Type::SPELL][$tId] = $tId;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
@@ -307,12 +307,12 @@ class EnchantmentListFilter extends Filter
|
|||||||
|
|
||||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||||
protected $inputFields = array(
|
protected $inputFields = array(
|
||||||
'cr' => [FILTER_V_RANGE, [2, 123], true ], // criteria ids
|
'cr' => [FILTER_V_RANGE, [2, 123], true ], // criteria ids
|
||||||
'crs' => [FILTER_V_RANGE, [1, 15], true ], // criteria operators
|
'crs' => [FILTER_V_RANGE, [1, 15], true ], // criteria operators
|
||||||
'crv' => [FILTER_V_RANGE, [0, 99999], true ], // criteria values - only numerals
|
'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
|
'na' => [FILTER_V_REGEX, '/[\p{C};%\\\\]/ui', false], // name - only printable chars, no delimiter
|
||||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||||
'ty' => [FILTER_V_RANGE, [1, 8], true ] // types
|
'ty' => [FILTER_V_RANGE, [1, 8], true ] // types
|
||||||
);
|
);
|
||||||
|
|
||||||
protected function createSQLForCriterium(&$cr)
|
protected function createSQLForCriterium(&$cr)
|
||||||
@@ -338,13 +338,7 @@ class EnchantmentListFilter extends Filter
|
|||||||
|
|
||||||
// type
|
// type
|
||||||
if (isset($_v['ty']))
|
if (isset($_v['ty']))
|
||||||
{
|
$parts[] = ['OR', ['type1', $_v['ty']], ['type2', $_v['ty']], ['type3', $_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;
|
return $parts;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class FactionList extends BaseType
|
class FactionList extends BaseType
|
||||||
{
|
{
|
||||||
public static $type = TYPE_FACTION;
|
public static $type = Type::FACTION;
|
||||||
public static $brickFile = 'faction';
|
public static $brickFile = 'faction';
|
||||||
public static $dataTable = '?_factions';
|
public static $dataTable = '?_factions';
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ class FactionList extends BaseType
|
|||||||
|
|
||||||
public static function getName($id)
|
public static function getName($id)
|
||||||
{
|
{
|
||||||
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM ?_factions WHERE id = ?d', $id);
|
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_factions WHERE id = ?d', $id);
|
||||||
return Util::localizedString($n, 'name');
|
return Util::localizedString($n, 'name');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ class FactionList extends BaseType
|
|||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
$data[TYPE_FACTION][$this->id] = ['name' => $this->getField('name', true)];
|
$data[Type::FACTION][$this->id] = ['name' => $this->getField('name', true)];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class GameObjectList extends BaseType
|
|||||||
{
|
{
|
||||||
use listviewHelper, spawnHelper;
|
use listviewHelper, spawnHelper;
|
||||||
|
|
||||||
public static $type = TYPE_OBJECT;
|
public static $type = Type::OBJECT;
|
||||||
public static $brickFile = 'object';
|
public static $brickFile = 'object';
|
||||||
public static $dataTable = '?_objects';
|
public static $dataTable = '?_objects';
|
||||||
|
|
||||||
@@ -31,6 +31,9 @@ class GameObjectList extends BaseType
|
|||||||
// post processing
|
// post processing
|
||||||
foreach ($this->iterate() as $_id => &$curTpl)
|
foreach ($this->iterate() as $_id => &$curTpl)
|
||||||
{
|
{
|
||||||
|
if (!$curTpl['name_loc0'])
|
||||||
|
$curTpl['name_loc0'] = 'Unnamed Object #' . $_id;
|
||||||
|
|
||||||
// unpack miscInfo
|
// unpack miscInfo
|
||||||
$curTpl['lootStack'] = [];
|
$curTpl['lootStack'] = [];
|
||||||
$curTpl['spells'] = [];
|
$curTpl['spells'] = [];
|
||||||
@@ -59,7 +62,7 @@ class GameObjectList extends BaseType
|
|||||||
|
|
||||||
public static function getName($id)
|
public static function getName($id)
|
||||||
{
|
{
|
||||||
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM ?_objects WHERE id = ?d', $id);
|
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_objects WHERE id = ?d', $id);
|
||||||
return Util::localizedString($n, 'name');
|
return Util::localizedString($n, 'name');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +103,7 @@ class GameObjectList extends BaseType
|
|||||||
if (isset($this->curTpl['lockId']))
|
if (isset($this->curTpl['lockId']))
|
||||||
if ($locks = Lang::getLocks($this->curTpl['lockId']))
|
if ($locks = Lang::getLocks($this->curTpl['lockId']))
|
||||||
foreach ($locks as $l)
|
foreach ($locks as $l)
|
||||||
$x .= '<tr><td>'.$l.'</td></tr>';
|
$x .= '<tr><td>'.sprintf(Lang::game('requires'), $l).'</td></tr>';
|
||||||
|
|
||||||
$x .= '</table>';
|
$x .= '</table>';
|
||||||
|
|
||||||
@@ -112,7 +115,7 @@ class GameObjectList extends BaseType
|
|||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
$data[TYPE_OBJECT][$this->id] = ['name' => $this->getField('name', true)];
|
$data[Type::OBJECT][$this->id] = ['name' => $this->getField('name', true)];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
@@ -125,7 +128,7 @@ class GameObjectList extends BaseType
|
|||||||
{
|
{
|
||||||
$data[$this->id] = array(
|
$data[$this->id] = array(
|
||||||
'n' => $this->getField('name', true),
|
'n' => $this->getField('name', true),
|
||||||
't' => TYPE_OBJECT,
|
't' => Type::OBJECT,
|
||||||
'ti' => $this->id
|
'ti' => $this->id
|
||||||
// 'bd' => bossdrop
|
// 'bd' => bossdrop
|
||||||
// 'dd' => dungeondifficulty
|
// 'dd' => dungeondifficulty
|
||||||
@@ -140,6 +143,15 @@ class GameObjectList extends BaseType
|
|||||||
class GameObjectListFilter extends Filter
|
class GameObjectListFilter extends Filter
|
||||||
{
|
{
|
||||||
public $extraOpts = [];
|
public $extraOpts = [];
|
||||||
|
protected $enums = array(
|
||||||
|
50 => array(
|
||||||
|
null, 1, 2, 3, 4,
|
||||||
|
663 => 663,
|
||||||
|
883 => 883,
|
||||||
|
FILTER_ENUM_ANY => true,
|
||||||
|
FILTER_ENUM_NONE => false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
protected $genericFilter = array(
|
protected $genericFilter = array(
|
||||||
1 => [FILTER_CR_ENUM, 's.areaId', null ], // foundin
|
1 => [FILTER_CR_ENUM, 's.areaId', null ], // foundin
|
||||||
@@ -152,15 +164,16 @@ class GameObjectListFilter extends Filter
|
|||||||
13 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
13 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||||
15 => [FILTER_CR_NUMERIC, 'id', NUM_CAST_INT ], // id
|
15 => [FILTER_CR_NUMERIC, 'id', NUM_CAST_INT ], // id
|
||||||
16 => [FILTER_CR_CALLBACK, 'cbRelEvent', null, null], // relatedevent (ignore removed by event)
|
16 => [FILTER_CR_CALLBACK, 'cbRelEvent', null, null], // relatedevent (ignore removed by event)
|
||||||
18 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ] // hasvideos
|
18 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
||||||
|
50 => [FILTER_CR_ENUM, 'spellFocusId', null, ], // SpellFocus
|
||||||
);
|
);
|
||||||
|
|
||||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||||
protected $inputFields = array(
|
protected $inputFields = array(
|
||||||
'cr' => [FILTER_V_LIST, [[1, 5], 7, 11, 13, 15, 16, 18], true ], // criteria ids
|
'cr' => [FILTER_V_LIST, [[1, 5], 7, 11, 13, 15, 16, 18, 50], true ], // criteria ids
|
||||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 5000]], true ], // criteria operators
|
'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
|
'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
|
'na' => [FILTER_V_REGEX, '/[\p{C};%\\\\]/ui', false], // name - only printable chars, no delimiter
|
||||||
'ma' => [FILTER_V_EQUAL, 1, false] // match any / all filter
|
'ma' => [FILTER_V_EQUAL, 1, false] // match any / all filter
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
167
includes/types/guide.class.php
Normal file
167
includes/types/guide.class.php
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
class GuideList extends BaseType
|
||||||
|
{
|
||||||
|
use ListviewHelper;
|
||||||
|
|
||||||
|
public const STATUS_COLORS = array(
|
||||||
|
GUIDE_STATUS_DRAFT => '#71D5FF',
|
||||||
|
GUIDE_STATUS_REVIEW => '#FFFF00',
|
||||||
|
GUIDE_STATUS_APPROVED => '#1EFF00',
|
||||||
|
GUIDE_STATUS_REJECTED => '#FF4040',
|
||||||
|
GUIDE_STATUS_ARCHIVED => '#FFD100'
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $type = Type::GUIDE;
|
||||||
|
public static $brickFile = 'guide';
|
||||||
|
public static $dataTable = '?_guides';
|
||||||
|
|
||||||
|
private $article = [];
|
||||||
|
private $jsGlobals = [];
|
||||||
|
|
||||||
|
protected $queryBase = 'SELECT g.*, g.id AS ARRAY_KEY FROM ?_guides g';
|
||||||
|
protected $queryOpts = array(
|
||||||
|
'g' => [['a', 'c'], 'g' => 'g.`id`'],
|
||||||
|
'a' => ['j' => ['?_account a ON a.id = g.userId', true], 's' => ', IFNULL(a.displayName, "") AS author'],
|
||||||
|
'c' => ['j' => ['?_comments c ON c.`type` = '.Type::GUIDE.' AND c.`typeId` = g.`id` AND (c.`flags` & '.CC_FLAG_DELETED.') = 0', true], 's' => ', COUNT(c.`id`) AS `comments`']
|
||||||
|
);
|
||||||
|
|
||||||
|
public function __construct($conditions = [])
|
||||||
|
{
|
||||||
|
parent::__construct($conditions);
|
||||||
|
|
||||||
|
if ($this->error)
|
||||||
|
return;
|
||||||
|
|
||||||
|
$ratings = DB::Aowow()->select('SELECT `entry` AS ARRAY_KEY, IFNULL(SUM(`value`), 0) AS `t`, IFNULL(COUNT(*), 0) AS `n`, IFNULL(MAX(IF(`userId` = ?d, `value`, 0)), 0) AS `s` FROM ?_user_ratings WHERE `type` = ?d AND `entry` IN (?a)', User::$id, RATING_GUIDE, $this->getFoundIDs());
|
||||||
|
|
||||||
|
// post processing
|
||||||
|
foreach ($this->iterate() as $id => &$_curTpl)
|
||||||
|
{
|
||||||
|
if (isset($ratings[$id]))
|
||||||
|
{
|
||||||
|
$_curTpl['nvotes'] = $ratings[$id]['n'];
|
||||||
|
$_curTpl['rating'] = $ratings[$id]['n'] < 5 ? -1 : $ratings[$id]['t'] / $ratings[$id]['n'];
|
||||||
|
$_curTpl['_self'] = $ratings[$id]['s'];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$_curTpl['nvotes'] = 0;
|
||||||
|
$_curTpl['rating'] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getArticle(int $rev = -1) : string
|
||||||
|
{
|
||||||
|
if ($rev < -1)
|
||||||
|
$rev = -1;
|
||||||
|
|
||||||
|
if (empty($this->article[$rev]))
|
||||||
|
{
|
||||||
|
$a = DB::Aowow()->selectRow('SELECT `article`, `rev` FROM ?_articles WHERE ((`type` = ?d AND `typeId` = ?d){ OR `url` = ?}){ AND `rev`= ?d} ORDER BY `rev` DESC LIMIT 1',
|
||||||
|
Type::GUIDE, $this->id, $this->getField('url') ?: DBSIMPLE_SKIP, $rev < 0 ? DBSIMPLE_SKIP : $rev);
|
||||||
|
|
||||||
|
$this->article[$a['rev']] = $a['article'];
|
||||||
|
if ($this->article[$a['rev']])
|
||||||
|
{
|
||||||
|
(new Markup($this->article[$a['rev']]))->parseGlobalsFromText($this->jsGlobals);
|
||||||
|
return $this->article[$a['rev']];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
trigger_error('GuideList::getArticle - linked article is missing');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->article[$rev] ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getListviewData(bool $addDescription = false) : array
|
||||||
|
{
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($this->iterate() as $__)
|
||||||
|
{
|
||||||
|
$data[$this->id] = array(
|
||||||
|
'id' => $this->id,
|
||||||
|
'category' => $this->getField('category'),
|
||||||
|
'title' => $this->getField('title'),
|
||||||
|
'description' => $this->getField('description'),
|
||||||
|
'sticky' => !!($this->getField('cuFlags') & CC_FLAG_STICKY),
|
||||||
|
'nvotes' => $this->getField('nvotes'),
|
||||||
|
'url' => '/?guide=' . ($this->getField('url') ?: $this->id),
|
||||||
|
'status' => $this->getField('status'),
|
||||||
|
'author' => $this->getField('author'),
|
||||||
|
'authorroles' => $this->getField('roles'),
|
||||||
|
'rating' => $this->getField('rating'),
|
||||||
|
'views' => $this->getField('views'),
|
||||||
|
'comments' => $this->getField('comments'),
|
||||||
|
// 'patch' => $this->getField(''), // 30305 - patch is pointless, use date instead
|
||||||
|
'date' => $this->getField('date'), // ok
|
||||||
|
'when' => date(Util::$dateFormatInternal, $this->getField('date'))
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function userCanView() : bool
|
||||||
|
{
|
||||||
|
// is owner || is staff
|
||||||
|
return $this->getField('userId') == User::$id || User::isInGroup(U_GROUP_STAFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canBeViewed() : bool
|
||||||
|
{
|
||||||
|
// currently approved || has prev. approved version
|
||||||
|
return $this->getField('status') == GUIDE_STATUS_APPROVED || $this->getField('rev') > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canBeReported() : bool
|
||||||
|
{
|
||||||
|
// not own guide && is not archived
|
||||||
|
return $this->getField('userId') != User::$id && $this->getField('status') != GUIDE_STATUS_ARCHIVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getJSGlobals($addMask = GLOBALINFO_ANY) : array
|
||||||
|
{
|
||||||
|
return $this->jsGlobals;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderTooltip() : string
|
||||||
|
{
|
||||||
|
$specStr = '';
|
||||||
|
|
||||||
|
if ($this->getField('classId') && $this->getField('category') == 1)
|
||||||
|
{
|
||||||
|
$c = $this->getField('classId');
|
||||||
|
if (($s = $this->getField('specId')) > -1)
|
||||||
|
{
|
||||||
|
$i = Game::$specIconStrings[$c][$s];
|
||||||
|
$n = Lang::game('classSpecs', $c, $s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$i = 'class_'.Game::$classFileStrings[$c];
|
||||||
|
$n = Lang::game('cl', $c);
|
||||||
|
}
|
||||||
|
|
||||||
|
$specStr = ' – <span class="icontiny c'.$c.'" style="background-image: url('.STATIC_URL.'/images/wow/icons/tiny/'.$i.'.gif)">'.$n.'</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$tt = '<table><tr><td><div style="max-width: 320px"><b class="q">'.$this->getField('title').'</b><br>';
|
||||||
|
$tt .= '<table width="100%"><tr><td>'.Lang::guide('guide').'</td><th>'.Lang::guide('byAuthor', [$this->getField('author')]).'</th></tr></table>';
|
||||||
|
$tt .= '<table width="100%"><tr><td>'.Lang::guide('category', $this->getField('category')).$specStr.'</td><th>'.Lang::guide('patch').' 3.3.5</th></tr></table>';
|
||||||
|
$tt .= '<div class="q" style="margin: 0.25em 0">'.$this->getField('description').'</div>';
|
||||||
|
$tt .= '</div></td></tr></table>';
|
||||||
|
|
||||||
|
return $tt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -16,14 +16,14 @@ class GuildList extends BaseType
|
|||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
{
|
{
|
||||||
$data[$this->id] = array(
|
$data[$this->id] = array(
|
||||||
'name' => "$'".$this->curTpl['name']."'", // MUST be a string
|
'name' => '$"'.str_replace ('"', '', $this->curTpl['name']).'"', // MUST be a string, omit any quotes in name
|
||||||
'members' => $this->curTpl['members'],
|
'members' => $this->curTpl['members'],
|
||||||
'faction' => $this->curTpl['faction'],
|
'faction' => $this->curTpl['faction'],
|
||||||
'achievementpoints' => $this->getField('achievementpoints'),
|
'achievementpoints' => $this->getField('achievementpoints'),
|
||||||
'gearscore' => $this->getField('gearscore'),
|
'gearscore' => $this->getField('gearscore'),
|
||||||
'realm' => Profiler::urlize($this->curTpl['realmName']),
|
'realm' => Profiler::urlize($this->curTpl['realmName'], true),
|
||||||
'realmname' => $this->curTpl['realmName'],
|
'realmname' => $this->curTpl['realmName'],
|
||||||
// 'battlegroup' => Profiler::urlize($this->curTpl['battlegroup']), // was renamed to subregion somewhere around cata release
|
// 'battlegroup' => Profiler::urlize($this->curTpl['battlegroup']), // was renamed to subregion somewhere around cata release
|
||||||
// 'battlegroupname' => $this->curTpl['battlegroup'],
|
// 'battlegroupname' => $this->curTpl['battlegroup'],
|
||||||
'region' => Profiler::urlize($this->curTpl['region'])
|
'region' => Profiler::urlize($this->curTpl['region'])
|
||||||
);
|
);
|
||||||
@@ -90,7 +90,7 @@ class GuildListFilter extends Filter
|
|||||||
|
|
||||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||||
protected $inputFields = array(
|
protected $inputFields = array(
|
||||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name - only printable chars, no delimiter
|
'na' => [FILTER_V_REGEX, '/[\p{C};%\\\\]/ui', false], // name - only printable chars, no delimiter
|
||||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||||
'ex' => [FILTER_V_EQUAL, 'on', false], // only match exact
|
'ex' => [FILTER_V_EQUAL, 'on', false], // only match exact
|
||||||
'si' => [FILTER_V_LIST, [1, 2], false], // side
|
'si' => [FILTER_V_LIST, [1, 2], false], // side
|
||||||
@@ -126,7 +126,7 @@ class GuildListFilter extends Filter
|
|||||||
|
|
||||||
protected function cbRegionCheck(&$v)
|
protected function cbRegionCheck(&$v)
|
||||||
{
|
{
|
||||||
if ($v == 'eu' || $v == 'us')
|
if (in_array($v, Util::$regions))
|
||||||
{
|
{
|
||||||
$this->parentCats[0] = $v; // directly redirect onto this region
|
$this->parentCats[0] = $v; // directly redirect onto this region
|
||||||
$v = ''; // remove from filter
|
$v = ''; // remove from filter
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class IconList extends BaseType
|
|||||||
{
|
{
|
||||||
use listviewHelper;
|
use listviewHelper;
|
||||||
|
|
||||||
public static $type = TYPE_ICON;
|
public static $type = Type::ICON;
|
||||||
public static $brickFile = 'icon';
|
public static $brickFile = 'icon';
|
||||||
public static $dataTable = '?_icons';
|
public static $dataTable = '?_icons';
|
||||||
public static $contribute = CONTRIBUTE_CO;
|
public static $contribute = CONTRIBUTE_CO;
|
||||||
@@ -24,7 +24,7 @@ class IconList extends BaseType
|
|||||||
|
|
||||||
protected $queryBase = 'SELECT ic.*, ic.id AS ARRAY_KEY FROM ?_icons ic';
|
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
|
/* this works, but takes ~100x more time than i'm comfortable with .. kept as reference
|
||||||
protected $queryOpts = array( // 29 => TYPE_ICON
|
protected $queryOpts = array( // 29 => Type::ICON
|
||||||
'ic' => [['s', 'i', 'a', 'c', 'p'], 'g' => 'ic.id'],
|
'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'],
|
'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'],
|
's' => ['j' => ['?_spell `s` ON `s`.`iconId` = `ic`.`id`', true], 's' => ', COUNT(DISTINCT `s`.`id`) AS nSpells'],
|
||||||
@@ -90,7 +90,7 @@ class IconList extends BaseType
|
|||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
$data[TYPE_ICON][$this->id] = ['name' => $this->getField('name', true, true), 'icon' => $this->getField('name', true, true)];
|
$data[Type::ICON][$this->id] = ['name' => $this->getField('name', true, true), 'icon' => $this->getField('name', true, true)];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ class IconListFilter extends Filter
|
|||||||
'cr' => [FILTER_V_LIST, [1, 2, 3, 6, 9, 11, 13], true ], // criteria ids
|
'cr' => [FILTER_V_LIST, [1, 2, 3, 6, 9, 11, 13], true ], // criteria ids
|
||||||
'crs' => [FILTER_V_RANGE, [1, 6], true ], // criteria operators
|
'crs' => [FILTER_V_RANGE, [1, 6], true ], // criteria operators
|
||||||
'crv' => [FILTER_V_RANGE, [0, 99999], true ], // criteria values - all criteria are numeric here
|
'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
|
'na' => [FILTER_V_REGEX, '/[\p{C};%\\\\]/ui', false], // name - only printable chars, no delimiter
|
||||||
'ma' => [FILTER_V_EQUAL, 1, false] // match any / all filter
|
'ma' => [FILTER_V_EQUAL, 1, false] // match any / all filter
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class ItemList extends BaseType
|
|||||||
{
|
{
|
||||||
use ListviewHelper;
|
use ListviewHelper;
|
||||||
|
|
||||||
public static $type = TYPE_ITEM;
|
public static $type = Type::ITEM;
|
||||||
public static $brickFile = 'item';
|
public static $brickFile = 'item';
|
||||||
public static $dataTable = '?_items';
|
public static $dataTable = '?_items';
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ class ItemList extends BaseType
|
|||||||
private $jsGlobals = []; // getExtendedCost creates some and has no access to template
|
private $jsGlobals = []; // getExtendedCost creates some and has no access to template
|
||||||
|
|
||||||
protected $queryBase = 'SELECT i.*, i.block AS tplBlock, i.id AS ARRAY_KEY, i.id AS id FROM ?_items i';
|
protected $queryBase = 'SELECT i.*, i.block AS tplBlock, i.id AS ARRAY_KEY, i.id AS id FROM ?_items i';
|
||||||
protected $queryOpts = array( // 3 => TYPE_ITEM
|
protected $queryOpts = array( // 3 => Type::ITEM
|
||||||
'i' => [['is', 'src', 'ic'], 'o' => 'i.quality DESC, i.itemLevel DESC'],
|
'i' => [['is', 'src', 'ic'], 'o' => 'i.quality DESC, i.itemLevel DESC'],
|
||||||
'ic' => ['j' => ['?_icons `ic` ON `ic`.`id` = `i`.`iconId`', true], 's' => ', ic.name AS iconString'],
|
'ic' => ['j' => ['?_icons `ic` ON `ic`.`id` = `i`.`iconId`', true], 's' => ', ic.name AS iconString'],
|
||||||
'is' => ['j' => ['?_item_stats `is` ON `is`.`type` = 3 AND `is`.`typeId` = `i`.`id`', true], 's' => ', `is`.*'],
|
'is' => ['j' => ['?_item_stats `is` ON `is`.`type` = 3 AND `is`.`typeId` = `i`.`id`', true], 's' => ', `is`.*'],
|
||||||
@@ -46,9 +46,16 @@ class ItemList extends BaseType
|
|||||||
|
|
||||||
$this->initJsonStats();
|
$this->initJsonStats();
|
||||||
|
|
||||||
// readdress itemset .. is wrong for virtual sets
|
if ($miscData)
|
||||||
if ($miscData && isset($miscData['pcsToSet']) && isset($miscData['pcsToSet'][$this->id]))
|
{
|
||||||
$this->json[$this->id]['itemset'] = $miscData['pcsToSet'][$this->id];
|
// readdress itemset .. is wrong for virtual sets
|
||||||
|
if (isset($miscData['pcsToSet']) && isset($miscData['pcsToSet'][$this->id]))
|
||||||
|
$this->json[$this->id]['itemset'] = $miscData['pcsToSet'][$this->id];
|
||||||
|
|
||||||
|
// additional rel attribute for listview rows
|
||||||
|
if (isset($miscData['extraOpts']['relEnchant']))
|
||||||
|
$this->relEnchant = $miscData['extraOpts']['relEnchant'];
|
||||||
|
}
|
||||||
|
|
||||||
// unify those pesky masks
|
// unify those pesky masks
|
||||||
$_ = &$_curTpl['requiredClass'];
|
$_ = &$_curTpl['requiredClass'];
|
||||||
@@ -77,7 +84,7 @@ class ItemList extends BaseType
|
|||||||
// use if you JUST need the name
|
// use if you JUST need the name
|
||||||
public static function getName($id)
|
public static function getName($id)
|
||||||
{
|
{
|
||||||
$n = DB::Aowow()->selectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM ?_items WHERE id = ?d', $id);
|
$n = DB::Aowow()->selectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_items WHERE id = ?d', $id);
|
||||||
return Util::localizedString($n, 'name');
|
return Util::localizedString($n, 'name');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,69 +95,87 @@ class ItemList extends BaseType
|
|||||||
if ($this->error)
|
if ($this->error)
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
|
$idx = $this->id;
|
||||||
|
|
||||||
if (empty($this->vendors))
|
if (empty($this->vendors))
|
||||||
{
|
{
|
||||||
$itemz = DB::World()->select('
|
$itemz = [];
|
||||||
SELECT nv.item AS ARRAY_KEY1, nv.entry AS ARRAY_KEY2, 0 AS eventId, nv.maxcount, nv.extendedCost FROM npc_vendor nv WHERE {nv.entry IN (?a) AND} nv.item IN (?a)
|
$xCostData = [];
|
||||||
|
$rawEntries = DB::World()->select('
|
||||||
|
SELECT nv.item, nv.entry, 0 AS eventId, nv.maxcount, nv.extendedCost FROM npc_vendor nv WHERE {nv.entry IN (?a) AND} nv.item IN (?a)
|
||||||
UNION
|
UNION
|
||||||
SELECT genv.item AS ARRAY_KEY1, c.id AS ARRAY_KEY2, ge.eventEntry AS eventId, genv.maxcount, genv.extendedCost FROM game_event_npc_vendor genv LEFT JOIN game_event ge ON genv.eventEntry = ge.eventEntry JOIN creature c ON c.guid = genv.guid WHERE {c.id IN (?a) AND} genv.item IN (?a)',
|
SELECT genv.item, c.id AS `entry`, ge.eventEntry AS eventId, genv.maxcount, genv.extendedCost FROM game_event_npc_vendor genv LEFT JOIN game_event ge ON genv.eventEntry = ge.eventEntry JOIN creature c ON c.guid = genv.guid WHERE {c.id IN (?a) AND} genv.item IN (?a)',
|
||||||
empty($filter[TYPE_NPC]) || !is_array($filter[TYPE_NPC]) ? DBSIMPLE_SKIP : $filter[TYPE_NPC],
|
empty($filter[Type::NPC]) || !is_array($filter[Type::NPC]) ? DBSIMPLE_SKIP : $filter[Type::NPC],
|
||||||
array_keys($this->templates),
|
array_keys($this->templates),
|
||||||
empty($filter[TYPE_NPC]) || !is_array($filter[TYPE_NPC]) ? DBSIMPLE_SKIP : $filter[TYPE_NPC],
|
empty($filter[Type::NPC]) || !is_array($filter[Type::NPC]) ? DBSIMPLE_SKIP : $filter[Type::NPC],
|
||||||
array_keys($this->templates)
|
array_keys($this->templates)
|
||||||
);
|
);
|
||||||
|
|
||||||
$xCosts = [];
|
foreach ($rawEntries as $costEntry)
|
||||||
foreach ($itemz as $i => $vendors)
|
{
|
||||||
$xCosts = array_merge($xCosts, array_column($vendors, 'extendedCost'));
|
if ($costEntry['extendedCost'])
|
||||||
|
$xCostData[] = $costEntry['extendedCost'];
|
||||||
|
|
||||||
if ($xCosts)
|
if (!isset($itemz[$costEntry['item']][$costEntry['entry']]))
|
||||||
$xCosts = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM ?_itemextendedcost WHERE id IN (?a)', $xCosts);
|
$itemz[$costEntry['item']][$costEntry['entry']] = [$costEntry];
|
||||||
|
else
|
||||||
|
$itemz[$costEntry['item']][$costEntry['entry']][] = $costEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($xCostData)
|
||||||
|
$xCostData = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM ?_itemextendedcost WHERE id IN (?a)', $xCostData);
|
||||||
|
|
||||||
$cItems = [];
|
$cItems = [];
|
||||||
foreach ($itemz as $k => $vendors)
|
foreach ($itemz as $k => $vendors)
|
||||||
{
|
{
|
||||||
foreach ($vendors as $l => $vInfo)
|
foreach ($vendors as $l => $vendor)
|
||||||
{
|
{
|
||||||
$costs = [];
|
foreach ($vendor as $m => $vInfo)
|
||||||
if (!empty($xCosts[$vInfo['extendedCost']]))
|
|
||||||
$costs = $xCosts[$vInfo['extendedCost']];
|
|
||||||
|
|
||||||
$data = array(
|
|
||||||
'stock' => $vInfo['maxcount'] ?: -1,
|
|
||||||
'event' => $vInfo['eventId'],
|
|
||||||
'reqRating' => $costs ? $costs['reqPersonalRating'] : 0,
|
|
||||||
'reqBracket' => $costs ? $costs['reqArenaSlot'] : 0
|
|
||||||
);
|
|
||||||
|
|
||||||
// hardcode arena(103) & honor(104)
|
|
||||||
if (!empty($costs['reqArenaPoints']))
|
|
||||||
{
|
{
|
||||||
$data[-103] = $costs['reqArenaPoints'];
|
$costs = [];
|
||||||
$this->jsGlobals[TYPE_CURRENCY][103] = 103;
|
if (!empty($xCostData[$vInfo['extendedCost']]))
|
||||||
}
|
$costs = $xCostData[$vInfo['extendedCost']];
|
||||||
|
|
||||||
if (!empty($costs['reqHonorPoints']))
|
$data = array(
|
||||||
{
|
'stock' => $vInfo['maxcount'] ?: -1,
|
||||||
$data[-104] = $costs['reqHonorPoints'];
|
'event' => $vInfo['eventId'],
|
||||||
$this->jsGlobals[TYPE_CURRENCY][104] = 104;
|
'reqRating' => $costs ? $costs['reqPersonalRating'] : 0,
|
||||||
}
|
'reqBracket' => $costs ? $costs['reqArenaSlot'] : 0
|
||||||
|
);
|
||||||
|
|
||||||
for ($i = 1; $i < 6; $i++)
|
// hardcode arena(103) & honor(104)
|
||||||
{
|
if (!empty($costs['reqArenaPoints']))
|
||||||
if (!empty($costs['reqItemId'.$i]) && $costs['itemCount'.$i] > 0)
|
|
||||||
{
|
{
|
||||||
$data[$costs['reqItemId'.$i]] = $costs['itemCount'.$i];
|
$data[-103] = $costs['reqArenaPoints'];
|
||||||
$cItems[] = $costs['reqItemId'.$i];
|
$this->jsGlobals[Type::CURRENCY][103] = 103;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($costs['reqHonorPoints']))
|
||||||
|
{
|
||||||
|
$data[-104] = $costs['reqHonorPoints'];
|
||||||
|
$this->jsGlobals[Type::CURRENCY][104] = 104;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i = 1; $i < 6; $i++)
|
||||||
|
{
|
||||||
|
if (!empty($costs['reqItemId'.$i]) && $costs['itemCount'.$i] > 0)
|
||||||
|
{
|
||||||
|
$data[$costs['reqItemId'.$i]] = $costs['itemCount'.$i];
|
||||||
|
$cItems[] = $costs['reqItemId'.$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no extended cost or additional gold required
|
||||||
|
if (!$costs || $this->getField('flagsExtra') & 0x04)
|
||||||
|
{
|
||||||
|
$this->getEntry($k);
|
||||||
|
if ($_ = $this->getField('buyPrice'))
|
||||||
|
$data[0] = $_;
|
||||||
|
}
|
||||||
|
|
||||||
|
$vendor[$m] = $data;
|
||||||
}
|
}
|
||||||
|
$vendors[$l] = $vendor;
|
||||||
// no extended cost or additional gold required
|
|
||||||
if (!$costs || $this->getField('flagsExtra') & 0x04)
|
|
||||||
if ($_ = $this->getField('buyPrice'))
|
|
||||||
$data[0] = $_;
|
|
||||||
|
|
||||||
$vendors[$l] = $data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$itemz[$k] = $vendors;
|
$itemz[$k] = $vendors;
|
||||||
@@ -164,33 +189,37 @@ class ItemList extends BaseType
|
|||||||
foreach ($jsData as $k => $v)
|
foreach ($jsData as $k => $v)
|
||||||
$this->jsGlobals[$type][$k] = $v;
|
$this->jsGlobals[$type][$k] = $v;
|
||||||
|
|
||||||
foreach ($itemz as $id => $vendors)
|
foreach ($itemz as $itemId => $vendors)
|
||||||
{
|
{
|
||||||
foreach ($vendors as $l => $costs)
|
foreach ($vendors as $npcId => $costData)
|
||||||
{
|
{
|
||||||
foreach ($costs as $k => $v)
|
foreach ($costData as $itr => $cost)
|
||||||
{
|
{
|
||||||
if (in_array($k, $cItems))
|
foreach ($cost as $k => $v)
|
||||||
{
|
{
|
||||||
$found = false;
|
if (in_array($k, $cItems))
|
||||||
foreach ($moneyItems->iterate() as $__)
|
|
||||||
{
|
{
|
||||||
if ($moneyItems->getField('itemId') == $k)
|
$found = false;
|
||||||
|
foreach ($moneyItems->iterate() as $__)
|
||||||
{
|
{
|
||||||
unset($costs[$k]);
|
if ($moneyItems->getField('itemId') == $k)
|
||||||
$costs[-$moneyItems->id] = $v;
|
{
|
||||||
$found = true;
|
unset($cost[$k]);
|
||||||
break;
|
$cost[-$moneyItems->id] = $v;
|
||||||
|
$found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!$found)
|
if (!$found)
|
||||||
$this->jsGlobals[TYPE_ITEM][$k] = $k;
|
$this->jsGlobals[Type::ITEM][$k] = $k;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
$costData[$itr] = $cost;
|
||||||
}
|
}
|
||||||
$vendors[$l] = $costs;
|
$vendors[$npcId] = $costData;
|
||||||
}
|
}
|
||||||
$itemz[$id] = $vendors;
|
$itemz[$itemId] = $vendors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,43 +229,46 @@ class ItemList extends BaseType
|
|||||||
$result = $this->vendors;
|
$result = $this->vendors;
|
||||||
|
|
||||||
// apply filter if given
|
// apply filter if given
|
||||||
$tok = !empty($filter[TYPE_ITEM]) ? $filter[TYPE_ITEM] : null;
|
$tok = !empty($filter[Type::ITEM]) ? $filter[Type::ITEM] : null;
|
||||||
$cur = !empty($filter[TYPE_CURRENCY]) ? $filter[TYPE_CURRENCY] : null;
|
$cur = !empty($filter[Type::CURRENCY]) ? $filter[Type::CURRENCY] : null;
|
||||||
|
|
||||||
foreach ($result as $itemId => &$data)
|
foreach ($result as $itemId => &$data)
|
||||||
{
|
{
|
||||||
$reqRating = [];
|
$reqRating = [];
|
||||||
foreach ($data as $npcId => $costs)
|
foreach ($data as $npcId => $entries)
|
||||||
{
|
{
|
||||||
if ($tok || $cur) // bought with specific token or currency
|
foreach ($entries as $costs)
|
||||||
{
|
{
|
||||||
$valid = false;
|
if ($tok || $cur) // bought with specific token or currency
|
||||||
foreach ($costs as $k => $qty)
|
|
||||||
{
|
{
|
||||||
if ((!$tok || $k == $tok) && (!$cur || $k == -$cur))
|
$valid = false;
|
||||||
|
foreach ($costs as $k => $qty)
|
||||||
{
|
{
|
||||||
$valid = true;
|
if ((!$tok || $k == $tok) && (!$cur || $k == -$cur))
|
||||||
break;
|
{
|
||||||
|
$valid = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$valid)
|
||||||
|
unset($data[$npcId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$valid)
|
// reqRating ins't really a cost .. so pass it by ref instead of return
|
||||||
unset($data[$npcId]);
|
// use highest total value
|
||||||
|
if (isset($data[$npcId]) && $costs['reqRating'] && (!$reqRating || $reqRating[0] < $costs['reqRating']))
|
||||||
|
$reqRating = [$costs['reqRating'], $costs['reqBracket']];
|
||||||
}
|
}
|
||||||
|
|
||||||
// reqRating ins't really a cost .. so pass it by ref instead of return
|
|
||||||
// use highest total value
|
|
||||||
if (isset($data[$npcId]) && $costs['reqRating'] && (!$reqRating || $reqRating[0] < $costs['reqRating']))
|
|
||||||
$reqRating = [$costs['reqRating'], $costs['reqBracket']];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($reqRating)
|
|
||||||
$data['reqRating'] = $reqRating[0];
|
|
||||||
|
|
||||||
if (empty($data))
|
if (empty($data))
|
||||||
unset($result[$itemId]);
|
unset($result[$itemId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// restore internal index;
|
||||||
|
$this->getEntry($idx);
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,6 +291,11 @@ class ItemList extends BaseType
|
|||||||
if ($addInfoMask & ITEMINFO_JSON)
|
if ($addInfoMask & ITEMINFO_JSON)
|
||||||
$this->extendJsonStats();
|
$this->extendJsonStats();
|
||||||
|
|
||||||
|
$extCosts = [];
|
||||||
|
if ($addInfoMask & ITEMINFO_VENDOR)
|
||||||
|
$extCosts = $this->getExtendedCost($miscData);
|
||||||
|
|
||||||
|
$extCostOther = [];
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
{
|
{
|
||||||
foreach ($this->json[$this->id] as $k => $v)
|
foreach ($this->json[$this->id] as $k => $v)
|
||||||
@@ -268,6 +305,15 @@ class ItemList extends BaseType
|
|||||||
$data[$this->id]['name'] = $data[$this->id]['quality'].$data[$this->id]['name'];
|
$data[$this->id]['name'] = $data[$this->id]['quality'].$data[$this->id]['name'];
|
||||||
unset($data[$this->id]['quality']);
|
unset($data[$this->id]['quality']);
|
||||||
|
|
||||||
|
if (!empty($this->relEnchant) && $this->curTpl['randomEnchant'])
|
||||||
|
{
|
||||||
|
if (($x = array_search($this->curTpl['randomEnchant'], array_column($this->relEnchant, 'entry'))) !== false)
|
||||||
|
{
|
||||||
|
$data[$this->id]['rel'] = 'rand='.$this->relEnchant[$x]['ench'];
|
||||||
|
$data[$this->id]['name'] .= ' '.$this->relEnchant[$x]['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($addInfoMask & ITEMINFO_JSON)
|
if ($addInfoMask & ITEMINFO_JSON)
|
||||||
{
|
{
|
||||||
foreach ($this->itemMods[$this->id] as $k => $v)
|
foreach ($this->itemMods[$this->id] as $k => $v)
|
||||||
@@ -293,42 +339,51 @@ class ItemList extends BaseType
|
|||||||
if ($addInfoMask & ITEMINFO_VENDOR)
|
if ($addInfoMask & ITEMINFO_VENDOR)
|
||||||
{
|
{
|
||||||
// just use the first results
|
// just use the first results
|
||||||
// todo (med): dont use first result; search for the right one
|
// todo (med): dont use first vendor; search for the right one
|
||||||
if (!empty($this->getExtendedCost($miscData)[$this->id]))
|
if (!empty($extCosts[$this->id]))
|
||||||
{
|
{
|
||||||
$cost = reset($this->getExtendedCost($miscData)[$this->id]);
|
$cost = reset($extCosts[$this->id]);
|
||||||
$currency = [];
|
foreach ($cost as $itr => $entries)
|
||||||
$tokens = [];
|
|
||||||
|
|
||||||
foreach ($cost as $k => $qty)
|
|
||||||
{
|
{
|
||||||
if (is_string($k))
|
$currency = [];
|
||||||
continue;
|
$tokens = [];
|
||||||
|
$costArr = [];
|
||||||
|
|
||||||
if ($k > 0)
|
foreach ($entries as $k => $qty)
|
||||||
$tokens[] = [$k, $qty];
|
{
|
||||||
else if ($k < 0)
|
if (is_string($k))
|
||||||
$currency[] = [-$k, $qty];
|
continue;
|
||||||
|
|
||||||
|
if ($k > 0)
|
||||||
|
$tokens[] = [$k, $qty];
|
||||||
|
else if ($k < 0)
|
||||||
|
$currency[] = [-$k, $qty];
|
||||||
|
}
|
||||||
|
|
||||||
|
$costArr['stock'] = $entries['stock'];// display as column in lv
|
||||||
|
$costArr['avail'] = $entries['stock'];// display as number on icon
|
||||||
|
$costArr['cost'] = [empty($entries[0]) ? 0 : $entries[0]];
|
||||||
|
|
||||||
|
if ($entries['event'])
|
||||||
|
{
|
||||||
|
$this->jsGlobals[Type::WORLDEVENT][$entries['event']] = $entries['event'];
|
||||||
|
$costArr['condition'][0][$this->id][] = [[CND_ACTIVE_EVENT, $entries['event']]];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($currency || $tokens) // fill idx:3 if required
|
||||||
|
$costArr['cost'][] = $currency;
|
||||||
|
|
||||||
|
if ($tokens)
|
||||||
|
$costArr['cost'][] = $tokens;
|
||||||
|
|
||||||
|
if (!empty($entries['reqRating']))
|
||||||
|
$costArr['reqarenartng'] = $entries['reqRating'];
|
||||||
|
|
||||||
|
if ($itr > 0)
|
||||||
|
$extCostOther[$this->id][] = $costArr;
|
||||||
|
else
|
||||||
|
$data[$this->id] = array_merge($data[$this->id], $costArr);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data[$this->id]['stock'] = $cost['stock']; // display as column in lv
|
|
||||||
$data[$this->id]['avail'] = $cost['stock']; // display as number on icon
|
|
||||||
$data[$this->id]['cost'] = [empty($cost[0]) ? 0 : $cost[0]];
|
|
||||||
|
|
||||||
if ($cost['event'])
|
|
||||||
{
|
|
||||||
$this->jsGlobals[TYPE_WORLDEVENT][$cost['event']] = $cost['event'];
|
|
||||||
$row['condition'][0][$this->id][] = [[CND_ACTIVE_EVENT, $cost['event']]];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($currency || $tokens) // fill idx:3 if required
|
|
||||||
$data[$this->id]['cost'][] = $currency;
|
|
||||||
|
|
||||||
if ($tokens)
|
|
||||||
$data[$this->id]['cost'][] = $tokens;
|
|
||||||
|
|
||||||
if (!empty($cost['reqRating']))
|
|
||||||
$data[$this->id]['reqarenartng'] = $cost['reqRating'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($x = $this->curTpl['buyPrice'])
|
if ($x = $this->curTpl['buyPrice'])
|
||||||
@@ -390,6 +445,10 @@ class ItemList extends BaseType
|
|||||||
$data[$this->id]['cooldown'] = $this->curTpl['cooldown'] / 1000;
|
$data[$this->id]['cooldown'] = $this->curTpl['cooldown'] / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($extCostOther as $itemId => $duplicates)
|
||||||
|
foreach ($duplicates as $d)
|
||||||
|
$data[] = array_merge($data[$itemId], $d); // we dont really use keys on data, but this may cause errors in future
|
||||||
|
|
||||||
/* even more complicated crap
|
/* even more complicated crap
|
||||||
modelviewer {type:X, displayid:Y, slot:z} .. not sure, when to set
|
modelviewer {type:X, displayid:Y, slot:z} .. not sure, when to set
|
||||||
*/
|
*/
|
||||||
@@ -405,7 +464,7 @@ class ItemList extends BaseType
|
|||||||
{
|
{
|
||||||
if ($addMask & GLOBALINFO_SELF)
|
if ($addMask & GLOBALINFO_SELF)
|
||||||
{
|
{
|
||||||
$data[TYPE_ITEM][$id] = array(
|
$data[Type::ITEM][$id] = array(
|
||||||
'name' => $this->getField('name', true),
|
'name' => $this->getField('name', true),
|
||||||
'quality' => $this->curTpl['quality'],
|
'quality' => $this->curTpl['quality'],
|
||||||
'icon' => $this->curTpl['iconString']
|
'icon' => $this->curTpl['iconString']
|
||||||
@@ -471,7 +530,7 @@ class ItemList extends BaseType
|
|||||||
if ($this->enhanceR['enchantId'.$i] <= 0)
|
if ($this->enhanceR['enchantId'.$i] <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$enchant = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE Id = ?d', $this->enhanceR['enchantId'.$i]);
|
$enchant = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE id = ?d', $this->enhanceR['enchantId'.$i]);
|
||||||
if ($this->enhanceR['allocationPct'.$i] > 0)
|
if ($this->enhanceR['allocationPct'.$i] > 0)
|
||||||
{
|
{
|
||||||
$amount = intVal($this->enhanceR['allocationPct'.$i] * $this->generateEnchSuffixFactor());
|
$amount = intVal($this->enhanceR['allocationPct'.$i] * $this->generateEnchSuffixFactor());
|
||||||
@@ -640,10 +699,10 @@ class ItemList extends BaseType
|
|||||||
if ($interactive)
|
if ($interactive)
|
||||||
$spanI = 'class="q2 tip" onmouseover="$WH.Tooltip.showAtCursor(event, $WH.sprintf(LANG.tooltip_armorbonus, '.$this->curTpl['armorDamageModifier'].'), 0, 0, \'q\')" onmousemove="$WH.Tooltip.cursorUpdate(event)" onmouseout="$WH.Tooltip.hide()"';
|
$spanI = 'class="q2 tip" onmouseover="$WH.Tooltip.showAtCursor(event, $WH.sprintf(LANG.tooltip_armorbonus, '.$this->curTpl['armorDamageModifier'].'), 0, 0, \'q\')" onmousemove="$WH.Tooltip.cursorUpdate(event)" onmouseout="$WH.Tooltip.hide()"';
|
||||||
|
|
||||||
$x .= '<span '.$spanI.'><!--addamr'.$this->curTpl['armorDamageModifier'].'--><span>'.Lang::item('armor', [intVal($this->curTpl['armor'] - $this->curTpl['armorDamageModifier'])]).'</span></span><br />';
|
$x .= '<span '.$spanI.'><!--addamr'.$this->curTpl['armorDamageModifier'].'--><span>'.Lang::item('armor', [$this->curTpl['armor']]).'</span></span><br />';
|
||||||
}
|
}
|
||||||
else if (($this->curTpl['armor'] - $this->curTpl['armorDamageModifier']) > 0)
|
else if ($this->curTpl['armor'])
|
||||||
$x .= '<span><!--amr-->'.Lang::item('armor', [intVal($this->curTpl['armor'] - $this->curTpl['armorDamageModifier'])]).'</span><br />';
|
$x .= '<span><!--amr-->'.Lang::item('armor', [$this->curTpl['armor']]).'</span><br />';
|
||||||
|
|
||||||
// Block (note: block value from field block and from field stats or parsed from itemSpells are displayed independently)
|
// Block (note: block value from field block and from field stats or parsed from itemSpells are displayed independently)
|
||||||
if ($this->curTpl['tplBlock'])
|
if ($this->curTpl['tplBlock'])
|
||||||
@@ -676,7 +735,7 @@ class ItemList extends BaseType
|
|||||||
$vspfArgs = [Lang::item('gemColors', $gemCnd['color'.$i] - 1), Lang::item('gemColors', $gemCnd['cmpColor'.$i] - 1)];
|
$vspfArgs = [Lang::item('gemColors', $gemCnd['color'.$i] - 1), Lang::item('gemColors', $gemCnd['cmpColor'.$i] - 1)];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
continue;
|
continue 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
$x .= '<span class="q0">'.Lang::achievement('reqNumCrt').' '.Lang::item('gemConditions', $gemCnd['comparator'.$i], $vspfArgs).'</span><br />';
|
$x .= '<span class="q0">'.Lang::achievement('reqNumCrt').' '.Lang::item('gemConditions', $gemCnd['comparator'.$i], $vspfArgs).'</span><br />';
|
||||||
@@ -727,7 +786,7 @@ class ItemList extends BaseType
|
|||||||
// Enchantment
|
// Enchantment
|
||||||
if (isset($enhance['e']))
|
if (isset($enhance['e']))
|
||||||
{
|
{
|
||||||
if ($enchText = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE Id = ?', $enhance['e']))
|
if ($enchText = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE id = ?', $enhance['e']))
|
||||||
$x .= '<span class="q2"><!--e-->'.Util::localizedString($enchText, 'name').'</span><br />';
|
$x .= '<span class="q2"><!--e-->'.Util::localizedString($enchText, 'name').'</span><br />';
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -806,33 +865,33 @@ class ItemList extends BaseType
|
|||||||
|
|
||||||
if ($_ = $this->curTpl['socketBonus'])
|
if ($_ = $this->curTpl['socketBonus'])
|
||||||
{
|
{
|
||||||
$sbonus = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE Id = ?d', $_);
|
$sbonus = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantment WHERE id = ?d', $_);
|
||||||
$x .= '<span class="q'.($hasMatch ? '2' : '0').'">'.Lang::item('socketBonus').Lang::main('colon').'<a href="?enchantment='.$_.'">'.Util::localizedString($sbonus, 'name').'</a></span><br />';
|
$x .= '<span class="q'.($hasMatch ? '2' : '0').'">'.Lang::item('socketBonus', ['<a href="?enchantment='.$_.'">'.Util::localizedString($sbonus, 'name').'</a>']).'</span><br />';
|
||||||
}
|
}
|
||||||
|
|
||||||
// durability
|
// durability
|
||||||
if ($dur = $this->curTpl['durability'])
|
if ($dur = $this->curTpl['durability'])
|
||||||
$x .= sprintf(Lang::item('durability'), $dur, $dur).'<br />';
|
$x .= sprintf(Lang::item('durability'), $dur, $dur).'<br />';
|
||||||
|
|
||||||
|
$jsg = [];
|
||||||
// required classes
|
// required classes
|
||||||
if ($classes = Lang::getClassString($this->curTpl['requiredClass'], $jsg, $__))
|
if ($classes = Lang::getClassString($this->curTpl['requiredClass'], $jsg))
|
||||||
{
|
{
|
||||||
foreach ($jsg as $js)
|
foreach ($jsg as $js)
|
||||||
if (empty($this->jsGlobals[TYPE_CLASS][$js]))
|
if (empty($this->jsGlobals[Type::CHR_CLASS][$js]))
|
||||||
$this->jsGlobals[TYPE_CLASS][$js] = $js;
|
$this->jsGlobals[Type::CHR_CLASS][$js] = $js;
|
||||||
|
|
||||||
$x .= Lang::game('classes').Lang::main('colon').$classes.'<br />';
|
$x .= Lang::game('classes').Lang::main('colon').$classes.'<br />';
|
||||||
}
|
}
|
||||||
|
|
||||||
// required races
|
// required races
|
||||||
if ($races = Lang::getRaceString($this->curTpl['requiredRace'], $__, $jsg, $__))
|
if ($races = Lang::getRaceString($this->curTpl['requiredRace'], $jsg))
|
||||||
{
|
{
|
||||||
foreach ($jsg as $js)
|
foreach ($jsg as $js)
|
||||||
if (empty($this->jsGlobals[TYPE_RACE][$js]))
|
if (empty($this->jsGlobals[Type::CHR_RACE][$js]))
|
||||||
$this->jsGlobals[TYPE_RACE][$js] = $js;
|
$this->jsGlobals[Type::CHR_ACE][$js] = $js;
|
||||||
|
|
||||||
if ($races != Lang::game('ra', 0)) // not "both", but display combinations like: troll, dwarf
|
$x .= Lang::game('races').Lang::main('colon').$races.'<br />';
|
||||||
$x .= Lang::game('races').Lang::main('colon').$races.'<br />';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// required honorRank (not used anymore)
|
// required honorRank (not used anymore)
|
||||||
@@ -875,8 +934,8 @@ class ItemList extends BaseType
|
|||||||
$x .= sprintf(Lang::game('requires'), '<a class="q1" href="?faction='.$reqFac.'">'.FactionList::getName($reqFac).'</a> - '.Lang::game('rep', $this->curTpl['requiredFactionRank'])).'<br />';
|
$x .= sprintf(Lang::game('requires'), '<a class="q1" href="?faction='.$reqFac.'">'.FactionList::getName($reqFac).'</a> - '.Lang::game('rep', $this->curTpl['requiredFactionRank'])).'<br />';
|
||||||
|
|
||||||
// locked or openable
|
// locked or openable
|
||||||
if ($locks = Lang::getLocks($this->curTpl['lockId'], true))
|
if ($locks = Lang::getLocks($this->curTpl['lockId'], $arr, true, true))
|
||||||
$x .= '<span class="q0">'.Lang::item('locked').'<br />'.implode('<br />', $locks).'</span><br />';
|
$x .= '<span class="q0">'.Lang::item('locked').'<br />'.implode('<br />', array_map(function($x) { return sprintf(Lang::game('requires'), $x); }, $locks)).'</span><br />';
|
||||||
else if ($this->curTpl['flags'] & ITEM_FLAG_OPENABLE)
|
else if ($this->curTpl['flags'] & ITEM_FLAG_OPENABLE)
|
||||||
$x .= '<span class="q2">'.Lang::item('openClick').'</span><br />';
|
$x .= '<span class="q2">'.Lang::item('openClick').'</span><br />';
|
||||||
|
|
||||||
@@ -896,9 +955,14 @@ class ItemList extends BaseType
|
|||||||
if ($cd < $this->curTpl['spellCategoryCooldown'.$j])
|
if ($cd < $this->curTpl['spellCategoryCooldown'.$j])
|
||||||
$cd = $this->curTpl['spellCategoryCooldown'.$j];
|
$cd = $this->curTpl['spellCategoryCooldown'.$j];
|
||||||
|
|
||||||
$cd = $cd < 5000 ? null : ' ('.sprintf(Lang::game('cooldown'), Util::formatTime($cd)).')';
|
$extra = [];
|
||||||
|
if ($cd >= 5000)
|
||||||
|
$extra[] = Lang::game('cooldown', [Util::formatTime($cd, true)]);
|
||||||
|
if ($this->curTpl['spellTrigger'.$j] == 2)
|
||||||
|
if ($ppm = $this->curTpl['spellppmRate'.$j])
|
||||||
|
$extra[] = Lang::spell('ppm', [$ppm]);
|
||||||
|
|
||||||
$itemSpellsAndTrigger[$this->curTpl['spellId'.$j]] = [$this->curTpl['spellTrigger'.$j], $cd];
|
$itemSpellsAndTrigger[$this->curTpl['spellId'.$j]] = [$this->curTpl['spellTrigger'.$j], $extra ? ' ('.implode(', ', $extra).')' : ''];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -942,12 +1006,33 @@ class ItemList extends BaseType
|
|||||||
$pieces = [];
|
$pieces = [];
|
||||||
if ($setId = $this->getField('itemset'))
|
if ($setId = $this->getField('itemset'))
|
||||||
{
|
{
|
||||||
// while Ids can technically be used multiple times the only difference in data are the items used. So it doesn't matter what we get
|
$condition = [
|
||||||
$itemset = new ItemsetList(array(['id', $setId]));
|
['refSetId', $setId],
|
||||||
|
// ['quality', $this->curTpl['quality']],
|
||||||
|
['minLevel', $this->curTpl['itemLevel'], '<='],
|
||||||
|
['maxLevel', $this->curTpl['itemLevel'], '>=']
|
||||||
|
];
|
||||||
|
|
||||||
|
$itemset = new ItemsetList($condition);
|
||||||
if (!$itemset->error && $itemset->pieceToSet)
|
if (!$itemset->error && $itemset->pieceToSet)
|
||||||
{
|
{
|
||||||
|
// handle special cases where:
|
||||||
|
// > itemset has items of different qualities (handled by not limiting for this in the initial query)
|
||||||
|
// > itemset is virtual and multiple instances have the same itemLevel but not quality (filter below)
|
||||||
|
if ($itemset->getMatches() > 1)
|
||||||
|
{
|
||||||
|
foreach ($itemset->iterate() as $id => $__)
|
||||||
|
{
|
||||||
|
if ($itemset->getField('quality') == $this->curTpl['quality'])
|
||||||
|
{
|
||||||
|
$itemset->pieceToSet = array_filter($itemset->pieceToSet, function($x) use ($id) { return $id == $x; });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$pieces = DB::Aowow()->select('
|
$pieces = DB::Aowow()->select('
|
||||||
SELECT b.id AS ARRAY_KEY, b.name_loc0, b.name_loc2, b.name_loc3, b.name_loc6, b.name_loc8, GROUP_CONCAT(a.id SEPARATOR \':\') AS equiv
|
SELECT b.id AS ARRAY_KEY, b.name_loc0, b.name_loc2, b.name_loc3, b.name_loc4, b.name_loc6, b.name_loc8, GROUP_CONCAT(a.id SEPARATOR \':\') AS equiv
|
||||||
FROM ?_items a, ?_items b
|
FROM ?_items a, ?_items b
|
||||||
WHERE a.slotBak = b.slotBak AND a.itemset = b.itemset AND b.id IN (?a)
|
WHERE a.slotBak = b.slotBak AND a.itemset = b.itemset AND b.id IN (?a)
|
||||||
GROUP BY b.id;',
|
GROUP BY b.id;',
|
||||||
@@ -959,7 +1044,7 @@ class ItemList extends BaseType
|
|||||||
|
|
||||||
$xSet = '<br /><span class="q">'.Lang::item('setName', ['<a href="?itemset='.$itemset->id.'" class="q">'.$itemset->getField('name', true).'</a>', 0, count($pieces)]).'</span>';
|
$xSet = '<br /><span class="q">'.Lang::item('setName', ['<a href="?itemset='.$itemset->id.'" class="q">'.$itemset->getField('name', true).'</a>', 0, count($pieces)]).'</span>';
|
||||||
|
|
||||||
if ($skId = $itemset->getField('skillId')) // bonus requires skill to activate
|
if ($skId = $itemset->getField('skillId')) // bonus requires skill to activate
|
||||||
{
|
{
|
||||||
$xSet .= '<br />'.sprintf(Lang::game('requires'), '<a href="?skills='.$skId.'" class="q1">'.SkillList::getName($skId).'</a>');
|
$xSet .= '<br />'.sprintf(Lang::game('requires'), '<a href="?skills='.$skId.'" class="q1">'.SkillList::getName($skId).'</a>');
|
||||||
|
|
||||||
@@ -1115,7 +1200,7 @@ class ItemList extends BaseType
|
|||||||
// is it available for this item? .. does it even exist?!
|
// is it available for this item? .. does it even exist?!
|
||||||
if (empty($this->enhanceR))
|
if (empty($this->enhanceR))
|
||||||
if (DB::World()->selectCell('SELECT 1 FROM item_enchantment_template WHERE entry = ?d AND ench = ?d', abs($this->getField('randomEnchant')), abs($randId)))
|
if (DB::World()->selectCell('SELECT 1 FROM item_enchantment_template WHERE entry = ?d AND ench = ?d', abs($this->getField('randomEnchant')), abs($randId)))
|
||||||
if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_itemrandomenchant WHERE Id = ?d', $randId))
|
if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_itemrandomenchant WHERE id = ?d', $randId))
|
||||||
$this->enhanceR = $_;
|
$this->enhanceR = $_;
|
||||||
|
|
||||||
return !empty($this->enhanceR);
|
return !empty($this->enhanceR);
|
||||||
@@ -1124,7 +1209,7 @@ class ItemList extends BaseType
|
|||||||
// from Trinity
|
// from Trinity
|
||||||
public function generateEnchSuffixFactor()
|
public function generateEnchSuffixFactor()
|
||||||
{
|
{
|
||||||
$rpp = DB::Aowow()->selectRow('SELECT * FROM ?_itemrandomproppoints WHERE Id = ?', $this->curTpl['itemLevel']);
|
$rpp = DB::Aowow()->selectRow('SELECT * FROM ?_itemrandomproppoints WHERE id = ?', $this->curTpl['itemLevel']);
|
||||||
if (!$rpp)
|
if (!$rpp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -1203,15 +1288,8 @@ class ItemList extends BaseType
|
|||||||
$this->itemMods[$this->id] = [];
|
$this->itemMods[$this->id] = [];
|
||||||
|
|
||||||
foreach (Game::$itemMods as $mod)
|
foreach (Game::$itemMods as $mod)
|
||||||
{
|
if ($_ = floatVal($this->curTpl[$mod]))
|
||||||
if (isset($this->curTpl[$mod]) && ($_ = floatVal($this->curTpl[$mod])))
|
Util::arraySumByKey($this->itemMods[$this->id], [$mod => $_]);
|
||||||
{
|
|
||||||
if (!isset($this->itemMods[$this->id][$mod]))
|
|
||||||
$this->itemMods[$this->id][$mod] = 0;
|
|
||||||
|
|
||||||
$this->itemMods[$this->id][$mod] += $_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetch and add socketbonusstats
|
// fetch and add socketbonusstats
|
||||||
if (!empty($this->json[$this->id]['socketbonus']))
|
if (!empty($this->json[$this->id]['socketbonus']))
|
||||||
@@ -1224,7 +1302,7 @@ class ItemList extends BaseType
|
|||||||
|
|
||||||
if ($enchantments)
|
if ($enchantments)
|
||||||
{
|
{
|
||||||
$eStats = DB::Aowow()->select('SELECT *, typeId AS ARRAY_KEY FROM ?_item_stats WHERE `type` = ?d AND typeId IN (?a)', TYPE_ENCHANTMENT, array_keys($enchantments));
|
$eStats = DB::Aowow()->select('SELECT *, typeId AS ARRAY_KEY FROM ?_item_stats WHERE `type` = ?d AND typeId IN (?a)', Type::ENCHANTMENT, array_keys($enchantments));
|
||||||
Util::checkNumeric($eStats);
|
Util::checkNumeric($eStats);
|
||||||
|
|
||||||
// and merge enchantments back
|
// and merge enchantments back
|
||||||
@@ -1238,7 +1316,7 @@ class ItemList extends BaseType
|
|||||||
if ($item > 0) // apply socketBonus
|
if ($item > 0) // apply socketBonus
|
||||||
$this->json[$item]['socketbonusstat'] = array_filter($eStats[$eId]);
|
$this->json[$item]['socketbonusstat'] = array_filter($eStats[$eId]);
|
||||||
else /* if ($item < 0) */ // apply gemEnchantment
|
else /* if ($item < 0) */ // apply gemEnchantment
|
||||||
Util::arraySumByKey($this->json[-$item][$mod], array_filter($eStats[$eId]));
|
Util::arraySumByKey($this->json[-$item], array_filter($eStats[$eId]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1284,7 +1362,7 @@ class ItemList extends BaseType
|
|||||||
{
|
{
|
||||||
$data[$this->id] = array(
|
$data[$this->id] = array(
|
||||||
'n' => $this->getField('name', true),
|
'n' => $this->getField('name', true),
|
||||||
't' => TYPE_ITEM,
|
't' => Type::ITEM,
|
||||||
'ti' => $this->id,
|
'ti' => $this->id,
|
||||||
'q' => $this->curTpl['quality'],
|
'q' => $this->curTpl['quality'],
|
||||||
// 'p' => PvP [NYI]
|
// 'p' => PvP [NYI]
|
||||||
@@ -1346,7 +1424,7 @@ class ItemList extends BaseType
|
|||||||
$buff[$_curTpl['moreType']][] = $_curTpl['moreTypeId'];
|
$buff[$_curTpl['moreType']][] = $_curTpl['moreTypeId'];
|
||||||
|
|
||||||
foreach ($buff as $type => $ids)
|
foreach ($buff as $type => $ids)
|
||||||
$this->sourceMore[$type] = (new Util::$typeClasses[$type](array(['id', $ids])))->getSourceData();
|
$this->sourceMore[$type] = (Type::newList($type, [['id', $ids]]))?->getSourceData();
|
||||||
}
|
}
|
||||||
|
|
||||||
$s = array_keys($this->sources[$this->id]);
|
$s = array_keys($this->sources[$this->id]);
|
||||||
@@ -1606,7 +1684,7 @@ class ItemList extends BaseType
|
|||||||
'frores' => $this->curTpl['resFrost'],
|
'frores' => $this->curTpl['resFrost'],
|
||||||
'shares' => $this->curTpl['resShadow'],
|
'shares' => $this->curTpl['resShadow'],
|
||||||
'arcres' => $this->curTpl['resArcane'],
|
'arcres' => $this->curTpl['resArcane'],
|
||||||
'armorbonus' => $this->curTpl['armorDamageModifier'],
|
'armorbonus' => max(0, intVal($this->curTpl['armorDamageModifier'])),
|
||||||
'armor' => $this->curTpl['armor'],
|
'armor' => $this->curTpl['armor'],
|
||||||
'dura' => $this->curTpl['durability'],
|
'dura' => $this->curTpl['durability'],
|
||||||
'itemset' => $this->curTpl['itemset'],
|
'itemset' => $this->curTpl['itemset'],
|
||||||
@@ -1647,9 +1725,6 @@ class ItemList extends BaseType
|
|||||||
$json['feratkpwr'] = $fap;
|
$json['feratkpwr'] = $fap;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->curTpl['armorDamageModifier'] > 0)
|
|
||||||
$json['armor'] -= $this->curTpl['armorDamageModifier'];
|
|
||||||
|
|
||||||
if ($this->curTpl['class'] == ITEM_CLASS_ARMOR || $this->curTpl['class'] == ITEM_CLASS_WEAPON)
|
if ($this->curTpl['class'] == ITEM_CLASS_ARMOR || $this->curTpl['class'] == ITEM_CLASS_WEAPON)
|
||||||
$json['gearscore'] = Util::getEquipmentScore($json['level'], $this->getField('quality'), $json['slot'], $json['nsockets']);
|
$json['gearscore'] = Util::getEquipmentScore($json['level'], $this->getField('quality'), $json['slot'], $json['nsockets']);
|
||||||
else if ($this->curTpl['class'] == ITEM_CLASS_GEM)
|
else if ($this->curTpl['class'] == ITEM_CLASS_GEM)
|
||||||
@@ -1785,7 +1860,7 @@ class ItemListFilter extends Filter
|
|||||||
38 => [FILTER_CR_NUMERIC, 'is.rgdatkpwr', NUM_CAST_INT, true ], // rgdatkpwr
|
38 => [FILTER_CR_NUMERIC, 'is.rgdatkpwr', NUM_CAST_INT, true ], // rgdatkpwr
|
||||||
39 => [FILTER_CR_NUMERIC, 'is.rgdhitrtng', NUM_CAST_INT, true ], // rgdhitrtng
|
39 => [FILTER_CR_NUMERIC, 'is.rgdhitrtng', NUM_CAST_INT, true ], // rgdhitrtng
|
||||||
40 => [FILTER_CR_NUMERIC, 'is.rgdcritstrkrtng', NUM_CAST_INT, true ], // rgdcritstrkrtng
|
40 => [FILTER_CR_NUMERIC, 'is.rgdcritstrkrtng', NUM_CAST_INT, true ], // rgdcritstrkrtng
|
||||||
41 => [FILTER_CR_NUMERIC, 'is.armor' , NUM_CAST_INT, true ], // armor
|
41 => [FILTER_CR_NUMERIC, 'is.armor', NUM_CAST_INT, true ], // armor
|
||||||
42 => [FILTER_CR_NUMERIC, 'is.defrtng', NUM_CAST_INT, true ], // defrtng
|
42 => [FILTER_CR_NUMERIC, 'is.defrtng', NUM_CAST_INT, true ], // defrtng
|
||||||
43 => [FILTER_CR_NUMERIC, 'is.block', NUM_CAST_INT, true ], // block
|
43 => [FILTER_CR_NUMERIC, 'is.block', NUM_CAST_INT, true ], // block
|
||||||
44 => [FILTER_CR_NUMERIC, 'is.blockrtng', NUM_CAST_INT, true ], // blockrtng
|
44 => [FILTER_CR_NUMERIC, 'is.blockrtng', NUM_CAST_INT, true ], // blockrtng
|
||||||
@@ -1914,10 +1989,10 @@ class ItemListFilter extends Filter
|
|||||||
'gm' => [FILTER_V_LIST, [2, 3, 4], false], // gem rarity for weight calculation
|
'gm' => [FILTER_V_LIST, [2, 3, 4], false], // gem rarity for weight calculation
|
||||||
'cr' => [FILTER_V_RANGE, [1, 177], true ], // criteria ids
|
'cr' => [FILTER_V_RANGE, [1, 177], true ], // criteria ids
|
||||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 99999]], true ], // criteria operators
|
'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
|
'crv' => [FILTER_V_REGEX, '/[\p{C};:%\\\\]/ui', true ], // criteria values - only printable chars, no delimiters
|
||||||
'upg' => [FILTER_V_RANGE, [1, 999999], true ], // upgrade item ids
|
'upg' => [FILTER_V_RANGE, [1, 999999], true ], // upgrade item ids
|
||||||
'gb' => [FILTER_V_LIST, [0, 1, 2, 3], false], // search result grouping
|
'gb' => [FILTER_V_LIST, [0, 1, 2, 3], false], // search result grouping
|
||||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name - only printable chars, no delimiter
|
'na' => [FILTER_V_REGEX, '/[\p{C};%\\\\]/ui', false], // name - only printable chars, no delimiter
|
||||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||||
'ub' => [FILTER_V_LIST, [[1, 9], 11], false], // usable by classId
|
'ub' => [FILTER_V_LIST, [[1, 9], 11], false], // usable by classId
|
||||||
'qu' => [FILTER_V_RANGE, [0, 7], true ], // quality ids
|
'qu' => [FILTER_V_RANGE, [0, 7], true ], // quality ids
|
||||||
@@ -2199,11 +2274,24 @@ class ItemListFilter extends Filter
|
|||||||
|
|
||||||
protected function cbHasRandEnchant($cr)
|
protected function cbHasRandEnchant($cr)
|
||||||
{
|
{
|
||||||
$randIds = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, ABS(id) FROM ?_itemrandomenchant WHERE name_loc?d LIKE ?', User::$localeId, '%'.$cr[2].'%');
|
$randIds = DB::Aowow()->select('SELECT id AS ARRAY_KEY, ABS(id) AS `id`, name_loc?d, name_loc0 FROM ?_itemrandomenchant WHERE name_loc?d LIKE ?', User::$localeId, User::$localeId, '%'.$cr[2].'%');
|
||||||
$tplIds = $randIds ? DB::World()->select('SELECT entry, ench FROM item_enchantment_template WHERE ench IN (?a)', $randIds) : [];
|
$tplIds = $randIds ? DB::World()->select('SELECT `entry`, `ench` FROM item_enchantment_template WHERE `ench` IN (?a)', array_column($randIds, 'id')) : [];
|
||||||
foreach ($tplIds as $k => &$set)
|
foreach ($tplIds as &$set)
|
||||||
if (array_search($set['ench'], $randIds) < 0)
|
{
|
||||||
|
$z = array_column($randIds, 'id');
|
||||||
|
$x = array_search($set['ench'], $z);
|
||||||
|
if (isset($randIds[-$z[$x]]))
|
||||||
|
{
|
||||||
$set['entry'] *= -1;
|
$set['entry'] *= -1;
|
||||||
|
$set['ench'] *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$set['name'] = Util::localizedString($randIds[$set['ench']], 'name', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// only enhance search results if enchantment by name is unique (implies only one enchantment per item is availabel)
|
||||||
|
if (count(array_unique(array_column($randIds, 'name_loc0'))) == 1)
|
||||||
|
$this->extraOpts['relEnchant'] = $tplIds;
|
||||||
|
|
||||||
if ($tplIds)
|
if ($tplIds)
|
||||||
return ['randomEnchant', array_column($tplIds, 'entry')];
|
return ['randomEnchant', array_column($tplIds, 'entry')];
|
||||||
@@ -2218,8 +2306,10 @@ class ItemListFilter extends Filter
|
|||||||
|
|
||||||
$this->formData['extraCols'][] = $cr[0];
|
$this->formData['extraCols'][] = $cr[0];
|
||||||
|
|
||||||
$costs = DB::Aowow()->selectCol('SELECT id FROM ?_itemextendedcost WHERE reqPersonalrating '.$cr[1].' '.$cr[2]);
|
$items = [0];
|
||||||
$items = DB::World()->selectCol($this->extCostQuery, $costs, $costs);
|
if ($costs = DB::Aowow()->selectCol('SELECT id FROM ?_itemextendedcost WHERE reqPersonalrating '.$cr[1].' '.$cr[2]))
|
||||||
|
$items = DB::World()->selectCol($this->extCostQuery, $costs, $costs);
|
||||||
|
|
||||||
return ['id', $items];
|
return ['id', $items];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2315,7 +2405,7 @@ class ItemListFilter extends Filter
|
|||||||
{
|
{
|
||||||
// todo: do something sensible..
|
// todo: do something sensible..
|
||||||
// // todo (med): get the avgbuyout into the listview
|
// // todo (med): get the avgbuyout into the listview
|
||||||
// if ($_ = DB::Characters()->select('SELECT ii.itemEntry AS ARRAY_KEY, AVG(ah.buyoutprice / ii.count) AS buyout FROM auctionhouse ah JOIN item_instance ii ON ah.itemguid = ii.guid GROUP BY ii.itemEntry HAVING avgbuyout '.$cr[1].' ?f', $c[1]))
|
// if ($_ = DB::Characters()->select('SELECT ii.itemEntry AS ARRAY_KEY, AVG(ah.buyoutprice / ii.count) AS buyout FROM auctionhouse ah JOIN item_instance ii ON ah.itemguid = ii.guid GROUP BY ii.itemEntry HAVING buyout '.$cr[1].' ?f', $c[1]))
|
||||||
// return ['i.id', array_keys($_)];
|
// return ['i.id', array_keys($_)];
|
||||||
// else
|
// else
|
||||||
// return [0];
|
// return [0];
|
||||||
@@ -2430,7 +2520,7 @@ class ItemListFilter extends Filter
|
|||||||
case 1: // Yes
|
case 1: // Yes
|
||||||
case 5: // No
|
case 5: // No
|
||||||
$w = 1;
|
$w = 1;
|
||||||
return;
|
break;
|
||||||
case 2: // Alliance
|
case 2: // Alliance
|
||||||
$w = 'reqRaceMask & '.RACE_MASK_ALLIANCE.' AND (reqRaceMask & '.RACE_MASK_HORDE.') = 0';
|
$w = 'reqRaceMask & '.RACE_MASK_ALLIANCE.' AND (reqRaceMask & '.RACE_MASK_HORDE.') = 0';
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class ItemsetList extends BaseType
|
|||||||
{
|
{
|
||||||
use ListviewHelper;
|
use ListviewHelper;
|
||||||
|
|
||||||
public static $type = TYPE_ITEMSET;
|
public static $type = Type::ITEMSET;
|
||||||
public static $brickFile = 'itemset';
|
public static $brickFile = 'itemset';
|
||||||
public static $dataTable = '?_itemset';
|
public static $dataTable = '?_itemset';
|
||||||
|
|
||||||
@@ -80,14 +80,14 @@ class ItemsetList extends BaseType
|
|||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
if ($this->classes && ($addMask & GLOBALINFO_RELATED))
|
if ($this->classes && ($addMask & GLOBALINFO_RELATED))
|
||||||
$data[TYPE_CLASS] = array_combine($this->classes, $this->classes);
|
$data[Type::CHR_CLASS] = array_combine($this->classes, $this->classes);
|
||||||
|
|
||||||
if ($this->pieceToSet && ($addMask & GLOBALINFO_SELF))
|
if ($this->pieceToSet && ($addMask & GLOBALINFO_SELF))
|
||||||
$data[TYPE_ITEM] = array_combine(array_keys($this->pieceToSet), array_keys($this->pieceToSet));
|
$data[Type::ITEM] = array_combine(array_keys($this->pieceToSet), array_keys($this->pieceToSet));
|
||||||
|
|
||||||
if ($addMask & GLOBALINFO_SELF)
|
if ($addMask & GLOBALINFO_SELF)
|
||||||
foreach ($this->iterate() as $id => $__)
|
foreach ($this->iterate() as $id => $__)
|
||||||
$data[TYPE_ITEMSET][$id] = ['name' => $this->getField('name', true)];
|
$data[Type::ITEMSET][$id] = ['name' => $this->getField('name', true)];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
@@ -98,19 +98,21 @@ class ItemsetList extends BaseType
|
|||||||
return array();
|
return array();
|
||||||
|
|
||||||
$x = '<table><tr><td>';
|
$x = '<table><tr><td>';
|
||||||
$x .= '<span class="q'.$this->getField('quality').'">'.Util::jsEscape($this->getField('name', true)).'</span><br />';
|
$x .= '<span class="q'.$this->getField('quality').'">'.$this->getField('name', true).'</span><br />';
|
||||||
|
|
||||||
$nClasses = 0;
|
$nCl = 0;
|
||||||
if ($_ = $this->getField('classMask'))
|
if ($_ = $this->getField('classMask'))
|
||||||
{
|
{
|
||||||
$cl = Lang::getClassString($_, $__, $nClasses);
|
$jsg = [];
|
||||||
$x .= Util::ucFirst($nClasses > 1 ? Lang::game('classes') : Lang::game('class')).Lang::main('colon').$cl.'<br />';
|
$cl = Lang::getClassString($_, $jsg);
|
||||||
|
$nCl = count($jsg);
|
||||||
|
$x .= Util::ucFirst($nCl > 1 ? Lang::game('classes') : Lang::game('class')).Lang::main('colon').$cl.'<br />';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($_ = $this->getField('contentGroup'))
|
if ($_ = $this->getField('contentGroup'))
|
||||||
$x .= Util::jsEscape(Lang::itemset('notes', $_)).($this->getField('heroic') ? ' <i class="q2">('.Lang::item('heroic').')</i>' : '').'<br />';
|
$x .= Lang::itemset('notes', $_).($this->getField('heroic') ? ' <i class="q2">('.Lang::item('heroic').')</i>' : '').'<br />';
|
||||||
|
|
||||||
if (!$nClasses || !$this->getField('contentGroup'))
|
if (!$nCl || !$this->getField('contentGroup'))
|
||||||
$x.= Lang::itemset('types', $this->getField('type')).'<br />';
|
$x.= Lang::itemset('types', $this->getField('type')).'<br />';
|
||||||
|
|
||||||
if ($bonuses = $this->getBonuses())
|
if ($bonuses = $this->getBonuses())
|
||||||
@@ -118,7 +120,7 @@ class ItemsetList extends BaseType
|
|||||||
$x .= '<span>';
|
$x .= '<span>';
|
||||||
|
|
||||||
foreach ($bonuses as $b)
|
foreach ($bonuses as $b)
|
||||||
$x .= '<br /><span class=\"q13\">'.$b['bonus'].' '.Lang::itemset('_pieces').Lang::main('colon').'</span>'.Util::jsEscape($b['desc']);
|
$x .= '<br /><span class="q13">'.$b['bonus'].' '.Lang::itemset('_pieces').Lang::main('colon').'</span>'.$b['desc'];
|
||||||
|
|
||||||
$x .= '</span>';
|
$x .= '</span>';
|
||||||
}
|
}
|
||||||
@@ -186,8 +188,8 @@ class ItemsetListFilter extends Filter
|
|||||||
protected $inputFields = array(
|
protected $inputFields = array(
|
||||||
'cr' => [FILTER_V_RANGE, [2, 12], true ], // criteria ids
|
'cr' => [FILTER_V_RANGE, [2, 12], true ], // criteria ids
|
||||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 424]], true ], // criteria operators
|
'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
|
'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
|
'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
|
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||||
'qu' => [FILTER_V_RANGE, [0, 7], true ], // quality
|
'qu' => [FILTER_V_RANGE, [0, 7], true ], // quality
|
||||||
'ty' => [FILTER_V_RANGE, [1, 12], true ], // set type
|
'ty' => [FILTER_V_RANGE, [1, 12], true ], // set type
|
||||||
|
|||||||
74
includes/types/mail.class.php
Normal file
74
includes/types/mail.class.php
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
class MailList extends BaseType
|
||||||
|
{
|
||||||
|
public static $type = Type::MAIL;
|
||||||
|
public static $brickFile = 'mail';
|
||||||
|
public static $dataTable = '?_mails';
|
||||||
|
|
||||||
|
protected $queryBase = 'SELECT m.*, m.id AS ARRAY_KEY FROM ?_mails m';
|
||||||
|
protected $queryOpts = [];
|
||||||
|
|
||||||
|
public function __construct($conditions = [])
|
||||||
|
{
|
||||||
|
parent::__construct($conditions);
|
||||||
|
|
||||||
|
if ($this->error)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// post processing
|
||||||
|
foreach ($this->iterate() as $_id => &$_curTpl)
|
||||||
|
{
|
||||||
|
$_curTpl['name'] = Util::localizedString($_curTpl, 'subject', true);
|
||||||
|
if (!$_curTpl['name'])
|
||||||
|
{
|
||||||
|
$_curTpl['name'] = sprintf(Lang::mail('untitled'), $_id);
|
||||||
|
$_curTpl['subject_loc0'] = $_curTpl['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getName($id)
|
||||||
|
{
|
||||||
|
$n = DB::Aowow()->SelectRow('SELECT subject_loc0, subject_loc2, subject_loc3, subject_loc4, subject_loc6, subject_loc8 FROM ?_mails WHERE id = ?d', $id);
|
||||||
|
return Util::localizedString($n, 'subject');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getListviewData()
|
||||||
|
{
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($this->iterate() as $__)
|
||||||
|
{
|
||||||
|
$body = str_replace('[br]', ' ', Util::parseHtmlText($this->getField('text', true), true));
|
||||||
|
|
||||||
|
$data[$this->id] = array(
|
||||||
|
'id' => $this->id,
|
||||||
|
'subject' => $this->getField('subject', true),
|
||||||
|
'body' => Lang::trimTextClean($body),
|
||||||
|
'attachments' => [$this->getField('attachment')]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getJSGlobals($addMask = 0)
|
||||||
|
{
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
foreach ($this->iterate() as $__)
|
||||||
|
if ($a = $this->curTpl['attachment'])
|
||||||
|
$data[Type::ITEM][$a] = $a;
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderTooltip() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -8,11 +8,11 @@ class PetList extends BaseType
|
|||||||
{
|
{
|
||||||
use ListviewHelper;
|
use ListviewHelper;
|
||||||
|
|
||||||
public static $type = TYPE_PET;
|
public static $type = Type::PET;
|
||||||
public static $brickFile = 'pet';
|
public static $brickFile = 'pet';
|
||||||
public static $dataTable = '?_pet';
|
public static $dataTable = '?_pet';
|
||||||
|
|
||||||
protected $queryBase = 'SELECT *, p.id AS ARRAY_KEY FROM ?_pet p';
|
protected $queryBase = 'SELECT p.*, p.id AS ARRAY_KEY FROM ?_pet p';
|
||||||
protected $queryOpts = array(
|
protected $queryOpts = array(
|
||||||
'p' => [['ic']],
|
'p' => [['ic']],
|
||||||
'ic' => ['j' => ['?_icons ic ON p.iconId = ic.id', true], 's' => ', ic.name AS iconString'],
|
'ic' => ['j' => ['?_icons ic ON p.iconId = ic.id', true], 's' => ', ic.name AS iconString'],
|
||||||
@@ -59,10 +59,10 @@ class PetList extends BaseType
|
|||||||
if ($addMask & GLOBALINFO_RELATED)
|
if ($addMask & GLOBALINFO_RELATED)
|
||||||
for ($i = 1; $i <= 4; $i++)
|
for ($i = 1; $i <= 4; $i++)
|
||||||
if ($this->curTpl['spellId'.$i] > 0)
|
if ($this->curTpl['spellId'.$i] > 0)
|
||||||
$data[TYPE_SPELL][$this->curTpl['spellId'.$i]] = $this->curTpl['spellId'.$i];
|
$data[Type::SPELL][$this->curTpl['spellId'.$i]] = $this->curTpl['spellId'.$i];
|
||||||
|
|
||||||
if ($addMask & GLOBALINFO_SELF)
|
if ($addMask & GLOBALINFO_SELF)
|
||||||
$data[TYPE_PET][$this->id] = ['icon' => $this->curTpl['iconString']];
|
$data[Type::PET][$this->id] = ['icon' => $this->curTpl['iconString']];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class ProfileList extends BaseType
|
|||||||
$data = [];
|
$data = [];
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
{
|
{
|
||||||
if ($this->getField('user') && User::$id != $this->getField('user') && !($this->getField('cuFlags') & PROFILER_CU_PUBLISHED))
|
if (!$this->isVisibleToUser())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (($addInfo & PROFILEINFO_PROFILE) && !$this->isCustom())
|
if (($addInfo & PROFILEINFO_PROFILE) && !$this->isCustom())
|
||||||
@@ -33,22 +33,22 @@ class ProfileList extends BaseType
|
|||||||
'talenttree1' => $this->getField('talenttree1'),
|
'talenttree1' => $this->getField('talenttree1'),
|
||||||
'talenttree2' => $this->getField('talenttree2'),
|
'talenttree2' => $this->getField('talenttree2'),
|
||||||
'talenttree3' => $this->getField('talenttree3'),
|
'talenttree3' => $this->getField('talenttree3'),
|
||||||
'talentspec' => $this->getField('activespec') + 1, // 0 => 1; 1 => 2
|
'talentspec' => $this->getField('activespec') + 1, // 0 => 1; 1 => 2
|
||||||
'achievementpoints' => $this->getField('achievementpoints'),
|
'achievementpoints' => $this->getField('achievementpoints'),
|
||||||
'guild' => '$"'.$this->getField('guildname').'"', // force this to be a string
|
'guild' => '$"'.str_replace ('"', '', $this->curTpl['guildname']).'"',// force this to be a string
|
||||||
'guildrank' => $this->getField('guildrank'),
|
'guildrank' => $this->getField('guildrank'),
|
||||||
'realm' => Profiler::urlize($this->getField('realmName')),
|
'realm' => Profiler::urlize($this->getField('realmName'), true),
|
||||||
'realmname' => $this->getField('realmName'),
|
'realmname' => $this->getField('realmName'),
|
||||||
// 'battlegroup' => Profiler::urlize($this->getField('battlegroup')), // was renamed to subregion somewhere around cata release
|
// 'battlegroup' => Profiler::urlize($this->getField('battlegroup')), // was renamed to subregion somewhere around cata release
|
||||||
// 'battlegroupname' => $this->getField('battlegroup'),
|
// 'battlegroupname' => $this->getField('battlegroup'),
|
||||||
'gearscore' => $this->getField('gearscore')
|
'gearscore' => $this->getField('gearscore')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($addInfo & PROFILEINFO_USER)
|
||||||
|
$data[$this->id]['published'] = (int)!!($this->getField('cuFlags') & PROFILER_CU_PUBLISHED);
|
||||||
|
|
||||||
// for the lv this determins if the link is profile=<id> or profile=<region>.<realm>.<name>
|
// for the lv this determins if the link is profile=<id> or profile=<region>.<realm>.<name>
|
||||||
if ($this->isCustom())
|
if (!$this->isCustom())
|
||||||
$data[$this->id]['published'] = (int)!!($this->getField('cuFlags') & PROFILER_CU_PUBLISHED);
|
|
||||||
else
|
|
||||||
$data[$this->id]['region'] = Profiler::urlize($this->getField('region'));
|
$data[$this->id]['region'] = Profiler::urlize($this->getField('region'));
|
||||||
|
|
||||||
if ($addInfo & PROFILEINFO_ARENA)
|
if ($addInfo & PROFILEINFO_ARENA)
|
||||||
@@ -64,12 +64,17 @@ class ProfileList extends BaseType
|
|||||||
$data[$this->id][$col] = $this->getField($col);
|
$data[$this->id][$col] = $this->getField($col);
|
||||||
|
|
||||||
if ($addInfo & PROFILEINFO_PROFILE)
|
if ($addInfo & PROFILEINFO_PROFILE)
|
||||||
|
{
|
||||||
if ($_ = $this->getField('description'))
|
if ($_ = $this->getField('description'))
|
||||||
$data[$this->id]['description'] = $_;
|
$data[$this->id]['description'] = $_;
|
||||||
|
|
||||||
if ($addInfo & PROFILEINFO_PROFILE)
|
|
||||||
if ($_ = $this->getField('icon'))
|
if ($_ = $this->getField('icon'))
|
||||||
$data[$this->id]['icon'] = $_;
|
$data[$this->id]['icon'] = $_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($addInfo & PROFILEINFO_CHARACTER)
|
||||||
|
if ($_ = $this->getField('renameItr'))
|
||||||
|
$data[$this->id]['renameItr'] = $_;
|
||||||
|
|
||||||
if ($this->getField('cuFlags') & PROFILER_CU_PINNED)
|
if ($this->getField('cuFlags') & PROFILER_CU_PINNED)
|
||||||
$data[$this->id]['pinned'] = 1;
|
$data[$this->id]['pinned'] = 1;
|
||||||
@@ -81,18 +86,18 @@ class ProfileList extends BaseType
|
|||||||
return array_values($data);
|
return array_values($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderTooltip($interactive = false)
|
public function renderTooltip()
|
||||||
{
|
{
|
||||||
if (!$this->curTpl)
|
if (!$this->curTpl)
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
$title = '';
|
$title = '';
|
||||||
$name = $this->getField('name');
|
$name = $this->getField('name');
|
||||||
if ($_ = $this->getField('chosenTitle'))
|
if ($_ = $this->getField('title'))
|
||||||
$title = (new TitleList(array(['bitIdx', $_])))->getField($this->getField('gender') ? 'female' : 'male', true);
|
$title = (new TitleList(array(['id', $_])))->getField($this->getField('gender') ? 'female' : 'male', true);
|
||||||
|
|
||||||
if ($this->isCustom())
|
if ($this->isCustom())
|
||||||
$name .= ' (Custom Profile)';
|
$name .= Lang::profiler('customProfile');
|
||||||
else if ($title)
|
else if ($title)
|
||||||
$name = sprintf($title, $name);
|
$name = sprintf($title, $name);
|
||||||
|
|
||||||
@@ -115,7 +120,7 @@ class ProfileList extends BaseType
|
|||||||
|
|
||||||
foreach ($this->iterate() as $id => $__)
|
foreach ($this->iterate() as $id => $__)
|
||||||
{
|
{
|
||||||
if (($addMask & PROFILEINFO_PROFILE) && ($this->getField('cuFlags') & PROFILER_CU_PROFILE))
|
if (($addMask & PROFILEINFO_PROFILE) && $this->isCustom())
|
||||||
{
|
{
|
||||||
$profile = array(
|
$profile = array(
|
||||||
'id' => $this->getField('id'),
|
'id' => $this->getField('id'),
|
||||||
@@ -134,7 +139,7 @@ class ProfileList extends BaseType
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($addMask & PROFILEINFO_CHARACTER && !($this->getField('cuFlags') & PROFILER_CU_PROFILE))
|
if ($addMask & PROFILEINFO_CHARACTER && !$this->isCustom())
|
||||||
{
|
{
|
||||||
if (!isset($realms[$this->getField('realm')]))
|
if (!isset($realms[$this->getField('realm')]))
|
||||||
continue;
|
continue;
|
||||||
@@ -161,6 +166,70 @@ class ProfileList extends BaseType
|
|||||||
{
|
{
|
||||||
return $this->getField('cuFlags') & PROFILER_CU_PROFILE;
|
return $this->getField('cuFlags') & PROFILER_CU_PROFILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isVisibleToUser()
|
||||||
|
{
|
||||||
|
if (!$this->isCustom() || User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if ($this->getField('cuFlags') & PROFILER_CU_DELETED)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (User::$id == $this->getField('user'))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return (bool)($this->getField('cuFlags') & PROFILER_CU_PUBLISHED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIcon()
|
||||||
|
{
|
||||||
|
if ($_ = $this->getField('icon'))
|
||||||
|
return $_;
|
||||||
|
|
||||||
|
$str = 'chr_';
|
||||||
|
|
||||||
|
switch ($this->getField('race'))
|
||||||
|
{
|
||||||
|
case 1: $str .= 'human_'; break;
|
||||||
|
case 2: $str .= 'orc_'; break;
|
||||||
|
case 3: $str .= 'dwarf_'; break;
|
||||||
|
case 4: $str .= 'nightelf_'; break;
|
||||||
|
case 5: $str .= 'scourge_'; break;
|
||||||
|
case 6: $str .= 'tauren_'; break;
|
||||||
|
case 7: $str .= 'gnome_'; break;
|
||||||
|
case 8: $str .= 'troll_'; break;
|
||||||
|
case 10: $str .= 'bloodelf_'; break;
|
||||||
|
case 11: $str .= 'draenei_'; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($this->getField('gender'))
|
||||||
|
{
|
||||||
|
case 0: $str .= 'male_'; break;
|
||||||
|
case 1: $str .= 'female_'; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($this->getField('class'))
|
||||||
|
{
|
||||||
|
case 1: $str .= 'warrior0'; break;
|
||||||
|
case 2: $str .= 'paladin0'; break;
|
||||||
|
case 3: $str .= 'hunter0'; break;
|
||||||
|
case 4: $str .= 'rogue0'; break;
|
||||||
|
case 5: $str .= 'priest0'; break;
|
||||||
|
case 6: $str .= 'deathknight0'; break;
|
||||||
|
case 7: $str .= 'shaman0'; break;
|
||||||
|
case 8: $str .= 'mage0'; break;
|
||||||
|
case 9: $str .= 'warlock0'; break;
|
||||||
|
case 11: $str .= 'druid0'; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$level = $this->getField('level');
|
||||||
|
if ($level > 59)
|
||||||
|
$str .= floor(($level - 60) / 10) + 2;
|
||||||
|
else
|
||||||
|
$str .= 1;
|
||||||
|
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -181,36 +250,36 @@ class ProfileListFilter extends Filter
|
|||||||
);
|
);
|
||||||
|
|
||||||
protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet
|
protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet
|
||||||
2 => [FILTER_CR_NUMERIC, 'gearscore', NUM_CAST_INT ], // gearscore [num]
|
2 => [FILTER_CR_NUMERIC, 'gearscore', NUM_CAST_INT ], // gearscore [num]
|
||||||
3 => [FILTER_CR_NUMERIC, 'achievementpoints', NUM_CAST_INT ], // achievementpoints [num]
|
3 => [FILTER_CR_CALLBACK, 'cbAchievs', null, null], // achievementpoints [num]
|
||||||
5 => [FILTER_CR_NUMERIC, 'talenttree1', NUM_CAST_INT ], // talenttree1 [num]
|
5 => [FILTER_CR_NUMERIC, 'talenttree1', NUM_CAST_INT ], // talenttree1 [num]
|
||||||
6 => [FILTER_CR_NUMERIC, 'talenttree2', NUM_CAST_INT ], // talenttree2 [num]
|
6 => [FILTER_CR_NUMERIC, 'talenttree2', NUM_CAST_INT ], // talenttree2 [num]
|
||||||
7 => [FILTER_CR_NUMERIC, 'talenttree3', NUM_CAST_INT ], // talenttree3 [num]
|
7 => [FILTER_CR_NUMERIC, 'talenttree3', NUM_CAST_INT ], // talenttree3 [num]
|
||||||
9 => [FILTER_CR_STRING, 'g.name', ], // guildname
|
9 => [FILTER_CR_STRING, 'g.name', ], // guildname
|
||||||
10 => [FILTER_CR_CALLBACK, 'cbHasGuildRank', null, null], // guildrank
|
10 => [FILTER_CR_CALLBACK, 'cbHasGuildRank', null, null], // guildrank
|
||||||
12 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname2v2
|
12 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname2v2
|
||||||
15 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname3v3
|
15 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname3v3
|
||||||
18 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname5v5
|
18 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname5v5
|
||||||
13 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng2v2
|
13 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng2v2
|
||||||
16 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng3v3
|
16 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng3v3
|
||||||
19 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng5v5
|
19 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng5v5
|
||||||
14 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib2v2 [num]
|
14 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib2v2 [num]
|
||||||
17 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib3v3 [num]
|
17 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib3v3 [num]
|
||||||
20 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib5v5 [num]
|
20 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib5v5 [num]
|
||||||
21 => [FILTER_CR_CALLBACK, 'cbWearsItems', null, null], // wearingitem [str]
|
21 => [FILTER_CR_CALLBACK, 'cbWearsItems', null, null], // wearingitem [str]
|
||||||
23 => [FILTER_CR_CALLBACK, 'cbCompletedAcv', null, null], // completedachievement
|
23 => [FILTER_CR_CALLBACK, 'cbCompletedAcv', null, null], // completedachievement
|
||||||
25 => [FILTER_CR_CALLBACK, 'cbProfession', 171, null], // alchemy [num]
|
25 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_ALCHEMY, null], // alchemy [num]
|
||||||
26 => [FILTER_CR_CALLBACK, 'cbProfession', 164, null], // blacksmithing [num]
|
26 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_BLACKSMITHING, null], // blacksmithing [num]
|
||||||
27 => [FILTER_CR_CALLBACK, 'cbProfession', 333, null], // enchanting [num]
|
27 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_ENCHANTING, null], // enchanting [num]
|
||||||
28 => [FILTER_CR_CALLBACK, 'cbProfession', 202, null], // engineering [num]
|
28 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_ENGINEERING, null], // engineering [num]
|
||||||
29 => [FILTER_CR_CALLBACK, 'cbProfession', 182, null], // herbalism [num]
|
29 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_HERBALISM, null], // herbalism [num]
|
||||||
30 => [FILTER_CR_CALLBACK, 'cbProfession', 773, null], // inscription [num]
|
30 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_INSCRIPTION, null], // inscription [num]
|
||||||
31 => [FILTER_CR_CALLBACK, 'cbProfession', 755, null], // jewelcrafting [num]
|
31 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_JEWELCRAFTING, null], // jewelcrafting [num]
|
||||||
32 => [FILTER_CR_CALLBACK, 'cbProfession', 165, null], // leatherworking [num]
|
32 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_LEATHERWORKING, null], // leatherworking [num]
|
||||||
33 => [FILTER_CR_CALLBACK, 'cbProfession', 186, null], // mining [num]
|
33 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_MINING, null], // mining [num]
|
||||||
34 => [FILTER_CR_CALLBACK, 'cbProfession', 393, null], // skinning [num]
|
34 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_SKINNING, null], // skinning [num]
|
||||||
35 => [FILTER_CR_CALLBACK, 'cbProfession', 197, null], // tailoring [num]
|
35 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_TAILORING, null], // tailoring [num]
|
||||||
36 => [FILTER_CR_CALLBACK, 'cbHasGuild', null, null] // hasguild [yn]
|
36 => [FILTER_CR_CALLBACK, 'cbHasGuild', null, null] // hasguild [yn]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -218,8 +287,8 @@ class ProfileListFilter extends Filter
|
|||||||
protected $inputFields = array(
|
protected $inputFields = array(
|
||||||
'cr' => [FILTER_V_RANGE, [1, 36], true ], // criteria ids
|
'cr' => [FILTER_V_RANGE, [1, 36], true ], // criteria ids
|
||||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 5000]], true ], // criteria operators
|
'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
|
'crv' => [FILTER_V_REGEX, '/[\p{C}:;%\\\\]/ui', true ], // criteria values
|
||||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name - only printable chars, no delimiter
|
'na' => [FILTER_V_REGEX, '/[\p{C};%\\\\]/ui', false], // name - only printable chars, no delimiter
|
||||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||||
'ex' => [FILTER_V_EQUAL, 'on', false], // only match exact
|
'ex' => [FILTER_V_EQUAL, 'on', false], // only match exact
|
||||||
'si' => [FILTER_V_LIST, [1, 2], false], // side
|
'si' => [FILTER_V_LIST, [1, 2], false], // side
|
||||||
@@ -246,7 +315,7 @@ class ProfileListFilter extends Filter
|
|||||||
parent::__construct($fromPOST, $opts);
|
parent::__construct($fromPOST, $opts);
|
||||||
|
|
||||||
if (!empty($this->fiData['c']['cr']))
|
if (!empty($this->fiData['c']['cr']))
|
||||||
if (array_intersect($this->fiData['c']['cr'], [2, 3, 5, 6, 7, 21]))
|
if (array_intersect($this->fiData['c']['cr'], [2, 5, 6, 7, 21]))
|
||||||
$this->useLocalList = true;
|
$this->useLocalList = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,8 +343,8 @@ class ProfileListFilter extends Filter
|
|||||||
// name [str] - the table is case sensitive. Since i down't want to destroy indizes, lets alter the search terms
|
// name [str] - the table is case sensitive. Since i down't want to destroy indizes, lets alter the search terms
|
||||||
if (!empty($_v['na']))
|
if (!empty($_v['na']))
|
||||||
{
|
{
|
||||||
$lower = $this->modularizeString([$k.'.name'], Util::lower($_v['na']), !empty($_v['ex']) && $_v['ex'] == 'on');
|
$lower = $this->modularizeString([$k.'.name'], Util::lower($_v['na']), !empty($_v['ex']) && $_v['ex'] == 'on', true);
|
||||||
$proper = $this->modularizeString([$k.'.name'], Util::ucWords($_v['na']), !empty($_v['ex']) && $_v['ex'] == 'on');
|
$proper = $this->modularizeString([$k.'.name'], Util::ucWords($_v['na']), !empty($_v['ex']) && $_v['ex'] == 'on', true);
|
||||||
|
|
||||||
$parts[] = ['OR', $lower, $proper];
|
$parts[] = ['OR', $lower, $proper];
|
||||||
}
|
}
|
||||||
@@ -310,7 +379,7 @@ class ProfileListFilter extends Filter
|
|||||||
|
|
||||||
protected function cbRegionCheck(&$v)
|
protected function cbRegionCheck(&$v)
|
||||||
{
|
{
|
||||||
if ($v == 'eu' || $v == 'us')
|
if (in_array($v, Util::$regions))
|
||||||
{
|
{
|
||||||
$this->parentCats[0] = $v; // directly redirect onto this region
|
$this->parentCats[0] = $v; // directly redirect onto this region
|
||||||
$v = ''; // remove from filter
|
$v = ''; // remove from filter
|
||||||
@@ -348,7 +417,7 @@ class ProfileListFilter extends Filter
|
|||||||
if ($this->useLocalList)
|
if ($this->useLocalList)
|
||||||
{
|
{
|
||||||
$this->extraOpts[$k] = array(
|
$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],
|
'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]
|
's' => [', '.$k.'.cur AS '.$col]
|
||||||
);
|
);
|
||||||
return [$k.'.typeId', null, '!'];
|
return [$k.'.typeId', null, '!'];
|
||||||
@@ -375,7 +444,7 @@ class ProfileListFilter extends Filter
|
|||||||
|
|
||||||
if ($this->useLocalList)
|
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]];
|
$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, '!'];
|
return [$k.'.typeId', null, '!'];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -436,6 +505,17 @@ class ProfileListFilter extends Filter
|
|||||||
|
|
||||||
return ['AND', ['at.type', $this->enums[-1][$cr[0]]], ['at.rating', $cr[2], $cr[1]]];
|
return ['AND', ['at.type', $this->enums[-1][$cr[0]]], ['at.rating', $cr[2], $cr[1]]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function cbAchievs($cr)
|
||||||
|
{
|
||||||
|
if (!Util::checkNumeric($cr[2], NUM_CAST_INT) || !$this->int2Op($cr[1]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ($this->useLocalList)
|
||||||
|
return ['p.achievementpoints', $cr[2], $cr[1]];
|
||||||
|
else
|
||||||
|
return ['cap.counter', $cr[2], $cr[1]];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -443,9 +523,8 @@ class RemoteProfileList extends ProfileList
|
|||||||
{
|
{
|
||||||
protected $queryBase = 'SELECT `c`.*, `c`.`guid` AS ARRAY_KEY FROM characters c';
|
protected $queryBase = 'SELECT `c`.*, `c`.`guid` AS ARRAY_KEY FROM characters c';
|
||||||
protected $queryOpts = array(
|
protected $queryOpts = array(
|
||||||
'c' => [['gm', 'g', 'ca', 'ct'], 'g' => 'ARRAY_KEY', 'o' => 'level DESC, name ASC'],
|
'c' => [['gm', 'g', 'cap']], // 12698: use criteria of Achievement 4496 as shortcut to get total achievement points
|
||||||
'ca' => ['j' => ['character_achievement ca ON ca.guid = c.guid', true], 's' => ', GROUP_CONCAT(DISTINCT ca.achievement SEPARATOR " ") AS _acvs'],
|
'cap' => ['j' => ['character_achievement_progress cap ON cap.guid = c.guid AND cap.criteria = 12698', true], 's' => ', IFNULL(cap.counter, 0) AS achievementpoints'],
|
||||||
'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'],
|
'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'],
|
'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'],
|
'atm' => ['j' => ['arena_team_member atm ON atm.guid = c.guid', true], 's' => ', atm.personalRating AS rating'],
|
||||||
@@ -467,14 +546,12 @@ class RemoteProfileList extends ProfileList
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
reset($this->dbNames); // only use when querying single realm
|
reset($this->dbNames); // only use when querying single realm
|
||||||
$realmId = key($this->dbNames);
|
$realmId = key($this->dbNames);
|
||||||
$realms = Profiler::getRealms();
|
$realms = Profiler::getRealms();
|
||||||
$acvCache = [];
|
$talentSpells = [];
|
||||||
$talentCache = [];
|
$talentLookup = [];
|
||||||
$atCache = [];
|
$distrib = null;
|
||||||
$distrib = null;
|
$limit = CFG_SQL_LIMIT_DEFAULT;
|
||||||
$talentData = [];
|
|
||||||
$limit = CFG_SQL_LIMIT_DEFAULT;
|
|
||||||
|
|
||||||
foreach ($conditions as $c)
|
foreach ($conditions as $c)
|
||||||
if (is_int($c))
|
if (is_int($c))
|
||||||
@@ -487,7 +564,7 @@ class RemoteProfileList extends ProfileList
|
|||||||
$curTpl['battlegroup'] = CFG_BATTLEGROUP;
|
$curTpl['battlegroup'] = CFG_BATTLEGROUP;
|
||||||
|
|
||||||
// realm
|
// realm
|
||||||
$r = explode(':', $guid)[0];
|
[$r, $g] = explode(':', $guid);
|
||||||
if (!empty($realms[$r]))
|
if (!empty($realms[$r]))
|
||||||
{
|
{
|
||||||
$curTpl['realm'] = $r;
|
$curTpl['realm'] = $r;
|
||||||
@@ -504,17 +581,10 @@ class RemoteProfileList extends ProfileList
|
|||||||
// temp id
|
// temp id
|
||||||
$curTpl['id'] = 0;
|
$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
|
// talent points pre
|
||||||
if ($talents = explode(' ', $curTpl['_talents']))
|
$talentLookup[$r][$g] = [];
|
||||||
foreach ($talents as $t)
|
$talentSpells[] = $curTpl['class'];
|
||||||
if ($t && !isset($talentCache[$t]))
|
$curTpl['activespec'] = $curTpl['activeTalentGroup'];
|
||||||
$talentCache[$t] = $t;
|
|
||||||
|
|
||||||
// equalize distribution
|
// equalize distribution
|
||||||
if ($limit != CFG_SQL_LIMIT_NONE)
|
if ($limit != CFG_SQL_LIMIT_NONE)
|
||||||
@@ -525,11 +595,29 @@ class RemoteProfileList extends ProfileList
|
|||||||
$distrib[$curTpl['realm']]++;
|
$distrib[$curTpl['realm']]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// char is pending rename
|
||||||
|
if ($curTpl['at_login'] & 0x1)
|
||||||
|
{
|
||||||
|
if (!isset($this->rnItr[$curTpl['name']]))
|
||||||
|
$this->rnItr[$curTpl['name']] = DB::Aowow()->selectCell('SELECT MAX(renameItr) FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID IS NOT NULL AND name = ?', $r, $curTpl['name']) ?: 0;
|
||||||
|
|
||||||
|
// already saved as "pending rename"
|
||||||
|
if ($rnItr = DB::Aowow()->selectCell('SELECT renameItr FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d', $r, $g))
|
||||||
|
$curTpl['renameItr'] = $rnItr;
|
||||||
|
// not yet recognized: get max itr
|
||||||
|
else
|
||||||
|
$curTpl['renameItr'] = ++$this->rnItr[$curTpl['name']];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$curTpl['renameItr'] = 0;
|
||||||
|
|
||||||
$curTpl['cuFlags'] = 0;
|
$curTpl['cuFlags'] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($talentCache)
|
foreach ($talentLookup as $realm => $chars)
|
||||||
$talentData = DB::Aowow()->select('SELECT spell AS ARRAY_KEY, tab, rank FROM ?_talents WHERE spell IN (?a)', $talentCache);
|
$talentLookup[$realm] = DB::Characters($realm)->selectCol('SELECT guid AS ARRAY_KEY, spell AS ARRAY_KEY2, talentGroup FROM character_talent ct WHERE guid IN (?a)', array_keys($chars));
|
||||||
|
|
||||||
|
$talentSpells = DB::Aowow()->select('SELECT spell AS ARRAY_KEY, tab, `rank` FROM ?_talents WHERE class IN (?a)', array_unique($talentSpells));
|
||||||
|
|
||||||
if ($distrib !== null)
|
if ($distrib !== null)
|
||||||
{
|
{
|
||||||
@@ -538,9 +626,6 @@ class RemoteProfileList extends ProfileList
|
|||||||
$d = ceil($limit * $d / $total);
|
$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)
|
foreach ($this->iterate() as $guid => &$curTpl)
|
||||||
{
|
{
|
||||||
if ($distrib !== null)
|
if ($distrib !== null)
|
||||||
@@ -555,22 +640,18 @@ class RemoteProfileList extends ProfileList
|
|||||||
$limit--;
|
$limit--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[$r, $g] = explode(':', $guid);
|
||||||
$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
|
// talent points post
|
||||||
$curTpl['talenttree1'] = 0;
|
$curTpl['talenttree1'] = 0;
|
||||||
$curTpl['talenttree2'] = 0;
|
$curTpl['talenttree2'] = 0;
|
||||||
$curTpl['talenttree3'] = 0;
|
$curTpl['talenttree3'] = 0;
|
||||||
foreach ($talentData as $spell => $data)
|
if (!empty($talentLookup[$r][$g]))
|
||||||
if (in_array($spell, $t))
|
{
|
||||||
|
$talents = array_filter($talentLookup[$r][$g], function($v) use ($curTpl) { return $curTpl['activespec'] == $v; } );
|
||||||
|
foreach (array_intersect_key($talentSpells, $talents) as $spell => $data)
|
||||||
$curTpl['talenttree'.($data['tab'] + 1)] += $data['rank'];
|
$curTpl['talenttree'.($data['tab'] + 1)] += $data['rank'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,6 +675,7 @@ class RemoteProfileList extends ProfileList
|
|||||||
'realm' => $this->getField('realm'),
|
'realm' => $this->getField('realm'),
|
||||||
'realmGUID' => $this->getField('guid'),
|
'realmGUID' => $this->getField('guid'),
|
||||||
'name' => $this->getField('name'),
|
'name' => $this->getField('name'),
|
||||||
|
'renameItr' => $this->getField('renameItr'),
|
||||||
'race' => $this->getField('race'),
|
'race' => $this->getField('race'),
|
||||||
'class' => $this->getField('class'),
|
'class' => $this->getField('class'),
|
||||||
'level' => $this->getField('level'),
|
'level' => $this->getField('level'),
|
||||||
@@ -633,7 +715,7 @@ class RemoteProfileList extends ProfileList
|
|||||||
if ($baseData)
|
if ($baseData)
|
||||||
{
|
{
|
||||||
foreach (Util::createSqlBatchInsert($baseData) as $ins)
|
foreach (Util::createSqlBatchInsert($baseData) as $ins)
|
||||||
DB::Aowow()->query('INSERT IGNORE INTO ?_profiler_profiles (?#) VALUES '.$ins, array_keys(reset($baseData)));
|
DB::Aowow()->query('INSERT INTO ?_profiler_profiles (?#) VALUES '.$ins.' ON DUPLICATE KEY UPDATE name = VALUES(name), renameItr = VALUES(renameItr)', array_keys(reset($baseData)));
|
||||||
|
|
||||||
// merge back local ids
|
// merge back local ids
|
||||||
$localIds = DB::Aowow()->select(
|
$localIds = DB::Aowow()->select(
|
||||||
@@ -672,7 +754,7 @@ class LocalProfileList extends ProfileList
|
|||||||
$realms = Profiler::getRealms();
|
$realms = Profiler::getRealms();
|
||||||
|
|
||||||
// post processing
|
// 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());
|
$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)
|
foreach ($this->iterate() as $id => &$curTpl)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class QuestList extends BaseType
|
class QuestList extends BaseType
|
||||||
{
|
{
|
||||||
public static $type = TYPE_QUEST;
|
public static $type = Type::QUEST;
|
||||||
public static $brickFile = 'quest';
|
public static $brickFile = 'quest';
|
||||||
public static $dataTable = '?_quests';
|
public static $dataTable = '?_quests';
|
||||||
|
|
||||||
@@ -49,18 +49,18 @@ class QuestList extends BaseType
|
|||||||
for ($i = 1; $i < 7; $i++)
|
for ($i = 1; $i < 7; $i++)
|
||||||
{
|
{
|
||||||
if ($_ = $_curTpl['reqItemId'.$i])
|
if ($_ = $_curTpl['reqItemId'.$i])
|
||||||
$requires[TYPE_ITEM][] = $_;
|
$requires[Type::ITEM][] = $_;
|
||||||
|
|
||||||
if ($i > 4)
|
if ($i > 4)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ($_curTpl['reqNpcOrGo'.$i] > 0)
|
if ($_curTpl['reqNpcOrGo'.$i] > 0)
|
||||||
$requires[TYPE_NPC][] = $_curTpl['reqNpcOrGo'.$i];
|
$requires[Type::NPC][] = $_curTpl['reqNpcOrGo'.$i];
|
||||||
else if ($_curTpl['reqNpcOrGo'.$i] < 0)
|
else if ($_curTpl['reqNpcOrGo'.$i] < 0)
|
||||||
$requires[TYPE_OBJECT][] = -$_curTpl['reqNpcOrGo'.$i];
|
$requires[Type::OBJECT][] = -$_curTpl['reqNpcOrGo'.$i];
|
||||||
|
|
||||||
if ($_ = $_curTpl['reqSourceItemId'.$i])
|
if ($_ = $_curTpl['reqSourceItemId'.$i])
|
||||||
$requires[TYPE_ITEM][] = $_;
|
$requires[Type::ITEM][] = $_;
|
||||||
}
|
}
|
||||||
if ($requires)
|
if ($requires)
|
||||||
$this->requires[$id] = $requires;
|
$this->requires[$id] = $requires;
|
||||||
@@ -70,24 +70,24 @@ class QuestList extends BaseType
|
|||||||
$choices = [];
|
$choices = [];
|
||||||
|
|
||||||
if ($_ = $_curTpl['rewardTitleId'])
|
if ($_ = $_curTpl['rewardTitleId'])
|
||||||
$rewards[TYPE_TITLE][] = $_;
|
$rewards[Type::TITLE][] = $_;
|
||||||
|
|
||||||
if ($_ = $_curTpl['rewardHonorPoints'])
|
if ($_ = $_curTpl['rewardHonorPoints'])
|
||||||
$rewards[TYPE_CURRENCY][104] = $_;
|
$rewards[Type::CURRENCY][104] = $_;
|
||||||
|
|
||||||
if ($_ = $_curTpl['rewardArenaPoints'])
|
if ($_ = $_curTpl['rewardArenaPoints'])
|
||||||
$rewards[TYPE_CURRENCY][103] = $_;
|
$rewards[Type::CURRENCY][103] = $_;
|
||||||
|
|
||||||
for ($i = 1; $i < 7; $i++)
|
for ($i = 1; $i < 7; $i++)
|
||||||
{
|
{
|
||||||
if ($_ = $_curTpl['rewardChoiceItemId'.$i])
|
if ($_ = $_curTpl['rewardChoiceItemId'.$i])
|
||||||
$choices[TYPE_ITEM][$_] = $_curTpl['rewardChoiceItemCount'.$i];
|
$choices[Type::ITEM][$_] = $_curTpl['rewardChoiceItemCount'.$i];
|
||||||
|
|
||||||
if ($i > 5)
|
if ($i > 5)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ($_ = $_curTpl['rewardFactionId'.$i])
|
if ($_ = $_curTpl['rewardFactionId'.$i])
|
||||||
$rewards[TYPE_FACTION][$_] = $_curTpl['rewardFactionValue'.$i];
|
$rewards[Type::FACTION][$_] = $_curTpl['rewardFactionValue'.$i];
|
||||||
|
|
||||||
if ($i > 4)
|
if ($i > 4)
|
||||||
continue;
|
continue;
|
||||||
@@ -96,9 +96,9 @@ class QuestList extends BaseType
|
|||||||
{
|
{
|
||||||
$qty = $_curTpl['rewardItemCount'.$i];
|
$qty = $_curTpl['rewardItemCount'.$i];
|
||||||
if (in_array($_, $currencies))
|
if (in_array($_, $currencies))
|
||||||
$rewards[TYPE_CURRENCY][array_search($_, $currencies)] = $qty;
|
$rewards[Type::CURRENCY][array_search($_, $currencies)] = $qty;
|
||||||
else
|
else
|
||||||
$rewards[TYPE_ITEM][$_] = $qty;
|
$rewards[Type::ITEM][$_] = $qty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($rewards)
|
if ($rewards)
|
||||||
@@ -112,7 +112,7 @@ class QuestList extends BaseType
|
|||||||
// static use START
|
// static use START
|
||||||
public static function getName($id)
|
public static function getName($id)
|
||||||
{
|
{
|
||||||
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM ?_quests WHERE id = ?d', $id);
|
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_quests WHERE id = ?d', $id);
|
||||||
return Util::localizedString($n, 'name');
|
return Util::localizedString($n, 'name');
|
||||||
}
|
}
|
||||||
// static use END
|
// static use END
|
||||||
@@ -156,7 +156,7 @@ class QuestList extends BaseType
|
|||||||
{
|
{
|
||||||
$data[$this->id] = array(
|
$data[$this->id] = array(
|
||||||
"n" => $this->getField('name', true),
|
"n" => $this->getField('name', true),
|
||||||
"t" => TYPE_QUEST,
|
"t" => Type::QUEST,
|
||||||
"ti" => $this->id,
|
"ti" => $this->id,
|
||||||
"c" => $this->curTpl['cat1'],
|
"c" => $this->curTpl['cat1'],
|
||||||
"c2" => $this->curTpl['cat2']
|
"c2" => $this->curTpl['cat2']
|
||||||
@@ -175,7 +175,7 @@ class QuestList extends BaseType
|
|||||||
if (!(Game::sideByRaceMask($this->curTpl['reqRaceMask']) & $side))
|
if (!(Game::sideByRaceMask($this->curTpl['reqRaceMask']) & $side))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
list($series, $first) = DB::Aowow()->SelectRow(
|
[$series, $first] = DB::Aowow()->SelectRow(
|
||||||
'SELECT IF(prev.id OR cur.nextQuestIdChain, 1, 0) AS "0", IF(prev.id IS NULL AND cur.nextQuestIdChain, 1, 0) AS "1" FROM ?_quests cur LEFT JOIN ?_quests prev ON prev.nextQuestIdChain = cur.id WHERE cur.id = ?d',
|
'SELECT IF(prev.id OR cur.nextQuestIdChain, 1, 0) AS "0", IF(prev.id IS NULL AND cur.nextQuestIdChain, 1, 0) AS "1" FROM ?_quests cur LEFT JOIN ?_quests prev ON prev.nextQuestIdChain = cur.id WHERE cur.id = ?d',
|
||||||
$this->id
|
$this->id
|
||||||
);
|
);
|
||||||
@@ -214,16 +214,16 @@ class QuestList extends BaseType
|
|||||||
'xp' => $this->curTpl['rewardXP']
|
'xp' => $this->curTpl['rewardXP']
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!empty($this->rewards[$this->id][TYPE_CURRENCY]))
|
if (!empty($this->rewards[$this->id][Type::CURRENCY]))
|
||||||
foreach ($this->rewards[$this->id][TYPE_CURRENCY] as $iId => $qty)
|
foreach ($this->rewards[$this->id][Type::CURRENCY] as $iId => $qty)
|
||||||
$data[$this->id]['currencyrewards'][] = [$iId, $qty];
|
$data[$this->id]['currencyrewards'][] = [$iId, $qty];
|
||||||
|
|
||||||
if (!empty($this->rewards[$this->id][TYPE_ITEM]))
|
if (!empty($this->rewards[$this->id][Type::ITEM]))
|
||||||
foreach ($this->rewards[$this->id][TYPE_ITEM] as $iId => $qty)
|
foreach ($this->rewards[$this->id][Type::ITEM] as $iId => $qty)
|
||||||
$data[$this->id]['itemrewards'][] = [$iId, $qty];
|
$data[$this->id]['itemrewards'][] = [$iId, $qty];
|
||||||
|
|
||||||
if (!empty($this->choices[$this->id][TYPE_ITEM]))
|
if (!empty($this->choices[$this->id][Type::ITEM]))
|
||||||
foreach ($this->choices[$this->id][TYPE_ITEM] as $iId => $qty)
|
foreach ($this->choices[$this->id][Type::ITEM] as $iId => $qty)
|
||||||
$data[$this->id]['itemchoices'][] = [$iId, $qty];
|
$data[$this->id]['itemchoices'][] = [$iId, $qty];
|
||||||
|
|
||||||
if ($_ = $this->curTpl['rewardTitleId'])
|
if ($_ = $this->curTpl['rewardTitleId'])
|
||||||
@@ -313,7 +313,7 @@ class QuestList extends BaseType
|
|||||||
if (!$this->curTpl)
|
if (!$this->curTpl)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
$title = Util::jsEscape($this->getField('name', true));
|
$title = htmlentities($this->getField('name', true));
|
||||||
$level = $this->curTpl['level'];
|
$level = $this->curTpl['level'];
|
||||||
if ($level < 0)
|
if ($level < 0)
|
||||||
$level = 0;
|
$level = 0;
|
||||||
@@ -332,7 +332,7 @@ class QuestList extends BaseType
|
|||||||
$x .= '<table><tr><td><b class="q">'.$title.'</b></td></tr></table>';
|
$x .= '<table><tr><td><b class="q">'.$title.'</b></td></tr></table>';
|
||||||
|
|
||||||
|
|
||||||
$x .= '<table><tr><td><br />'.$this->parseText('objectives');
|
$x .= '<table><tr><td><br />'.$this->parseText('objectives', false);
|
||||||
|
|
||||||
|
|
||||||
$xReq = '';
|
$xReq = '';
|
||||||
@@ -350,7 +350,7 @@ class QuestList extends BaseType
|
|||||||
else
|
else
|
||||||
$name = $rng > 0 ? CreatureList::getName($rng) : GameObjectList::getName(-$rng);
|
$name = $rng > 0 ? CreatureList::getName($rng) : GameObjectList::getName(-$rng);
|
||||||
|
|
||||||
$xReq .= '<br /> - '.Util::jsEscape($name).($rngQty > 1 ? ' x '.$rngQty : null);
|
$xReq .= '<br /> - '.$name.($rngQty > 1 ? ' x '.$rngQty : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
for ($i = 1; $i < 7; $i++)
|
for ($i = 1; $i < 7; $i++)
|
||||||
@@ -361,11 +361,11 @@ class QuestList extends BaseType
|
|||||||
if (!$ri || $riQty < 1)
|
if (!$ri || $riQty < 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$xReq .= '<br /> - '.Util::jsEscape(ItemList::getName($ri)).($riQty > 1 ? ' x '.$riQty : null);
|
$xReq .= '<br /> - '.ItemList::getName($ri).($riQty > 1 ? ' x '.$riQty : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($et = $this->getField('end', true))
|
if ($et = $this->getField('end', true))
|
||||||
$xReq .= '<br /> - '.Util::jsEscape($et);
|
$xReq .= '<br /> - '.$et;
|
||||||
|
|
||||||
if ($_ = $this->getField('rewardOrReqMoney'))
|
if ($_ = $this->getField('rewardOrReqMoney'))
|
||||||
if ($_ < 0)
|
if ($_ < 0)
|
||||||
@@ -390,31 +390,31 @@ class QuestList extends BaseType
|
|||||||
// items
|
// items
|
||||||
for ($i = 1; $i < 5; $i++)
|
for ($i = 1; $i < 5; $i++)
|
||||||
if ($this->curTpl['rewardItemId'.$i] > 0)
|
if ($this->curTpl['rewardItemId'.$i] > 0)
|
||||||
$data[TYPE_ITEM][$this->curTpl['rewardItemId'.$i]] = $this->curTpl['rewardItemId'.$i];
|
$data[Type::ITEM][$this->curTpl['rewardItemId'.$i]] = $this->curTpl['rewardItemId'.$i];
|
||||||
|
|
||||||
for ($i = 1; $i < 7; $i++)
|
for ($i = 1; $i < 7; $i++)
|
||||||
if ($this->curTpl['rewardChoiceItemId'.$i] > 0)
|
if ($this->curTpl['rewardChoiceItemId'.$i] > 0)
|
||||||
$data[TYPE_ITEM][$this->curTpl['rewardChoiceItemId'.$i]] = $this->curTpl['rewardChoiceItemId'.$i];
|
$data[Type::ITEM][$this->curTpl['rewardChoiceItemId'.$i]] = $this->curTpl['rewardChoiceItemId'.$i];
|
||||||
|
|
||||||
// spells
|
// spells
|
||||||
if ($this->curTpl['rewardSpell'] > 0)
|
if ($this->curTpl['rewardSpell'] > 0)
|
||||||
$data[TYPE_SPELL][$this->curTpl['rewardSpell']] = $this->curTpl['rewardSpell'];
|
$data[Type::SPELL][$this->curTpl['rewardSpell']] = $this->curTpl['rewardSpell'];
|
||||||
|
|
||||||
if ($this->curTpl['rewardSpellCast'] > 0)
|
if ($this->curTpl['rewardSpellCast'] > 0)
|
||||||
$data[TYPE_SPELL][$this->curTpl['rewardSpellCast']] = $this->curTpl['rewardSpellCast'];
|
$data[Type::SPELL][$this->curTpl['rewardSpellCast']] = $this->curTpl['rewardSpellCast'];
|
||||||
|
|
||||||
// titles
|
// titles
|
||||||
if ($this->curTpl['rewardTitleId'] > 0)
|
if ($this->curTpl['rewardTitleId'] > 0)
|
||||||
$data[TYPE_TITLE][$this->curTpl['rewardTitleId']] = $this->curTpl['rewardTitleId'];
|
$data[Type::TITLE][$this->curTpl['rewardTitleId']] = $this->curTpl['rewardTitleId'];
|
||||||
|
|
||||||
// currencies
|
// currencies
|
||||||
if (!empty($this->rewards[$this->id][TYPE_CURRENCY]))
|
if (!empty($this->rewards[$this->id][Type::CURRENCY]))
|
||||||
foreach ($this->rewards[$this->id][TYPE_CURRENCY] as $id => $__)
|
foreach ($this->rewards[$this->id][Type::CURRENCY] as $id => $__)
|
||||||
$data[TYPE_CURRENCY][$id] = $id;
|
$data[Type::CURRENCY][$id] = $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($addMask & GLOBALINFO_SELF)
|
if ($addMask & GLOBALINFO_SELF)
|
||||||
$data[TYPE_QUEST][$this->id] = ['name' => $this->getField('name', true)];
|
$data[Type::QUEST][$this->id] = ['name' => $this->getField('name', true)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
@@ -457,7 +457,7 @@ class QuestListFilter extends Filter
|
|||||||
34 => [FILTER_CR_CALLBACK, 'cbAvailable', null, null], // availabletoplayers [yn]
|
34 => [FILTER_CR_CALLBACK, 'cbAvailable', null, null], // availabletoplayers [yn]
|
||||||
36 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
36 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
||||||
37 => [FILTER_CR_CALLBACK, 'cbClassSpec', null, null], // classspecific [enum]
|
37 => [FILTER_CR_CALLBACK, 'cbClassSpec', null, null], // classspecific [enum]
|
||||||
37 => [FILTER_CR_CALLBACK, 'cbRaceSpec', null, null], // racespecific [enum]
|
38 => [FILTER_CR_CALLBACK, 'cbRaceSpec', null, null], // racespecific [enum]
|
||||||
42 => [FILTER_CR_STAFFFLAG, 'flags' ], // flags
|
42 => [FILTER_CR_STAFFFLAG, 'flags' ], // flags
|
||||||
43 => [FILTER_CR_CALLBACK, 'cbCurrencyReward', null, null], // currencyrewarded [enum]
|
43 => [FILTER_CR_CALLBACK, 'cbCurrencyReward', null, null], // currencyrewarded [enum]
|
||||||
44 => [FILTER_CR_CALLBACK, 'cbLoremaster', null, null], // countsforloremaster_stc [yn]
|
44 => [FILTER_CR_CALLBACK, 'cbLoremaster', null, null], // countsforloremaster_stc [yn]
|
||||||
@@ -469,7 +469,7 @@ class QuestListFilter extends Filter
|
|||||||
'cr' => [FILTER_V_RANGE, [1, 45], true ], // criteria ids
|
'cr' => [FILTER_V_RANGE, [1, 45], true ], // criteria ids
|
||||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 99999]], true ], // criteria operators
|
'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
|
'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
|
'na' => [FILTER_V_REGEX, '/[\p{C};%\\\\]/ui', false], // name / text - only printable chars, no delimiter
|
||||||
'ex' => [FILTER_V_EQUAL, 'on', false], // also match subname
|
'ex' => [FILTER_V_EQUAL, 'on', false], // also match subname
|
||||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||||
'minle' => [FILTER_V_RANGE, [1, 99], false], // min quest level
|
'minle' => [FILTER_V_RANGE, [1, 99], false], // min quest level
|
||||||
@@ -581,11 +581,11 @@ class QuestListFilter extends Filter
|
|||||||
switch ($cr[1])
|
switch ($cr[1])
|
||||||
{
|
{
|
||||||
case 1: // npc
|
case 1: // npc
|
||||||
return ['AND', ['qse.type', TYPE_NPC], ['qse.method', $flags, '&']];
|
return ['AND', ['qse.type', Type::NPC], ['qse.method', $flags, '&']];
|
||||||
case 2: // object
|
case 2: // object
|
||||||
return ['AND', ['qse.type', TYPE_OBJECT], ['qse.method', $flags, '&']];
|
return ['AND', ['qse.type', Type::OBJECT], ['qse.method', $flags, '&']];
|
||||||
case 3: // item
|
case 3: // item
|
||||||
return ['AND', ['qse.type', TYPE_ITEM], ['qse.method', $flags, '&']];
|
return ['AND', ['qse.type', Type::ITEM], ['qse.method', $flags, '&']];
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class SkillList extends BaseType
|
class SkillList extends BaseType
|
||||||
{
|
{
|
||||||
public static $type = TYPE_SKILL;
|
public static $type = Type::SKILL;
|
||||||
public static $brickFile = 'skill';
|
public static $brickFile = 'skill';
|
||||||
public static $dataTable = '?_skillline';
|
public static $dataTable = '?_skillline';
|
||||||
|
|
||||||
protected $queryBase = 'SELECT *, sl.id AS ARRAY_KEY FROM ?_skillline sl';
|
protected $queryBase = 'SELECT sl.*, sl.id AS ARRAY_KEY FROM ?_skillline sl';
|
||||||
protected $queryOpts = array(
|
protected $queryOpts = array(
|
||||||
'sl' => [['ic']],
|
'sl' => [['ic']],
|
||||||
'ic' => ['j' => ['?_icons ic ON ic.id = sl.iconId', true], 's' => ', ic.name AS iconString'],
|
'ic' => ['j' => ['?_icons ic ON ic.id = sl.iconId', true], 's' => ', ic.name AS iconString'],
|
||||||
@@ -40,7 +40,7 @@ class SkillList extends BaseType
|
|||||||
|
|
||||||
public static function getName($id)
|
public static function getName($id)
|
||||||
{
|
{
|
||||||
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM ?_skillline WHERE id = ?d', $id);
|
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_skillline WHERE id = ?d', $id);
|
||||||
return Util::localizedString($n, 'name');
|
return Util::localizedString($n, 'name');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +54,11 @@ class SkillList extends BaseType
|
|||||||
'category' => $this->curTpl['typeCat'],
|
'category' => $this->curTpl['typeCat'],
|
||||||
'categorybak' => $this->curTpl['categoryId'],
|
'categorybak' => $this->curTpl['categoryId'],
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'name' => Util::jsEscape($this->getField('name', true)),
|
'name' => $this->getField('name', true),
|
||||||
'profession' => $this->curTpl['professionMask'],
|
'profession' => $this->curTpl['professionMask'],
|
||||||
'recipeSubclass' => $this->curTpl['recipeSubClass'],
|
'recipeSubclass' => $this->curTpl['recipeSubClass'],
|
||||||
'specializations' => Util::toJSON($this->curTpl['specializations'], JSON_NUMERIC_CHECK),
|
'specializations' => Util::toJSON($this->curTpl['specializations'], JSON_NUMERIC_CHECK),
|
||||||
'icon' => Util::jsEscape($this->curTpl['iconString'])
|
'icon' => $this->curTpl['iconString']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ class SkillList extends BaseType
|
|||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
$data[self::$type][$this->id] = ['name' => Util::jsEscape($this->getField('name', true)), 'icon' => Util::jsEscape($this->curTpl['iconString'])];
|
$data[self::$type][$this->id] = ['name' => $this->getField('name', true), 'icon' => $this->curTpl['iconString']];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ class SoundList extends BaseType
|
|||||||
{
|
{
|
||||||
use spawnHelper;
|
use spawnHelper;
|
||||||
|
|
||||||
public static $type = TYPE_SOUND;
|
public static $type = Type::SOUND;
|
||||||
public static $brickFile = 'sound';
|
public static $brickFile = 'sound';
|
||||||
public static $dataTable = '?_sounds';
|
public static $dataTable = '?_sounds';
|
||||||
public static $contribute = CONTRIBUTE_CO;
|
public static $contribute = CONTRIBUTE_CO;
|
||||||
|
|
||||||
protected $queryBase = 'SELECT *, s.id AS ARRAY_KEY FROM ?_sounds s';
|
protected $queryBase = 'SELECT s.*, s.id AS ARRAY_KEY FROM ?_sounds s';
|
||||||
|
|
||||||
private $fileBuffer = [];
|
private $fileBuffer = [];
|
||||||
private static $fileTypes = array(
|
private static $fileTypes = array(
|
||||||
@@ -43,9 +43,11 @@ class SoundList extends BaseType
|
|||||||
|
|
||||||
if ($this->fileBuffer)
|
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));
|
$files = DB::Aowow()->select('SELECT id AS ARRAY_KEY, `id`, `file` AS title, `type`, `path` FROM ?_sounds_files sf WHERE id IN (?a)', array_keys($this->fileBuffer));
|
||||||
foreach ($files as $id => $data)
|
foreach ($files as $id => $data)
|
||||||
{
|
{
|
||||||
|
// 3.3.5 bandaid - need fullpath to play via wow API, remove for cata and later
|
||||||
|
$data['path'] = str_replace('\\', '\\\\', $data['path'] ? $data['path'] . '\\' . $data['title'] : $data['title']);
|
||||||
// skipp file extension
|
// skipp file extension
|
||||||
$data['title'] = substr($data['title'], 0, -4);
|
$data['title'] = substr($data['title'], 0, -4);
|
||||||
// enum to string
|
// enum to string
|
||||||
@@ -58,13 +60,6 @@ class SoundList extends BaseType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getName($id)
|
|
||||||
{
|
|
||||||
$this->getEntry($id);
|
|
||||||
|
|
||||||
return $this->getField('name');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getListviewData()
|
public function getListviewData()
|
||||||
{
|
{
|
||||||
$data = [];
|
$data = [];
|
||||||
@@ -88,7 +83,7 @@ class SoundList extends BaseType
|
|||||||
|
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
$data[self::$type][$this->id] = array(
|
$data[self::$type][$this->id] = array(
|
||||||
'name' => Util::jsEscape($this->getField('name', true)),
|
'name' => $this->getField('name', true),
|
||||||
'type' => $this->getField('cat'),
|
'type' => $this->getField('cat'),
|
||||||
'files' => array_values(array_filter($this->getField('files')))
|
'files' => array_values(array_filter($this->getField('files')))
|
||||||
);
|
);
|
||||||
@@ -101,6 +96,12 @@ class SoundList extends BaseType
|
|||||||
|
|
||||||
class SoundListFilter extends Filter
|
class SoundListFilter extends Filter
|
||||||
{
|
{
|
||||||
|
// 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
|
||||||
|
);
|
||||||
|
|
||||||
// we have no criteria for this one...
|
// we have no criteria for this one...
|
||||||
protected function createSQLForCriterium(&$cr)
|
protected function createSQLForCriterium(&$cr)
|
||||||
{
|
{
|
||||||
@@ -109,12 +110,6 @@ class SoundListFilter extends Filter
|
|||||||
return [1];
|
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()
|
protected function createSQLForValues()
|
||||||
{
|
{
|
||||||
$parts = [];
|
$parts = [];
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class SpellList extends BaseType
|
|||||||
public $relItems = null;
|
public $relItems = null;
|
||||||
public $sources = [];
|
public $sources = [];
|
||||||
|
|
||||||
public static $type = TYPE_SPELL;
|
public static $type = Type::SPELL;
|
||||||
public static $brickFile = 'spell';
|
public static $brickFile = 'spell';
|
||||||
public static $dataTable = '?_spell';
|
public static $dataTable = '?_spell';
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ class SpellList extends BaseType
|
|||||||
);
|
);
|
||||||
|
|
||||||
public static $effects = array(
|
public static $effects = array(
|
||||||
'heal' => [ 0,/*3,*/10, 67, 75, 136 ], // <no effect>, Dummy, Heal, Heal Max Health, Heal Mechanical, Heal Percent
|
'heal' => [ 0,/*3,*/10, 67, 75, 136 ], // <no effect>, /*Dummy*/, Heal, Heal Max Health, Heal Mechanical, Heal Percent
|
||||||
'damage' => [ 0, 2, 3, 9, 62 ], // <no effect>, Dummy, School Damage, Health Leech, Power Burn
|
'damage' => [ 0, 2, 3, 9, 62 ], // <no effect>, Dummy, School Damage, Health Leech, Power Burn
|
||||||
'itemCreate' => [24, 34, 59, 66, 157 ], // createItem, changeItem, randomItem, createManaGem, createItem2
|
'itemCreate' => [24, 34, 59, 66, 157 ], // createItem, changeItem, randomItem, createManaGem, createItem2
|
||||||
'trigger' => [ 3, 32, 64, 101, 142, 148, 151, 152, 155, 160, 164], // dummy, trigger missile, trigger spell, feed pet, force cast, force cast with value, unk, trigger spell 2, unk, dualwield 2H, unk, remove aura
|
'trigger' => [ 3, 32, 64, 101, 142, 148, 151, 152, 155, 160, 164], // dummy, trigger missile, trigger spell, feed pet, force cast, force cast with value, unk, trigger spell 2, unk, dualwield 2H, unk, remove aura
|
||||||
@@ -54,10 +54,10 @@ class SpellList extends BaseType
|
|||||||
|
|
||||||
protected $queryBase = 'SELECT s.*, s.id AS ARRAY_KEY FROM ?_spell s';
|
protected $queryBase = 'SELECT s.*, s.id AS ARRAY_KEY FROM ?_spell s';
|
||||||
protected $queryOpts = array(
|
protected $queryOpts = array(
|
||||||
's' => [['src', 'sr', 'ic', 'ica']], // 6: TYPE_SPELL
|
's' => [['src', 'sr', 'ic', 'ica']], // 6: Type::SPELL
|
||||||
'ic' => ['j' => ['?_icons ic ON ic.id = s.iconId', true], 's' => ', ic.name AS iconString'],
|
'ic' => ['j' => ['?_icons ic ON ic.id = s.iconId', true], 's' => ', ic.name AS iconString'],
|
||||||
'ica' => ['j' => ['?_icons ica ON ica.id = s.iconIdAlt', true], 's' => ', ica.name AS iconStringAlt'],
|
'ica' => ['j' => ['?_icons ica ON ica.id = s.iconIdAlt', true], 's' => ', ica.name AS iconStringAlt'],
|
||||||
'sr' => ['j' => ['?_spellrange sr ON sr.id = s.rangeId'], 's' => ', sr.rangeMinHostile, sr.rangeMinFriend, sr.rangeMaxHostile, sr.rangeMaxFriend, sr.name_loc0 AS rangeText_loc0, sr.name_loc2 AS rangeText_loc2, sr.name_loc3 AS rangeText_loc3, sr.name_loc6 AS rangeText_loc6, sr.name_loc8 AS rangeText_loc8'],
|
'sr' => ['j' => ['?_spellrange sr ON sr.id = s.rangeId'], 's' => ', sr.rangeMinHostile, sr.rangeMinFriend, sr.rangeMaxHostile, sr.rangeMaxFriend, sr.name_loc0 AS rangeText_loc0, sr.name_loc2 AS rangeText_loc2, sr.name_loc3 AS rangeText_loc3, sr.name_loc4 AS rangeText_loc4, sr.name_loc6 AS rangeText_loc6, sr.name_loc8 AS rangeText_loc8'],
|
||||||
'src' => ['j' => ['?_source src ON type = 6 AND typeId = s.id', true], 's' => ', src1, src2, src3, src4, src5, src6, src7, src8, src9, src10, src11, src12, src13, src14, src15, src16, src17, src18, src19, src20, src21, src22, src23, src24']
|
'src' => ['j' => ['?_source src ON type = 6 AND typeId = s.id', true], 's' => ', src1, src2, src3, src4, src5, src6, src7, src8, src9, src10, src11, src12, src13, src14, src15, src16, src17, src18, src19, src20, src21, src22, src23, src24']
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ class SpellList extends BaseType
|
|||||||
// use if you JUST need the name
|
// use if you JUST need the name
|
||||||
public static function getName($id)
|
public static function getName($id)
|
||||||
{
|
{
|
||||||
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM ?_spell WHERE id = ?d', $id );
|
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_spell WHERE id = ?d', $id );
|
||||||
return Util::localizedString($n, 'name');
|
return Util::localizedString($n, 'name');
|
||||||
}
|
}
|
||||||
// end static use
|
// end static use
|
||||||
@@ -161,7 +161,7 @@ class SpellList extends BaseType
|
|||||||
// Enchant Item Permanent (53) / Temporary (54)
|
// Enchant Item Permanent (53) / Temporary (54)
|
||||||
if (in_array($this->curTpl['effect'.$i.'Id'], [53, 54]))
|
if (in_array($this->curTpl['effect'.$i.'Id'], [53, 54]))
|
||||||
{
|
{
|
||||||
if ($mv && ($json = DB::Aowow()->selectRow('SELECT * FROM ?_item_stats WHERE `type` = ?d AND `typeId` = ?d', TYPE_ENCHANTMENT, $mv)))
|
if ($mv && ($json = DB::Aowow()->selectRow('SELECT * FROM ?_item_stats WHERE `type` = ?d AND `typeId` = ?d', Type::ENCHANTMENT, $mv)))
|
||||||
{
|
{
|
||||||
$mods = [];
|
$mods = [];
|
||||||
foreach ($json as $str => $val)
|
foreach ($json as $str => $val)
|
||||||
@@ -637,18 +637,18 @@ class SpellList extends BaseType
|
|||||||
// GO Model from MiscVal
|
// GO Model from MiscVal
|
||||||
if (in_array($this->curTpl['effect'.$i.'Id'], [50, 76, 104, 105, 106, 107]))
|
if (in_array($this->curTpl['effect'.$i.'Id'], [50, 76, 104, 105, 106, 107]))
|
||||||
{
|
{
|
||||||
if (isset($displays[TYPE_OBJECT][$id]))
|
if (isset($displays[Type::OBJECT][$id]))
|
||||||
$displays[TYPE_OBJECT][$id][0][] = $i;
|
$displays[Type::OBJECT][$id][0][] = $i;
|
||||||
else
|
else
|
||||||
$displays[TYPE_OBJECT][$id] = [[$i], $effMV];
|
$displays[Type::OBJECT][$id] = [[$i], $effMV];
|
||||||
}
|
}
|
||||||
// NPC Model from MiscVal
|
// NPC Model from MiscVal
|
||||||
else if (in_array($this->curTpl['effect'.$i.'Id'], [28, 90, 134]) || in_array($this->curTpl['effect'.$i.'AuraId'], [56, 78]))
|
else if (in_array($this->curTpl['effect'.$i.'Id'], [28, 90, 56, 112, 134]) || in_array($this->curTpl['effect'.$i.'AuraId'], [56, 78]))
|
||||||
{
|
{
|
||||||
if (isset($displays[TYPE_NPC][$id]))
|
if (isset($displays[Type::NPC][$id]))
|
||||||
$displays[TYPE_NPC][$id][0][] = $i;
|
$displays[Type::NPC][$id][0][] = $i;
|
||||||
else
|
else
|
||||||
$displays[TYPE_NPC][$id] = [[$i], $effMV];
|
$displays[Type::NPC][$id] = [[$i], $effMV];
|
||||||
}
|
}
|
||||||
// Shapeshift
|
// Shapeshift
|
||||||
else if ($this->curTpl['effect'.$i.'AuraId'] == 36)
|
else if ($this->curTpl['effect'.$i.'AuraId'] == 36)
|
||||||
@@ -679,44 +679,46 @@ class SpellList extends BaseType
|
|||||||
|
|
||||||
$results = $displays[0];
|
$results = $displays[0];
|
||||||
|
|
||||||
if (!empty($displays[TYPE_NPC]))
|
if (!empty($displays[Type::NPC]))
|
||||||
{
|
{
|
||||||
$nModels = new CreatureList(array(['id', array_column($displays[TYPE_NPC], 1)]));
|
$nModels = new CreatureList(array(['id', array_column($displays[Type::NPC], 1)]));
|
||||||
foreach ($nModels->iterate() as $nId => $__)
|
foreach ($nModels->iterate() as $nId => $__)
|
||||||
{
|
{
|
||||||
$srcId = 0;
|
foreach ($displays[Type::NPC] as $srcId => [$indizes, $npcId])
|
||||||
foreach ($displays[TYPE_NPC] as $srcId => $set)
|
|
||||||
if ($set[1] == $nId)
|
|
||||||
break;
|
|
||||||
|
|
||||||
foreach ($set[0] as $idx)
|
|
||||||
{
|
{
|
||||||
$results[$srcId][$idx] = array(
|
if ($npcId == $nId)
|
||||||
'typeId' => $nId,
|
{
|
||||||
'displayId' => $nModels->getRandomModelId(),
|
foreach ($indizes as $idx)
|
||||||
'displayName' => $nModels->getField('name', true)
|
{
|
||||||
);
|
$results[$srcId][$idx] = array(
|
||||||
|
'typeId' => $nId,
|
||||||
|
'displayId' => $nModels->getRandomModelId(),
|
||||||
|
'displayName' => $nModels->getField('name', true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($displays[TYPE_OBJECT]))
|
if (!empty($displays[Type::OBJECT]))
|
||||||
{
|
{
|
||||||
$oModels = new GameObjectList(array(['id', array_column($displays[TYPE_OBJECT], 1)]));
|
$oModels = new GameObjectList(array(['id', array_column($displays[Type::OBJECT], 1)]));
|
||||||
foreach ($oModels->iterate() as $oId => $__)
|
foreach ($oModels->iterate() as $oId => $__)
|
||||||
{
|
{
|
||||||
$srcId = 0;
|
foreach ($displays[Type::OBJECT] as $srcId => [$indizes, $objId])
|
||||||
foreach ($displays[TYPE_OBJECT] as $srcId => $set)
|
|
||||||
if ($set[1] == $oId)
|
|
||||||
break;
|
|
||||||
|
|
||||||
foreach ($set[0] as $idx)
|
|
||||||
{
|
{
|
||||||
$results[$srcId][$idx] = array(
|
if ($objId == $oId)
|
||||||
'typeId' => $oId,
|
{
|
||||||
'displayId' => $oModels->getField('displayId'),
|
foreach ($indizes as $idx)
|
||||||
'displayName' => $oModels->getField('name', true)
|
{
|
||||||
);
|
$results[$srcId][$idx] = array(
|
||||||
|
'typeId' => $oId,
|
||||||
|
'displayId' => $oModels->getField('displayId'),
|
||||||
|
'displayName' => $oModels->getField('name', true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -757,7 +759,7 @@ class SpellList extends BaseType
|
|||||||
$pt = $this->curTpl['powerType'];
|
$pt = $this->curTpl['powerType'];
|
||||||
|
|
||||||
if ($pt == POWER_RUNE && ($rCost = ($this->curTpl['powerCostRunes'] & 0x333)))
|
if ($pt == POWER_RUNE && ($rCost = ($this->curTpl['powerCostRunes'] & 0x333)))
|
||||||
{ // Blood 2|1 - Unholy 2|1 - Frost 2|1
|
{ // Frost 2|1 - Unholy 2|1 - Blood 2|1
|
||||||
$runes = [];
|
$runes = [];
|
||||||
if ($_ = (($rCost & 0x300) >> 8))
|
if ($_ = (($rCost & 0x300) >> 8))
|
||||||
$runes[] = $_.' '.Lang::spell('powerRunes', 2);
|
$runes[] = $_.' '.Lang::spell('powerRunes', 2);
|
||||||
@@ -769,7 +771,7 @@ class SpellList extends BaseType
|
|||||||
$str .= implode(', ', $runes);
|
$str .= implode(', ', $runes);
|
||||||
}
|
}
|
||||||
else if ($this->curTpl['powerCostPercent'] > 0) // power cost: pct over static
|
else if ($this->curTpl['powerCostPercent'] > 0) // power cost: pct over static
|
||||||
$str .= $this->curTpl['powerCostPercent']."% ".sprintf(Lang::spell('pctCostOf'), strtolower(Lang::spell('powerTypes', $pt)));
|
$str .= $this->curTpl['powerCostPercent']."% ".sprintf(Lang::spell('pctCostOf'), mb_strtolower(Lang::spell('powerTypes', $pt)));
|
||||||
else if ($this->curTpl['powerCost'] > 0 || $this->curTpl['powerPerSecond'] > 0 || $this->curTpl['powerCostPerLevel'] > 0)
|
else if ($this->curTpl['powerCost'] > 0 || $this->curTpl['powerPerSecond'] > 0 || $this->curTpl['powerCostPerLevel'] > 0)
|
||||||
$str .= ($pt == POWER_RAGE || $pt == POWER_RUNIC_POWER ? $this->curTpl['powerCost'] / 10 : $this->curTpl['powerCost']).' '.Util::ucFirst(Lang::spell('powerTypes', $pt));
|
$str .= ($pt == POWER_RAGE || $pt == POWER_RUNIC_POWER ? $this->curTpl['powerCost'] / 10 : $this->curTpl['powerCost']).' '.Util::ucFirst(Lang::spell('powerTypes', $pt));
|
||||||
|
|
||||||
@@ -789,12 +791,12 @@ class SpellList extends BaseType
|
|||||||
if ($this->isChanneledSpell())
|
if ($this->isChanneledSpell())
|
||||||
return Lang::spell('channeled');
|
return Lang::spell('channeled');
|
||||||
else if ($this->curTpl['castTime'] > 0)
|
else if ($this->curTpl['castTime'] > 0)
|
||||||
return $short ? sprintf(Lang::spell('castIn'), $this->curTpl['castTime'] / 1000) : Util::formatTime($this->curTpl['castTime']);
|
return $short ? sprintf(Lang::spell('castIn'), $this->curTpl['castTime']) : Util::formatTime($this->curTpl['castTime'] * 1000);
|
||||||
// show instant only for player/pet/npc abilities (todo (low): unsure when really hidden (like talent-case))
|
// show instant only for player/pet/npc abilities (todo (low): unsure when really hidden (like talent-case))
|
||||||
else if ($noInstant && !in_array($this->curTpl['typeCat'], [11, 7, -3, -6, -8, 0]) && !($this->curTpl['cuFlags'] & SPELL_CU_TALENTSPELL))
|
else if ($noInstant && !in_array($this->curTpl['typeCat'], [11, 7, -3, -6, -8, 0]) && !($this->curTpl['cuFlags'] & SPELL_CU_TALENTSPELL))
|
||||||
return '';
|
return '';
|
||||||
// SPELL_ATTR0_ABILITY instant ability.. yeah, wording thing only (todo (low): rule is imperfect)
|
// SPELL_ATTR0_ABILITY instant ability.. yeah, wording thing only (todo (low): rule is imperfect)
|
||||||
else if ($this->curTpl['damageClass'] != 1 || $this->curTpl['attributes0'] & 0x10)
|
else if ($this->curTpl['damageClass'] != 1 || $this->curTpl['attributes0'] & SPELL_ATTR0_ABILITY)
|
||||||
return Lang::spell('instantPhys');
|
return Lang::spell('instantPhys');
|
||||||
else // instant cast
|
else // instant cast
|
||||||
return Lang::spell('instantMagic');
|
return Lang::spell('instantMagic');
|
||||||
@@ -813,7 +815,7 @@ class SpellList extends BaseType
|
|||||||
// formulae base from TC
|
// formulae base from TC
|
||||||
private function calculateAmountForCurrent($effIdx, $altTpl = null)
|
private function calculateAmountForCurrent($effIdx, $altTpl = null)
|
||||||
{
|
{
|
||||||
$ref = $altTpl ? $altTpl : $this;
|
$ref = $altTpl ?: $this;
|
||||||
$level = $this->charLevel;
|
$level = $this->charLevel;
|
||||||
$rppl = $ref->getField('effect'.$effIdx.'RealPointsPerLevel');
|
$rppl = $ref->getField('effect'.$effIdx.'RealPointsPerLevel');
|
||||||
$base = $ref->getField('effect'.$effIdx.'BasePoints');
|
$base = $ref->getField('effect'.$effIdx.'BasePoints');
|
||||||
@@ -821,6 +823,7 @@ class SpellList extends BaseType
|
|||||||
$maxLvl = $ref->getField('maxLevel');
|
$maxLvl = $ref->getField('maxLevel');
|
||||||
$baseLvl = $ref->getField('baseLevel');
|
$baseLvl = $ref->getField('baseLevel');
|
||||||
|
|
||||||
|
/* when should level scaling be actively worked into tooltips?
|
||||||
if ($rppl)
|
if ($rppl)
|
||||||
{
|
{
|
||||||
if ($level > $maxLvl && $maxLvl > 0)
|
if ($level > $maxLvl && $maxLvl > 0)
|
||||||
@@ -828,11 +831,12 @@ class SpellList extends BaseType
|
|||||||
else if ($level < $baseLvl)
|
else if ($level < $baseLvl)
|
||||||
$level = $baseLvl;
|
$level = $baseLvl;
|
||||||
|
|
||||||
if (!$ref->getField('atributes0') & 0x40) // SPELL_ATTR0_PASSIVE
|
if (!$ref->getField('atributes0') & SPELL_ATTR0_PASSIVE)
|
||||||
$level -= $ref->getField('spellLevel');
|
$level -= $ref->getField('spellLevel');
|
||||||
|
|
||||||
$base += (int)($level * $rppl);
|
$base += (int)($level * $rppl);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
return [
|
return [
|
||||||
$add ? $base + 1 : $base,
|
$add ? $base + 1 : $base,
|
||||||
@@ -877,7 +881,7 @@ class SpellList extends BaseType
|
|||||||
|
|
||||||
public function isChanneledSpell()
|
public function isChanneledSpell()
|
||||||
{
|
{
|
||||||
return $this->curTpl['attributes1'] & 0x44;
|
return $this->curTpl['attributes1'] & (SPELL_ATTR1_CHANNELED_1 | SPELL_ATTR1_CHANNELED_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isHealingSpell()
|
public function isHealingSpell()
|
||||||
@@ -955,7 +959,7 @@ class SpellList extends BaseType
|
|||||||
$cond = $COND = function($a, $b, $c) { return $a ? $b : $c; };
|
$cond = $COND = function($a, $b, $c) { return $a ? $b : $c; };
|
||||||
$eq = $EQ = function($a, $b) { return $a == $b; };
|
$eq = $EQ = function($a, $b) { return $a == $b; };
|
||||||
$gt = $GT = function($a, $b) { return $a > $b; };
|
$gt = $GT = function($a, $b) { return $a > $b; };
|
||||||
$gte = $GTE = function($a, $b) { return $a <= $b; };
|
$gte = $GTE = function($a, $b) { return $a >= $b; };
|
||||||
$floor = $FLOOR = function($a) { return floor($a); };
|
$floor = $FLOOR = function($a) { return floor($a); };
|
||||||
$max = $MAX = function($a, $b) { return max($a, $b); };
|
$max = $MAX = function($a, $b) { return max($a, $b); };
|
||||||
$min = $MIN = function($a, $b) { return min($a, $b); };
|
$min = $MIN = function($a, $b) { return min($a, $b); };
|
||||||
@@ -990,7 +994,7 @@ class SpellList extends BaseType
|
|||||||
$cond = $COND = !$this->interactive ? 'COND' : sprintf(Util::$dfnString, 'COND(<span class=\'q1\'>a</span>, <span class=\'q1\'>b</span>, <span class=\'q1\'>c</span>)<br /> <span class=\'q1\'>a</span> ? <span class=\'q1\'>b</span> : <span class=\'q1\'>c</span>', 'COND');
|
$cond = $COND = !$this->interactive ? 'COND' : sprintf(Util::$dfnString, 'COND(<span class=\'q1\'>a</span>, <span class=\'q1\'>b</span>, <span class=\'q1\'>c</span>)<br /> <span class=\'q1\'>a</span> ? <span class=\'q1\'>b</span> : <span class=\'q1\'>c</span>', 'COND');
|
||||||
$eq = $EQ = !$this->interactive ? 'EQ' : sprintf(Util::$dfnString, 'EQ(<span class=\'q1\'>a</span>, <span class=\'q1\'>b</span>)<br /> <span class=\'q1\'>a</span> == <span class=\'q1\'>b</span>', 'EQ');
|
$eq = $EQ = !$this->interactive ? 'EQ' : sprintf(Util::$dfnString, 'EQ(<span class=\'q1\'>a</span>, <span class=\'q1\'>b</span>)<br /> <span class=\'q1\'>a</span> == <span class=\'q1\'>b</span>', 'EQ');
|
||||||
$gt = $GT = !$this->interactive ? 'GT' : sprintf(Util::$dfnString, 'GT(<span class=\'q1\'>a</span>, <span class=\'q1\'>b</span>)<br /> <span class=\'q1\'>a</span> > <span class=\'q1\'>b</span>', 'GT');
|
$gt = $GT = !$this->interactive ? 'GT' : sprintf(Util::$dfnString, 'GT(<span class=\'q1\'>a</span>, <span class=\'q1\'>b</span>)<br /> <span class=\'q1\'>a</span> > <span class=\'q1\'>b</span>', 'GT');
|
||||||
$gte = $GTE = !$this->interactive ? 'GTE' : sprintf(Util::$dfnString, 'GTE(<span class=\'q1\'>a</span>, <span class=\'q1\'>b</span>)<br /> <span class=\'q1\'>a</span> <= <span class=\'q1\'>b</span>', 'GT');
|
$gte = $GTE = !$this->interactive ? 'GTE' : sprintf(Util::$dfnString, 'GTE(<span class=\'q1\'>a</span>, <span class=\'q1\'>b</span>)<br /> <span class=\'q1\'>a</span> >= <span class=\'q1\'>b</span>', 'GTE');
|
||||||
$floor = $FLOOR = !$this->interactive ? 'FLOOR' : sprintf(Util::$dfnString, 'FLOOR(<span class=\'q1\'>a</span>)', 'FLOOR');
|
$floor = $FLOOR = !$this->interactive ? 'FLOOR' : sprintf(Util::$dfnString, 'FLOOR(<span class=\'q1\'>a</span>)', 'FLOOR');
|
||||||
$min = $MIN = !$this->interactive ? 'MIN' : sprintf(Util::$dfnString, 'MIN(<span class=\'q1\'>a</span>, <span class=\'q1\'>b</span>)', 'MIN');
|
$min = $MIN = !$this->interactive ? 'MIN' : sprintf(Util::$dfnString, 'MIN(<span class=\'q1\'>a</span>, <span class=\'q1\'>b</span>)', 'MIN');
|
||||||
$max = $MAX = !$this->interactive ? 'MAX' : sprintf(Util::$dfnString, 'MAX(<span class=\'q1\'>a</span>, <span class=\'q1\'>b</span>)', 'MAX');
|
$max = $MAX = !$this->interactive ? 'MAX' : sprintf(Util::$dfnString, 'MAX(<span class=\'q1\'>a</span>, <span class=\'q1\'>b</span>)', 'MAX');
|
||||||
@@ -1205,7 +1209,7 @@ class SpellList extends BaseType
|
|||||||
break;
|
break;
|
||||||
case 'o': // TotalAmount for periodic auras (with variance)
|
case 'o': // TotalAmount for periodic auras (with variance)
|
||||||
case 'O':
|
case 'O':
|
||||||
list($min, $max, $modStrMin, $modStrMax) = $this->calculateAmountForCurrent($effIdx, $srcSpell);
|
[$min, $max, $modStrMin, $modStrMax] = $this->calculateAmountForCurrent($effIdx, $srcSpell);
|
||||||
$periode = $srcSpell->getField('effect'.$effIdx.'Periode');
|
$periode = $srcSpell->getField('effect'.$effIdx.'Periode');
|
||||||
$duration = $srcSpell->getField('duration');
|
$duration = $srcSpell->getField('duration');
|
||||||
|
|
||||||
@@ -1257,7 +1261,7 @@ class SpellList extends BaseType
|
|||||||
break;
|
break;
|
||||||
case 's': // BasePoints (with variance)
|
case 's': // BasePoints (with variance)
|
||||||
case 'S':
|
case 'S':
|
||||||
list($min, $max, $modStrMin, $modStrMax) = $this->calculateAmountForCurrent($effIdx, $srcSpell);
|
[$min, $max, $modStrMin, $modStrMax] = $this->calculateAmountForCurrent($effIdx, $srcSpell);
|
||||||
$mv = $srcSpell->getField('effect'.$effIdx.'MiscValue');
|
$mv = $srcSpell->getField('effect'.$effIdx.'MiscValue');
|
||||||
$aura = $srcSpell->getField('effect'.$effIdx.'AuraId');
|
$aura = $srcSpell->getField('effect'.$effIdx.'AuraId');
|
||||||
|
|
||||||
@@ -1352,7 +1356,7 @@ class SpellList extends BaseType
|
|||||||
|
|
||||||
$formOutStr = '';
|
$formOutStr = '';
|
||||||
|
|
||||||
while ($formCurPos <= strlen($formula))
|
while ($formCurPos < strlen($formula))
|
||||||
{
|
{
|
||||||
$char = $formula[$formCurPos];
|
$char = $formula[$formCurPos];
|
||||||
|
|
||||||
@@ -1377,7 +1381,7 @@ class SpellList extends BaseType
|
|||||||
++$formCurPos; // for some odd reason the precision decimal survives if we dont increment further..
|
++$formCurPos; // for some odd reason the precision decimal survives if we dont increment further..
|
||||||
}
|
}
|
||||||
|
|
||||||
list($formOutStr, $fSuffix, $fRating) = $this->resolveFormulaString($formOutStr, $formPrecision, $scaling);
|
[$formOutStr, $fSuffix, $fRating] = $this->resolveFormulaString($formOutStr, $formPrecision, $scaling);
|
||||||
|
|
||||||
$formula = substr_replace($formula, $formOutStr, $formStartPos, ($formCurPos - $formStartPos));
|
$formula = substr_replace($formula, $formOutStr, $formStartPos, ($formCurPos - $formStartPos));
|
||||||
}
|
}
|
||||||
@@ -1436,7 +1440,7 @@ class SpellList extends BaseType
|
|||||||
// step 3: try to evaluate result
|
// step 3: try to evaluate result
|
||||||
$evaled = $this->resolveEvaluation($str);
|
$evaled = $this->resolveEvaluation($str);
|
||||||
|
|
||||||
$return = is_numeric($evaled) ? Lang::nf($evaled, $precision, true) : $evaled;
|
$return = is_numeric($evaled) ? round($evaled, $precision) : $evaled;
|
||||||
|
|
||||||
return [$return, $fSuffix, $fRating];
|
return [$return, $fSuffix, $fRating];
|
||||||
}
|
}
|
||||||
@@ -1646,7 +1650,7 @@ class SpellList extends BaseType
|
|||||||
|
|
||||||
$formOutStr = '';
|
$formOutStr = '';
|
||||||
|
|
||||||
while ($formCurPos <= strlen($data)) // only hard-exit condition, we'll hit those breaks eventually^^
|
while ($formCurPos < strlen($data)) // only hard-exit condition, we'll hit those breaks eventually^^
|
||||||
{
|
{
|
||||||
$char = $data[$formCurPos];
|
$char = $data[$formCurPos];
|
||||||
|
|
||||||
@@ -1674,7 +1678,7 @@ class SpellList extends BaseType
|
|||||||
$formPrecision = $data[$formCurPos + 1];
|
$formPrecision = $data[$formCurPos + 1];
|
||||||
$formCurPos += 2;
|
$formCurPos += 2;
|
||||||
}
|
}
|
||||||
list($formOutVal, $formOutStr, $ratingId) = $this->resolveFormulaString($formOutStr, $formPrecision ?: ($topLevel ? 0 : 10), $scaling);
|
[$formOutVal, $formOutStr, $ratingId] = $this->resolveFormulaString($formOutStr, $formPrecision ?: ($topLevel ? 0 : 10), $scaling);
|
||||||
|
|
||||||
if ($ratingId && Util::checkNumeric($formOutVal) && $this->interactive)
|
if ($ratingId && Util::checkNumeric($formOutVal) && $this->interactive)
|
||||||
$resolved = sprintf($formOutStr, $ratingId, abs($formOutVal), sprintf(Util::$setRatingLevelString, $this->charLevel, $ratingId, abs($formOutVal), Util::setRatingLevel($this->charLevel, $ratingId, abs($formOutVal))));
|
$resolved = sprintf($formOutStr, $ratingId, abs($formOutVal), sprintf(Util::$setRatingLevelString, $this->charLevel, $ratingId, abs($formOutVal), Util::setRatingLevel($this->charLevel, $ratingId, abs($formOutVal))));
|
||||||
@@ -1750,7 +1754,7 @@ class SpellList extends BaseType
|
|||||||
$condParts = [];
|
$condParts = [];
|
||||||
$isLastElse = false;
|
$isLastElse = false;
|
||||||
|
|
||||||
while ($condCurPos <= strlen($data)) // only hard-exit condition, we'll hit those breaks eventually^^
|
while ($condCurPos < strlen($data)) // only hard-exit condition, we'll hit those breaks eventually^^
|
||||||
{
|
{
|
||||||
$char = $data[$condCurPos];
|
$char = $data[$condCurPos];
|
||||||
|
|
||||||
@@ -1912,9 +1916,9 @@ class SpellList extends BaseType
|
|||||||
|
|
||||||
$reagents = array_reverse($reagents);
|
$reagents = array_reverse($reagents);
|
||||||
|
|
||||||
// get stances (check: SPELL_ATTR2_NOT_NEED_SHAPESHIFT)
|
// get stances
|
||||||
$stances = '';
|
$stances = '';
|
||||||
if ($this->curTpl['stanceMask'] && !($this->curTpl['attributes2'] & 0x80000))
|
if ($this->curTpl['stanceMask'] && !($this->curTpl['attributes2'] & SPELL_ATTR2_NOT_NEED_SHAPESHIFT))
|
||||||
$stances = Lang::game('requires2').' '.Lang::getStances($this->curTpl['stanceMask']);
|
$stances = Lang::game('requires2').' '.Lang::getStances($this->curTpl['stanceMask']);
|
||||||
|
|
||||||
// get item requirement (skip for professions)
|
// get item requirement (skip for professions)
|
||||||
@@ -2074,23 +2078,23 @@ class SpellList extends BaseType
|
|||||||
return $x;
|
return $x;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getColorsForCurrent()
|
public function getColorsForCurrent() : array
|
||||||
{
|
{
|
||||||
$gry = $this->curTpl['skillLevelGrey'];
|
$gry = $this->curTpl['skillLevelGrey'];
|
||||||
$ylw = $this->curTpl['skillLevelYellow'];
|
$ylw = $this->curTpl['skillLevelYellow'];
|
||||||
$grn = (int)(($ylw + $gry) / 2);
|
$grn = (int)(($ylw + $gry) / 2);
|
||||||
$org = $this->curTpl['learnedAt'];
|
$org = $this->curTpl['learnedAt'];
|
||||||
|
|
||||||
if (($org && $ylw < $org) || $ylw >= $gry)
|
if ($ylw < $org)
|
||||||
$ylw = 0;
|
$ylw = 0;
|
||||||
|
|
||||||
if (($org && $grn < $org) || $grn >= $gry)
|
if ($grn < $org || $grn < $ylw)
|
||||||
$grn = 0;
|
$grn = 0;
|
||||||
|
|
||||||
if (($grn && $org >= $grn) || $org >= $gry)
|
if ($org >= $ylw || $org >= $grn || $org >= $gry)
|
||||||
$org = 0;
|
$org = 0;
|
||||||
|
|
||||||
return $gry > 1 ? [$org, $ylw, $grn, $gry] : null;
|
return $gry > 1 ? [$org, $ylw, $grn, $gry] : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getListviewData($addInfoMask = 0x0)
|
public function getListviewData($addInfoMask = 0x0)
|
||||||
@@ -2201,24 +2205,24 @@ class SpellList extends BaseType
|
|||||||
if ($mask = $this->curTpl['reqClassMask'])
|
if ($mask = $this->curTpl['reqClassMask'])
|
||||||
for ($i = 0; $i < 11; $i++)
|
for ($i = 0; $i < 11; $i++)
|
||||||
if ($mask & (1 << $i))
|
if ($mask & (1 << $i))
|
||||||
$data[TYPE_CLASS][$i + 1] = $i + 1;
|
$data[Type::CHR_CLASS][$i + 1] = $i + 1;
|
||||||
|
|
||||||
if ($mask = $this->curTpl['reqRaceMask'])
|
if ($mask = $this->curTpl['reqRaceMask'])
|
||||||
for ($i = 0; $i < 11; $i++)
|
for ($i = 0; $i < 11; $i++)
|
||||||
if ($mask & (1 << $i))
|
if ($mask & (1 << $i))
|
||||||
$data[TYPE_RACE][$i + 1] = $i + 1;
|
$data[Type::CHR_RACE][$i + 1] = $i + 1;
|
||||||
|
|
||||||
// play sound effect
|
// play sound effect
|
||||||
for ($i = 1; $i < 4; $i++)
|
for ($i = 1; $i < 4; $i++)
|
||||||
if ($this->getField('effect'.$i.'Id') == 131 || $this->getField('effect'.$i.'Id') == 132)
|
if ($this->getField('effect'.$i.'Id') == 131 || $this->getField('effect'.$i.'Id') == 132)
|
||||||
$data[TYPE_SOUND][$this->getField('effect'.$i.'MiscValue')] = $this->getField('effect'.$i.'MiscValue');
|
$data[Type::SOUND][$this->getField('effect'.$i.'MiscValue')] = $this->getField('effect'.$i.'MiscValue');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($addMask & GLOBALINFO_SELF)
|
if ($addMask & GLOBALINFO_SELF)
|
||||||
{
|
{
|
||||||
$iconString = $this->curTpl['iconStringAlt'] ? 'iconStringAlt' : 'iconString';
|
$iconString = $this->curTpl['iconStringAlt'] ? 'iconStringAlt' : 'iconString';
|
||||||
|
|
||||||
$data[TYPE_SPELL][$id] = array(
|
$data[Type::SPELL][$id] = array(
|
||||||
'icon' => $this->curTpl[$iconString],
|
'icon' => $this->curTpl[$iconString],
|
||||||
'name' => $this->getField('name', true),
|
'name' => $this->getField('name', true),
|
||||||
);
|
);
|
||||||
@@ -2230,12 +2234,12 @@ class SpellList extends BaseType
|
|||||||
$tTip = $this->renderTooltip(MAX_LEVEL, true);
|
$tTip = $this->renderTooltip(MAX_LEVEL, true);
|
||||||
|
|
||||||
foreach ($tTip[1] as $relId => $_)
|
foreach ($tTip[1] as $relId => $_)
|
||||||
if (empty($data[TYPE_SPELL][$relId]))
|
if (empty($data[Type::SPELL][$relId]))
|
||||||
$data[TYPE_SPELL][$relId] = $relId;
|
$data[Type::SPELL][$relId] = $relId;
|
||||||
|
|
||||||
foreach ($buff[1] as $relId => $_)
|
foreach ($buff[1] as $relId => $_)
|
||||||
if (empty($data[TYPE_SPELL][$relId]))
|
if (empty($data[Type::SPELL][$relId]))
|
||||||
$data[TYPE_SPELL][$relId] = $relId;
|
$data[Type::SPELL][$relId] = $relId;
|
||||||
|
|
||||||
$extra[$id] = array(
|
$extra[$id] = array(
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
@@ -2254,7 +2258,7 @@ class SpellList extends BaseType
|
|||||||
public function getCastingTimeForBonus($asDOT = false)
|
public function getCastingTimeForBonus($asDOT = false)
|
||||||
{
|
{
|
||||||
$areaTargets = [7, 8, 15, 16, 20, 24, 30, 31, 33, 34, 37, 54, 56, 59, 104, 108];
|
$areaTargets = [7, 8, 15, 16, 20, 24, 30, 31, 33, 34, 37, 54, 56, 59, 104, 108];
|
||||||
$castingTime = $this->IsChanneledSpell() ? $this->curTpl['duration'] : $this->curTpl['castTime'];
|
$castingTime = $this->IsChanneledSpell() ? $this->curTpl['duration'] : ($this->curTpl['castTime'] * 1000);
|
||||||
|
|
||||||
if (!$castingTime)
|
if (!$castingTime)
|
||||||
return 3500;
|
return 3500;
|
||||||
@@ -2291,8 +2295,8 @@ class SpellList extends BaseType
|
|||||||
if ($overTime > 0 && $castingTime > 0 && $isDirect)
|
if ($overTime > 0 && $castingTime > 0 && $isDirect)
|
||||||
{
|
{
|
||||||
// mainly for DoTs which are 3500 here otherwise
|
// mainly for DoTs which are 3500 here otherwise
|
||||||
$originalCastTime = $this->curTpl['castTime'];
|
$originalCastTime = $this->curTpl['castTime'] * 1000;
|
||||||
if ($this->curTpl['attributes0'] & 0x2) // requires Ammo
|
if ($this->curTpl['attributes0'] & SPELL_ATTR0_REQ_AMMO)
|
||||||
$originalCastTime += 500;
|
$originalCastTime += 500;
|
||||||
|
|
||||||
if ($originalCastTime > 7000)
|
if ($originalCastTime > 7000)
|
||||||
@@ -2332,7 +2336,7 @@ class SpellList extends BaseType
|
|||||||
{
|
{
|
||||||
$data[$this->id] = array(
|
$data[$this->id] = array(
|
||||||
'n' => $this->getField('name', true),
|
'n' => $this->getField('name', true),
|
||||||
't' => TYPE_SPELL,
|
't' => Type::SPELL,
|
||||||
'ti' => $this->id,
|
'ti' => $this->id,
|
||||||
's' => empty($this->curTpl['skillLines']) ? 0 : $this->curTpl['skillLines'][0],
|
's' => empty($this->curTpl['skillLines']) ? 0 : $this->curTpl['skillLines'][0],
|
||||||
'c' => $this->curTpl['typeCat'],
|
'c' => $this->curTpl['typeCat'],
|
||||||
@@ -2347,9 +2351,11 @@ class SpellList extends BaseType
|
|||||||
|
|
||||||
class SpellListFilter extends Filter
|
class SpellListFilter extends Filter
|
||||||
{
|
{
|
||||||
// sources in filter and general use different indizes
|
const MAX_SPELL_EFFECT = 167;
|
||||||
private $enums = array(
|
const MAX_SPELL_AURA = 316;
|
||||||
9 => array(
|
|
||||||
|
protected $enums = array(
|
||||||
|
9 => array( // sources index
|
||||||
1 => true, // Any
|
1 => true, // Any
|
||||||
2 => false, // None
|
2 => false, // None
|
||||||
3 => 1, // Crafted
|
3 => 1, // Crafted
|
||||||
@@ -2359,36 +2365,147 @@ class SpellListFilter extends Filter
|
|||||||
8 => 6, // Trainer
|
8 => 6, // Trainer
|
||||||
9 => 7, // Discovery
|
9 => 7, // Discovery
|
||||||
10 => 9 // Talent
|
10 => 9 // Talent
|
||||||
|
),
|
||||||
|
40 => array( // damage class index
|
||||||
|
1 => 0, // none
|
||||||
|
2 => 1, // magic
|
||||||
|
3 => 2, // melee
|
||||||
|
4 => 3 // ranged
|
||||||
|
),
|
||||||
|
45 => array( // power type index
|
||||||
|
// 1 => ??, // burning embers
|
||||||
|
// 2 => ??, // chi
|
||||||
|
// 3 => ??, // demonic fury
|
||||||
|
4 => POWER_ENERGY, // energy
|
||||||
|
5 => POWER_FOCUS, // focus
|
||||||
|
6 => POWER_HEALTH, // health
|
||||||
|
// 7 => ??, // holy power
|
||||||
|
8 => POWER_MANA, // mana
|
||||||
|
9 => POWER_RAGE, // rage
|
||||||
|
10 => POWER_RUNE, // runes
|
||||||
|
11 => POWER_RUNIC_POWER, // runic power
|
||||||
|
// 12 => ??, // shadow orbs
|
||||||
|
// 13 => ??, // soul shard
|
||||||
|
14 => POWER_HAPPINESS, // happiness v custom v
|
||||||
|
15 => -1, // ammo
|
||||||
|
16 => -41, // pyrite
|
||||||
|
17 => -61, // steam pressure
|
||||||
|
18 => -101, // heat
|
||||||
|
19 => -121, // ooze
|
||||||
|
20 => -141, // blood power
|
||||||
|
21 => -142 // wrath
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// cr => [type, field, misc, extraCol]
|
// cr => [type, field, misc, extraCol]
|
||||||
protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet
|
protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet
|
||||||
1 => [FILTER_CR_CALLBACK, 'cbCost', null, null], // costAbs [op] [int]
|
1 => [FILTER_CR_CALLBACK, 'cbCost', ], // costAbs [op] [int]
|
||||||
2 => [FILTER_CR_NUMERIC, 'powerCostPercent', NUM_CAST_INT ], // prcntbasemanarequired
|
2 => [FILTER_CR_NUMERIC, 'powerCostPercent', NUM_CAST_INT ], // prcntbasemanarequired
|
||||||
3 => [FILTER_CR_BOOLEAN, 'spellFocusObject' ], // requiresnearbyobject
|
3 => [FILTER_CR_BOOLEAN, 'spellFocusObject' ], // requiresnearbyobject
|
||||||
4 => [FILTER_CR_NUMERIC, 'trainingcost', NUM_CAST_INT ], // trainingcost
|
4 => [FILTER_CR_NUMERIC, 'trainingcost', NUM_CAST_INT ], // trainingcost
|
||||||
5 => [FILTER_CR_BOOLEAN, 'reqSpellId' ], // requiresprofspec
|
5 => [FILTER_CR_BOOLEAN, 'reqSpellId' ], // requiresprofspec
|
||||||
8 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
8 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
||||||
9 => [FILTER_CR_CALLBACK, 'cbSource', null, null], // source [enum]
|
9 => [FILTER_CR_CALLBACK, 'cbSource', ], // source [enum]
|
||||||
10 => [FILTER_CR_FLAG, 'cuFlags', SPELL_CU_FIRST_RANK ], // firstrank
|
10 => [FILTER_CR_FLAG, 'cuFlags', SPELL_CU_FIRST_RANK ], // firstrank
|
||||||
11 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
11 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
|
||||||
12 => [FILTER_CR_FLAG, 'cuFlags', SPELL_CU_LAST_RANK ], // lastrank
|
12 => [FILTER_CR_FLAG, 'cuFlags', SPELL_CU_LAST_RANK ], // lastrank
|
||||||
13 => [FILTER_CR_NUMERIC, 'rankNo', NUM_CAST_INT ], // rankno
|
13 => [FILTER_CR_NUMERIC, 'rankNo', NUM_CAST_INT ], // rankno
|
||||||
14 => [FILTER_CR_NUMERIC, 'id', NUM_CAST_INT, true], // id
|
14 => [FILTER_CR_NUMERIC, 'id', NUM_CAST_INT, true ], // id
|
||||||
15 => [FILTER_CR_STRING, 'ic.name', ], // icon
|
15 => [FILTER_CR_STRING, 'ic.name', ], // icon
|
||||||
17 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
17 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
|
||||||
19 => [FILTER_CR_FLAG, 'attributes0', 0x80000 ], // scaling
|
19 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION ], // scaling
|
||||||
20 => [FILTER_CR_CALLBACK, 'cbReagents', null, null], // has Reagents [yn]
|
20 => [FILTER_CR_CALLBACK, 'cbReagents', ], // has Reagents [yn]
|
||||||
25 => [FILTER_CR_BOOLEAN, 'skillLevelYellow' ] // rewardsskillups
|
// 22 => [FILTER_CR_NYI_PH, null, null, null ], // proficiencytype [proficiencytype] pointless
|
||||||
|
25 => [FILTER_CR_BOOLEAN, 'skillLevelYellow' ], // rewardsskillups
|
||||||
|
27 => [FILTER_CR_FLAG, 'attributes1', SPELL_ATTR1_CHANNELED_1, true ], // channeled [yn]
|
||||||
|
28 => [FILTER_CR_NUMERIC, 'castTime', NUM_CAST_FLOAT ], // casttime [num]
|
||||||
|
29 => [FILTER_CR_CALLBACK, 'cbAuraNames', ], // appliesaura [effectauranames]
|
||||||
|
// 31 => [FILTER_CR_NYI_PH, null, null, null ], // usablewhenshapeshifted [yn] pointless
|
||||||
|
33 => [FILTER_CR_CALLBACK, 'cbInverseFlag', 'attributes0', SPELL_ATTR0_CANT_USED_IN_COMBAT], // combatcastable [yn]
|
||||||
|
34 => [FILTER_CR_CALLBACK, 'cbInverseFlag', 'attributes2', SPELL_ATTR2_CANT_CRIT ], // chancetocrit [yn]
|
||||||
|
35 => [FILTER_CR_CALLBACK, 'cbInverseFlag', 'attributes3', SPELL_ATTR3_IGNORE_HIT_RESULT ], // chancetomiss [yn]
|
||||||
|
36 => [FILTER_CR_FLAG, 'attributes3', SPELL_ATTR3_DEATH_PERSISTENT ], // persiststhroughdeath [yn]
|
||||||
|
38 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_ONLY_STEALTHED ], // requiresstealth [yn]
|
||||||
|
39 => [FILTER_CR_CALLBACK, 'cbSpellstealable', 'attributes4', SPELL_ATTR4_NOT_STEALABLE ], // spellstealable [yn]
|
||||||
|
40 => [FILTER_CR_ENUM, 'damageClass' ], // damagetype [damagetype]
|
||||||
|
41 => [FILTER_CR_FLAG, 'stanceMask', (1 << (22 - 1)) ], // requiresmetamorphosis [yn]
|
||||||
|
42 => [FILTER_CR_FLAG, 'attributes5', SPELL_ATTR5_USABLE_WHILE_STUNNED ], // usablewhenstunned [yn]
|
||||||
|
44 => [FILTER_CR_CALLBACK, 'cbUsableInArena' ], // usableinarenas [yn]
|
||||||
|
45 => [FILTER_CR_ENUM, 'powerType' ], // resourcetype [resourcetype]
|
||||||
|
// 46 => [FILTER_CR_NYI_PH, null, null, null ], // disregardimmunity [yn]
|
||||||
|
47 => [FILTER_CR_FLAG, 'attributes1', SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE ], // disregardschoolimmunity [yn]
|
||||||
|
48 => [FILTER_CR_CALLBACK, 'cbEquippedWeapon', 0x0004000C, false ], // reqrangedweapon [yn]
|
||||||
|
49 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_ON_NEXT_SWING ], // onnextswingplayers [yn]
|
||||||
|
50 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_PASSIVE ], // passivespell [yn]
|
||||||
|
51 => [FILTER_CR_FLAG, 'attributes1', SPELL_ATTR1_DONT_DISPLAY_IN_AURA_BAR ], // hiddenaura [yn]
|
||||||
|
52 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_ON_NEXT_SWING_2 ], // onnextswingnpcs [yn]
|
||||||
|
53 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_DAYTIME_ONLY ], // daytimeonly [yn]
|
||||||
|
54 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_NIGHT_ONLY ], // nighttimeonly [yn]
|
||||||
|
55 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_INDOORS_ONLY ], // indoorsonly [yn]
|
||||||
|
56 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_OUTDOORS_ONLY ], // outdoorsonly [yn]
|
||||||
|
57 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_CANT_CANCEL ], // uncancellableaura [yn]
|
||||||
|
58 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION ], // damagedependsonlevel [yn]
|
||||||
|
59 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_STOP_ATTACK_TARGET ], // stopsautoattack [yn]
|
||||||
|
60 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK ], // cannotavoid [yn]
|
||||||
|
61 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_CASTABLE_WHILE_DEAD ], // usabledead [yn]
|
||||||
|
62 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_CASTABLE_WHILE_MOUNTED ], // usablemounted [yn]
|
||||||
|
63 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_DISABLED_WHILE_ACTIVE ], // delayedrecoverystarttime [yn]
|
||||||
|
64 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_CASTABLE_WHILE_SITTING ], // usablesitting [yn]
|
||||||
|
65 => [FILTER_CR_FLAG, 'attributes1', SPELL_ATTR1_DRAIN_ALL_POWER ], // usesallpower [yn]
|
||||||
|
66 => [FILTER_CR_FLAG, 'attributes1', SPELL_ATTR1_CHANNELED_2, true ], // channeled [yn]
|
||||||
|
67 => [FILTER_CR_FLAG, 'attributes1', SPELL_ATTR1_CANT_BE_REFLECTED ], // cannotreflect [yn]
|
||||||
|
68 => [FILTER_CR_FLAG, 'attributes1', SPELL_ATTR1_NOT_BREAK_STEALTH ], // usablestealthed [yn]
|
||||||
|
69 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_NEGATIVE_1 ], // harmful [yn]
|
||||||
|
70 => [FILTER_CR_FLAG, 'attributes1', SPELL_ATTR1_CANT_TARGET_IN_COMBAT ], // targetnotincombat [yn]
|
||||||
|
71 => [FILTER_CR_FLAG, 'attributes1', SPELL_ATTR1_NO_THREAT ], // nothreat [yn]
|
||||||
|
72 => [FILTER_CR_FLAG, 'attributes1', SPELL_ATTR1_IS_PICKPOCKET ], // pickpocket [yn]
|
||||||
|
73 => [FILTER_CR_FLAG, 'attributes1', SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY ], // dispelauraonimmunity [yn]
|
||||||
|
74 => [FILTER_CR_CALLBACK, 'cbEquippedWeapon', 0x00100000, false ], // reqfishingpole [yn]
|
||||||
|
75 => [FILTER_CR_FLAG, 'attributes2', SPELL_ATTR2_CANT_TARGET_TAPPED ], // requntappedtarget [yn]
|
||||||
|
// 76 => [FILTER_CR_NYI_PH, null, null, null ], // targetownitem [yn] // the flag for this has to be somewhere....
|
||||||
|
77 => [FILTER_CR_FLAG, 'attributes2', SPELL_ATTR2_NOT_NEED_SHAPESHIFT ], // doesntreqshapeshift [yn]
|
||||||
|
78 => [FILTER_CR_FLAG, 'attributes2', SPELL_ATTR2_FOOD_BUFF ], // foodbuff [yn]
|
||||||
|
79 => [FILTER_CR_FLAG, 'attributes3', SPELL_ATTR3_ONLY_TARGET_PLAYERS ], // targetonlyplayer [yn]
|
||||||
|
80 => [FILTER_CR_CALLBACK, 'cbEquippedWeapon', 1 << INVTYPE_WEAPONMAINHAND, true ], // reqmainhand [yn]
|
||||||
|
81 => [FILTER_CR_FLAG, 'attributes3', SPELL_ATTR3_NO_INITIAL_AGGRO ], // doesntengagetarget [yn]
|
||||||
|
82 => [FILTER_CR_CALLBACK, 'cbEquippedWeapon', 0x00080000, false ], // reqwand [yn]
|
||||||
|
83 => [FILTER_CR_CALLBACK, 'cbEquippedWeapon', 1 << INVTYPE_WEAPONOFFHAND, true ], // reqoffhand [yn]
|
||||||
|
84 => [FILTER_CR_FLAG, 'attributes0', SPELL_ATTR0_HIDE_IN_COMBAT_LOG ], // nolog [yn]
|
||||||
|
85 => [FILTER_CR_FLAG, 'attributes4', SPELL_ATTR4_FADES_WHILE_LOGGED_OUT ], // auratickswhileloggedout [yn]
|
||||||
|
87 => [FILTER_CR_FLAG, 'attributes5', SPELL_ATTR5_START_PERIODIC_AT_APPLY ], // startstickingatapplication [yn]
|
||||||
|
88 => [FILTER_CR_FLAG, 'attributes5', SPELL_ATTR5_USABLE_WHILE_CONFUSED ], // usableconfused [yn]
|
||||||
|
89 => [FILTER_CR_FLAG, 'attributes5', SPELL_ATTR5_USABLE_WHILE_FEARED ], // usablefeared [yn]
|
||||||
|
90 => [FILTER_CR_FLAG, 'attributes6', SPELL_ATTR6_ONLY_IN_ARENA ], // onlyarena [yn]
|
||||||
|
91 => [FILTER_CR_FLAG, 'attributes6', SPELL_ATTR6_NOT_IN_RAID_INSTANCE ], // notinraid [yn]
|
||||||
|
92 => [FILTER_CR_FLAG, 'attributes7', SPELL_ATTR7_REACTIVATE_AT_RESURRECT ], // paladinaura [yn]
|
||||||
|
93 => [FILTER_CR_FLAG, 'attributes7', SPELL_ATTR7_SUMMON_PLAYER_TOTEM ], // totemspell [yn]
|
||||||
|
95 => [FILTER_CR_CALLBACK, 'cbBandageSpell' ], // bandagespell [yn] ...don't ask
|
||||||
|
96 => [FILTER_CR_STAFFFLAG, 'attributes0' ], // flags1 [flags]
|
||||||
|
97 => [FILTER_CR_STAFFFLAG, 'attributes1' ], // flags2 [flags]
|
||||||
|
98 => [FILTER_CR_STAFFFLAG, 'attributes2' ], // flags3 [flags]
|
||||||
|
99 => [FILTER_CR_STAFFFLAG, 'attributes3' ], // flags4 [flags]
|
||||||
|
100 => [FILTER_CR_STAFFFLAG, 'attributes4' ], // flags5 [flags]
|
||||||
|
101 => [FILTER_CR_STAFFFLAG, 'attributes5' ], // flags6 [flags]
|
||||||
|
102 => [FILTER_CR_STAFFFLAG, 'attributes6' ], // flags7 [flags]
|
||||||
|
103 => [FILTER_CR_STAFFFLAG, 'attributes7' ], // flags8 [flags]
|
||||||
|
104 => [FILTER_CR_STAFFFLAG, 'targets' ], // flags9 [flags]
|
||||||
|
105 => [FILTER_CR_STAFFFLAG, 'stanceMaskNot' ], // flags10 [flags]
|
||||||
|
106 => [FILTER_CR_STAFFFLAG, 'spellFamilyFlags1' ], // flags11 [flags]
|
||||||
|
107 => [FILTER_CR_STAFFFLAG, 'spellFamilyFlags2' ], // flags12 [flags]
|
||||||
|
108 => [FILTER_CR_STAFFFLAG, 'spellFamilyFlags3' ], // flags13 [flags]
|
||||||
|
109 => [FILTER_CR_CALLBACK, 'cbEffectNames', ], // effecttype [effecttype]
|
||||||
|
// 110 => [FILTER_CR_NYI_PH, null, null, null ], // scalingap [yn] // unreasonably complex for now
|
||||||
|
// 111 => [FILTER_CR_NYI_PH, null, null, null ], // scalingsp [yn] // unreasonably complex for now
|
||||||
|
114 => [FILTER_CR_CALLBACK, 'cbReqFaction' ], // requiresfaction [side]
|
||||||
|
116 => [FILTER_CR_BOOLEAN, 'startRecoveryTime' ] // onGlobalCooldown [yn]
|
||||||
);
|
);
|
||||||
|
|
||||||
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
// fieldId => [checkType, checkValue[, fieldIsArray]]
|
||||||
protected $inputFields = array(
|
protected $inputFields = array(
|
||||||
'cr' => [FILTER_V_RANGE, [1, 25], true ], // criteria ids
|
'cr' => [FILTER_V_RANGE, [1, 116], true ], // criteria ids
|
||||||
'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 99999]], true ], // criteria operators
|
'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
|
'crv' => [FILTER_V_REGEX, '/[\p{C};:%\\\\]/ui', true ], // criteria values - only printable chars, no delimiters
|
||||||
'na' => [FILTER_V_REGEX, '/[\p{C};]/ui', false], // name / text - only printable chars, no delimiter
|
'na' => [FILTER_V_REGEX, '/[\p{C};%\\\\]/ui', false], // name / text - only printable chars, no delimiter
|
||||||
'ex' => [FILTER_V_EQUAL, 'on', false], // extended name search
|
'ex' => [FILTER_V_EQUAL, 'on', false], // extended name search
|
||||||
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter
|
||||||
'minle' => [FILTER_V_RANGE, [1, 99], false], // spell level min
|
'minle' => [FILTER_V_RANGE, [1, 99], false], // spell level min
|
||||||
@@ -2475,6 +2592,11 @@ class SpellListFilter extends Filter
|
|||||||
return $parts;
|
return $parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getGenericFilter($cr) // access required by SpellDetailPage's SpellAttributes list
|
||||||
|
{
|
||||||
|
return $this->genericFilter[$cr] ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
protected function cbClasses(&$val)
|
protected function cbClasses(&$val)
|
||||||
{
|
{
|
||||||
if (!$this->parentCats || !in_array($this->parentCats[0], [-13, -2, 7]))
|
if (!$this->parentCats || !in_array($this->parentCats[0], [-13, -2, 7]))
|
||||||
@@ -2508,7 +2630,10 @@ class SpellListFilter extends Filter
|
|||||||
if (!Util::checkNumeric($cr[2], NUM_CAST_INT) || !$this->int2Op($cr[1]))
|
if (!Util::checkNumeric($cr[2], NUM_CAST_INT) || !$this->int2Op($cr[1]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return ['OR', ['AND', ['powerType', [1, 6]], ['powerCost', (10 * $cr[2]), $cr[1]]], ['AND', ['powerType', [1, 6], '!'], ['powerCost', $cr[2], $cr[1]]]];
|
return ['OR',
|
||||||
|
['AND', ['powerType', [POWER_RAGE, POWER_RUNIC_POWER]], ['powerCost', (10 * $cr[2]), $cr[1]]],
|
||||||
|
['AND', ['powerType', [POWER_RAGE, POWER_RUNIC_POWER], '!'], ['powerCost', $cr[2], $cr[1]]]
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function cbSource($cr)
|
protected function cbSource($cr)
|
||||||
@@ -2520,9 +2645,9 @@ class SpellListFilter extends Filter
|
|||||||
if (is_int($_)) // specific
|
if (is_int($_)) // specific
|
||||||
return ['src.src'.$_, null, '!'];
|
return ['src.src'.$_, null, '!'];
|
||||||
else if ($_) // any
|
else if ($_) // any
|
||||||
return ['OR', ['src.src1', null, '!'], ['src.src2', null, '!'], ['src.src4', null, '!'], ['src.src5', null, '!'], ['src.src6', null, '!'], ['src.src7', null, '!'], ['src.src9', null, '!']];
|
return ['OR', ['src.src1', null, '!'], ['src.src2', null, '!'], ['src.src4', null, '!'], ['src.src5', null, '!'], ['src.src6', null, '!'], ['src.src7', null, '!'], ['src.src9', null, '!'], ['src.src10', null, '!']];
|
||||||
else if (!$_) // none
|
else if (!$_) // none
|
||||||
return ['AND', ['src.src1', null], ['src.src2', null], ['src.src4', null], ['src.src5', null], ['src.src6', null], ['src.src7', null], ['src.src9', null]];
|
return ['AND', ['src.src1', null], ['src.src2', null], ['src.src4', null], ['src.src5', null], ['src.src6', null], ['src.src7', null], ['src.src9', null], ['src.src10', null]];
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2537,6 +2662,104 @@ class SpellListFilter extends Filter
|
|||||||
else
|
else
|
||||||
return ['AND', ['reagent1', 0], ['reagent2', 0], ['reagent3', 0], ['reagent4', 0], ['reagent5', 0], ['reagent6', 0], ['reagent7', 0], ['reagent8', 0]];
|
return ['AND', ['reagent1', 0], ['reagent2', 0], ['reagent3', 0], ['reagent4', 0], ['reagent5', 0], ['reagent6', 0], ['reagent7', 0], ['reagent8', 0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function cbAuraNames($cr)
|
||||||
|
{
|
||||||
|
if (!Util::checkNumeric($cr[1], NUM_CAST_INT) || $cr[1] <= 0 || $cr[1] > self::MAX_SPELL_AURA)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ['OR', ['effect1AuraId', $cr[1]], ['effect2AuraId', $cr[1]], ['effect3AuraId', $cr[1]]];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cbEffectNames($cr)
|
||||||
|
{
|
||||||
|
if (!Util::checkNumeric($cr[1], NUM_CAST_INT) || $cr[1] <= 0 || $cr[1] > self::MAX_SPELL_EFFECT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ['OR', ['effect1Id', $cr[1]], ['effect2Id', $cr[1]], ['effect3Id', $cr[1]]];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cbInverseFlag($cr, $field, $flag)
|
||||||
|
{
|
||||||
|
if (!$this->int2Bool($cr[1]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ($cr[1])
|
||||||
|
return [[$field, $flag, '&'], 0];
|
||||||
|
else
|
||||||
|
return [$field, $flag, '&'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cbSpellstealable($cr, $field, $flag)
|
||||||
|
{
|
||||||
|
if (!$this->int2Bool($cr[1]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ($cr[1])
|
||||||
|
return ['AND', [[$field, $flag, '&'], 0], ['dispelType', 1]];
|
||||||
|
else
|
||||||
|
return ['OR', [$field, $flag, '&'], ['dispelType', 1, '!']];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cbReqFaction($cr)
|
||||||
|
{
|
||||||
|
switch ($cr[1])
|
||||||
|
{
|
||||||
|
case 1: // yes
|
||||||
|
return ['reqRaceMask', 0, '!'];
|
||||||
|
case 2: // alliance
|
||||||
|
return ['AND', [['reqRaceMask', RACE_MASK_HORDE, '&'], 0], ['reqRaceMask', RACE_MASK_ALLIANCE, '&']];
|
||||||
|
case 3: // horde
|
||||||
|
return ['AND', [['reqRaceMask', RACE_MASK_ALLIANCE, '&'], 0], ['reqRaceMask', RACE_MASK_HORDE, '&']];
|
||||||
|
case 4: // both
|
||||||
|
return ['AND', ['reqRaceMask', RACE_MASK_ALLIANCE, '&'], ['reqRaceMask', RACE_MASK_HORDE, '&']];
|
||||||
|
case 5: // no
|
||||||
|
return ['reqRaceMask', 0];
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cbEquippedWeapon($cr, $mask, $useInvType)
|
||||||
|
{
|
||||||
|
if (!$this->int2Bool($cr[1]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$field = $useInvType ? 'equippedItemInventoryTypeMask' : 'equippedItemSubClassMask';
|
||||||
|
|
||||||
|
if ($cr[1])
|
||||||
|
return ['AND', ['equippedItemClass', ITEM_CLASS_WEAPON], [$field, $mask, '&']];
|
||||||
|
else
|
||||||
|
return ['OR', ['equippedItemClass', ITEM_CLASS_WEAPON, '!'], [[$field, $mask, '&'], 0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cbUsableInArena($cr)
|
||||||
|
{
|
||||||
|
if (!$this->int2Bool($cr[1]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ($cr[1])
|
||||||
|
return ['AND',
|
||||||
|
[['attributes4', SPELL_ATTR4_NOT_USABLE_IN_ARENA, '&'], 0],
|
||||||
|
['OR', ['recoveryTime', 10 * MINUTE * 1000, '<='], ['attributes4', SPELL_ATTR4_USABLE_IN_ARENA, '&']]
|
||||||
|
];
|
||||||
|
else
|
||||||
|
return ['OR',
|
||||||
|
['attributes4', SPELL_ATTR4_NOT_USABLE_IN_ARENA, '&'],
|
||||||
|
['AND', ['recoveryTime', 10 * MINUTE * 1000, '>'], [['attributes4', SPELL_ATTR4_USABLE_IN_ARENA, '&'], 0]]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cbBandageSpell($cr)
|
||||||
|
{
|
||||||
|
if (!$this->int2Bool($cr[1]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ($cr[1]) // match exact, not as flag
|
||||||
|
return ['AND', ['attributes1', SPELL_ATTR1_CHANNELED_1 | SPELL_ATTR1_CHANNELED_2 | SPELL_ATTR1_CHANNEL_TRACK_TARGET], ['effect1ImplicitTargetA', 21]];
|
||||||
|
else
|
||||||
|
return ['OR', ['attributes1', SPELL_ATTR1_CHANNELED_1 | SPELL_ATTR1_CHANNELED_2 | SPELL_ATTR1_CHANNEL_TRACK_TARGET, '!'], ['effect1ImplicitTargetA', 21, '!']];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class TitleList extends BaseType
|
|||||||
{
|
{
|
||||||
use listviewHelper;
|
use listviewHelper;
|
||||||
|
|
||||||
public static $type = TYPE_TITLE;
|
public static $type = Type::TITLE;
|
||||||
public static $brickFile = 'title';
|
public static $brickFile = 'title';
|
||||||
public static $dataTable = '?_titles';
|
public static $dataTable = '?_titles';
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ class TitleList extends BaseType
|
|||||||
|
|
||||||
protected $queryBase = 'SELECT t.*, id AS ARRAY_KEY FROM ?_titles t';
|
protected $queryBase = 'SELECT t.*, id AS ARRAY_KEY FROM ?_titles t';
|
||||||
protected $queryOpts = array(
|
protected $queryOpts = array(
|
||||||
't' => [['src']], // 11: TYPE_TITLE
|
't' => [['src']], // 11: Type::TITLE
|
||||||
'src' => ['j' => ['?_source src ON type = 11 AND typeId = t.id', true], 's' => ', src13, moreType, moreTypeId']
|
'src' => ['j' => ['?_source src ON type = 11 AND typeId = t.id', true], 's' => ', src13, moreType, moreTypeId']
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -28,9 +28,9 @@ class TitleList extends BaseType
|
|||||||
foreach ($this->iterate() as $id => &$_curTpl)
|
foreach ($this->iterate() as $id => &$_curTpl)
|
||||||
{
|
{
|
||||||
// preparse sources - notice: under this system titles can't have more than one source (or two for achivements), which is enough for standard TC cases but may break custom cases
|
// preparse sources - notice: under this system titles can't have more than one source (or two for achivements), which is enough for standard TC cases but may break custom cases
|
||||||
if ($_curTpl['moreType'] == TYPE_ACHIEVEMENT)
|
if ($_curTpl['moreType'] == Type::ACHIEVEMENT)
|
||||||
$this->sources[$this->id][12][] = $_curTpl['moreTypeId'];
|
$this->sources[$this->id][12][] = $_curTpl['moreTypeId'];
|
||||||
else if ($_curTpl['moreType'] == TYPE_QUEST)
|
else if ($_curTpl['moreType'] == Type::QUEST)
|
||||||
$this->sources[$this->id][4][] = $_curTpl['moreTypeId'];
|
$this->sources[$this->id][4][] = $_curTpl['moreTypeId'];
|
||||||
else if ($_curTpl['src13'])
|
else if ($_curTpl['src13'])
|
||||||
$this->sources[$this->id][13][] = $_curTpl['src13'];
|
$this->sources[$this->id][13][] = $_curTpl['src13'];
|
||||||
@@ -81,10 +81,10 @@ class TitleList extends BaseType
|
|||||||
|
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
{
|
{
|
||||||
$data[TYPE_TITLE][$this->id]['name'] = $this->getField('male', true);
|
$data[Type::TITLE][$this->id]['name'] = $this->getField('male', true);
|
||||||
|
|
||||||
if ($_ = $this->getField('female', true))
|
if ($_ = $this->getField('female', true))
|
||||||
$data[TYPE_TITLE][$this->id]['namefemale'] = $_;
|
$data[Type::TITLE][$this->id]['namefemale'] = $_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
@@ -115,9 +115,6 @@ class TitleList extends BaseType
|
|||||||
if (!empty($sources[12]))
|
if (!empty($sources[12]))
|
||||||
$sources[12] = (new AchievementList(array(['id', $sources[12]])))->getSourceData();
|
$sources[12] = (new AchievementList(array(['id', $sources[12]])))->getSourceData();
|
||||||
|
|
||||||
if (!empty($sources[13]))
|
|
||||||
$sources[13] = DB::Aowow()->SELECT('SELECT *, Id AS ARRAY_KEY FROM ?_sourcestrings WHERE Id IN (?a)', $sources[13]);
|
|
||||||
|
|
||||||
foreach ($this->sources as $Id => $src)
|
foreach ($this->sources as $Id => $src)
|
||||||
{
|
{
|
||||||
$tmp = [];
|
$tmp = [];
|
||||||
@@ -148,7 +145,7 @@ class TitleList extends BaseType
|
|||||||
|
|
||||||
// other source (only one item possible, so no iteration needed)
|
// other source (only one item possible, so no iteration needed)
|
||||||
if (isset($src[13]))
|
if (isset($src[13]))
|
||||||
$tmp[13] = [Util::localizedString($sources[13][$this->sources[$Id][13][0]], 'source')];
|
$tmp[13] = [Lang::game('pvpSources', $this->sources[$Id][13][0])];
|
||||||
|
|
||||||
$this->templates[$Id]['source'] = $tmp;
|
$this->templates[$Id]['source'] = $tmp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class UserList extends BaseType
|
class UserList extends BaseType
|
||||||
{
|
{
|
||||||
public static $type = TYPE_USER;
|
public static $type = Type::USER;
|
||||||
public static $brickFile = 'user';
|
public static $brickFile = 'user';
|
||||||
public static $dataTable = ''; // doesn't have community content
|
public static $dataTable = ''; // doesn't have community content
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ class UserList extends BaseType
|
|||||||
// border: seen as null|1|3 .. changes the border around the avatar (i suspect its meaning changed and got decupled from premium-status with the introduction of patron-status)
|
// border: seen as null|1|3 .. changes the border around the avatar (i suspect its meaning changed and got decupled from premium-status with the introduction of patron-status)
|
||||||
}
|
}
|
||||||
|
|
||||||
return [TYPE_USER => $data];
|
return [Type::USER => $data];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderTooltip() { }
|
public function renderTooltip() { }
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class WorldEventList extends BaseType
|
class WorldEventList extends BaseType
|
||||||
{
|
{
|
||||||
public static $type = TYPE_WORLDEVENT;
|
public static $type = Type::WORLDEVENT;
|
||||||
public static $brickFile = 'event';
|
public static $brickFile = 'event';
|
||||||
public static $dataTable = '?_events';
|
public static $dataTable = '?_events';
|
||||||
|
|
||||||
@@ -71,6 +71,7 @@ class WorldEventList extends BaseType
|
|||||||
IFNULL(h.name_loc0, e.description) AS name_loc0,
|
IFNULL(h.name_loc0, e.description) AS name_loc0,
|
||||||
h.name_loc2,
|
h.name_loc2,
|
||||||
h.name_loc3,
|
h.name_loc3,
|
||||||
|
h.name_loc4,
|
||||||
h.name_loc6,
|
h.name_loc6,
|
||||||
h.name_loc8
|
h.name_loc8
|
||||||
FROM
|
FROM
|
||||||
@@ -161,7 +162,7 @@ class WorldEventList extends BaseType
|
|||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
$data[TYPE_WORLDEVENT][$this->id] = ['name' => $this->getField('name', true), 'icon' => $this->curTpl['iconString']];
|
$data[Type::WORLDEVENT][$this->id] = ['name' => $this->getField('name', true), 'icon' => $this->curTpl['iconString']];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
@@ -174,7 +175,7 @@ class WorldEventList extends BaseType
|
|||||||
$x = '<table><tr><td>';
|
$x = '<table><tr><td>';
|
||||||
|
|
||||||
// head v that extra % is nesecary because we are using sprintf later on
|
// 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>';
|
$x .= '<table width="100%%"><tr><td><b>'.$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
|
// use string-placeholder for dates
|
||||||
// start
|
// start
|
||||||
@@ -187,7 +188,7 @@ class WorldEventList extends BaseType
|
|||||||
// desc
|
// desc
|
||||||
if ($this->getField('holidayId'))
|
if ($this->getField('holidayId'))
|
||||||
if ($_ = $this->getField('description', true))
|
if ($_ = $this->getField('description', true))
|
||||||
$x .= '<table><tr><td><span class="q">'.Util::jsEscape($_).'</span></td></tr></table>';
|
$x .= '<table><tr><td><span class="q">'.$_.'</span></td></tr></table>';
|
||||||
|
|
||||||
return $x;
|
return $x;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ class ZoneList extends BaseType
|
|||||||
{
|
{
|
||||||
use listviewHelper;
|
use listviewHelper;
|
||||||
|
|
||||||
public static $type = TYPE_ZONE;
|
public static $type = Type::ZONE;
|
||||||
public static $brickFile = 'zone';
|
public static $brickFile = 'zone';
|
||||||
public static $dataTable = '?_zones';
|
public static $dataTable = '?_zones';
|
||||||
|
|
||||||
protected $queryBase = 'SELECT *, id AS ARRAY_KEY FROM ?_zones z';
|
protected $queryBase = 'SELECT z.*, id AS ARRAY_KEY FROM ?_zones z';
|
||||||
|
|
||||||
public function __construct($conditions = [], $miscData = null)
|
public function __construct($conditions = [], $miscData = null)
|
||||||
{
|
{
|
||||||
@@ -54,7 +54,7 @@ class ZoneList extends BaseType
|
|||||||
// use if you JUST need the name
|
// use if you JUST need the name
|
||||||
public static function getName($id)
|
public static function getName($id)
|
||||||
{
|
{
|
||||||
$n = DB::Aowow()->selectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM ?_zones WHERE id = ?d', $id );
|
$n = DB::Aowow()->selectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 FROM ?_zones WHERE id = ?d', $id );
|
||||||
return Util::localizedString($n, 'name');
|
return Util::localizedString($n, 'name');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ class ZoneList extends BaseType
|
|||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
foreach ($this->iterate() as $__)
|
foreach ($this->iterate() as $__)
|
||||||
$data[TYPE_ZONE][$this->id] = ['name' => $this->getField('name', true)];
|
$data[Type::ZONE][$this->id] = ['name' => $this->getField('name', true)];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,10 +183,11 @@ class User
|
|||||||
{
|
{
|
||||||
$loc = strtolower(substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2));
|
$loc = strtolower(substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2));
|
||||||
switch ($loc) {
|
switch ($loc) {
|
||||||
case 'ru': $loc = LOCALE_RU; break;
|
|
||||||
case 'es': $loc = LOCALE_ES; break;
|
|
||||||
case 'de': $loc = LOCALE_DE; break;
|
|
||||||
case 'fr': $loc = LOCALE_FR; break;
|
case 'fr': $loc = LOCALE_FR; break;
|
||||||
|
case 'de': $loc = LOCALE_DE; break;
|
||||||
|
case 'zh': $loc = LOCALE_CN; break; // may cause issues in future with zh-tw
|
||||||
|
case 'es': $loc = LOCALE_ES; break;
|
||||||
|
case 'ru': $loc = LOCALE_RU; break;
|
||||||
default: $loc = LOCALE_EN;
|
default: $loc = LOCALE_EN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,12 +283,11 @@ class User
|
|||||||
if (!DB::isConnectable(DB_AUTH))
|
if (!DB::isConnectable(DB_AUTH))
|
||||||
return AUTH_INTERNAL_ERR;
|
return AUTH_INTERNAL_ERR;
|
||||||
|
|
||||||
$wow = DB::Auth()->selectRow('SELECT a.id, a.sha_pass_hash, ab.active AS hasBan FROM account a LEFT JOIN account_banned ab ON ab.id = a.id AND active <> 0 WHERE username = ? LIMIT 1', $name);
|
$wow = DB::Auth()->selectRow('SELECT a.id, a.salt, a.verifier, ab.active AS hasBan FROM account a LEFT JOIN account_banned ab ON ab.id = a.id AND active <> 0 WHERE username = ? LIMIT 1', $name);
|
||||||
if (!$wow)
|
if (!$wow)
|
||||||
return AUTH_WRONGUSER;
|
return AUTH_WRONGUSER;
|
||||||
|
|
||||||
self::$passHash = $wow['sha_pass_hash'];
|
if (!self::verifySRP6($name, $pass, $wow['salt'], $wow['verifier']))
|
||||||
if (!self::verifySHA1($name, $pass))
|
|
||||||
return AUTH_WRONGPASS;
|
return AUTH_WRONGPASS;
|
||||||
|
|
||||||
if ($wow['hasBan'])
|
if ($wow['hasBan'])
|
||||||
@@ -386,15 +386,17 @@ class User
|
|||||||
return $_ === crypt($pass, $_);
|
return $_ === crypt($pass, $_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sha1 used by TC / MaNGOS
|
private static function verifySRP6($user, $pass, $salt, $verifier)
|
||||||
private static function hashSHA1($name, $pass)
|
|
||||||
{
|
{
|
||||||
return sha1(strtoupper($name).':'.strtoupper($pass));
|
$g = gmp_init(7);
|
||||||
}
|
$N = gmp_init('894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7', 16);
|
||||||
|
$x = gmp_import(
|
||||||
private static function verifySHA1($name, $pass)
|
sha1($salt . sha1(strtoupper($user . ':' . $pass), TRUE), TRUE),
|
||||||
{
|
1,
|
||||||
return strtoupper(self::$passHash) === strtoupper(self::hashSHA1($name, $pass));
|
GMP_LSW_FIRST
|
||||||
|
);
|
||||||
|
$v = gmp_powm($g, $x, $N);
|
||||||
|
return ($verifier === str_pad(gmp_export($v, 1, GMP_LSW_FIRST), 32, chr(0), STR_PAD_RIGHT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isValidName($name, &$errCode = 0)
|
public static function isValidName($name, &$errCode = 0)
|
||||||
@@ -516,6 +518,14 @@ class User
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function canWriteGuide()
|
||||||
|
{
|
||||||
|
if (!self::$id || self::$banStatus & (ACC_BAN_GUIDE | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static function canSuggestVideo()
|
public static function canSuggestVideo()
|
||||||
{
|
{
|
||||||
if (!self::$id || self::$banStatus & (ACC_BAN_VIDEO | ACC_BAN_PERM | ACC_BAN_TEMP))
|
if (!self::$id || self::$banStatus & (ACC_BAN_VIDEO | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||||
@@ -587,6 +597,9 @@ class User
|
|||||||
if ($_ = self::getProfiles())
|
if ($_ = self::getProfiles())
|
||||||
$gUser['profiles'] = $_;
|
$gUser['profiles'] = $_;
|
||||||
|
|
||||||
|
if ($_ = self::getGuides())
|
||||||
|
$gUser['guides'] = $_;
|
||||||
|
|
||||||
if ($_ = self::getWeightScales())
|
if ($_ = self::getWeightScales())
|
||||||
$gUser['weightscales'] = $_;
|
$gUser['weightscales'] = $_;
|
||||||
|
|
||||||
@@ -639,6 +652,20 @@ class User
|
|||||||
return self::$profiles->getJSGlobals(PROFILEINFO_PROFILE);
|
return self::$profiles->getJSGlobals(PROFILEINFO_PROFILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getGuides()
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
if ($guides = DB::Aowow()->select('SELECT `id`, `title`, `url` FROM ?_guides WHERE `userId` = ?d AND `status` <> ?d', self::$id, GUIDE_STATUS_ARCHIVED))
|
||||||
|
{
|
||||||
|
// fix url
|
||||||
|
array_walk($guides, fn(&$x) => $x['url'] = '/?guide='.($x['url'] ?? $x['id']));
|
||||||
|
$result = $guides;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
public static function getCookies()
|
public static function getCookies()
|
||||||
{
|
{
|
||||||
$data = [];
|
$data = [];
|
||||||
@@ -648,6 +675,33 @@ class User
|
|||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getFavorites()
|
||||||
|
{
|
||||||
|
if (!self::$id)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
$res = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, `typeId` AS ARRAY_KEY2, `typeId` FROM ?_account_favorites WHERE `userId` = ?d', self::$id);
|
||||||
|
if (!$res)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
foreach ($res as $type => $ids)
|
||||||
|
{
|
||||||
|
$tc = Type::newList($type, [['id', array_values($ids)]]);
|
||||||
|
if (!$tc || $tc->error)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$entities = [];
|
||||||
|
foreach ($tc->iterate() as $id => $__)
|
||||||
|
$entities[] = [$id, $tc->getField('name', true, true)];
|
||||||
|
|
||||||
|
if ($entities)
|
||||||
|
$data[] = ['id' => $type, 'entities' => $entities];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
25
index.php
25
index.php
@@ -22,6 +22,8 @@ switch ($pageCall)
|
|||||||
case 'account': // account management [nyi]
|
case 'account': // account management [nyi]
|
||||||
case 'achievement':
|
case 'achievement':
|
||||||
case 'achievements':
|
case 'achievements':
|
||||||
|
case 'areatrigger':
|
||||||
|
case 'areatriggers':
|
||||||
case 'arena-team':
|
case 'arena-team':
|
||||||
case 'arena-teams':
|
case 'arena-teams':
|
||||||
case 'class':
|
case 'class':
|
||||||
@@ -37,6 +39,8 @@ switch ($pageCall)
|
|||||||
case 'events':
|
case 'events':
|
||||||
case 'faction':
|
case 'faction':
|
||||||
case 'factions':
|
case 'factions':
|
||||||
|
case 'guide':
|
||||||
|
case 'guides':
|
||||||
case 'guild':
|
case 'guild':
|
||||||
case 'guilds':
|
case 'guilds':
|
||||||
case 'icon':
|
case 'icon':
|
||||||
@@ -46,6 +50,11 @@ switch ($pageCall)
|
|||||||
case 'itemset':
|
case 'itemset':
|
||||||
case 'itemsets':
|
case 'itemsets':
|
||||||
case 'maps': // tool: map listing
|
case 'maps': // tool: map listing
|
||||||
|
case 'mail':
|
||||||
|
case 'mails':
|
||||||
|
case 'my-guides':
|
||||||
|
if ($pageCall == 'my-guides')
|
||||||
|
$altClass = 'guides';
|
||||||
case 'npc':
|
case 'npc':
|
||||||
case 'npcs':
|
case 'npcs':
|
||||||
case 'object':
|
case 'object':
|
||||||
@@ -82,14 +91,18 @@ switch ($pageCall)
|
|||||||
case 'cookie': // lossless cookies and user settings
|
case 'cookie': // lossless cookies and user settings
|
||||||
case 'contactus':
|
case 'contactus':
|
||||||
case 'comment':
|
case 'comment':
|
||||||
|
case 'edit': // guide editor: targeted by QQ fileuploader, detail-page article editor
|
||||||
|
case 'get-description': // guide editor: shorten fulltext into description
|
||||||
case 'filter': // pre-evaluate filter POST-data; sanitize and forward as GET-data
|
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 'go-to-comment': // find page the comment is on and forward
|
||||||
case 'locale': // subdomain-workaround, change the language
|
case 'locale': // subdomain-workaround, change the language
|
||||||
$cleanName = str_replace(['-', '_'], '', ucFirst($altClass ?: $pageCall));
|
$cleanName = str_replace(['-', '_'], '', ucFirst($altClass ?: $pageCall));
|
||||||
try // can it be handled as ajax?
|
try // can it be handled as ajax?
|
||||||
{
|
{
|
||||||
|
$out = '';
|
||||||
$class = 'Ajax'.$cleanName;
|
$class = 'Ajax'.$cleanName;
|
||||||
$ajax = new $class(explode('.', $pageParam));
|
$ajax = new $class(explode('.', $pageParam));
|
||||||
|
|
||||||
if ($ajax->handle($out))
|
if ($ajax->handle($out))
|
||||||
{
|
{
|
||||||
Util::sendNoCacheHeader();
|
Util::sendNoCacheHeader();
|
||||||
@@ -98,7 +111,7 @@ switch ($pageCall)
|
|||||||
header('Location: '.$out, true, 302);
|
header('Location: '.$out, true, 302);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
header('Content-type: '.$ajax->getContentType());
|
header($ajax->getContentType());
|
||||||
die($out);
|
die($out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,7 +121,14 @@ switch ($pageCall)
|
|||||||
catch (Exception $e) // no, apparently not..
|
catch (Exception $e) // no, apparently not..
|
||||||
{
|
{
|
||||||
$class = $cleanName.'Page';
|
$class = $cleanName.'Page';
|
||||||
(new $class($pageCall, $pageParam))->display();
|
$classInstance = new $class($pageCall, $pageParam);
|
||||||
|
|
||||||
|
if (is_callable([$classInstance, 'display']))
|
||||||
|
$classInstance->display();
|
||||||
|
else if (isset($_GET['power']))
|
||||||
|
die('$WowheadPower.register(0, '.User::$localeId.', {})');
|
||||||
|
else // in conjunction with a proper rewriteRule in .htaccess...
|
||||||
|
(new GenericPage($pageCall))->error();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -127,7 +147,6 @@ switch ($pageCall)
|
|||||||
(new MorePage($pageCall, $pageParam))->display();
|
(new MorePage($pageCall, $pageParam))->display();
|
||||||
break;
|
break;
|
||||||
case 'latest-additions':
|
case 'latest-additions':
|
||||||
case 'latest-articles':
|
|
||||||
case 'latest-comments':
|
case 'latest-comments':
|
||||||
case 'latest-screenshots':
|
case 'latest-screenshots':
|
||||||
case 'latest-videos':
|
case 'latest-videos':
|
||||||
|
|||||||
@@ -6,15 +6,17 @@ class Lang
|
|||||||
private static $main;
|
private static $main;
|
||||||
private static $account;
|
private static $account;
|
||||||
private static $user;
|
private static $user;
|
||||||
private static $mail;
|
|
||||||
private static $game;
|
private static $game;
|
||||||
private static $maps;
|
private static $maps;
|
||||||
private static $profiler;
|
private static $profiler;
|
||||||
private static $screenshot;
|
private static $screenshot;
|
||||||
private static $privileges;
|
private static $privileges;
|
||||||
|
private static $smartAI;
|
||||||
|
private static $unit;
|
||||||
|
|
||||||
// types
|
// types
|
||||||
private static $achievement;
|
private static $achievement;
|
||||||
|
private static $areatrigger;
|
||||||
private static $chrClass;
|
private static $chrClass;
|
||||||
private static $currency;
|
private static $currency;
|
||||||
private static $event;
|
private static $event;
|
||||||
@@ -23,6 +25,7 @@ class Lang
|
|||||||
private static $icon;
|
private static $icon;
|
||||||
private static $item;
|
private static $item;
|
||||||
private static $itemset;
|
private static $itemset;
|
||||||
|
private static $mail;
|
||||||
private static $npc;
|
private static $npc;
|
||||||
private static $pet;
|
private static $pet;
|
||||||
private static $quest;
|
private static $quest;
|
||||||
@@ -32,10 +35,20 @@ class Lang
|
|||||||
private static $spell;
|
private static $spell;
|
||||||
private static $title;
|
private static $title;
|
||||||
private static $zone;
|
private static $zone;
|
||||||
|
private static $guide;
|
||||||
|
|
||||||
private static $emote;
|
private static $emote;
|
||||||
private static $enchantment;
|
private static $enchantment;
|
||||||
|
|
||||||
|
private static $locales = array(
|
||||||
|
LOCALE_EN => 'English',
|
||||||
|
LOCALE_FR => 'Français',
|
||||||
|
LOCALE_DE => 'Deutsch',
|
||||||
|
LOCALE_CN => '简体中文',
|
||||||
|
LOCALE_ES => 'Español',
|
||||||
|
LOCALE_RU => 'Русский'
|
||||||
|
);
|
||||||
|
|
||||||
public static function load($loc)
|
public static function load($loc)
|
||||||
{
|
{
|
||||||
if (!file_exists('localization/locale_'.$loc.'.php'))
|
if (!file_exists('localization/locale_'.$loc.'.php'))
|
||||||
@@ -49,13 +62,6 @@ class Lang
|
|||||||
// *cough* .. reuse-hacks (because copy-pastaing text for 5 locales sucks)
|
// *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] = [self::$item['cat'][2], self::$spell['weaponSubClass']];
|
||||||
self::$item['cat'][2][1][14] .= ' ('.self::$item['cat'][2][0].')';
|
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'];
|
self::$main['moreTitles']['privilege'] = self::$privileges['_privileges'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +69,9 @@ class Lang
|
|||||||
{
|
{
|
||||||
if (!isset(self::$$prop))
|
if (!isset(self::$$prop))
|
||||||
{
|
{
|
||||||
trigger_error('Lang - tried to use undefined property Lang::$'.$prop, E_USER_WARNING);
|
$dbt = debug_backtrace()[0];
|
||||||
|
$file = explode(DIRECTORY_SEPARATOR, $dbt['file']);
|
||||||
|
trigger_error('Lang - tried to use undefined property Lang::$'.$prop.', called in '.array_pop($file).':'.$dbt['line'], E_USER_WARNING);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +87,9 @@ class Lang
|
|||||||
}
|
}
|
||||||
else if (!isset($var[$arg]))
|
else if (!isset($var[$arg]))
|
||||||
{
|
{
|
||||||
trigger_error('Lang - undefined key "'.$arg.'" in property Lang::$'.$prop.'[\''.implode('\'][\'', $args).'\']', E_USER_WARNING);
|
$dbt = debug_backtrace()[0];
|
||||||
|
$file = explode(DIRECTORY_SEPARATOR, $dbt['file']);
|
||||||
|
trigger_error('Lang - undefined property Lang::$'.$prop.'[\''.implode('\'][\'', $args).'\'], called in '.array_pop($file).':'.$dbt['line'], E_USER_WARNING);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +131,66 @@ class Lang
|
|||||||
return $b;
|
return $b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// truncate string after X chars. If X is inside a word truncate behind it.
|
||||||
|
public static function trimTextClean(string $text, int $len = 100) : string
|
||||||
|
{
|
||||||
|
// remove line breaks
|
||||||
|
$text = strtr($text, ["\n" => ' ', "\r" => ' ']);
|
||||||
|
|
||||||
|
// limit whitespaces to one at a time
|
||||||
|
$text = preg_replace('/\s+/', ' ', trim($text));
|
||||||
|
|
||||||
|
if ($len > 0 && mb_strlen($text) > $len)
|
||||||
|
{
|
||||||
|
$n = 0;
|
||||||
|
$b = [];
|
||||||
|
$parts = explode(' ', $text);
|
||||||
|
while ($n < $len && $parts)
|
||||||
|
{
|
||||||
|
$_ = array_shift($parts);
|
||||||
|
$n += mb_strlen($_);
|
||||||
|
$b[] = $_;
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = implode(' ', $b).'…';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add line breaks to string after X chars. If X is inside a word break behind it.
|
||||||
|
public static function breakTextClean(string $text, int $len = 30, bool $asHTML = true) : string
|
||||||
|
{
|
||||||
|
// remove line breaks
|
||||||
|
$text = strtr($text, ["\n" => ' ', "\r" => ' ']);
|
||||||
|
|
||||||
|
// limit whitespaces to one at a time
|
||||||
|
$text = preg_replace('/\s+/', ' ', trim($text));
|
||||||
|
|
||||||
|
$row = [];
|
||||||
|
if ($len > 0 && mb_strlen($text) > $len)
|
||||||
|
{
|
||||||
|
$i = 0;
|
||||||
|
$n = 0;
|
||||||
|
$parts = explode(' ', $text);
|
||||||
|
foreach ($parts as $p)
|
||||||
|
{
|
||||||
|
$row[$i][] = $p;
|
||||||
|
$n += (mb_strlen($p) + 1);
|
||||||
|
|
||||||
|
if ($n < $len)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$n = 0;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
foreach ($row as &$r)
|
||||||
|
$r = implode(' ', $r);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode($asHTML ? '<br />' : '[br]', $row);
|
||||||
|
}
|
||||||
|
|
||||||
public static function sort($prop, $group, $method = SORT_NATURAL)
|
public static function sort($prop, $group, $method = SORT_NATURAL)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -160,9 +230,10 @@ class Lang
|
|||||||
return $tmp;
|
return $tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getLocks($lockId, $interactive = false)
|
public static function getLocks(int $lockId, ?array &$ids = [], bool $interactive = false, bool $asHTML = false) : array
|
||||||
{
|
{
|
||||||
$locks = [];
|
$locks = [];
|
||||||
|
$ids = [];
|
||||||
$lock = DB::Aowow()->selectRow('SELECT * FROM ?_lock WHERE id = ?d', $lockId);
|
$lock = DB::Aowow()->selectRow('SELECT * FROM ?_lock WHERE id = ?d', $lockId);
|
||||||
if (!$lock)
|
if (!$lock)
|
||||||
return $locks;
|
return $locks;
|
||||||
@@ -173,47 +244,71 @@ class Lang
|
|||||||
$rank = $lock['reqSkill'.$i];
|
$rank = $lock['reqSkill'.$i];
|
||||||
$name = '';
|
$name = '';
|
||||||
|
|
||||||
if ($lock['type'.$i] == 1) // opened by item
|
if ($lock['type'.$i] == LOCK_TYPE_ITEM)
|
||||||
{
|
{
|
||||||
$name = ItemList::getName($prop);
|
$name = ItemList::getName($prop);
|
||||||
if (!$name)
|
if (!$name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ($interactive)
|
if ($interactive && $asHTML)
|
||||||
$name = '<a class="q1" href="?item='.$prop.'">'.$name.'</a>';
|
$name = '<a class="q1" href="?item='.$prop.'">'.$name.'</a>';
|
||||||
|
else if ($interactive && !$asHTML)
|
||||||
|
{
|
||||||
|
$name = '[item='.$prop.']';
|
||||||
|
$ids[Type::ITEM][] = $prop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ($lock['type'.$i] == 2) // opened by skill
|
else if ($lock['type'.$i] == LOCK_TYPE_SKILL)
|
||||||
{
|
{
|
||||||
// exclude unusual stuff
|
|
||||||
if (!in_array($prop, [1, 2, 3, 4, 9, 16, 20]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$name = self::spell('lockType', $prop);
|
$name = self::spell('lockType', $prop);
|
||||||
if (!$name)
|
if (!$name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ($interactive)
|
// skills
|
||||||
|
if (in_array($prop, [1, 2, 3, 20]))
|
||||||
{
|
{
|
||||||
$skill = 0;
|
$skills = array(
|
||||||
switch ($prop)
|
1 => SKILL_LOCKPICKING,
|
||||||
|
2 => SKILL_HERBALISM,
|
||||||
|
3 => SKILL_MINING,
|
||||||
|
20 => SKILL_INSCRIPTION
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($interactive && $asHTML)
|
||||||
|
$name = '<a href="?skill='.$skills[$prop].'">'.$name.'</a>';
|
||||||
|
else if ($interactive && !$asHTML)
|
||||||
{
|
{
|
||||||
case 1: $skill = 633; break; // Lockpicking
|
$name = '[skill='.$skills[$prop].']';
|
||||||
case 2: $skill = 182; break; // Herbing
|
$ids[Type::SKILL][] = $skills[$prop];
|
||||||
case 3: $skill = 186; break; // Mining
|
|
||||||
case 20: $skill = 773; break; // Scribing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($skill)
|
if ($rank > 0)
|
||||||
$name = '<a href="?skill='.$skill.'">'.$name.'</a>';
|
$name .= ' ('.$rank.')';
|
||||||
}
|
}
|
||||||
|
// Lockpicking
|
||||||
if ($rank > 0)
|
else if ($prop == 4)
|
||||||
$name .= ' ('.$rank.')';
|
{
|
||||||
|
if ($interactive && $asHTML)
|
||||||
|
$name = '<a href="?spell=1842">'.$name.'</a>';
|
||||||
|
else if ($interactive && !$asHTML)
|
||||||
|
{
|
||||||
|
$name = '[spell=1842]';
|
||||||
|
$ids[Type::SPELL][] = 1842;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// exclude unusual stuff
|
||||||
|
else if (User::isInGroup(U_GROUP_STAFF))
|
||||||
|
{
|
||||||
|
if ($rank > 0)
|
||||||
|
$name .= ' ('.$rank.')';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$locks[$lock['type'.$i] == 1 ? $prop : -$prop] = sprintf(self::game('requires'), $name);
|
$locks[$lock['type'.$i] == LOCK_TYPE_ITEM ? $prop : -$prop] = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $locks;
|
return $locks;
|
||||||
@@ -252,7 +347,7 @@ class Lang
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($class == ITEM_CLASS_MISC) // yeah hardcoded.. sue me!
|
if ($class == ITEM_CLASS_MISC) // yeah hardcoded.. sue me!
|
||||||
return self::spell('cat', -5);
|
return self::spell('cat', -5, 0);
|
||||||
|
|
||||||
$tmp = [];
|
$tmp = [];
|
||||||
$strs = self::spell($class == ITEM_CLASS_ARMOR ? 'armorSubClass' : 'weaponSubClass');
|
$strs = self::spell($class == ITEM_CLASS_ARMOR ? 'armorSubClass' : 'weaponSubClass');
|
||||||
@@ -307,7 +402,7 @@ class Lang
|
|||||||
return implode(', ', $tmp);
|
return implode(', ', $tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getClassString($classMask, &$ids = [], &$n = 0, $asHTML = true)
|
public static function getClassString(int $classMask, array &$ids = [], bool $asHTML = true) : string
|
||||||
{
|
{
|
||||||
$classMask &= CLASS_MASK_ALL; // clamp to available classes..
|
$classMask &= CLASS_MASK_ALL; // clamp to available classes..
|
||||||
|
|
||||||
@@ -329,36 +424,26 @@ class Lang
|
|||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
$n = count($tmp);
|
|
||||||
$ids = array_keys($tmp);
|
$ids = array_keys($tmp);
|
||||||
|
|
||||||
return implode(', ', $tmp);
|
return implode(', ', $tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getRaceString($raceMask, &$side = 0, &$ids = [], &$n = 0, $asHTML = true)
|
public static function getRaceString(int $raceMask, array &$ids = [], bool $asHTML = true) : string
|
||||||
{
|
{
|
||||||
$raceMask &= RACE_MASK_ALL; // clamp to available races..
|
$raceMask &= RACE_MASK_ALL; // clamp to available races..
|
||||||
|
|
||||||
if ($raceMask == RACE_MASK_ALL) // available to all races (we don't display 'both factions')
|
if ($raceMask == RACE_MASK_ALL) // available to all races (we don't display 'both factions')
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!$raceMask)
|
||||||
|
return false;
|
||||||
|
|
||||||
$tmp = [];
|
$tmp = [];
|
||||||
$i = 1;
|
$i = 1;
|
||||||
$base = $asHTML ? '<a href="?race=%d" class="q1">%s</a>' : '[race=%d]';
|
$base = $asHTML ? '<a href="?race=%d" class="q1">%s</a>' : '[race=%d]';
|
||||||
$br = $asHTML ? '' : '[br]';
|
$br = $asHTML ? '' : '[br]';
|
||||||
|
|
||||||
if (!$raceMask)
|
|
||||||
{
|
|
||||||
$side |= SIDE_BOTH;
|
|
||||||
return self::game('ra', 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($raceMask & RACE_MASK_HORDE)
|
|
||||||
$side |= SIDE_HORDE;
|
|
||||||
|
|
||||||
if ($raceMask & RACE_MASK_ALLIANCE)
|
|
||||||
$side |= SIDE_ALLIANCE;
|
|
||||||
|
|
||||||
if ($raceMask == RACE_MASK_HORDE)
|
if ($raceMask == RACE_MASK_HORDE)
|
||||||
return self::game('ra', -2);
|
return self::game('ra', -2);
|
||||||
|
|
||||||
@@ -375,12 +460,22 @@ class Lang
|
|||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
$n = count($tmp);
|
|
||||||
$ids = array_keys($tmp);
|
$ids = array_keys($tmp);
|
||||||
|
|
||||||
return implode(', ', $tmp);
|
return implode(', ', $tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function formatSkillBreakpoints(array $bp, bool $html = false) : string
|
||||||
|
{
|
||||||
|
$tmp = Lang::game('difficulty').Lang::main('colon');
|
||||||
|
|
||||||
|
for ($i = 0; $i < 4; $i++)
|
||||||
|
if (!empty($bp[$i]))
|
||||||
|
$tmp .= $html ? '<span class="r'.($i + 1).'">'.$bp[$i].'</span> ' : '[color=r'.($i + 1).']'.$bp[$i].'[/color] ';
|
||||||
|
|
||||||
|
return trim($tmp);
|
||||||
|
}
|
||||||
|
|
||||||
public static function nf($number, $decimals = 0, $no1k = false)
|
public static function nf($number, $decimals = 0, $no1k = false)
|
||||||
{
|
{
|
||||||
// [decimal, thousand]
|
// [decimal, thousand]
|
||||||
@@ -388,6 +483,7 @@ class Lang
|
|||||||
LOCALE_EN => [',', '.'],
|
LOCALE_EN => [',', '.'],
|
||||||
LOCALE_FR => [' ', ','],
|
LOCALE_FR => [' ', ','],
|
||||||
LOCALE_DE => ['.', ','],
|
LOCALE_DE => ['.', ','],
|
||||||
|
LOCALE_CN => [',', '.'],
|
||||||
LOCALE_ES => ['.', ','],
|
LOCALE_ES => ['.', ','],
|
||||||
LOCALE_RU => [' ', ',']
|
LOCALE_RU => [' ', ',']
|
||||||
);
|
);
|
||||||
@@ -395,6 +491,12 @@ class Lang
|
|||||||
return number_format($number, $decimals, $seps[User::$localeId][1], $no1k ? '' : $seps[User::$localeId][0]);
|
return number_format($number, $decimals, $seps[User::$localeId][1], $no1k ? '' : $seps[User::$localeId][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function typeName(int $type) : string
|
||||||
|
{
|
||||||
|
return Util::ucFirst(self::game(Type::getFileString($type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static function vspf($var, $args)
|
private static function vspf($var, $args)
|
||||||
{
|
{
|
||||||
if (is_array($var))
|
if (is_array($var))
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1945
localization/locale_zhcn.php
Normal file
1945
localization/locale_zhcn.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,8 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
class AccountPage extends GenericPage
|
class AccountPage extends GenericPage
|
||||||
{
|
{
|
||||||
protected $tpl = 'acc-dashboard';
|
protected $tpl = 'acc-dashboard';
|
||||||
protected $js = ['user.js', 'profile.js'];
|
protected $js = [[JS_FILE, 'user.js'], [JS_FILE, 'profile.js']];
|
||||||
protected $css = [['path' => 'Profiler.css']];
|
protected $css = [[CSS_FILE, 'Profiler.css']];
|
||||||
protected $mode = CACHE_TYPE_NONE;
|
protected $mode = CACHE_TYPE_NONE;
|
||||||
protected $category = null;
|
protected $category = null;
|
||||||
protected $validCats = array(
|
protected $validCats = array(
|
||||||
@@ -27,13 +27,18 @@ class AccountPage extends GenericPage
|
|||||||
protected $lvTabs = [];
|
protected $lvTabs = [];
|
||||||
protected $banned = [];
|
protected $banned = [];
|
||||||
|
|
||||||
private $_post = array(
|
protected $_get = array(
|
||||||
'username' => [FILTER_SANITIZE_SPECIAL_CHARS, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
|
'token' => ['filter' => FILTER_SANITIZE_SPECIAL_CHARS, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
'password' => [FILTER_UNSAFE_RAW, null],
|
'next' => ['filter' => FILTER_SANITIZE_SPECIAL_CHARS, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
'c_password' => [FILTER_UNSAFE_RAW, null],
|
);
|
||||||
'token' => [FILTER_UNSAFE_RAW, null],
|
|
||||||
'remember_me' => [FILTER_CALLBACK, ['options' => 'AccountPage::rememberCallback']],
|
protected $_post = array(
|
||||||
'email' => [FILTER_SANITIZE_EMAIL, null]
|
'username' => ['filter' => FILTER_SANITIZE_SPECIAL_CHARS, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
|
'password' => ['filter' => FILTER_UNSAFE_RAW],
|
||||||
|
'c_password' => ['filter' => FILTER_UNSAFE_RAW],
|
||||||
|
'token' => ['filter' => FILTER_UNSAFE_RAW],
|
||||||
|
'remember_me' => ['filter' => FILTER_CALLBACK, 'options' => 'AccountPage::rememberCallback'],
|
||||||
|
'email' => ['filter' => FILTER_SANITIZE_EMAIL]
|
||||||
);
|
);
|
||||||
|
|
||||||
public function __construct($pageCall, $pageParam)
|
public function __construct($pageCall, $pageParam)
|
||||||
@@ -43,9 +48,6 @@ class AccountPage extends GenericPage
|
|||||||
|
|
||||||
parent::__construct($pageCall, $pageParam);
|
parent::__construct($pageCall, $pageParam);
|
||||||
|
|
||||||
foreach ($this->_post as $k => &$v)
|
|
||||||
$v = !empty($_POST[$k]) ? filter_input(INPUT_POST, $k, $v[0], $v[1]) : null;
|
|
||||||
|
|
||||||
if ($pageParam)
|
if ($pageParam)
|
||||||
{
|
{
|
||||||
// requires auth && not authed
|
// requires auth && not authed
|
||||||
@@ -57,7 +59,7 @@ class AccountPage extends GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function rememberCallback($val)
|
protected static function rememberCallback($val)
|
||||||
{
|
{
|
||||||
return $val == 'yes' ? $val : null;
|
return $val == 'yes' ? $val : null;
|
||||||
}
|
}
|
||||||
@@ -128,7 +130,7 @@ class AccountPage extends GenericPage
|
|||||||
header('Location: '.$this->getNext(true), true, 302);
|
header('Location: '.$this->getNext(true), true, 302);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!empty($_GET['token']) && ($_ = DB::Aowow()->selectCell('SELECT user FROM ?_account WHERE status IN (?a) AND token = ? AND statusTimer > UNIX_TIMESTAMP()', [ACC_STATUS_RECOVER_USER, ACC_STATUS_OK], $_GET['token'])))
|
else if ($this->_get['token'] && ($_ = DB::Aowow()->selectCell('SELECT user FROM ?_account WHERE status IN (?a) AND token = ? AND statusTimer > UNIX_TIMESTAMP()', [ACC_STATUS_RECOVER_USER, ACC_STATUS_OK], $this->_get['token'])))
|
||||||
$this->user = $_;
|
$this->user = $_;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -156,13 +158,13 @@ class AccountPage extends GenericPage
|
|||||||
$this->text = sprintf(Lang::account('createAccSent'), $this->_post['email']);
|
$this->text = sprintf(Lang::account('createAccSent'), $this->_post['email']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!empty($_GET['token']) && ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE status = ?d AND token = ?', ACC_STATUS_NEW, $_GET['token'])))
|
else if ($this->_get['token'] && ($newId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE status = ?d AND token = ?', ACC_STATUS_NEW, $this->_get['token'])))
|
||||||
{
|
{
|
||||||
$nStep = 2;
|
$nStep = 2;
|
||||||
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('UPDATE ?_account SET status = ?d, statusTimer = 0, token = 0, userGroups = ?d WHERE token = ?', ACC_STATUS_OK, U_GROUP_NONE, $this->_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);
|
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']);
|
$this->text = sprintf(Lang::account('accActivated'), $this->_get['token']);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
$this->next = $this->getNext();
|
$this->next = $this->getNext();
|
||||||
@@ -313,17 +315,17 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
|||||||
$this->text = sprintf(Lang::account('recovPassSent'), $this->_post['email']);
|
$this->text = sprintf(Lang::account('recovPassSent'), $this->_post['email']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isset($_GET['token'])) // step 2
|
else if ($this->_get['token']) // step 2
|
||||||
{
|
{
|
||||||
$step = 2;
|
$step = 2;
|
||||||
$this->resetPass = true;
|
$this->resetPass = true;
|
||||||
$this->token = $_GET['token'];
|
$this->token = $this->_get['token'];
|
||||||
}
|
}
|
||||||
else if ($this->_post['token'] && $this->_post['email'] && $this->_post['password'] && $this->_post['c_password'])
|
else if ($this->_post['token'] && $this->_post['email'] && $this->_post['password'] && $this->_post['c_password'])
|
||||||
{
|
{
|
||||||
$step = 2;
|
$step = 2;
|
||||||
$this->resetPass = true;
|
$this->resetPass = true;
|
||||||
$this->token = $_GET['token']; // insecure source .. that sucks; but whats the worst that could happen .. this account cannot be recovered for some minutes
|
$this->token = $this->_post['token']; // insecure source .. that sucks; but whats the worst that could happen .. this account cannot be recovered for some minutes
|
||||||
|
|
||||||
if ($err = $this->doResetPass())
|
if ($err = $this->doResetPass())
|
||||||
$this->error = $err;
|
$this->error = $err;
|
||||||
@@ -413,7 +415,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
|||||||
}
|
}
|
||||||
|
|
||||||
// username taken
|
// username taken
|
||||||
if ($_ = DB::Aowow()->SelectCell('SELECT user FROM ?_account WHERE (user = ? OR email = ?) AND (status <> ?d OR (status = ?d AND statusTimer > UNIX_TIMESTAMP()))', $this->_post['username'], $email, ACC_STATUS_NEW, ACC_STATUS_NEW))
|
if ($_ = DB::Aowow()->SelectCell('SELECT user FROM ?_account WHERE (user = ? OR email = ?) AND (status <> ?d OR (status = ?d AND statusTimer > UNIX_TIMESTAMP()))', $this->_post['username'], $this->_post['email'], ACC_STATUS_NEW, ACC_STATUS_NEW))
|
||||||
return $_ == $this->_post['username'] ? Lang::account('nameInUse') : Lang::account('mailInUse');
|
return $_ == $this->_post['username'] ? Lang::account('nameInUse') : Lang::account('mailInUse');
|
||||||
|
|
||||||
// create..
|
// create..
|
||||||
@@ -433,7 +435,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
|||||||
);
|
);
|
||||||
if (!$ok)
|
if (!$ok)
|
||||||
return Lang::main('intError');
|
return Lang::main('intError');
|
||||||
else if ($_ = $this->sendMail(Lang::mail('accConfirm', 0), sprintf(Lang::mail('accConfirm', 1), $token), CFG_ACC_CREATE_SAVE_DECAY))
|
else if ($_ = $this->sendMail(Lang::user('accConfirm', 0), sprintf(Lang::user('accConfirm', 1), $token), CFG_ACC_CREATE_SAVE_DECAY))
|
||||||
{
|
{
|
||||||
if ($id = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE token = ?', $token))
|
if ($id = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE token = ?', $token))
|
||||||
Util::gainSiteReputation($id, SITEREP_ACTION_REGISTER);
|
Util::gainSiteReputation($id, SITEREP_ACTION_REGISTER);
|
||||||
@@ -454,7 +456,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
|||||||
return $_;
|
return $_;
|
||||||
|
|
||||||
// send recovery mail
|
// send recovery mail
|
||||||
return $this->sendMail(Lang::mail('resetPass', 0), sprintf(Lang::mail('resetPass', 1), $token), CFG_ACC_RECOVERY_DECAY);
|
return $this->sendMail(Lang::user('resetPass', 0), sprintf(Lang::user('resetPass', 1), $token), CFG_ACC_RECOVERY_DECAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function doResetPass()
|
private function doResetPass()
|
||||||
@@ -473,10 +475,10 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
|||||||
if (!$uId)
|
if (!$uId)
|
||||||
return Lang::account('emailNotFound'); // assume they didn't meddle with the token
|
return Lang::account('emailNotFound'); // assume they didn't meddle with the token
|
||||||
|
|
||||||
if (!User::verifyCrypt($newPass))
|
if (!User::verifyCrypt($this->_post['c_password']))
|
||||||
return Lang::account('newPassDiff');
|
return Lang::account('newPassDiff');
|
||||||
|
|
||||||
if (!DB::Aowow()->query('UPDATE ?_account SET passHash = ?, status = ?d WHERE id = ?d', User::hashcrypt($newPass), ACC_STATUS_OK, $uId))
|
if (!DB::Aowow()->query('UPDATE ?_account SET passHash = ?, status = ?d WHERE id = ?d', User::hashCrypt($this->_post['c_password']), ACC_STATUS_OK, $uId))
|
||||||
return Lang::main('intError');
|
return Lang::main('intError');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,7 +488,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
|||||||
return $_;
|
return $_;
|
||||||
|
|
||||||
// send recovery mail
|
// send recovery mail
|
||||||
return $this->sendMail(Lang::mail('recoverUser', 0), sprintf(Lang::mail('recoverUser', 1), $token), CFG_ACC_RECOVERY_DECAY);
|
return $this->sendMail(Lang::user('recoverUser', 0), sprintf(Lang::user('recoverUser', 1), $token), CFG_ACC_RECOVERY_DECAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function initRecovery($type, $delay, &$token)
|
private function initRecovery($type, $delay, &$token)
|
||||||
@@ -508,7 +510,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
|||||||
{
|
{
|
||||||
// send recovery mail
|
// send recovery mail
|
||||||
$subj = CFG_NAME_SHORT.Lang::main('colon') . $subj;
|
$subj = CFG_NAME_SHORT.Lang::main('colon') . $subj;
|
||||||
$msg .= "\r\n\r\n".sprintf(Lang::mail('tokenExpires'), Util::formatTime($delay * 1000))."\r\n";
|
$msg .= "\r\n\r\n".sprintf(Lang::user('tokenExpires'), Util::formatTime($delay * 1000))."\r\n";
|
||||||
$header = 'From: '.CFG_CONTACT_EMAIL . "\r\n" .
|
$header = 'From: '.CFG_CONTACT_EMAIL . "\r\n" .
|
||||||
'Reply-To: '.CFG_CONTACT_EMAIL . "\r\n" .
|
'Reply-To: '.CFG_CONTACT_EMAIL . "\r\n" .
|
||||||
'X-Mailer: PHP/' . phpversion();
|
'X-Mailer: PHP/' . phpversion();
|
||||||
@@ -520,8 +522,8 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
|
|||||||
private function getNext($forHeader = false)
|
private function getNext($forHeader = false)
|
||||||
{
|
{
|
||||||
$next = $forHeader ? '.' : '';
|
$next = $forHeader ? '.' : '';
|
||||||
if (isset($_GET['next']))
|
if ($this->_get['next'])
|
||||||
$next = $_GET['next'];
|
$next = $this->_get['next'];
|
||||||
else if (isset($_SERVER['HTTP_REFERER']) && strstr($_SERVER['HTTP_REFERER'], '?'))
|
else if (isset($_SERVER['HTTP_REFERER']) && strstr($_SERVER['HTTP_REFERER'], '?'))
|
||||||
$next = explode('?', $_SERVER['HTTP_REFERER'])[1];
|
$next = explode('?', $_SERVER['HTTP_REFERER'])[1];
|
||||||
|
|
||||||
|
|||||||
@@ -23,28 +23,32 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class AchievementPage extends GenericPage
|
class AchievementPage extends GenericPage
|
||||||
{
|
{
|
||||||
use DetailPage;
|
use TrDetailPage;
|
||||||
|
|
||||||
protected $type = TYPE_ACHIEVEMENT;
|
protected $type = Type::ACHIEVEMENT;
|
||||||
protected $typeId = 0;
|
protected $typeId = 0;
|
||||||
protected $tpl = 'achievement';
|
protected $tpl = 'achievement';
|
||||||
protected $path = [0, 9];
|
protected $path = [0, 9];
|
||||||
protected $tabId = 0;
|
protected $tabId = 0;
|
||||||
protected $mode = CACHE_TYPE_PAGE;
|
protected $mode = CACHE_TYPE_PAGE;
|
||||||
|
|
||||||
|
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']];
|
||||||
|
|
||||||
|
private $powerTpl = '$WowheadPower.registerAchievement(%d, %d, %s);';
|
||||||
|
|
||||||
public function __construct($pageCall, $id)
|
public function __construct($pageCall, $id)
|
||||||
{
|
{
|
||||||
parent::__construct($pageCall, $id);
|
parent::__construct($pageCall, $id);
|
||||||
|
|
||||||
// temp locale
|
// temp locale
|
||||||
if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain']))
|
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
|
||||||
Util::powerUseLocale($_GET['domain']);
|
Util::powerUseLocale($this->_get['domain']);
|
||||||
|
|
||||||
$this->typeId = intVal($id);
|
$this->typeId = intVal($id);
|
||||||
|
|
||||||
$this->subject = new AchievementList(array(['id', $this->typeId]));
|
$this->subject = new AchievementList(array(['id', $this->typeId]));
|
||||||
if ($this->subject->error)
|
if ($this->subject->error)
|
||||||
$this->notFound();
|
$this->notFound(Lang::game('achievement'), Lang::achievement('notFound'));
|
||||||
|
|
||||||
$this->extendGlobalData($this->subject->getJSGlobals(GLOBALINFO_REWARDS));
|
$this->extendGlobalData($this->subject->getJSGlobals(GLOBALINFO_REWARDS));
|
||||||
|
|
||||||
@@ -58,7 +62,7 @@ class AchievementPage extends GenericPage
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
array_unshift($this->path, $curCat);
|
array_unshift($this->path, $curCat);
|
||||||
$curCat = DB::Aowow()->SelectCell('SELECT parentCategory FROM ?_achievementcategory WHERE id = ?d', $curCat);
|
$curCat = DB::Aowow()->SelectCell('SELECT parentCat FROM ?_achievementcategory WHERE id = ?d', $curCat);
|
||||||
}
|
}
|
||||||
while ($curCat > 0);
|
while ($curCat > 0);
|
||||||
|
|
||||||
@@ -99,6 +103,13 @@ class AchievementPage extends GenericPage
|
|||||||
$infobox[] = Lang::main('side').Lang::main('colon').Lang::game('si', SIDE_BOTH);
|
$infobox[] = Lang::main('side').Lang::main('colon').Lang::game('si', SIDE_BOTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// icon
|
||||||
|
if ($_ = $this->subject->getField('iconId'))
|
||||||
|
{
|
||||||
|
$infobox[] = Util::ucFirst(lang::game('icon')).Lang::main('colon').'[icondb='.$_.' name=true]';
|
||||||
|
$this->extendGlobalIds(Type::ICON, $_);
|
||||||
|
}
|
||||||
|
|
||||||
// realm first available?
|
// realm first available?
|
||||||
if ($this->subject->getField('flags') & 0x100 && DB::isConnectable(DB_AUTH))
|
if ($this->subject->getField('flags') & 0x100 && DB::isConnectable(DB_AUTH))
|
||||||
{
|
{
|
||||||
@@ -129,7 +140,7 @@ class AchievementPage extends GenericPage
|
|||||||
|
|
||||||
$series[$pos][] = array(
|
$series[$pos][] = array(
|
||||||
'side' => $chainAcv->getField('faction'),
|
'side' => $chainAcv->getField('faction'),
|
||||||
'typeStr' => Util::$typeStrings[TYPE_ACHIEVEMENT],
|
'typeStr' => Type::getFileString(Type::ACHIEVEMENT),
|
||||||
'typeId' => $aId,
|
'typeId' => $aId,
|
||||||
'name' => $chainAcv->getField('name', true)
|
'name' => $chainAcv->getField('name', true)
|
||||||
);
|
);
|
||||||
@@ -143,13 +154,13 @@ class AchievementPage extends GenericPage
|
|||||||
$this->mail = $this->createMail($reqBook);
|
$this->mail = $this->createMail($reqBook);
|
||||||
$this->headIcons = [$this->subject->getField('iconString')];
|
$this->headIcons = [$this->subject->getField('iconString')];
|
||||||
$this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
|
$this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
|
||||||
$this->series = $series ? [[$series, null]] : null;
|
$this->series = $series ? [[array_values($series), null]] : null;
|
||||||
$this->description = $this->subject->getField('description', true);
|
$this->description = $this->subject->getField('description', true);
|
||||||
$this->redButtons = array(
|
$this->redButtons = array(
|
||||||
BUTTON_WOWHEAD => !($this->subject->getField('cuFlags') & CUSTOM_SERVERSIDE),
|
BUTTON_WOWHEAD => !($this->subject->getField('cuFlags') & CUSTOM_SERVERSIDE),
|
||||||
BUTTON_LINKS => array(
|
BUTTON_LINKS => array(
|
||||||
'linkColor' => 'ffffff00',
|
'linkColor' => 'ffffff00',
|
||||||
'linkId' => Util::$typeStrings[TYPE_ACHIEVEMENT].':'.$this->typeId.':"..UnitGUID("player")..":0:0:0:0:0:0:0:0',
|
'linkId' => Type::getFileString(Type::ACHIEVEMENT).':'.$this->typeId.':"..UnitGUID("player")..":0:0:0:0:0:0:0:0',
|
||||||
'linkName' => $this->name,
|
'linkName' => $this->name,
|
||||||
'type' => $this->type,
|
'type' => $this->type,
|
||||||
'typeId' => $this->typeId
|
'typeId' => $this->typeId
|
||||||
@@ -162,13 +173,13 @@ class AchievementPage extends GenericPage
|
|||||||
);
|
);
|
||||||
|
|
||||||
if ($reqBook)
|
if ($reqBook)
|
||||||
$this->addCss(['path' => 'Book.css']);
|
$this->addScript([CSS_FILE, 'Book.css']);
|
||||||
|
|
||||||
// create rewards
|
// create rewards
|
||||||
if ($foo = $this->subject->getField('rewards'))
|
if ($foo = $this->subject->getField('rewards'))
|
||||||
{
|
{
|
||||||
array_walk($foo, function(&$item) {
|
array_walk($foo, function(&$item) {
|
||||||
$item = $item[0] != TYPE_ITEM ? null : $item[1];
|
$item = $item[0] != Type::ITEM ? null : $item[1];
|
||||||
});
|
});
|
||||||
|
|
||||||
$bar = new ItemList(array(['i.id', $foo]));
|
$bar = new ItemList(array(['i.id', $foo]));
|
||||||
@@ -177,9 +188,9 @@ class AchievementPage extends GenericPage
|
|||||||
$this->rewards['item'][] = array(
|
$this->rewards['item'][] = array(
|
||||||
'name' => $bar->getField('name', true),
|
'name' => $bar->getField('name', true),
|
||||||
'quality' => $bar->getField('quality'),
|
'quality' => $bar->getField('quality'),
|
||||||
'typeStr' => Util::$typeStrings[TYPE_ITEM],
|
'typeStr' => Type::getFileString(Type::ITEM),
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'globalStr' => 'g_items'
|
'globalStr' => Type::getJSGlobalString(Type::ITEM)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,7 +198,7 @@ class AchievementPage extends GenericPage
|
|||||||
if ($foo = $this->subject->getField('rewards'))
|
if ($foo = $this->subject->getField('rewards'))
|
||||||
{
|
{
|
||||||
array_walk($foo, function(&$item) {
|
array_walk($foo, function(&$item) {
|
||||||
$item = $item[0] != TYPE_TITLE ? null : $item[1];
|
$item = $item[0] != Type::TITLE ? null : $item[1];
|
||||||
});
|
});
|
||||||
|
|
||||||
$bar = new TitleList(array(['id', $foo]));
|
$bar = new TitleList(array(['id', $foo]));
|
||||||
@@ -259,9 +270,13 @@ class AchievementPage extends GenericPage
|
|||||||
$scripts = [];
|
$scripts = [];
|
||||||
|
|
||||||
// serverside extra-Data
|
// serverside extra-Data
|
||||||
$crtIds = array_column($this->subject->getCriteria(), 'id');
|
if ($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);
|
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);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$crtExtraData = [];
|
||||||
|
|
||||||
foreach ($this->subject->getCriteria() as $i => $crt)
|
foreach ($this->subject->getCriteria() as $i => $crt)
|
||||||
{
|
{
|
||||||
@@ -351,10 +366,10 @@ class AchievementPage extends GenericPage
|
|||||||
$tmp['icon'] = $iconId;
|
$tmp['icon'] = $iconId;
|
||||||
$this->criteria['icons'][] = array(
|
$this->criteria['icons'][] = array(
|
||||||
'itr' => $iconId++,
|
'itr' => $iconId++,
|
||||||
'type' => 'g_achievements',
|
'type' => Type::getJSGlobalString(Type::ACHIEVEMENT),
|
||||||
'id' => $obj,
|
'id' => $obj,
|
||||||
);
|
);
|
||||||
$this->extendGlobalIds(TYPE_ACHIEVEMENT, $obj);
|
$this->extendGlobalIds(Type::ACHIEVEMENT, $obj);
|
||||||
break;
|
break;
|
||||||
// link to quest
|
// link to quest
|
||||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
|
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
|
||||||
@@ -374,11 +389,11 @@ class AchievementPage extends GenericPage
|
|||||||
'href' => '?spell='.$obj,
|
'href' => '?spell='.$obj,
|
||||||
'text' => ($crtName ?: SpellList::getName($obj))
|
'text' => ($crtName ?: SpellList::getName($obj))
|
||||||
);
|
);
|
||||||
$this->extendGlobalIds(TYPE_SPELL, $obj);
|
$this->extendGlobalIds(Type::SPELL, $obj);
|
||||||
$tmp['icon'] = $iconId;
|
$tmp['icon'] = $iconId;
|
||||||
$this->criteria['icons'][] = array(
|
$this->criteria['icons'][] = array(
|
||||||
'itr' => $iconId++,
|
'itr' => $iconId++,
|
||||||
'type' => 'g_spells',
|
'type' => Type::getJSGlobalString(Type::SPELL),
|
||||||
'id' => $obj,
|
'id' => $obj,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -398,7 +413,7 @@ class AchievementPage extends GenericPage
|
|||||||
$tmp['icon'] = $iconId;
|
$tmp['icon'] = $iconId;
|
||||||
$this->criteria['icons'][] = array(
|
$this->criteria['icons'][] = array(
|
||||||
'itr' => $iconId++,
|
'itr' => $iconId++,
|
||||||
'type' => 'g_items',
|
'type' => Type::getJSGlobalString(Type::ITEM),
|
||||||
'id' => $obj,
|
'id' => $obj,
|
||||||
'count' => $qty,
|
'count' => $qty,
|
||||||
);
|
);
|
||||||
@@ -516,43 +531,17 @@ class AchievementPage extends GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function generateTooltip($asError = false)
|
protected function generateTooltip()
|
||||||
{
|
{
|
||||||
if ($asError)
|
$power = new StdClass();
|
||||||
return '$WowheadPower.registerAchievement('.$this->typeId.', '.User::$localeId.', {});';
|
if (!$this->subject->error)
|
||||||
|
|
||||||
$x = '$WowheadPower.registerAchievement('.$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();
|
$power->{'name_'.User::$localeString} = $this->subject->getField('name', true);
|
||||||
$this->saveCache($tt);
|
$power->icon = rawurlencode($this->subject->getField('iconString', true, true));
|
||||||
|
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
header('Content-type: application/x-javascript; charset=utf-8');
|
return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
|
||||||
die($tt);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function notFound($title = '', $msg = '')
|
|
||||||
{
|
|
||||||
if ($this->mode != CACHE_TYPE_TOOLTIP)
|
|
||||||
return parent::notFound($title ?: Lang::game('achievement'), $msg ?: Lang::achievement('notFound'));
|
|
||||||
|
|
||||||
header('Content-type: application/x-javascript; charset=utf-8');
|
|
||||||
echo $this->generateTooltip(true);
|
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createMail(&$reqCss = false)
|
private function createMail(&$reqCss = false)
|
||||||
@@ -561,31 +550,35 @@ class AchievementPage extends GenericPage
|
|||||||
|
|
||||||
if ($_ = $this->subject->getField('mailTemplate'))
|
if ($_ = $this->subject->getField('mailTemplate'))
|
||||||
{
|
{
|
||||||
$letter = DB::Aowow()->selectRow('SELECT * FROM ?_mailtemplate WHERE id = ?d', $_);
|
$letter = DB::Aowow()->selectRow('SELECT * FROM ?_mails WHERE id = ?d', $_);
|
||||||
if (!$letter)
|
if (!$letter)
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
$reqCss = true;
|
$reqCss = true;
|
||||||
$mail = array(
|
$mail = array(
|
||||||
'delay' => null,
|
'id' => $_,
|
||||||
'sender' => null,
|
'delay' => null,
|
||||||
'subject' => Util::parseHtmlText(Util::localizedString($letter, 'subject', true)),
|
'sender' => null,
|
||||||
'text' => Util::parseHtmlText(Util::localizedString($letter, 'text', true))
|
'attachments' => [],
|
||||||
|
'subject' => Util::parseHtmlText(Util::localizedString($letter, 'subject', true)),
|
||||||
|
'text' => Util::parseHtmlText(Util::localizedString($letter, 'text', true))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if ($_ = Util::parseHtmlText($this->subject->getField('text', true, true)))
|
else if ($_ = Util::parseHtmlText($this->subject->getField('text', true, true)))
|
||||||
{
|
{
|
||||||
$reqCss = true;
|
$reqCss = true;
|
||||||
$mail = array(
|
$mail = array(
|
||||||
'delay' => null,
|
'id' => -$this->typeId,
|
||||||
'sender' => null,
|
'delay' => null,
|
||||||
'subject' => Util::parseHtmlText($this->subject->getField('subject', true, true)),
|
'sender' => null,
|
||||||
'text' => $_
|
'attachments' => [],
|
||||||
|
'subject' => Util::parseHtmlText($this->subject->getField('subject', true, true)),
|
||||||
|
'text' => $_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($_ = CreatureList::getName($this->subject->getField('sender')))
|
if ($_ = CreatureList::getName($this->subject->getField('sender')))
|
||||||
$mail['sender'] = sprintf(Lang::quest('mailBy'), $this->subject->getField('sender'), $_);
|
$mail['sender'] = sprintf(Lang::mail('mailBy'), $this->subject->getField('sender'), $_);
|
||||||
|
|
||||||
return $mail;
|
return $mail;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,14 +8,17 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class AchievementsPage extends GenericPage
|
class AchievementsPage extends GenericPage
|
||||||
{
|
{
|
||||||
use ListPage;
|
use TrListPage;
|
||||||
|
|
||||||
protected $type = TYPE_ACHIEVEMENT;
|
protected $type = Type::ACHIEVEMENT;
|
||||||
protected $tpl = 'achievements';
|
protected $tpl = 'achievements';
|
||||||
protected $path = [0, 9];
|
protected $path = [0, 9];
|
||||||
protected $tabId = 0;
|
protected $tabId = 0;
|
||||||
protected $mode = CACHE_TYPE_PAGE;
|
protected $mode = CACHE_TYPE_PAGE;
|
||||||
protected $js = ['filters.js'];
|
protected $js = [[JS_FILE, 'filters.js']];
|
||||||
|
|
||||||
|
protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]];
|
||||||
|
|
||||||
protected $validCats = array(
|
protected $validCats = array(
|
||||||
92 => true,
|
92 => true,
|
||||||
96 => [14861, 14862, 14863],
|
96 => [14861, 14862, 14863],
|
||||||
@@ -64,7 +67,7 @@ class AchievementsPage extends GenericPage
|
|||||||
|
|
||||||
// recreate form selection
|
// recreate form selection
|
||||||
$this->filter = $this->filterObj->getForm();
|
$this->filter = $this->filterObj->getForm();
|
||||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
|
$this->filter['query'] = $this->_get['filter'];
|
||||||
$this->filter['initData'] = ['init' => 'achievements'];
|
$this->filter['initData'] = ['init' => 'achievements'];
|
||||||
|
|
||||||
if ($x = $this->filterObj->getSetCriteria())
|
if ($x = $this->filterObj->getSetCriteria())
|
||||||
@@ -76,16 +79,11 @@ class AchievementsPage extends GenericPage
|
|||||||
$acvList = new AchievementList($conditions);
|
$acvList = new AchievementList($conditions);
|
||||||
if (!$acvList->getMatches())
|
if (!$acvList->getMatches())
|
||||||
{
|
{
|
||||||
$curCats = $catList = [!empty($this->category) ? (int)end($this->category) : 0];
|
$category = [!empty($this->category) ? (int)end($this->category) : 0];
|
||||||
while ($curCats)
|
|
||||||
{
|
|
||||||
$curCats = DB::Aowow()->SelectCol('SELECT Id FROM ?_achievementcategory WHERE parentCategory IN (?a)', $curCats);
|
|
||||||
$catList = array_merge($catList, $curCats);
|
|
||||||
}
|
|
||||||
$conditions = [];
|
$conditions = [];
|
||||||
if ($fiCnd)
|
if ($fiCnd)
|
||||||
$conditions[] = $fiCnd;
|
$conditions[] = $fiCnd;
|
||||||
if ($catList)
|
if ($catList = DB::Aowow()->SelectCol('SELECT Id FROM ?_achievementcategory WHERE parentCat IN (?a) OR parentCat2 IN (?a) ', $category, $category))
|
||||||
$conditions[] = ['category', $catList];
|
$conditions[] = ['category', $catList];
|
||||||
|
|
||||||
$acvList = new AchievementList($conditions);
|
$acvList = new AchievementList($conditions);
|
||||||
@@ -127,20 +125,14 @@ class AchievementsPage extends GenericPage
|
|||||||
{
|
{
|
||||||
array_unshift($this->title, Util::ucFirst(Lang::game('achievements')));
|
array_unshift($this->title, Util::ucFirst(Lang::game('achievements')));
|
||||||
if ($this->category)
|
if ($this->category)
|
||||||
{
|
array_unshift($this->title, Lang::achievement('cat', end($this->category)));
|
||||||
$catrow = DB::Aowow()->SelectRow('SELECT * FROM ?_achievementcategory WHERE id = ?d', end($this->category));
|
|
||||||
array_unshift($this->title, Util::localizedString($catrow, 'name'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function generatePath()
|
protected function generatePath()
|
||||||
{
|
{
|
||||||
if ($this->category)
|
if ($this->category)
|
||||||
{
|
foreach ($this->category as $cat)
|
||||||
$catrows = DB::Aowow()->SelectCol('SELECT id FROM ?_achievementcategory WHERE id IN (?a)', $this->category);
|
|
||||||
foreach ($catrows as $cat)
|
|
||||||
$this->path[] = $cat;
|
$this->path[] = $cat;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,19 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
class AdminPage extends GenericPage
|
class AdminPage extends GenericPage
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $tpl = null; // depends on the subject
|
protected $tpl = null; // depends on the subject
|
||||||
protected $reqUGroup = U_GROUP_NONE; // actual group dependant on the subPage
|
protected $reqUGroup = U_GROUP_NONE; // actual group dependant on the subPage
|
||||||
protected $reqAuth = true;
|
protected $reqAuth = true;
|
||||||
protected $path = [4];
|
protected $path = [4];
|
||||||
protected $tabId = 4;
|
protected $tabId = 4;
|
||||||
|
|
||||||
|
protected $_get = array(
|
||||||
|
'all' => ['filter' => FILTER_UNSAFE_RAW],
|
||||||
|
'type' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'],
|
||||||
|
'typeid' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'],
|
||||||
|
'user' => ['filter' => FILTER_CALLBACK, 'options' => 'urldecode'],
|
||||||
|
);
|
||||||
|
|
||||||
private $generator = '';
|
private $generator = '';
|
||||||
|
|
||||||
public function __construct($pageCall, $pageParam)
|
public function __construct($pageCall, $pageParam)
|
||||||
@@ -51,13 +57,21 @@ class AdminPage extends GenericPage
|
|||||||
array_push($this->path, 2, 16);
|
array_push($this->path, 2, 16);
|
||||||
$this->name = 'Weight Presets';
|
$this->name = 'Weight Presets';
|
||||||
break;
|
break;
|
||||||
|
case 'guides':
|
||||||
|
$this->reqUGroup = U_GROUP_STAFF;
|
||||||
|
$this->generator = 'handleGuideApprove';
|
||||||
|
$this->tpl = 'list-page-generic';
|
||||||
|
|
||||||
|
array_push($this->path, 1, 25);
|
||||||
|
$this->name = 'Pending Guides';
|
||||||
|
break;
|
||||||
default: // error out through unset template
|
default: // error out through unset template
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::__construct($pageCall, $pageParam);
|
parent::__construct($pageCall, $pageParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function generateContent()
|
protected function generateContent() : void
|
||||||
{
|
{
|
||||||
if (!$this->generator || function_exists($this->generator))
|
if (!$this->generator || function_exists($this->generator))
|
||||||
return;
|
return;
|
||||||
@@ -65,17 +79,17 @@ class AdminPage extends GenericPage
|
|||||||
$this->{$this->generator}();
|
$this->{$this->generator}();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleConfig()
|
private function handleConfig() : void
|
||||||
{
|
{
|
||||||
$this->addCSS(array(
|
$this->addScript(
|
||||||
['string' => '.grid input[type=\'text\'], .grid input[type=\'number\'] { width:250px; text-align:left; }'],
|
[CSS_STRING, '.grid input[type=\'text\'], .grid input[type=\'number\'] { width:250px; text-align:left; }'],
|
||||||
['string' => '.grid input[type=\'button\'] { width:65px; padding:2px; }'],
|
[CSS_STRING, '.grid input[type=\'button\'] { width:65px; padding:2px; }'],
|
||||||
['string' => '.grid a.tip { margin:0px 5px; opacity:0.8; }'],
|
[CSS_STRING, '.grid a.tip { margin:0px 5px; opacity:0.8; }'],
|
||||||
['string' => '.grid a.tip:hover { opacity:1; }'],
|
[CSS_STRING, '.grid a.tip:hover { opacity:1; }'],
|
||||||
['string' => '.grid tr { height:30px; }'],
|
[CSS_STRING, '.grid tr { height:30px; }'],
|
||||||
['string' => '.grid .disabled { opacity:0.4 !important; }'],
|
[CSS_STRING, '.grid .disabled { opacity:0.4 !important; }'],
|
||||||
['string' => '.grid .status { position:absolute; right:5px; }'],
|
[CSS_STRING, '.grid .status { position:absolute; right:5px; }'],
|
||||||
));
|
);
|
||||||
|
|
||||||
$head = '<table class="grid"><tr><th><b>Key</b></th><th><b>Value</b></th><th style="width:150px;"><b>Options</b></th></tr>';
|
$head = '<table class="grid"><tr><th><b>Key</b></th><th><b>Value</b></th><th style="width:150px;"><b>Options</b></th></tr>';
|
||||||
$mainTab = [];
|
$mainTab = [];
|
||||||
@@ -115,10 +129,10 @@ class AdminPage extends GenericPage
|
|||||||
)];
|
)];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handlePhpInfo()
|
private function handlePhpInfo() : void
|
||||||
{
|
{
|
||||||
$this->addCSS([
|
$this->addScript([
|
||||||
'string' => "\npre {margin: 0px; font-family: monospace;}\n" .
|
CSS_STRING, "\npre {margin: 0px; font-family: monospace;}\n" .
|
||||||
"td, th { border: 1px solid #000000; vertical-align: baseline;}\n" .
|
"td, th { border: 1px solid #000000; vertical-align: baseline;}\n" .
|
||||||
".p {text-align: left;}\n" .
|
".p {text-align: left;}\n" .
|
||||||
".e {background-color: #ccccff; font-weight: bold; color: #000000;}\n" .
|
".e {background-color: #ccccff; font-weight: bold; color: #000000;}\n" .
|
||||||
@@ -179,30 +193,29 @@ class AdminPage extends GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleScreenshots()
|
private function handleScreenshots() : void
|
||||||
{
|
{
|
||||||
$this->addJS('screenshot.js');
|
$this->addScript(
|
||||||
$this->addCSS(array(
|
[JS_FILE, 'screenshot.js'],
|
||||||
['string' => '.layout {margin: 0px 25px; max-width: inherit; min-width: 1200px; }'],
|
[CSS_STRING, '.layout {margin: 0px 25px; max-width: inherit; min-width: 1200px; }'],
|
||||||
['string' => '#highlightedRow { background-color: #322C1C; }']
|
[CSS_STRING, '#highlightedRow { background-color: #322C1C; }'],
|
||||||
));
|
);
|
||||||
|
|
||||||
$ssGetAll = isset($_GET['all']) && empty($_GET['all']);
|
$ssGetAll = $this->_get['all'];
|
||||||
$ssPages = [];
|
$ssPages = [];
|
||||||
$ssData = [];
|
$ssData = [];
|
||||||
$nMatches = 0;
|
$nMatches = 0;
|
||||||
|
|
||||||
if (!empty($_GET['type']) && !empty($_GET['typeid']))
|
if ($this->_get['type'] && $this->_get['typeId'])
|
||||||
{
|
{
|
||||||
$ssData = CommunityContent::getScreenshotsForManager(intVal($_GET['type']), intVal($_GET['typeid']));
|
$ssData = CommunityContent::getScreenshotsForManager($this->_get['type'], $this->_get['typeid']);
|
||||||
$nMatches = count($ssData);
|
$nMatches = count($ssData);
|
||||||
}
|
}
|
||||||
else if (!empty($_GET['user']))
|
else if ($this->_get['user'])
|
||||||
{
|
{
|
||||||
$name = urldecode($_GET['user']);
|
if (mb_strlen($this->_get['user']) >= 3)
|
||||||
if (mb_strlen($name) >= 3)
|
|
||||||
{
|
{
|
||||||
if ($uId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE displayName = ?', ucFirst($name)))
|
if ($uId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE displayName = ?', ucFirst($this->_get['user'])))
|
||||||
{
|
{
|
||||||
$ssData = CommunityContent::getScreenshotsForManager(0, 0, $uId);
|
$ssData = CommunityContent::getScreenshotsForManager(0, 0, $uId);
|
||||||
$nMatches = count($ssData);
|
$nMatches = count($ssData);
|
||||||
@@ -218,10 +231,12 @@ class AdminPage extends GenericPage
|
|||||||
$this->ssNFound = $nMatches; // ssm_numPagesFound
|
$this->ssNFound = $nMatches; // ssm_numPagesFound
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleWeightPresets()
|
private function handleWeightPresets() : void
|
||||||
{
|
{
|
||||||
$this->addCSS(['string' => '.wt-edit {display:inline-block; vertical-align:top; width:350px;}']);
|
$this->addScript(
|
||||||
$this->addJS('filters.js');
|
[JS_FILE, 'filters.js'],
|
||||||
|
[CSS_STRING, '.wt-edit {display:inline-block; vertical-align:top; width:350px;}'],
|
||||||
|
);
|
||||||
|
|
||||||
$head = $body = '';
|
$head = $body = '';
|
||||||
|
|
||||||
@@ -245,6 +260,26 @@ class AdminPage extends GenericPage
|
|||||||
$this->extraHTML = '<script type="text/javascript">var wt_presets = '.Util::toJSON($weights).";</script>\n\n";
|
$this->extraHTML = '<script type="text/javascript">var wt_presets = '.Util::toJSON($weights).";</script>\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function handleGuideApprove() : void
|
||||||
|
{
|
||||||
|
$pending = new GuideList([['status', GUIDE_STATUS_REVIEW]]);
|
||||||
|
if ($pending->error)
|
||||||
|
$data = [];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$data = $pending->getListviewData();
|
||||||
|
$latest = DB::Aowow()->selectCol('SELECT `typeId` AS ARRAY_KEY, MAX(`rev`) FROM ?_articles WHERE `type` = ?d AND `typeId` IN (?a) GROUP BY `rev`', Type::GUIDE, $pending->getFoundIDs());
|
||||||
|
foreach ($latest as $id => $rev)
|
||||||
|
$data[$id]['rev'] = $rev;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->lvTabs[] = ['guide', array(
|
||||||
|
'data' => array_values($data),
|
||||||
|
'hiddenCols' => ['patch', 'comments', 'views', 'rating'],
|
||||||
|
'extraCols' => '$_'
|
||||||
|
), 'guideAdminCol'];
|
||||||
|
}
|
||||||
|
|
||||||
private function configAddRow($r)
|
private function configAddRow($r)
|
||||||
{
|
{
|
||||||
$buff = '<tr>';
|
$buff = '<tr>';
|
||||||
|
|||||||
146
pages/areatrigger.php
Normal file
146
pages/areatrigger.php
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
// menuId 102: Areatrigger g_initPath()
|
||||||
|
// tabid 0: Database g_initHeader()
|
||||||
|
class AreaTriggerPage extends GenericPage
|
||||||
|
{
|
||||||
|
use TrDetailPage;
|
||||||
|
|
||||||
|
protected $type = Type::AREATRIGGER;
|
||||||
|
protected $typeId = 0;
|
||||||
|
protected $tpl = 'detail-page-generic';
|
||||||
|
protected $path = [0, 102];
|
||||||
|
protected $tabId = 0;
|
||||||
|
protected $mode = CACHE_TYPE_PAGE;
|
||||||
|
protected $reqUGroup = U_GROUP_STAFF;
|
||||||
|
|
||||||
|
public function __construct($pageCall, $id)
|
||||||
|
{
|
||||||
|
$this->contribute = CONTRIBUTE_NONE;
|
||||||
|
|
||||||
|
parent::__construct($pageCall, $id);
|
||||||
|
|
||||||
|
$this->typeId = intVal($id);
|
||||||
|
|
||||||
|
$this->subject = new AreaTriggerList(array(['id', $this->typeId]));
|
||||||
|
if ($this->subject->error)
|
||||||
|
$this->notFound(Lang::game('areatrigger'), Lang::areatrigger('notFound'));
|
||||||
|
|
||||||
|
$this->name = $this->subject->getField('name') ?: 'AT #'.$this->typeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generatePath()
|
||||||
|
{
|
||||||
|
$this->path[] = $this->subject->getField('type');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateTitle()
|
||||||
|
{
|
||||||
|
array_unshift($this->title, $this->name, Util::ucFirst(Lang::game('areatrigger')));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateContent()
|
||||||
|
{
|
||||||
|
$this->addScript([JS_FILE, '?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']]);
|
||||||
|
|
||||||
|
$_type = $this->subject->getField('type');
|
||||||
|
|
||||||
|
|
||||||
|
/****************/
|
||||||
|
/* Main Content */
|
||||||
|
/****************/
|
||||||
|
|
||||||
|
// get spawns
|
||||||
|
$map = null;
|
||||||
|
if ($spawns = $this->subject->getSpawns(SPAWNINFO_FULL))
|
||||||
|
{
|
||||||
|
$ta = $this->subject->getField('teleportA');
|
||||||
|
$tf = $this->subject->getField('teleportF');
|
||||||
|
$tx = $this->subject->getField('teleportX');
|
||||||
|
$ty = $this->subject->getField('teleportY');
|
||||||
|
$to = $this->subject->getField('teleportO');
|
||||||
|
|
||||||
|
// add teleport target
|
||||||
|
if ($ta && $tx && $ty)
|
||||||
|
{
|
||||||
|
$o = Util::O2Deg($to);
|
||||||
|
$endPoint = array($tx, $ty, array(
|
||||||
|
'type' => 4,
|
||||||
|
'tooltip' => array(
|
||||||
|
'Teleport Destination' => array(
|
||||||
|
'info' => ['Orientation'.Lang::main('colon').$o[0].'° ('.$o[1].')']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
if (isset($spawns[$ta][$tf]))
|
||||||
|
$spawns[$ta][$tf]['coords'][] = $endPoint;
|
||||||
|
else
|
||||||
|
$spawns[$ta][$tf]['coords'] = [$endPoint];
|
||||||
|
}
|
||||||
|
|
||||||
|
$map = array(
|
||||||
|
'data' => ['parent' => 'mapper-generic'],
|
||||||
|
'mapperData' => &$spawns
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($spawns as $areaId => &$areaData)
|
||||||
|
$map['extra'][$areaId] = ZoneList::getName($areaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// smart AI
|
||||||
|
$sai = null;
|
||||||
|
if ($_type == AT_TYPE_SMART)
|
||||||
|
{
|
||||||
|
$sai = new SmartAI(SAI_SRC_TYPE_AREATRIGGER, $this->typeId, ['name' => $this->name, 'teleportA' => $this->subject->getField('teleportA')]);
|
||||||
|
if ($sai->prepare())
|
||||||
|
$this->extendGlobalData($sai->getJSGlobals());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$this->map = $map;
|
||||||
|
$this->infobox = false;
|
||||||
|
$this->smartAI = $sai ? $sai->getMarkdown() : null;
|
||||||
|
$this->redButtons = array(
|
||||||
|
BUTTON_LINKS => false,
|
||||||
|
BUTTON_WOWHEAD => false
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************/
|
||||||
|
/* Extra Tabs */
|
||||||
|
/**************/
|
||||||
|
|
||||||
|
if ($_type == AT_TYPE_OBJECTIVE)
|
||||||
|
{
|
||||||
|
$relQuest = new QuestList(array(['id', $this->subject->getField('quest')]));
|
||||||
|
if (!$relQuest->error)
|
||||||
|
{
|
||||||
|
$this->extendGlobalData($relQuest->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_REWARDS));
|
||||||
|
$this->lvTabs[] = ['quest', ['data' => array_values($relQuest->getListviewData())]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ($_type == AT_TYPE_TELEPORT)
|
||||||
|
{
|
||||||
|
$relZone = new ZoneList(array(['id', $this->subject->getField('teleportA')]));
|
||||||
|
if (!$relZone->error)
|
||||||
|
{
|
||||||
|
$this->lvTabs[] = ['zone', ['data' => array_values($relZone->getListviewData())]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ($_type == AT_TYPE_SCRIPT)
|
||||||
|
{
|
||||||
|
$relTrigger = new AreaTriggerList(array(['id', $this->typeId, '!'], ['name', $this->subject->getField('name')]));
|
||||||
|
if (!$relTrigger->error)
|
||||||
|
{
|
||||||
|
$this->lvTabs[] = ['areatrigger', ['data' => array_values($relTrigger->getListviewData()), 'name' => Util::ucFirst(Lang::game('areatrigger'))], 'areatrigger'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
89
pages/areatriggers.php
Normal file
89
pages/areatriggers.php
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
// menuId 102: Areatrigger g_initPath()
|
||||||
|
// tabid 0: Database g_initHeader()
|
||||||
|
class AreaTriggersPage extends GenericPage
|
||||||
|
{
|
||||||
|
use TrListPage;
|
||||||
|
|
||||||
|
protected $type = Type::AREATRIGGER;
|
||||||
|
protected $tpl = 'areatriggers';
|
||||||
|
protected $path = [0, 102];
|
||||||
|
protected $tabId = 0;
|
||||||
|
protected $mode = CACHE_TYPE_PAGE;
|
||||||
|
protected $validCats = [0, 1, 2, 3, 4, 5];
|
||||||
|
protected $js = [[JS_FILE, 'filters.js']];
|
||||||
|
protected $reqUGroup = U_GROUP_STAFF;
|
||||||
|
|
||||||
|
protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]];
|
||||||
|
|
||||||
|
public function __construct($pageCall, $pageParam)
|
||||||
|
{
|
||||||
|
$this->getCategoryFromUrl($pageParam);;
|
||||||
|
if (isset($this->category[0]))
|
||||||
|
header('Location: ?areatriggers&filter=ty='.$this->category[0], true, 302);
|
||||||
|
|
||||||
|
$this->filterObj = new AreaTriggerListFilter();
|
||||||
|
|
||||||
|
parent::__construct($pageCall, $pageParam);
|
||||||
|
|
||||||
|
$this->name = Util::ucFirst(Lang::game('areatriggers'));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateContent()
|
||||||
|
{
|
||||||
|
// recreate form selection
|
||||||
|
$this->filter = $this->filterObj->getForm();
|
||||||
|
$this->filter['query'] = $this->_get['filter'];
|
||||||
|
$this->filter['initData'] = ['init' => 'areatrigger'];
|
||||||
|
|
||||||
|
if ($x = $this->filterObj->getSetCriteria())
|
||||||
|
$this->filter['initData']['sc'] = $x;
|
||||||
|
|
||||||
|
$conditions = [];
|
||||||
|
if ($_ = $this->filterObj->getConditions())
|
||||||
|
$conditions[] = $_;
|
||||||
|
|
||||||
|
$tabData = [];
|
||||||
|
$trigger = new AreaTriggerList($conditions);
|
||||||
|
if (!$trigger->error)
|
||||||
|
{
|
||||||
|
$tabData['data'] = array_values($trigger->getListviewData());
|
||||||
|
|
||||||
|
// create note if search limit was exceeded; overwriting 'note' is intentional
|
||||||
|
if ($trigger->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||||
|
{
|
||||||
|
$tabData['note'] = sprintf(Util::$tryFilteringEntityString, $trigger->getMatches(), '"'.Lang::game('areatriggers').'"', CFG_SQL_LIMIT_DEFAULT);
|
||||||
|
$tabData['_truncated'] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->filterObj->error)
|
||||||
|
$tabData['_errors'] = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->lvTabs[] = ['areatrigger', $tabData, 'areatrigger'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateTitle()
|
||||||
|
{
|
||||||
|
array_unshift($this->title, $this->name);
|
||||||
|
|
||||||
|
$form = $this->filterObj->getForm();
|
||||||
|
if (isset($form['ty']) && count($form['ty']) == 1)
|
||||||
|
array_unshift($this->title, Lang::areatrigger('types', $form['ty'][0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generatePath()
|
||||||
|
{
|
||||||
|
$form = $this->filterObj->getForm();
|
||||||
|
if (isset($form['ty']) && count($form['ty']) == 1)
|
||||||
|
$this->path[] = $form['ty'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -12,14 +12,19 @@ class ArenaTeamPage extends GenericPage
|
|||||||
|
|
||||||
protected $lvTabs = [];
|
protected $lvTabs = [];
|
||||||
|
|
||||||
|
protected $type = Type::ARENA_TEAM;
|
||||||
|
|
||||||
protected $tabId = 1;
|
protected $tabId = 1;
|
||||||
protected $path = [1, 5, 3];
|
protected $path = [1, 5, 3];
|
||||||
protected $tpl = 'roster';
|
protected $tpl = 'roster';
|
||||||
protected $js = ['profile_all.js', 'profile.js'];
|
protected $js = [[JS_FILE, 'profile_all.js'], [JS_FILE, 'profile.js']];
|
||||||
protected $css = [['path' => 'Profiler.css']];
|
protected $css = [[CSS_FILE, 'Profiler.css']];
|
||||||
|
|
||||||
public function __construct($pageCall, $pageParam)
|
public function __construct($pageCall, $pageParam)
|
||||||
{
|
{
|
||||||
|
if (!CFG_PROFILER_ENABLE)
|
||||||
|
$this->error();
|
||||||
|
|
||||||
$params = array_map('urldecode', explode('.', $pageParam));
|
$params = array_map('urldecode', explode('.', $pageParam));
|
||||||
if ($params[0])
|
if ($params[0])
|
||||||
$params[0] = Profiler::urlize($params[0]);
|
$params[0] = Profiler::urlize($params[0]);
|
||||||
@@ -92,7 +97,7 @@ class ArenaTeamPage extends GenericPage
|
|||||||
if ($this->doResync)
|
if ($this->doResync)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$this->addJS('?data=realms.weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
$this->addScript([JS_FILE, '?data=realms.weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']]);
|
||||||
|
|
||||||
$this->redButtons[BUTTON_RESYNC] = [$this->subjectGUID, 'arena-team'];
|
$this->redButtons[BUTTON_RESYNC] = [$this->subjectGUID, 'arena-team'];
|
||||||
|
|
||||||
@@ -121,15 +126,15 @@ class ArenaTeamPage extends GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function notFound($title = '', $msg = '')
|
public function notFound(string $title = '', string $msg = '') : void
|
||||||
{
|
{
|
||||||
return parent::notFound($title ?: Util::ucFirst(Lang::profiler('profiler')), $msg ?: Lang::profiler('notFound', 'arenateam'));
|
parent::notFound($title ?: Util::ucFirst(Lang::profiler('profiler')), $msg ?: Lang::profiler('notFound', 'arenateam'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleIncompleteData($teamGuid)
|
private function handleIncompleteData($teamGuid)
|
||||||
{
|
{
|
||||||
//display empty page and queue status
|
//display empty page and queue status
|
||||||
$newId = Profiler::scheduleResync(TYPE_ARENA_TEAM, $this->realmId, $teamGuid);
|
$newId = Profiler::scheduleResync(Type::ARENA_TEAM, $this->realmId, $teamGuid);
|
||||||
|
|
||||||
$this->doResync = ['arena-team', $newId];
|
$this->doResync = ['arena-team', $newId];
|
||||||
$this->initialSync();
|
$this->initialSync();
|
||||||
|
|||||||
@@ -10,13 +10,20 @@ class ArenaTeamsPage extends GenericPage
|
|||||||
{
|
{
|
||||||
use TrProfiler;
|
use TrProfiler;
|
||||||
|
|
||||||
|
protected $type = Type::ARENA_TEAM;
|
||||||
|
|
||||||
protected $tabId = 1;
|
protected $tabId = 1;
|
||||||
protected $path = [1, 5, 3];
|
protected $path = [1, 5, 3];
|
||||||
protected $tpl = 'arena-teams';
|
protected $tpl = 'arena-teams';
|
||||||
protected $js = ['filters.js', 'profile_all.js', 'profile.js'];
|
protected $js = [[JS_FILE, 'filters.js'], [JS_FILE, 'profile_all.js'], [JS_FILE, 'profile.js']];
|
||||||
|
|
||||||
|
protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]];
|
||||||
|
|
||||||
public function __construct($pageCall, $pageParam)
|
public function __construct($pageCall, $pageParam)
|
||||||
{
|
{
|
||||||
|
if (!CFG_PROFILER_ENABLE)
|
||||||
|
$this->error();
|
||||||
|
|
||||||
$this->getSubjectFromUrl($pageParam);
|
$this->getSubjectFromUrl($pageParam);
|
||||||
|
|
||||||
$this->filterObj = new ArenaTeamListFilter();
|
$this->filterObj = new ArenaTeamListFilter();
|
||||||
@@ -50,7 +57,7 @@ class ArenaTeamsPage extends GenericPage
|
|||||||
|
|
||||||
protected function generateContent()
|
protected function generateContent()
|
||||||
{
|
{
|
||||||
$this->addJS('?data=realms&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
$this->addScript([JS_FILE, '?data=realms&locale='.User::$localeId.'&t='.$_SESSION['dataKey']]);
|
||||||
|
|
||||||
$conditions = [];
|
$conditions = [];
|
||||||
if (!User::isInGroup(U_GROUP_EMPLOYEE))
|
if (!User::isInGroup(U_GROUP_EMPLOYEE))
|
||||||
@@ -61,7 +68,7 @@ class ArenaTeamsPage extends GenericPage
|
|||||||
|
|
||||||
// recreate form selection
|
// recreate form selection
|
||||||
$this->filter = $this->filterObj->getForm();
|
$this->filter = $this->filterObj->getForm();
|
||||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
|
$this->filter['query'] = $this->_get['filter'];
|
||||||
$this->filter['initData'] = ['type' => 'arenateams'];
|
$this->filter['initData'] = ['type' => 'arenateams'];
|
||||||
|
|
||||||
$tabData = array(
|
$tabData = array(
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class ClassPage extends GenericPage
|
class ClassPage extends GenericPage
|
||||||
{
|
{
|
||||||
use DetailPage;
|
use TrDetailPage;
|
||||||
|
|
||||||
protected $type = TYPE_CLASS;
|
protected $type = Type::CHR_CLASS;
|
||||||
protected $typeId = 0;
|
protected $typeId = 0;
|
||||||
protected $tpl = 'detail-page-generic';
|
protected $tpl = 'detail-page-generic';
|
||||||
protected $path = [0, 12];
|
protected $path = [0, 12];
|
||||||
protected $tabId = 0;
|
protected $tabId = 0;
|
||||||
protected $mode = CACHE_TYPE_PAGE;
|
protected $mode = CACHE_TYPE_PAGE;
|
||||||
protected $js = ['swfobject.js'];
|
protected $js = [[JS_FILE, 'swfobject.js']];
|
||||||
|
|
||||||
public function __construct($pageCall, $id)
|
public function __construct($pageCall, $id)
|
||||||
{
|
{
|
||||||
@@ -43,7 +43,7 @@ class ClassPage extends GenericPage
|
|||||||
|
|
||||||
protected function generateContent()
|
protected function generateContent()
|
||||||
{
|
{
|
||||||
$this->addJS('?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
$this->addScript([JS_FILE, '?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']]);
|
||||||
|
|
||||||
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
|
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
|
||||||
$_mask = 1 << ($this->typeId - 1);
|
$_mask = 1 << ($this->typeId - 1);
|
||||||
@@ -213,7 +213,7 @@ class ClassPage extends GenericPage
|
|||||||
$conditions = array(
|
$conditions = array(
|
||||||
['npcflag', 0x30, '&'], // is trainer
|
['npcflag', 0x30, '&'], // is trainer
|
||||||
['trainerType', 0], // trains class spells
|
['trainerType', 0], // trains class spells
|
||||||
['trainerClass', $this->typeId]
|
['trainerRequirement', $this->typeId]
|
||||||
);
|
);
|
||||||
|
|
||||||
$trainer = new CreatureList($conditions);
|
$trainer = new CreatureList($conditions);
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class ClassesPage extends GenericPage
|
class ClassesPage extends GenericPage
|
||||||
{
|
{
|
||||||
use ListPage;
|
use TrListPage;
|
||||||
|
|
||||||
protected $type = TYPE_CLASS;
|
protected $type = Type::CHR_CLASS;
|
||||||
protected $tpl = 'list-page-generic';
|
protected $tpl = 'list-page-generic';
|
||||||
protected $path = [0, 12];
|
protected $path = [0, 12];
|
||||||
protected $tabId = 0;
|
protected $tabId = 0;
|
||||||
|
|||||||
@@ -12,28 +12,31 @@ class ComparePage extends GenericPage
|
|||||||
protected $path = [1, 3];
|
protected $path = [1, 3];
|
||||||
protected $mode = CACHE_TYPE_NONE;
|
protected $mode = CACHE_TYPE_NONE;
|
||||||
protected $js = array(
|
protected $js = array(
|
||||||
'profile.js',
|
[JS_FILE, 'profile.js'],
|
||||||
'Draggable.js',
|
[JS_FILE, 'Draggable.js'],
|
||||||
'filters.js',
|
[JS_FILE, 'filters.js'],
|
||||||
'Summary.js',
|
[JS_FILE, 'Summary.js'],
|
||||||
'swfobject.js',
|
[JS_FILE, 'swfobject.js'],
|
||||||
);
|
);
|
||||||
protected $css = [['path' => 'Summary.css']];
|
protected $css = [[CSS_FILE, 'Summary.css']];
|
||||||
|
|
||||||
protected $summary = [];
|
protected $summary = [];
|
||||||
protected $cmpItems = [];
|
protected $cmpItems = [];
|
||||||
|
|
||||||
|
protected $_get = ['compare' => ['filter' => FILTER_CALLBACK, 'options' => 'ComparePage::checkCompareString']];
|
||||||
|
protected $_cookie = ['compare_groups' => ['filter' => FILTER_CALLBACK, 'options' => 'ComparePage::checkCompareString']];
|
||||||
|
|
||||||
private $compareString = '';
|
private $compareString = '';
|
||||||
|
|
||||||
public function __construct($pageCall, $__)
|
public function __construct($pageCall, $__)
|
||||||
{
|
{
|
||||||
parent::__construct($pageCall, $__);
|
parent::__construct($pageCall, $__);
|
||||||
|
|
||||||
// prefer $_GET over $_COOKIE
|
// prefer GET over COOKIE
|
||||||
if (!empty($_GET['compare']))
|
if ($this->_get['compare'])
|
||||||
$this->compareString = $_GET['compare'];
|
$this->compareString = $this->_get['compare'];
|
||||||
else if (!empty($_COOKIE['compare_groups']))
|
else if ($this->_cookie['compare_groups'])
|
||||||
$this->compareString = urldecode($_COOKIE['compare_groups']);
|
$this->compareString = $this->_cookie['compare_groups'];
|
||||||
|
|
||||||
$this->name = Lang::main('compareTool');
|
$this->name = Lang::main('compareTool');
|
||||||
}
|
}
|
||||||
@@ -41,7 +44,7 @@ class ComparePage extends GenericPage
|
|||||||
protected function generateContent()
|
protected function generateContent()
|
||||||
{
|
{
|
||||||
// add conditional js
|
// add conditional js
|
||||||
$this->addJS('?data=weight-presets.gems.enchants.itemsets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
$this->addScript([JS_FILE, '?data=weight-presets.gems.enchants.itemsets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']]);
|
||||||
|
|
||||||
$this->summary = array(
|
$this->summary = array(
|
||||||
'template' => 'compare',
|
'template' => 'compare',
|
||||||
@@ -56,14 +59,12 @@ class ComparePage extends GenericPage
|
|||||||
$items = $outSet = [];
|
$items = $outSet = [];
|
||||||
foreach ($sets as $set)
|
foreach ($sets as $set)
|
||||||
{
|
{
|
||||||
$itemSting = explode(':', $set);
|
$itemString = explode(':', $set);
|
||||||
$outString = [];
|
$outString = [];
|
||||||
foreach ($itemSting as $substring)
|
foreach ($itemString as $is)
|
||||||
{
|
{
|
||||||
$params = explode('.', $substring);
|
$params = array_pad(explode('.', $is), 7, 0);
|
||||||
$items[] = (int)$params[0];
|
$items[] = (int)$params[0];
|
||||||
while (sizeof($params) < 7)
|
|
||||||
$params[] = 0;
|
|
||||||
|
|
||||||
$outString[] = $params;
|
$outString[] = $params;
|
||||||
}
|
}
|
||||||
@@ -100,6 +101,15 @@ class ComparePage extends GenericPage
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function generatePath() {}
|
protected function generatePath() {}
|
||||||
|
|
||||||
|
protected static function checkCompareString(string $val) : string
|
||||||
|
{
|
||||||
|
$val = urldecode($val);
|
||||||
|
if (preg_match('/[^\d\.:;]/', $val))
|
||||||
|
return '';
|
||||||
|
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class CurrenciesPage extends GenericPage
|
class CurrenciesPage extends GenericPage
|
||||||
{
|
{
|
||||||
use ListPage;
|
use TrListPage;
|
||||||
|
|
||||||
protected $type = TYPE_CURRENCY;
|
protected $type = Type::CURRENCY;
|
||||||
protected $tpl = 'list-page-generic';
|
protected $tpl = 'list-page-generic';
|
||||||
protected $path = [0, 15];
|
protected $path = [0, 15];
|
||||||
protected $tabId = 0;
|
protected $tabId = 0;
|
||||||
|
|||||||
@@ -8,28 +8,32 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class CurrencyPage extends GenericPage
|
class CurrencyPage extends GenericPage
|
||||||
{
|
{
|
||||||
use DetailPage;
|
use TrDetailPage;
|
||||||
|
|
||||||
protected $type = TYPE_CURRENCY;
|
protected $type = Type::CURRENCY;
|
||||||
protected $typeId = 0;
|
protected $typeId = 0;
|
||||||
protected $tpl = 'detail-page-generic';
|
protected $tpl = 'detail-page-generic';
|
||||||
protected $path = [0, 15];
|
protected $path = [0, 15];
|
||||||
protected $tabId = 0;
|
protected $tabId = 0;
|
||||||
protected $mode = CACHE_TYPE_PAGE;
|
protected $mode = CACHE_TYPE_PAGE;
|
||||||
|
|
||||||
|
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']];
|
||||||
|
|
||||||
|
private $powerTpl = '$WowheadPower.registerCurrency(%d, %d, %s);';
|
||||||
|
|
||||||
public function __construct($pageCall, $id)
|
public function __construct($pageCall, $id)
|
||||||
{
|
{
|
||||||
parent::__construct($pageCall, $id);
|
parent::__construct($pageCall, $id);
|
||||||
|
|
||||||
// temp locale
|
// temp locale
|
||||||
if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain']))
|
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
|
||||||
Util::powerUseLocale($_GET['domain']);
|
Util::powerUseLocale($this->_get['domain']);
|
||||||
|
|
||||||
$this->typeId = intVal($id);
|
$this->typeId = intVal($id);
|
||||||
|
|
||||||
$this->subject = new CurrencyList(array(['id', $this->typeId]));
|
$this->subject = new CurrencyList(array(['id', $this->typeId]));
|
||||||
if ($this->subject->error)
|
if ($this->subject->error)
|
||||||
$this->notFound();
|
$this->notFound(Lang::game('currency'), Lang::currency('notFound'));
|
||||||
|
|
||||||
$this->name = $this->subject->getField('name', true);
|
$this->name = $this->subject->getField('name', true);
|
||||||
}
|
}
|
||||||
@@ -46,7 +50,7 @@ class CurrencyPage extends GenericPage
|
|||||||
|
|
||||||
protected function generateContent()
|
protected function generateContent()
|
||||||
{
|
{
|
||||||
$this->addJS('?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
$this->addScript([JS_FILE, '?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']]);
|
||||||
|
|
||||||
$_itemId = $this->subject->getField('itemId');
|
$_itemId = $this->subject->getField('itemId');
|
||||||
|
|
||||||
@@ -56,9 +60,17 @@ class CurrencyPage extends GenericPage
|
|||||||
|
|
||||||
$infobox = Lang::getInfoBoxForFlags(intval($this->subject->getField('cuFlags')));
|
$infobox = Lang::getInfoBoxForFlags(intval($this->subject->getField('cuFlags')));
|
||||||
|
|
||||||
|
// cap
|
||||||
if ($_ = $this->subject->getField('cap'))
|
if ($_ = $this->subject->getField('cap'))
|
||||||
$infobox[] = Lang::currency('cap').Lang::main('colon').Lang::nf($_);
|
$infobox[] = Lang::currency('cap').Lang::main('colon').Lang::nf($_);
|
||||||
|
|
||||||
|
// icon
|
||||||
|
if ($_ = $this->subject->getField('iconId'))
|
||||||
|
{
|
||||||
|
$infobox[] = Util::ucFirst(lang::game('icon')).Lang::main('colon').'[icondb='.$_.' name=true]';
|
||||||
|
$this->extendGlobalIds(Type::ICON, $_);
|
||||||
|
}
|
||||||
|
|
||||||
/****************/
|
/****************/
|
||||||
/* Main Content */
|
/* Main Content */
|
||||||
/****************/
|
/****************/
|
||||||
@@ -87,7 +99,7 @@ class CurrencyPage extends GenericPage
|
|||||||
{
|
{
|
||||||
$this->extendGlobalData($lootTabs->jsGlobals);
|
$this->extendGlobalData($lootTabs->jsGlobals);
|
||||||
|
|
||||||
foreach ($lootTabs->iterate() as list($file, $tabData))
|
foreach ($lootTabs->iterate() as [$file, $tabData])
|
||||||
$this->lvTabs[] = [$file, $tabData];
|
$this->lvTabs[] = [$file, $tabData];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +121,8 @@ class CurrencyPage extends GenericPage
|
|||||||
{
|
{
|
||||||
$items = [];
|
$items = [];
|
||||||
$tokens = [];
|
$tokens = [];
|
||||||
foreach ($vendors[$k] as $id => $qty)
|
// note: can only display one entry per row, so only use first entry of each vendor
|
||||||
|
foreach ($vendors[$k][0] as $id => $qty)
|
||||||
{
|
{
|
||||||
if (is_string($id))
|
if (is_string($id))
|
||||||
continue;
|
continue;
|
||||||
@@ -120,16 +133,16 @@ class CurrencyPage extends GenericPage
|
|||||||
$items[] = [-$id, $qty];
|
$items[] = [-$id, $qty];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($vendors[$k]['event'])
|
if ($vendors[$k][0]['event'])
|
||||||
{
|
{
|
||||||
if (count($extraCols) == 3) // not already pushed
|
if (count($extraCols) == 3) // not already pushed
|
||||||
$extraCols[] = '$Listview.extraCols.condition';
|
$extraCols[] = '$Listview.extraCols.condition';
|
||||||
|
|
||||||
$this->extendGlobalIds(TYPE_WORLDEVENT, $vendors[$k]['event']);
|
$this->extendGlobalIds(Type::WORLDEVENT, $vendors[$k][0]['event']);
|
||||||
$row['condition'][0][$this->typeId][] = [[CND_ACTIVE_EVENT, $vendors[$k]['event']]];
|
$row['condition'][0][$this->typeId][] = [[CND_ACTIVE_EVENT, $vendors[$k][0]['event']]];
|
||||||
}
|
}
|
||||||
|
|
||||||
$row['stock'] = $vendors[$k]['stock'];
|
$row['stock'] = $vendors[$k][0]['stock'];
|
||||||
$row['stack'] = $itemObj->getField('buyCount');
|
$row['stack'] = $itemObj->getField('buyCount');
|
||||||
$row['cost'] = array(
|
$row['cost'] = array(
|
||||||
$itemObj->getField('buyPrice'),
|
$itemObj->getField('buyPrice'),
|
||||||
@@ -195,10 +208,10 @@ class CurrencyPage extends GenericPage
|
|||||||
if (!$boughtBy->error)
|
if (!$boughtBy->error)
|
||||||
{
|
{
|
||||||
$tabData = array(
|
$tabData = array(
|
||||||
'data' => array_values($boughtBy->getListviewData(ITEMINFO_VENDOR, [TYPE_CURRENCY => $this->typeId])),
|
'data' => array_values($boughtBy->getListviewData(ITEMINFO_VENDOR, [Type::CURRENCY => $this->typeId])),
|
||||||
'name' => '$LANG.tab_currencyfor',
|
'name' => '$LANG.tab_currencyfor',
|
||||||
'id' => 'currency-for',
|
'id' => 'currency-for',
|
||||||
'extraCols' => ["\$Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')"],
|
'extraCols' => ["\$Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", '$Listview.extraCols.cost'],
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($boughtBy->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
if ($boughtBy->getMatches() > CFG_SQL_LIMIT_DEFAULT)
|
||||||
@@ -211,43 +224,17 @@ class CurrencyPage extends GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function generateTooltip($asError = false)
|
protected function generateTooltip()
|
||||||
{
|
{
|
||||||
if ($asError)
|
$power = new StdClass();
|
||||||
return '$WowheadPower.registerCurrency('.$this->typeId.', '.User::$localeId.', {});';
|
if (!$this->subject->error)
|
||||||
|
|
||||||
$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();
|
$power->{'name_'.User::$localeString} = $this->subject->getField('name', true);
|
||||||
$this->saveCache($tt);
|
$power->icon = rawurlencode($this->subject->getField('iconString', true, true));
|
||||||
|
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
header('Content-type: application/x-javascript; charset=utf-8');
|
return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabid 0: Database g_initHeader()
|
// tabid 0: Database g_initHeader()
|
||||||
class EmotePage extends GenericPage
|
class EmotePage extends GenericPage
|
||||||
{
|
{
|
||||||
use DetailPage;
|
use TrDetailPage;
|
||||||
|
|
||||||
protected $type = TYPE_EMOTE;
|
protected $type = Type::EMOTE;
|
||||||
protected $typeId = 0;
|
protected $typeId = 0;
|
||||||
protected $tpl = 'detail-page-generic';
|
protected $tpl = 'detail-page-generic';
|
||||||
protected $path = [0, 100];
|
protected $path = [0, 100];
|
||||||
@@ -25,7 +25,7 @@ class EmotePage extends GenericPage
|
|||||||
|
|
||||||
$this->subject = new EmoteList(array(['id', $this->typeId]));
|
$this->subject = new EmoteList(array(['id', $this->typeId]));
|
||||||
if ($this->subject->error)
|
if ($this->subject->error)
|
||||||
$this->notFound(Util::ucFirst(Lang::game('emote')), Lang::emote('notFound'));
|
$this->notFound(Lang::game('emote'), Lang::emote('notFound'));
|
||||||
|
|
||||||
$this->name = Util::ucFirst($this->subject->getField('cmd'));
|
$this->name = Util::ucFirst($this->subject->getField('cmd'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabid 0: Database g_initHeader()
|
// tabid 0: Database g_initHeader()
|
||||||
class EmotesPage extends GenericPage
|
class EmotesPage extends GenericPage
|
||||||
{
|
{
|
||||||
use ListPage;
|
use TrListPage;
|
||||||
|
|
||||||
protected $type = TYPE_EMOTE;
|
protected $type = Type::EMOTE;
|
||||||
protected $tpl = 'list-page-generic';
|
protected $tpl = 'list-page-generic';
|
||||||
protected $path = [0, 100];
|
protected $path = [0, 100];
|
||||||
protected $tabId = 0;
|
protected $tabId = 0;
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class EnchantmentPage extends GenericPage
|
class EnchantmentPage extends GenericPage
|
||||||
{
|
{
|
||||||
use DetailPage;
|
use TrDetailPage;
|
||||||
|
|
||||||
protected $type = TYPE_ENCHANTMENT;
|
protected $type = Type::ENCHANTMENT;
|
||||||
protected $typeId = 0;
|
protected $typeId = 0;
|
||||||
protected $tpl = 'enchantment';
|
protected $tpl = 'enchantment';
|
||||||
protected $path = [0, 101];
|
protected $path = [0, 101];
|
||||||
@@ -25,7 +25,7 @@ class EnchantmentPage extends GenericPage
|
|||||||
|
|
||||||
$this->subject = new EnchantmentList(array(['id', $this->typeId]));
|
$this->subject = new EnchantmentList(array(['id', $this->typeId]));
|
||||||
if ($this->subject->error)
|
if ($this->subject->error)
|
||||||
$this->notFound(Util::ucFirst(Lang::game('enchantment')), Lang::enchantment('notFound'));
|
$this->notFound(Lang::game('enchantment'), Lang::enchantment('notFound'));
|
||||||
|
|
||||||
$this->extendGlobalData($this->subject->getJSGlobals());
|
$this->extendGlobalData($this->subject->getJSGlobals());
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ class EnchantmentPage extends GenericPage
|
|||||||
// reqskill
|
// reqskill
|
||||||
if ($_ = $this->subject->getField('skillLine'))
|
if ($_ = $this->subject->getField('skillLine'))
|
||||||
{
|
{
|
||||||
$this->extendGlobalIds(TYPE_SKILL, $_);
|
$this->extendGlobalIds(Type::SKILL, $_);
|
||||||
|
|
||||||
$foo = sprintf(Lang::game('requires'), ' [skill='.$_.']');
|
$foo = sprintf(Lang::game('requires'), ' [skill='.$_.']');
|
||||||
if ($_ = $this->subject->getField('skillLevel'))
|
if ($_ = $this->subject->getField('skillLevel'))
|
||||||
@@ -195,7 +195,7 @@ class EnchantmentPage extends GenericPage
|
|||||||
{
|
{
|
||||||
$this->lvTabs[] = ['item', array(
|
$this->lvTabs[] = ['item', array(
|
||||||
'data' => array_values($socketsList->getListviewData()),
|
'data' => array_values($socketsList->getListviewData()),
|
||||||
'name' => '$LANG.tab_usedby + \' \' + \''.Lang::item('socketBonus').'\'',
|
'name' => '$LANG.tab_socketbonus',
|
||||||
'id' => 'used-by-socketbonus',
|
'id' => 'used-by-socketbonus',
|
||||||
)];
|
)];
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,16 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class EnchantmentsPage extends GenericPage
|
class EnchantmentsPage extends GenericPage
|
||||||
{
|
{
|
||||||
use ListPage;
|
use TrListPage;
|
||||||
|
|
||||||
protected $type = TYPE_ENCHANTMENT;
|
protected $type = Type::ENCHANTMENT;
|
||||||
protected $tpl = 'enchantments';
|
protected $tpl = 'enchantments';
|
||||||
protected $path = [0, 101];
|
protected $path = [0, 101];
|
||||||
protected $tabId = 0;
|
protected $tabId = 0;
|
||||||
protected $mode = CACHE_TYPE_PAGE;
|
protected $mode = CACHE_TYPE_PAGE;
|
||||||
protected $js = ['filters.js'];
|
protected $js = [[JS_FILE, 'filters.js']];
|
||||||
|
|
||||||
|
protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]];
|
||||||
|
|
||||||
public function __construct($pageCall, $pageParam)
|
public function __construct($pageCall, $pageParam)
|
||||||
{
|
{
|
||||||
@@ -25,7 +27,7 @@ class EnchantmentsPage extends GenericPage
|
|||||||
parent::__construct($pageCall, $pageParam);
|
parent::__construct($pageCall, $pageParam);
|
||||||
|
|
||||||
$this->name = Util::ucFirst(Lang::game('enchantments'));
|
$this->name = Util::ucFirst(Lang::game('enchantments'));
|
||||||
$this->subCat = $pageParam !== null ? '='.$pageParam : '';
|
$this->subCat = $pageParam !== '' ? '='.$pageParam : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function generateContent()
|
protected function generateContent()
|
||||||
@@ -50,7 +52,7 @@ class EnchantmentsPage extends GenericPage
|
|||||||
|
|
||||||
// recreate form selection
|
// recreate form selection
|
||||||
$this->filter = $this->filterObj->getForm();
|
$this->filter = $this->filterObj->getForm();
|
||||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL;
|
$this->filter['query'] = $this->_get['filter'];
|
||||||
$this->filter['initData'] = ['init' => 'enchantments'];
|
$this->filter['initData'] = ['init' => 'enchantments'];
|
||||||
|
|
||||||
if ($x = $this->filterObj->getSetCriteria())
|
if ($x = $this->filterObj->getSetCriteria())
|
||||||
@@ -100,8 +102,8 @@ class EnchantmentsPage extends GenericPage
|
|||||||
protected function generatePath()
|
protected function generatePath()
|
||||||
{
|
{
|
||||||
$form = $this->filterObj->getForm('form');
|
$form = $this->filterObj->getForm('form');
|
||||||
if (isset($form['ty']) && !is_array($form['ty']))
|
if (isset($form['ty']) && count($form['ty']) == 1)
|
||||||
$this->path[] = $form['ty'];
|
$this->path[] = $form['ty'][0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,15 +8,18 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class EventPage extends GenericPage
|
class EventPage extends GenericPage
|
||||||
{
|
{
|
||||||
use DetailPage;
|
use TrDetailPage;
|
||||||
|
|
||||||
protected $type = TYPE_WORLDEVENT;
|
protected $type = Type::WORLDEVENT;
|
||||||
protected $typeId = 0;
|
protected $typeId = 0;
|
||||||
protected $tpl = 'detail-page-generic';
|
protected $tpl = 'detail-page-generic';
|
||||||
protected $path = [0, 11];
|
protected $path = [0, 11];
|
||||||
protected $tabId = 0;
|
protected $tabId = 0;
|
||||||
protected $mode = CACHE_TYPE_PAGE;
|
protected $mode = CACHE_TYPE_PAGE;
|
||||||
|
|
||||||
|
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']];
|
||||||
|
|
||||||
|
private $powerTpl = '$WowheadPower.registerHoliday(%d, %d, %s);';
|
||||||
private $hId = 0;
|
private $hId = 0;
|
||||||
private $eId = 0;
|
private $eId = 0;
|
||||||
|
|
||||||
@@ -25,14 +28,14 @@ class EventPage extends GenericPage
|
|||||||
parent::__construct($pageCall, $id);
|
parent::__construct($pageCall, $id);
|
||||||
|
|
||||||
// temp locale
|
// temp locale
|
||||||
if ($this->mode == CACHE_TYPE_TOOLTIP && isset($_GET['domain']))
|
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
|
||||||
Util::powerUseLocale($_GET['domain']);
|
Util::powerUseLocale($this->_get['domain']);
|
||||||
|
|
||||||
$this->typeId = intVal($id);
|
$this->typeId = intVal($id);
|
||||||
|
|
||||||
$this->subject = new WorldEventList(array(['id', $this->typeId]));
|
$this->subject = new WorldEventList(array(['id', $this->typeId]));
|
||||||
if ($this->subject->error)
|
if ($this->subject->error)
|
||||||
$this->notFound();
|
$this->notFound(Lang::game('event'), Lang::event('notFound'));
|
||||||
|
|
||||||
$this->hId = $this->subject->getField('holidayId');
|
$this->hId = $this->subject->getField('holidayId');
|
||||||
$this->eId = $this->typeId;
|
$this->eId = $this->typeId;
|
||||||
@@ -64,7 +67,7 @@ class EventPage extends GenericPage
|
|||||||
|
|
||||||
protected function generateContent()
|
protected function generateContent()
|
||||||
{
|
{
|
||||||
$this->addJS('?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
$this->addScript([JS_FILE, '?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']]);
|
||||||
|
|
||||||
/***********/
|
/***********/
|
||||||
/* Infobox */
|
/* Infobox */
|
||||||
@@ -75,7 +78,7 @@ class EventPage extends GenericPage
|
|||||||
// boss
|
// boss
|
||||||
if ($_ = $this->subject->getField('bossCreature'))
|
if ($_ = $this->subject->getField('bossCreature'))
|
||||||
{
|
{
|
||||||
$this->extendGlobalIds(TYPE_NPC, $_);
|
$this->extendGlobalIds(Type::NPC, $_);
|
||||||
$this->infobox[] = Lang::npc('rank', 3).Lang::main('colon').'[npc='.$_.']';
|
$this->infobox[] = Lang::npc('rank', 3).Lang::main('colon').'[npc='.$_.']';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,10 +187,10 @@ class EventPage extends GenericPage
|
|||||||
$this->lvTabs[] = ['quest', $tabData];
|
$this->lvTabs[] = ['quest', $tabData];
|
||||||
|
|
||||||
$questItems = [];
|
$questItems = [];
|
||||||
foreach (array_column($quests->rewards, TYPE_ITEM) as $arr)
|
foreach (array_column($quests->rewards, Type::ITEM) as $arr)
|
||||||
$questItems = array_merge($questItems, $arr);
|
$questItems = array_merge($questItems, $arr);
|
||||||
|
|
||||||
foreach (array_column($quests->requires, TYPE_ITEM) as $arr)
|
foreach (array_column($quests->requires, Type::ITEM) as $arr)
|
||||||
$questItems = array_merge($questItems, $arr);
|
$questItems = array_merge($questItems, $arr);
|
||||||
|
|
||||||
if ($questItems)
|
if ($questItems)
|
||||||
@@ -247,7 +250,7 @@ class EventPage extends GenericPage
|
|||||||
if ($r <= 0)
|
if ($r <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$this->extendGlobalIds(TYPE_WORLDEVENT, $r);
|
$this->extendGlobalIds(Type::WORLDEVENT, $r);
|
||||||
|
|
||||||
$d = $this->subject->getListviewData();
|
$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]];
|
||||||
@@ -266,6 +269,22 @@ class EventPage extends GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function generateTooltip() : string
|
||||||
|
{
|
||||||
|
$power = new StdClass();
|
||||||
|
if (!$this->subject->error)
|
||||||
|
{
|
||||||
|
$power->{'name_'.User::$localeString} = $this->subject->getField('name', true);
|
||||||
|
|
||||||
|
if ($this->subject->getField('iconString') != 'trade_engineering')
|
||||||
|
$power->icon = rawurlencode($this->subject->getField('iconString', true, true));
|
||||||
|
|
||||||
|
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
|
||||||
|
}
|
||||||
|
|
||||||
protected function postCache()
|
protected function postCache()
|
||||||
{
|
{
|
||||||
// update dates to now()
|
// update dates to now()
|
||||||
@@ -326,50 +345,6 @@ class EventPage extends GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class EventsPage extends GenericPage
|
class EventsPage extends GenericPage
|
||||||
{
|
{
|
||||||
use ListPage;
|
use TrListPage;
|
||||||
|
|
||||||
protected $type = TYPE_WORLDEVENT;
|
protected $type = Type::WORLDEVENT;
|
||||||
protected $tpl = 'list-page-generic';
|
protected $tpl = 'list-page-generic';
|
||||||
protected $path = [0, 11];
|
protected $path = [0, 11];
|
||||||
protected $tabId = 0;
|
protected $tabId = 0;
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class FactionPage extends GenericPage
|
class FactionPage extends GenericPage
|
||||||
{
|
{
|
||||||
use DetailPage;
|
use TrDetailPage;
|
||||||
|
|
||||||
protected $type = TYPE_FACTION;
|
protected $type = Type::FACTION;
|
||||||
protected $typeId = 0;
|
protected $typeId = 0;
|
||||||
protected $tpl = 'detail-page-generic';
|
protected $tpl = 'detail-page-generic';
|
||||||
protected $path = [0, 7];
|
protected $path = [0, 7];
|
||||||
@@ -48,7 +48,7 @@ class FactionPage extends GenericPage
|
|||||||
|
|
||||||
protected function generateContent()
|
protected function generateContent()
|
||||||
{
|
{
|
||||||
$this->addJS('?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
$this->addScript([JS_FILE, '?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']]);
|
||||||
|
|
||||||
/***********/
|
/***********/
|
||||||
/* Infobox */
|
/* Infobox */
|
||||||
@@ -58,7 +58,7 @@ class FactionPage extends GenericPage
|
|||||||
// Quartermaster if any
|
// Quartermaster if any
|
||||||
if ($ids = $this->subject->getField('qmNpcIds'))
|
if ($ids = $this->subject->getField('qmNpcIds'))
|
||||||
{
|
{
|
||||||
$this->extendGlobalIds(TYPE_NPC, $ids);
|
$this->extendGlobalIds(Type::NPC, ...$ids);
|
||||||
|
|
||||||
$qmStr = Lang::faction('quartermaster').Lang::main('colon');
|
$qmStr = Lang::faction('quartermaster').Lang::main('colon');
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ class FactionPage extends GenericPage
|
|||||||
case 'creature_rate': $buff .= '[tr][td]'.Lang::game('npcs') .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 'spell_rate': $buff .= '[tr][td]'.Lang::game('spells') .Lang::main('colon').'[/td]'; break;
|
||||||
default:
|
default:
|
||||||
continue;
|
continue 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
$buff .= '[td width=35px align=right][span class=q'.($v < 1 ? '10]' : '2]+').intVal(($v - 1) * 100).'%[/span][/td][/tr]';
|
$buff .= '[td width=35px align=right][span class=q'.($v < 1 ? '10]' : '2]+').intVal(($v - 1) * 100).'%[/span][/td][/tr]';
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class FactionsPage extends GenericPage
|
class FactionsPage extends GenericPage
|
||||||
{
|
{
|
||||||
use ListPage;
|
use TrListPage;
|
||||||
|
|
||||||
protected $type = TYPE_FACTION;
|
protected $type = Type::FACTION;
|
||||||
protected $tpl = 'list-page-generic';
|
protected $tpl = 'list-page-generic';
|
||||||
protected $path = [0, 7];
|
protected $path = [0, 7];
|
||||||
protected $tabId = 0;
|
protected $tabId = 0;
|
||||||
|
|||||||
@@ -4,21 +4,20 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
die('illegal access');
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
trait DetailPage
|
trait TrDetailPage
|
||||||
{
|
{
|
||||||
protected $hasComContent = true;
|
protected $category = null; // not used on detail pages
|
||||||
protected $category = null; // not used on detail pages
|
protected $lvTabs = []; // most pages have this
|
||||||
protected $lvTabs = []; // most pages have this
|
|
||||||
|
|
||||||
protected $ssError = null;
|
protected $ssError = null;
|
||||||
protected $coError = null;
|
protected $coError = null;
|
||||||
protected $viError = null;
|
protected $viError = null;
|
||||||
|
|
||||||
protected $subject = null; // so it will not get cached
|
protected $subject = null; // so it will not get cached
|
||||||
|
|
||||||
protected $contribute = CONTRIBUTE_ANY;
|
protected $contribute = CONTRIBUTE_ANY;
|
||||||
|
|
||||||
protected function generateCacheKey($withStaff = true)
|
protected function generateCacheKey(bool $withStaff = true) : string
|
||||||
{
|
{
|
||||||
$staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE));
|
$staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE));
|
||||||
|
|
||||||
@@ -32,7 +31,7 @@ trait DetailPage
|
|||||||
return implode('_', $key);
|
return implode('_', $key);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function applyCCErrors()
|
protected function applyCCErrors() : void
|
||||||
{
|
{
|
||||||
if (!empty($_SESSION['error']['co']))
|
if (!empty($_SESSION['error']['co']))
|
||||||
$this->coError = $_SESSION['error']['co'];
|
$this->coError = $_SESSION['error']['co'];
|
||||||
@@ -48,7 +47,7 @@ trait DetailPage
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
trait ListPage
|
trait TrListPage
|
||||||
{
|
{
|
||||||
protected $category = null;
|
protected $category = null;
|
||||||
protected $filter = [];
|
protected $filter = [];
|
||||||
@@ -56,7 +55,7 @@ trait ListPage
|
|||||||
|
|
||||||
private $filterObj = null;
|
private $filterObj = null;
|
||||||
|
|
||||||
protected function generateCacheKey($withStaff = true)
|
protected function generateCacheKey(bool $withStaff = true) : string
|
||||||
{
|
{
|
||||||
$staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE));
|
$staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE));
|
||||||
|
|
||||||
@@ -73,6 +72,7 @@ trait ListPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
trait TrProfiler
|
trait TrProfiler
|
||||||
{
|
{
|
||||||
protected $region = '';
|
protected $region = '';
|
||||||
@@ -85,22 +85,29 @@ trait TrProfiler
|
|||||||
|
|
||||||
protected $doResync = null;
|
protected $doResync = null;
|
||||||
|
|
||||||
protected function getSubjectFromUrl($str)
|
protected function generateCacheKey(bool $withStaff = true) : string
|
||||||
{
|
{
|
||||||
if (!$str)
|
$staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE));
|
||||||
|
|
||||||
|
// mode, type, typeId, employee-flag, localeId, category, filter
|
||||||
|
$key = [$this->mode, $this->type, $this->subject->getField('id'), $staff, User::$localeId, '-1', '-1'];
|
||||||
|
|
||||||
|
return implode('_', $key);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getSubjectFromUrl(string $pageParam) : void
|
||||||
|
{
|
||||||
|
if (!$pageParam)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// cat[0] is always region
|
// cat[0] is always region
|
||||||
// cat[1] is realm or bGroup (must be realm if cat[2] is set)
|
// cat[1] is realm or bGroup (must be realm if cat[2] is set)
|
||||||
// cat[2] is arena-team, guild or player
|
// cat[2] is arena-team, guild or player
|
||||||
$cat = explode('.', $str, 3);
|
$cat = explode('.', $pageParam, 3);
|
||||||
|
|
||||||
$cat = array_map('urldecode', $cat);
|
$cat = array_map('urldecode', $cat);
|
||||||
|
|
||||||
if (count($cat) > 3)
|
if (array_search($cat[0], Util::$regions) === false)
|
||||||
return;
|
|
||||||
|
|
||||||
if ($cat[0] !== 'eu' && $cat[0] !== 'us')
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$this->region = $cat[0];
|
$this->region = $cat[0];
|
||||||
@@ -111,11 +118,11 @@ trait TrProfiler
|
|||||||
{
|
{
|
||||||
foreach (Profiler::getRealms() as $rId => $r)
|
foreach (Profiler::getRealms() as $rId => $r)
|
||||||
{
|
{
|
||||||
if (Profiler::urlize($r['name']) == $cat[1])
|
if (Profiler::urlize($r['name'], true) == $cat[1])
|
||||||
{
|
{
|
||||||
$this->realm = $r['name'];
|
$this->realm = $r['name'];
|
||||||
$this->realmId = $rId;
|
$this->realmId = $rId;
|
||||||
if (isset($cat[2]) && mb_strlen($cat[2]) >= 3)
|
if (isset($cat[2]) && mb_strlen($cat[2]) >= 2)
|
||||||
$this->subjectName = $cat[2]; // cannot reconstruct original name from urlized form; match against special name field
|
$this->subjectName = $cat[2]; // cannot reconstruct original name from urlized form; match against special name field
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -124,44 +131,49 @@ trait TrProfiler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function initialSync()
|
protected function initialSync() : void
|
||||||
{
|
{
|
||||||
$this->prepareContent();
|
$this->prepareContent();
|
||||||
|
|
||||||
$this->notFound = array(
|
$this->contribute = CONTRIBUTE_NONE;
|
||||||
|
$this->notFound = array(
|
||||||
'title' => sprintf(Lang::profiler('firstUseTitle'), $this->subjectName, $this->realm),
|
'title' => sprintf(Lang::profiler('firstUseTitle'), $this->subjectName, $this->realm),
|
||||||
'msg' => ''
|
'msg' => ''
|
||||||
);
|
);
|
||||||
$this->hasComContent = false;
|
|
||||||
Util::arraySumByKey($this->mysql, DB::Aowow()->getStatistics(), DB::World()->getStatistics());
|
|
||||||
|
|
||||||
if (isset($this->tabId))
|
if (isset($this->tabId))
|
||||||
$this->pageTemplate['activeTab'] = $this->tabId;
|
$this->pageTemplate['activeTab'] = $this->tabId;
|
||||||
|
|
||||||
|
$this->sumSQLStats();
|
||||||
|
|
||||||
$this->display('text-page-generic');
|
$this->display('text-page-generic');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function generatePath()
|
protected function generatePath() : void
|
||||||
{
|
{
|
||||||
if ($this->region)
|
if ($this->region)
|
||||||
{
|
{
|
||||||
$this->path[] = $this->region;
|
$this->path[] = $this->region;
|
||||||
|
|
||||||
if ($this->realm)
|
if ($this->realm)
|
||||||
$this->path[] = Profiler::urlize($this->realm);
|
$this->path[] = Profiler::urlize($this->realm, true);
|
||||||
// else
|
// else
|
||||||
// $this->path[] = Profiler::urlize(CFG_BATTLEGROUP);
|
// $this->path[] = Profiler::urlize(CFG_BATTLEGROUP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class GenericPage
|
class GenericPage
|
||||||
{
|
{
|
||||||
|
use TrRequestData;
|
||||||
|
|
||||||
protected $tpl = '';
|
protected $tpl = '';
|
||||||
protected $reqUGroup = U_GROUP_NONE;
|
protected $reqUGroup = U_GROUP_NONE;
|
||||||
protected $reqAuth = false;
|
protected $reqAuth = false;
|
||||||
protected $mode = CACHE_TYPE_NONE;
|
protected $mode = CACHE_TYPE_NONE;
|
||||||
|
// protected $contribute; // defined in __construct()
|
||||||
|
|
||||||
protected $jsGlobals = [];
|
protected $jsGlobals = [];
|
||||||
protected $lvData = [];
|
protected $lvData = [];
|
||||||
@@ -191,6 +203,7 @@ class GenericPage
|
|||||||
|
|
||||||
private $lvTemplates = array(
|
private $lvTemplates = array(
|
||||||
'achievement' => ['template' => 'achievement', 'id' => 'achievements', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_achievements' ],
|
'achievement' => ['template' => 'achievement', 'id' => 'achievements', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_achievements' ],
|
||||||
|
'areatrigger' => ['template' => 'areatrigger', 'id' => 'areatrigger', 'parent' => 'lv-generic', 'data' => [], ],
|
||||||
'calendar' => ['template' => 'holidaycal', 'id' => 'calendar', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_calendar' ],
|
'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' ],
|
'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' ],
|
'commentpreview' => ['template' => 'commentpreview', 'id' => 'comments', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_comments' ],
|
||||||
@@ -204,6 +217,7 @@ class GenericPage
|
|||||||
'icongallery' => ['template' => 'icongallery', 'id' => 'icons', 'parent' => 'lv-generic', 'data' => [] ],
|
'icongallery' => ['template' => 'icongallery', 'id' => 'icons', 'parent' => 'lv-generic', 'data' => [] ],
|
||||||
'item' => ['template' => 'item', 'id' => 'items', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_items' ],
|
'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' ],
|
'itemset' => ['template' => 'itemset', 'id' => 'itemsets', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_itemsets' ],
|
||||||
|
'mail' => ['template' => 'mail', 'id' => 'mails', 'parent' => 'lv-generic', 'data' => [] ],
|
||||||
'model' => ['template' => 'model', 'id' => 'gallery', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_gallery' ],
|
'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' ],
|
'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' ],
|
'pet' => ['template' => 'pet', 'id' => 'hunter-pets', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_pets' ],
|
||||||
@@ -219,13 +233,19 @@ class GenericPage
|
|||||||
'title' => ['template' => 'title', 'id' => 'titles', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_titles' ],
|
'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' ],
|
'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' ],
|
'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' ]
|
'zone' => ['template' => 'zone', 'id' => 'zones', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_zones' ],
|
||||||
|
'guide' => ['template' => 'guide', 'id' => 'guides', 'parent' => 'lv-generic', 'data' => [], ]
|
||||||
);
|
);
|
||||||
|
|
||||||
public function __construct($pageCall, $pageParam = null)
|
public function __construct(string $pageCall = '', string $pageParam = '')
|
||||||
{
|
{
|
||||||
$this->time = microtime(true);
|
$this->time = microtime(true);
|
||||||
|
|
||||||
|
$this->initRequestData();
|
||||||
|
|
||||||
|
if (!isset($this->contribute))
|
||||||
|
$this->contribute = CONTRIBUTE_NONE;
|
||||||
|
|
||||||
$this->fullParams = $pageCall;
|
$this->fullParams = $pageCall;
|
||||||
if ($pageParam)
|
if ($pageParam)
|
||||||
$this->fullParams .= '='.$pageParam;
|
$this->fullParams .= '='.$pageParam;
|
||||||
@@ -255,7 +275,8 @@ class GenericPage
|
|||||||
if ($ahl = DB::Aowow()->selectCell('SELECT altHeaderLogo FROM ?_home_featuredbox WHERE ?d BETWEEN startDate AND endDate ORDER BY id DESC', time()))
|
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->headerLogo = Util::defStatic($ahl);
|
||||||
|
|
||||||
$this->gUser = User::getUserGlobals();
|
$this->gUser = User::getUserGlobals();
|
||||||
|
$this->gFavorites = User::getFavorites();
|
||||||
$this->pageTemplate['pageName'] = strtolower($pageCall);
|
$this->pageTemplate['pageName'] = strtolower($pageCall);
|
||||||
|
|
||||||
if (!$this->isValidPage())
|
if (!$this->isValidPage())
|
||||||
@@ -264,7 +285,7 @@ class GenericPage
|
|||||||
|
|
||||||
// requires authed user
|
// requires authed user
|
||||||
if ($this->reqAuth && !User::$id)
|
if ($this->reqAuth && !User::$id)
|
||||||
$this->forwardToSignIn($_SERVER['QUERY_STRING']);
|
$this->forwardToSignIn($_SERVER['QUERY_STRING'] ?? '');
|
||||||
|
|
||||||
// restricted access
|
// restricted access
|
||||||
if ($this->reqUGroup && !User::isInGroup($this->reqUGroup))
|
if ($this->reqUGroup && !User::isInGroup($this->reqUGroup))
|
||||||
@@ -272,7 +293,7 @@ class GenericPage
|
|||||||
if (User::$id)
|
if (User::$id)
|
||||||
$this->error();
|
$this->error();
|
||||||
else
|
else
|
||||||
$this->forwardToSignIn($_SERVER['QUERY_STRING']);
|
$this->forwardToSignIn($_SERVER['QUERY_STRING'] ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CFG_MAINTENANCE && !User::isInGroup(U_GROUP_EMPLOYEE))
|
if (CFG_MAINTENANCE && !User::isInGroup(U_GROUP_EMPLOYEE))
|
||||||
@@ -285,11 +306,13 @@ class GenericPage
|
|||||||
$this->applyCCErrors();
|
$this->applyCCErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********/
|
/**********/
|
||||||
/* Checks */
|
/* Checks */
|
||||||
/**********/
|
/**********/
|
||||||
|
|
||||||
private function isSaneInclude($path, $file) // "template_exists"
|
// "template_exists"
|
||||||
|
private function isSaneInclude(string $path, string $file) : bool
|
||||||
{
|
{
|
||||||
if (preg_match('/[^\w\-]/i', str_replace('admin/', '', $file)))
|
if (preg_match('/[^\w\-]/i', str_replace('admin/', '', $file)))
|
||||||
return false;
|
return false;
|
||||||
@@ -300,7 +323,8 @@ class GenericPage
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function isValidPage() // has a valid combination of categories
|
// has a valid combination of categories
|
||||||
|
private function isValidPage() : bool
|
||||||
{
|
{
|
||||||
if (!isset($this->category) || empty($this->validCats))
|
if (!isset($this->category) || empty($this->validCats))
|
||||||
return true;
|
return true;
|
||||||
@@ -330,26 +354,34 @@ class GenericPage
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************/
|
/****************/
|
||||||
/* Prepare Page */
|
/* Prepare Page */
|
||||||
/****************/
|
/****************/
|
||||||
|
|
||||||
protected function prepareContent() // get from cache ?: run generators
|
// get from cache ?: run generators
|
||||||
|
protected function prepareContent() : void
|
||||||
{
|
{
|
||||||
if (!$this->loadCache())
|
if (!$this->loadCache())
|
||||||
{
|
{
|
||||||
$this->addArticle();
|
|
||||||
|
|
||||||
$this->generateContent();
|
$this->generateContent();
|
||||||
$this->generatePath();
|
$this->generatePath();
|
||||||
$this->generateTitle();
|
$this->generateTitle();
|
||||||
|
$this->addArticle();
|
||||||
|
|
||||||
$this->applyGlobals();
|
$this->applyGlobals();
|
||||||
|
|
||||||
$this->saveCache();
|
$this->saveCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->type) && isset($this->typeId))
|
if ($this instanceof GuidePage)
|
||||||
|
{
|
||||||
|
$this->gPageInfo = ['name' => $this->name];
|
||||||
|
if (isset($this->author))
|
||||||
|
$this->gPageInfo['author'] = $this->author;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (isset($this->type) && isset($this->typeId))
|
||||||
{
|
{
|
||||||
$this->gPageInfo = array( // varies slightly for special pages like maps, user-dashboard or profiler
|
$this->gPageInfo = array( // varies slightly for special pages like maps, user-dashboard or profiler
|
||||||
'type' => $this->type,
|
'type' => $this->type,
|
||||||
@@ -357,7 +389,9 @@ class GenericPage
|
|||||||
'name' => $this->name
|
'name' => $this->name
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (!empty($this->articleUrl))
|
|
||||||
|
// only adds edit links to the staff menu: precursor to guides?
|
||||||
|
if (!empty($this->articleUrl) && !($this instanceof GuidePage && $this->show == GuidePage::SHOW_GUIDE))
|
||||||
{
|
{
|
||||||
$this->gPageInfo = array(
|
$this->gPageInfo = array(
|
||||||
'articleUrl' => $this->fullParams, // is actually be the url-param
|
'articleUrl' => $this->fullParams, // is actually be the url-param
|
||||||
@@ -375,70 +409,81 @@ class GenericPage
|
|||||||
$this->postCache();
|
$this->postCache();
|
||||||
|
|
||||||
// determine contribute tabs
|
// determine contribute tabs
|
||||||
if (isset($this->subject))
|
if (isset($this->subject) && !isset($this->contribute))
|
||||||
{
|
{
|
||||||
$x = get_class($this->subject);
|
$x = get_class($this->subject);
|
||||||
$this->contribute = $x::$contribute;
|
$this->contribute = $x::$contribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($this->hasComContent)) // get comments, screenshots, videos
|
if ($this->contribute & CONTRIBUTE_CO)
|
||||||
|
$this->community['co'] = CommunityContent::getComments($this->type, $this->typeId);
|
||||||
|
|
||||||
|
if ($this->contribute & CONTRIBUTE_SS)
|
||||||
|
$this->community['ss'] = CommunityContent::getScreenshots($this->type, $this->typeId);
|
||||||
|
|
||||||
|
if ($this->contribute & CONTRIBUTE_VI)
|
||||||
|
$this->community['vi'] = CommunityContent::getVideos($this->type, $this->typeId);
|
||||||
|
|
||||||
|
// as comments are not cached, those globals cant be either
|
||||||
|
if ($this->contribute)
|
||||||
{
|
{
|
||||||
$this->community = CommunityContent::getAll($this->type, $this->typeId, $jsGlobals);
|
$this->extendGlobalData(CommunityContent::getJSGlobals());
|
||||||
$this->extendGlobalData($jsGlobals); // as comments are not cached, those globals cant be either
|
|
||||||
$this->applyGlobals();
|
$this->applyGlobals();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->time = microtime(true) - $this->time;
|
$this->time = microtime(true) - $this->time;
|
||||||
Util::arraySumByKey($this->mysql, DB::Aowow()->getStatistics(), DB::World()->getStatistics());
|
$this->sumSQLStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addJS($name, $unshift = false)
|
public function addScript(array ...$structs) : void
|
||||||
{
|
{
|
||||||
if (is_array($name))
|
foreach ($structs as $s) // iType, sContent, bFront, sIeCnd
|
||||||
{
|
{
|
||||||
foreach ($name as $n)
|
if (empty($s[1]))
|
||||||
$this->addJS($n, $unshift);
|
{
|
||||||
}
|
trigger_error('GenericPage::addScript - content empty', E_USER_WARNING);
|
||||||
else if (!in_array($name, $this->js))
|
continue;
|
||||||
{
|
}
|
||||||
if ($unshift)
|
|
||||||
array_unshift($this->js, $name);
|
$s = array_pad($s, 4, '');
|
||||||
else
|
switch ($s[0])
|
||||||
$this->js[] = $name;
|
{
|
||||||
|
case JS_FILE:
|
||||||
|
case JS_STRING:
|
||||||
|
if (empty($s[2]))
|
||||||
|
$this->js[] = $s;
|
||||||
|
else
|
||||||
|
array_unshift($this->js, $s);
|
||||||
|
break;
|
||||||
|
case CSS_FILE:
|
||||||
|
case CSS_STRING:
|
||||||
|
if (empty($s[2]))
|
||||||
|
$this->css[] = $s;
|
||||||
|
else
|
||||||
|
array_unshift($this->css, $s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
trigger_error('GenericPage::addScript - unknown script type #'.$s[0], E_USER_WARNING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addCSS($struct, $unshift = false)
|
// get article & static infobox (run before processing jsGlobals)
|
||||||
|
private function addArticle() :void
|
||||||
{
|
{
|
||||||
if (is_array($struct) && empty($struct['path']) && empty($struct['string']))
|
if (isset($this->article))
|
||||||
{
|
return;
|
||||||
foreach ($struct as $s)
|
|
||||||
$this->addCSS($s, $unshift);
|
|
||||||
}
|
|
||||||
else if (!in_array($struct, $this->css))
|
|
||||||
{
|
|
||||||
if ($unshift)
|
|
||||||
array_unshift($this->css, $struct);
|
|
||||||
else
|
|
||||||
$this->css[] = $struct;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function addArticle() // get article & static infobox (run before processing jsGlobals)
|
|
||||||
{
|
|
||||||
$article = [];
|
$article = [];
|
||||||
if (!empty($this->type) && isset($this->typeId))
|
if (isset($this->guideRevision))
|
||||||
{
|
$article = DB::Aowow()->selectRow('SELECT `article`, `quickInfo`, `locale`, `editAccess` FROM ?_articles WHERE `type` = ?d AND `typeId` = ?d AND `rev` = ?d',
|
||||||
$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',
|
Type::GUIDE, $this->typeId, $this->guideRevision);
|
||||||
$this->type, $this->typeId, User::$localeId, $this->type, $this->typeId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (!empty($this->articleUrl))
|
else if (!empty($this->articleUrl))
|
||||||
{
|
$article = DB::Aowow()->selectRow('SELECT `article`, `quickInfo`, `locale`, `editAccess` FROM ?_articles WHERE `url` = ? AND `locale` IN (?a) ORDER BY `locale`, `rev` DESC LIMIT 1',
|
||||||
$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, LOCALE_EN]);
|
||||||
$this->articleUrl, User::$localeId, $this->articleUrl
|
else 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` IN (?a) ORDER BY `locale`, `rev` DESC LIMIT 1',
|
||||||
}
|
$this->type, $this->typeId, [User::$localeId, LOCALE_EN]);
|
||||||
|
|
||||||
if ($article)
|
if ($article)
|
||||||
{
|
{
|
||||||
@@ -480,7 +525,8 @@ class GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function addAnnouncements() // get announcements and notes for user
|
// get announcements and notes for user
|
||||||
|
private function addAnnouncements() : void
|
||||||
{
|
{
|
||||||
if (!isset($this->announcements))
|
if (!isset($this->announcements))
|
||||||
$this->announcements = [];
|
$this->announcements = [];
|
||||||
@@ -527,9 +573,9 @@ class GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getCategoryFromUrl($str)
|
protected function getCategoryFromUrl(string $urlParam) : void
|
||||||
{
|
{
|
||||||
$arr = explode('.', $str);
|
$arr = explode('.', $urlParam);
|
||||||
$params = [];
|
$params = [];
|
||||||
|
|
||||||
foreach ($arr as $v)
|
foreach ($arr as $v)
|
||||||
@@ -539,37 +585,61 @@ class GenericPage
|
|||||||
$this->category = $params;
|
$this->category = $params;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function forwardToSignIn($next = '')
|
protected function forwardToSignIn(string $next = '') : void
|
||||||
{
|
{
|
||||||
$next = $next ? '&next='.$next : '';
|
$next = $next ? '&next='.$next : '';
|
||||||
header('Location: ?account=signin'.$next, true, 302);
|
header('Location: ?account=signin'.$next, true, 302);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function sumSQLStats() : void
|
||||||
|
{
|
||||||
|
Util::arraySumByKey($this->mysql, DB::Aowow()->getStatistics(), DB::World()->getStatistics());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************/
|
/*******************/
|
||||||
/* Special Display */
|
/* Special Display */
|
||||||
/*******************/
|
/*******************/
|
||||||
|
|
||||||
public function notFound($title, $msg = '') // unknown entry
|
// unknown entry
|
||||||
|
public function notFound(string $title = '', string $msg = '') : void
|
||||||
{
|
{
|
||||||
array_unshift($this->title, Lang::main('nfPageTitle'));
|
if ($this->mode == CACHE_TYPE_TOOLTIP && method_exists($this, 'generateTooltip'))
|
||||||
|
{
|
||||||
|
header(MIME_TYPE_JSON);
|
||||||
|
echo $this->generateTooltip();
|
||||||
|
}
|
||||||
|
else if ($this->mode == CACHE_TYPE_XML && method_exists($this, 'generateXML'))
|
||||||
|
{
|
||||||
|
header(MIME_TYPE_XML);
|
||||||
|
echo $this->generateXML();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
header('HTTP/1.0 404 Not Found', true, 404);
|
||||||
|
|
||||||
$this->notFound = array(
|
array_unshift($this->title, Lang::main('nfPageTitle'));
|
||||||
'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());
|
|
||||||
|
|
||||||
if (isset($this->tabId))
|
$this->contribute = CONTRIBUTE_NONE;
|
||||||
$this->pageTemplate['activeTab'] = $this->tabId;
|
$this->notFound = array(
|
||||||
|
'title' => isset($this->typeId) ? Util::ucFirst($title).' #'.$this->typeId : $title,
|
||||||
|
'msg' => !$msg && isset($this->typeId) ? sprintf(Lang::main('pageNotFound'), $title) : $msg
|
||||||
|
);
|
||||||
|
|
||||||
header('HTTP/1.0 404 Not Found', true, 404);
|
if (isset($this->tabId))
|
||||||
|
$this->pageTemplate['activeTab'] = $this->tabId;
|
||||||
|
|
||||||
|
$this->sumSQLStats();
|
||||||
|
|
||||||
|
|
||||||
|
$this->display('list-page-generic');
|
||||||
|
}
|
||||||
|
|
||||||
$this->display('list-page-generic');
|
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function error() // unknown page
|
// unknown page
|
||||||
|
public function error() : void
|
||||||
{
|
{
|
||||||
$this->path = null;
|
$this->path = null;
|
||||||
$this->tabId = null;
|
$this->tabId = null;
|
||||||
@@ -580,7 +650,7 @@ class GenericPage
|
|||||||
|
|
||||||
$this->addArticle();
|
$this->addArticle();
|
||||||
|
|
||||||
Util::arraySumByKey($this->mysql, DB::Aowow()->getStatistics(), DB::World()->getStatistics());
|
$this->sumSQLStats();
|
||||||
|
|
||||||
header('HTTP/1.0 404 Not Found', true, 404);
|
header('HTTP/1.0 404 Not Found', true, 404);
|
||||||
|
|
||||||
@@ -588,7 +658,8 @@ class GenericPage
|
|||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function maintenance() // display brb gnomes
|
// display brb gnomes
|
||||||
|
public function maintenance() : void
|
||||||
{
|
{
|
||||||
header('HTTP/1.0 503 Service Temporarily Unavailable', true, 503);
|
header('HTTP/1.0 503 Service Temporarily Unavailable', true, 503);
|
||||||
header('Retry-After: '.(3 * HOUR));
|
header('Retry-After: '.(3 * HOUR));
|
||||||
@@ -597,49 +668,80 @@ class GenericPage
|
|||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************/
|
/*******************/
|
||||||
/* General Display */
|
/* General Display */
|
||||||
/*******************/
|
/*******************/
|
||||||
|
|
||||||
public function display($override = '') // load given template string or GenericPage::$tpl
|
// load given template string or GenericPage::$tpl
|
||||||
|
public function display(string $override = '') : void
|
||||||
{
|
{
|
||||||
// Heisenbug: IE11 and FF32 will sometimes (under unknown circumstances) cache 302 redirects and stop
|
// Heisenbug: IE11 and FF32 will sometimes (under unknown circumstances) cache 302 redirects and stop
|
||||||
// re-requesting them from the server but load them from local cache, thus breaking menu features.
|
// re-requesting them from the server but load them from local cache, thus breaking menu features.
|
||||||
Util::sendNoCacheHeader();
|
Util::sendNoCacheHeader();
|
||||||
|
|
||||||
if (isset($this->tabId))
|
if ($this->mode == CACHE_TYPE_TOOLTIP && method_exists($this, 'generateTooltip'))
|
||||||
$this->pageTemplate['activeTab'] = $this->tabId;
|
$this->displayExtra([$this, 'generateTooltip']);
|
||||||
|
else if ($this->mode == CACHE_TYPE_XML && method_exists($this, 'generateXML'))
|
||||||
if ($override)
|
$this->displayExtra([$this, 'generateXML'], MIME_TYPE_XML);
|
||||||
{
|
|
||||||
$this->addAnnouncements();
|
|
||||||
|
|
||||||
include('template/pages/'.$override.'.tpl.php');
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
else if ($this->tpl)
|
|
||||||
{
|
|
||||||
$this->prepareContent();
|
|
||||||
|
|
||||||
if (!$this->isSaneInclude('template/pages/', $this->tpl))
|
|
||||||
{
|
|
||||||
trigger_error('Error: nonexistant template requested: template/pages/'.$this->tpl.'.tpl.php', E_USER_ERROR);
|
|
||||||
$this->error();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->addAnnouncements();
|
|
||||||
|
|
||||||
include('template/pages/'.$this->tpl.'.tpl.php');
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
$this->error();
|
{
|
||||||
|
if (isset($this->tabId))
|
||||||
|
$this->pageTemplate['activeTab'] = $this->tabId;
|
||||||
|
|
||||||
|
if ($override)
|
||||||
|
{
|
||||||
|
$this->addAnnouncements();
|
||||||
|
|
||||||
|
include('template/pages/'.$override.'.tpl.php');
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else if ($this->tpl)
|
||||||
|
{
|
||||||
|
$this->prepareContent();
|
||||||
|
|
||||||
|
if (!$this->isSaneInclude('template/pages/', $this->tpl))
|
||||||
|
{
|
||||||
|
trigger_error('Error: nonexistant template requested: template/pages/'.$this->tpl.'.tpl.php', E_USER_ERROR);
|
||||||
|
$this->error();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->addAnnouncements();
|
||||||
|
|
||||||
|
include('template/pages/'.$this->tpl.'.tpl.php');
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$this->error();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function writeGlobalVars() // load jsGlobal
|
// generate and cache
|
||||||
|
public function displayExtra(callable $generator, string $mime = MIME_TYPE_JSON) : void
|
||||||
|
{
|
||||||
|
$outString = '';
|
||||||
|
if (!$this->loadCache($outString))
|
||||||
|
{
|
||||||
|
$outString = $generator();
|
||||||
|
$this->saveCache($outString);
|
||||||
|
}
|
||||||
|
|
||||||
|
header($mime);
|
||||||
|
|
||||||
|
if (method_exists($this, 'postCache') && ($pc = $this->postCache()))
|
||||||
|
die(sprintf($outString, ...$pc));
|
||||||
|
else
|
||||||
|
die($outString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load jsGlobal
|
||||||
|
public function writeGlobalVars() : string
|
||||||
{
|
{
|
||||||
$buff = '';
|
$buff = '';
|
||||||
|
|
||||||
|
if (!empty($this->guideRating))
|
||||||
|
$buff .= sprintf(Util::$guideratingString, ...$this->guideRating);
|
||||||
|
|
||||||
foreach ($this->jsGlobals as $type => $struct)
|
foreach ($this->jsGlobals as $type => $struct)
|
||||||
{
|
{
|
||||||
$buff .= " var _ = ".$struct[0].';';
|
$buff .= " var _ = ".$struct[0].';';
|
||||||
@@ -648,8 +750,8 @@ class GenericPage
|
|||||||
{
|
{
|
||||||
foreach ($data as $k => $v)
|
foreach ($data as $k => $v)
|
||||||
{
|
{
|
||||||
// localizes expected fields
|
// localizes expected fields .. except for icons .. icons are special
|
||||||
if (in_array($k, ['name', 'namefemale']))
|
if (in_array($k, ['name', 'namefemale']) && $struct[0] != Type::getJSGlobalString(Type::ICON))
|
||||||
{
|
{
|
||||||
$data[$k.'_'.User::$localeString] = $v;
|
$data[$k.'_'.User::$localeString] = $v;
|
||||||
unset($data[$k]);
|
unset($data[$k]);
|
||||||
@@ -682,7 +784,8 @@ class GenericPage
|
|||||||
return $buff;
|
return $buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function brick($file, array $localVars = []) // load brick
|
// load brick
|
||||||
|
public function brick(string $file, array $localVars = []) : void
|
||||||
{
|
{
|
||||||
foreach ($localVars as $n => $v)
|
foreach ($localVars as $n => $v)
|
||||||
$$n = $v;
|
$$n = $v;
|
||||||
@@ -693,7 +796,8 @@ class GenericPage
|
|||||||
include('template/bricks/'.$file.'.tpl.php');
|
include('template/bricks/'.$file.'.tpl.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function lvBrick($file) // load listview addIns
|
// load listview addIns
|
||||||
|
public function lvBrick(string $file) : void
|
||||||
{
|
{
|
||||||
if (!$this->isSaneInclude('template/listviews/', $file))
|
if (!$this->isSaneInclude('template/listviews/', $file))
|
||||||
trigger_error('Nonexistant Listview addin requested: template/listviews/'.$file.'.tpl.php', E_USER_ERROR);
|
trigger_error('Nonexistant Listview addin requested: template/listviews/'.$file.'.tpl.php', E_USER_ERROR);
|
||||||
@@ -701,7 +805,8 @@ class GenericPage
|
|||||||
include('template/listviews/'.$file.'.tpl.php');
|
include('template/listviews/'.$file.'.tpl.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function localizedBrick($file, $loc = LOCALE_EN) // load brick with more text then vars
|
// load brick with more text then vars
|
||||||
|
public function localizedBrick(string $file, int $loc = LOCALE_EN) : void
|
||||||
{
|
{
|
||||||
if (!$this->isSaneInclude('template/localized/', $file.'_'.$loc))
|
if (!$this->isSaneInclude('template/localized/', $file.'_'.$loc))
|
||||||
{
|
{
|
||||||
@@ -714,28 +819,26 @@ class GenericPage
|
|||||||
include('template/localized/'.$file.'_'.$loc.'.tpl.php');
|
include('template/localized/'.$file.'_'.$loc.'.tpl.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************/
|
/**********************/
|
||||||
/* Prepare js-Globals */
|
/* Prepare js-Globals */
|
||||||
/**********************/
|
/**********************/
|
||||||
|
|
||||||
public function extendGlobalIds($type, $data) // add typeIds <int|array[int]> that should be displayed as jsGlobal on the page
|
// add typeIds <int|array[int]> that should be displayed as jsGlobal on the page
|
||||||
|
public function extendGlobalIds(int $type, int ...$ids) : void
|
||||||
{
|
{
|
||||||
if (!$type || !$data)
|
if (!$type || !$ids)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
if (!isset($this->jsgBuffer[$type]))
|
if (!isset($this->jsgBuffer[$type]))
|
||||||
$this->jsgBuffer[$type] = [];
|
$this->jsgBuffer[$type] = [];
|
||||||
|
|
||||||
if (is_array($data))
|
foreach ($ids as $id)
|
||||||
{
|
$this->jsgBuffer[$type][] = $id;
|
||||||
foreach ($data as $id)
|
|
||||||
$this->jsgBuffer[$type][] = (int)$id;
|
|
||||||
}
|
|
||||||
else if (is_numeric($data))
|
|
||||||
$this->jsgBuffer[$type][] = (int)$data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function extendGlobalData($data, $extra = null) // add jsGlobals or typeIds (can be mixed in one array: TYPE => [mixeddata]) to display on the page
|
// add jsGlobals or typeIds (can be mixed in one array: TYPE => [mixeddata]) to display on the page
|
||||||
|
public function extendGlobalData(array $data, ?array $extra = null) : void
|
||||||
{
|
{
|
||||||
foreach ($data as $type => $globals)
|
foreach ($data as $type => $globals)
|
||||||
{
|
{
|
||||||
@@ -760,41 +863,20 @@ class GenericPage
|
|||||||
$this->jsGlobals[$type][2] = $extra;
|
$this->jsGlobals[$type][2] = $extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function initJSGlobal($type) // init store for type
|
// init store for type
|
||||||
|
private function initJSGlobal(int $type) : void
|
||||||
{
|
{
|
||||||
$jsg = &$this->jsGlobals; // shortcut
|
$jsg = &$this->jsGlobals; // shortcut
|
||||||
|
|
||||||
if (isset($jsg[$type]))
|
if (isset($jsg[$type]))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch ($type)
|
if ($tpl = Type::getJSGlobalTemplate($type))
|
||||||
{ // [varName, [data], [extra]]
|
$jsg[$type] = $tpl;
|
||||||
case TYPE_NPC: $jsg[TYPE_NPC] = ['g_npcs', [], []]; break;
|
|
||||||
case TYPE_OBJECT: $jsg[TYPE_OBJECT] = ['g_objects', [], []]; break;
|
|
||||||
case TYPE_ITEM: $jsg[TYPE_ITEM] = ['g_items', [], []]; break;
|
|
||||||
case TYPE_ITEMSET: $jsg[TYPE_ITEMSET] = ['g_itemsets', [], []]; break;
|
|
||||||
case TYPE_QUEST: $jsg[TYPE_QUEST] = ['g_quests', [], []]; break;
|
|
||||||
case TYPE_SPELL: $jsg[TYPE_SPELL] = ['g_spells', [], []]; break;
|
|
||||||
case TYPE_ZONE: $jsg[TYPE_ZONE] = ['g_gatheredzones', [], []]; break;
|
|
||||||
case TYPE_FACTION: $jsg[TYPE_FACTION] = ['g_factions', [], []]; break;
|
|
||||||
case TYPE_PET: $jsg[TYPE_PET] = ['g_pets', [], []]; break;
|
|
||||||
case TYPE_ACHIEVEMENT: $jsg[TYPE_ACHIEVEMENT] = ['g_achievements', [], []]; break;
|
|
||||||
case TYPE_TITLE: $jsg[TYPE_TITLE] = ['g_titles', [], []]; break;
|
|
||||||
case TYPE_WORLDEVENT: $jsg[TYPE_WORLDEVENT] = ['g_holidays', [], []]; break;
|
|
||||||
case TYPE_CLASS: $jsg[TYPE_CLASS] = ['g_classes', [], []]; break;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function applyGlobals() // lookup jsGlobals from collected typeIds
|
// lookup jsGlobals from collected typeIds
|
||||||
|
private function applyGlobals() : void
|
||||||
{
|
{
|
||||||
foreach ($this->jsgBuffer as $type => $ids)
|
foreach ($this->jsgBuffer as $type => $ids)
|
||||||
{
|
{
|
||||||
@@ -807,33 +889,9 @@ class GenericPage
|
|||||||
|
|
||||||
$this->initJSGlobal($type);
|
$this->initJSGlobal($type);
|
||||||
|
|
||||||
$cnd = [CFG_SQL_LIMIT_NONE, ['id', array_unique($ids, SORT_NUMERIC)]];
|
$obj = Type::newList($type, [CFG_SQL_LIMIT_NONE, ['id', array_unique($ids, SORT_NUMERIC)]]);
|
||||||
|
if (!$obj)
|
||||||
switch ($type)
|
continue;
|
||||||
{
|
|
||||||
case TYPE_NPC: $obj = new CreatureList($cnd); break;
|
|
||||||
case TYPE_OBJECT: $obj = new GameobjectList($cnd); break;
|
|
||||||
case TYPE_ITEM: $obj = new ItemList($cnd); break;
|
|
||||||
case TYPE_ITEMSET: $obj = new ItemsetList($cnd); break;
|
|
||||||
case TYPE_QUEST: $obj = new QuestList($cnd); break;
|
|
||||||
case TYPE_SPELL: $obj = new SpellList($cnd); break;
|
|
||||||
case TYPE_ZONE: $obj = new ZoneList($cnd); break;
|
|
||||||
case TYPE_FACTION: $obj = new FactionList($cnd); break;
|
|
||||||
case TYPE_PET: $obj = new PetList($cnd); break;
|
|
||||||
case TYPE_ACHIEVEMENT: $obj = new AchievementList($cnd); break;
|
|
||||||
case TYPE_TITLE: $obj = new TitleList($cnd); break;
|
|
||||||
case TYPE_WORLDEVENT: $obj = new WorldEventList($cnd); break;
|
|
||||||
case TYPE_CLASS: $obj = new CharClassList($cnd); break;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->extendGlobalData($obj->getJSGlobals(GLOBALINFO_SELF));
|
$this->extendGlobalData($obj->getJSGlobals(GLOBALINFO_SELF));
|
||||||
|
|
||||||
@@ -842,14 +900,16 @@ class GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********/
|
/*********/
|
||||||
/* Cache */
|
/* Cache */
|
||||||
/*********/
|
/*********/
|
||||||
|
|
||||||
public function saveCache($saveString = null) // visible properties or given strings are cached
|
// visible properties or given strings are cached
|
||||||
|
private function saveCache(string $saveString = '') : void
|
||||||
{
|
{
|
||||||
if ($this->mode == CACHE_TYPE_NONE)
|
if ($this->mode == CACHE_TYPE_NONE)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
if (!CFG_CACHE_MODE || CFG_DEBUG)
|
if (!CFG_CACHE_MODE || CFG_DEBUG)
|
||||||
return;
|
return;
|
||||||
@@ -863,8 +923,8 @@ class GenericPage
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// public, protected and an undocumented flag added to properties created on the fly..?
|
$rp = new ReflectionProperty($this, $key);
|
||||||
if ((new ReflectionProperty($this, $key))->getModifiers() & 0x1300)
|
if ($rp && ($rp->isPublic() || $rp->isProtected()))
|
||||||
if (!in_array($key, $noCache))
|
if (!in_array($key, $noCache))
|
||||||
$cache[$key] = $val;
|
$cache[$key] = $val;
|
||||||
}
|
}
|
||||||
@@ -872,7 +932,7 @@ class GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
$cache = (string)$saveString;
|
$cache = $saveString;
|
||||||
|
|
||||||
if (CFG_CACHE_MODE & CACHE_MODE_MEMCACHED)
|
if (CFG_CACHE_MODE & CACHE_MODE_MEMCACHED)
|
||||||
{
|
{
|
||||||
@@ -927,7 +987,7 @@ class GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadCache(&$saveString = null)
|
private function loadCache(string &$saveString = '') : bool
|
||||||
{
|
{
|
||||||
if ($this->mode == CACHE_TYPE_NONE)
|
if ($this->mode == CACHE_TYPE_NONE)
|
||||||
return false;
|
return false;
|
||||||
@@ -966,7 +1026,7 @@ class GenericPage
|
|||||||
if (substr_count($cache[0], ' ') < 2)
|
if (substr_count($cache[0], ' ') < 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
list($time, $rev, $type) = explode(' ', $cache[0]);
|
[$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;
|
$cache = null;
|
||||||
@@ -999,7 +1059,7 @@ class GenericPage
|
|||||||
return false;;
|
return false;;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function memcached()
|
private function memcached() : Memcached
|
||||||
{
|
{
|
||||||
if (!$this->memcached && (CFG_CACHE_MODE & CACHE_MODE_MEMCACHED))
|
if (!$this->memcached && (CFG_CACHE_MODE & CACHE_MODE_MEMCACHED))
|
||||||
{
|
{
|
||||||
|
|||||||
555
pages/guide.php
Normal file
555
pages/guide.php
Normal file
@@ -0,0 +1,555 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
// menuId ?: Category g_initPath()
|
||||||
|
// tabid 6: Guides g_initHeader()
|
||||||
|
class GuidePage extends GenericPage
|
||||||
|
{
|
||||||
|
use TrDetailPage;
|
||||||
|
|
||||||
|
const SHOW_NEW = 1;
|
||||||
|
const SHOW_EDITOR = 2;
|
||||||
|
const SHOW_GUIDE = 3;
|
||||||
|
const SHOW_CHANGELOG = 4;
|
||||||
|
|
||||||
|
const VALID_URL = '/^[a-z0-9=_&\.\/\-]{2,64}$/i';
|
||||||
|
|
||||||
|
protected /* int */ $type = Type::GUIDE;
|
||||||
|
protected /* int */ $typeId = 0;
|
||||||
|
protected /* int */ $guideRevision = -1;
|
||||||
|
protected /* string */ $tpl = 'detail-page-generic';
|
||||||
|
protected /* array */ $path = [6];
|
||||||
|
protected /* int */ $tabId = 6;
|
||||||
|
protected /* int */ $mode = CACHE_TYPE_PAGE;
|
||||||
|
protected /* string */ $author = '';
|
||||||
|
protected /* array */ $gPageInfo = [];
|
||||||
|
protected /* int */ $show = self::SHOW_GUIDE;
|
||||||
|
protected /* int */ $articleUrl = '';
|
||||||
|
|
||||||
|
private /* array */ $validCats = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||||
|
private /* string */ $extra = '';
|
||||||
|
private /* string */ $powerTpl = '$WowheadPower.registerGuide(%s, %d, %s);';
|
||||||
|
private /* array */ $editorFields = [];
|
||||||
|
|
||||||
|
protected /* array */ $_get = array(
|
||||||
|
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'],
|
||||||
|
'rev' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt']
|
||||||
|
);
|
||||||
|
|
||||||
|
protected /* array */ $_post = array(
|
||||||
|
'save' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet'],
|
||||||
|
'submit' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet'],
|
||||||
|
'title' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
|
'name' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
|
'description' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
|
'changelog' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
|
||||||
|
'body' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkFulltext'],
|
||||||
|
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'],
|
||||||
|
'category' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'],
|
||||||
|
'specId' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'],
|
||||||
|
'classId' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt']
|
||||||
|
);
|
||||||
|
|
||||||
|
public function __construct($pageCall, $pageParam)
|
||||||
|
{
|
||||||
|
$this->contribute = CONTRIBUTE_CO;
|
||||||
|
|
||||||
|
$guide = explode( "&", $pageParam, 2);
|
||||||
|
|
||||||
|
parent::__construct($pageCall, $pageParam);
|
||||||
|
|
||||||
|
if (isset($guide[1]) && preg_match(self::VALID_URL, $guide[1]))
|
||||||
|
$this->extra = $guide[1];
|
||||||
|
|
||||||
|
|
||||||
|
/**********************/
|
||||||
|
/* get mode + guideId */
|
||||||
|
/**********************/
|
||||||
|
|
||||||
|
if (Util::checkNumeric($guide[0], NUM_CAST_INT))
|
||||||
|
$this->typeId = $guide[0];
|
||||||
|
else if (preg_match(self::VALID_URL, $guide[0]))
|
||||||
|
{
|
||||||
|
switch ($guide[0])
|
||||||
|
{
|
||||||
|
case 'changelog':
|
||||||
|
if (!$this->_get['id'])
|
||||||
|
break;
|
||||||
|
|
||||||
|
$this->show = self::SHOW_CHANGELOG;
|
||||||
|
$this->tpl = 'text-page-generic';
|
||||||
|
$this->article = false; // do not include article from db
|
||||||
|
|
||||||
|
// main container should be tagged: <div class="text guide-changelog">
|
||||||
|
// why is this here: is there a mediawiki like diff function for staff?
|
||||||
|
$this->addScript([CSS_STRING, 'li input[type="radio"] {margin:0}']);
|
||||||
|
|
||||||
|
$this->typeId = $this->_get['id']; // just to display sensible not-found msg
|
||||||
|
if ($id = DB::Aowow()->selectCell('SELECT `id` FROM ?_guides WHERE `id` = ?d', $this->typeId))
|
||||||
|
$this->typeId = intVal($id);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'new':
|
||||||
|
if (User::canWriteGuide())
|
||||||
|
{
|
||||||
|
$this->show = self::SHOW_NEW;
|
||||||
|
$this->guideRevision = null;
|
||||||
|
|
||||||
|
$this->initNew();
|
||||||
|
return; // do not create new GuideList
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'edit':
|
||||||
|
if (User::canWriteGuide())
|
||||||
|
{
|
||||||
|
if (!$this->initEdit())
|
||||||
|
$this->notFound(Lang::guide('guide'), Lang::guide('notFound'));
|
||||||
|
|
||||||
|
$this->show = self::SHOW_EDITOR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ($id = DB::Aowow()->selectCell('SELECT `id` FROM ?_guides WHERE `url` = ?', Util::lower($guide[0])))
|
||||||
|
{
|
||||||
|
$this->typeId = intVal($id);
|
||||||
|
$this->guideRevision = null;
|
||||||
|
$this->articleUrl = Util::lower($guide[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*********************/
|
||||||
|
/* load actual guide */
|
||||||
|
/*********************/
|
||||||
|
|
||||||
|
$this->subject = new GuideList(array(['id', $this->typeId]));
|
||||||
|
if ($this->subject->error)
|
||||||
|
$this->notFound(Lang::guide('guide'), Lang::guide('notFound'));
|
||||||
|
|
||||||
|
if (!$this->subject->canBeViewed() && !$this->subject->userCanView())
|
||||||
|
header('Location: ?guides='.$this->subject->getField('category'), true, 302);
|
||||||
|
|
||||||
|
if ($this->show == self::SHOW_GUIDE && $this->_get['rev'] !== null && !$this->articleUrl && $this->subject->userCanView())
|
||||||
|
$this->guideRevision = $this->_get['rev'];
|
||||||
|
else if ($this->show == self::SHOW_GUIDE && !$this->articleUrl)
|
||||||
|
$this->guideRevision = $this->subject->getField('rev');
|
||||||
|
else
|
||||||
|
$this->guideRevision = null;
|
||||||
|
|
||||||
|
if (!$this->name)
|
||||||
|
$this->name = $this->subject->getField('name');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateContent() : void
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
match ($this->show)
|
||||||
|
{
|
||||||
|
self::SHOW_NEW => $this->displayNew(),
|
||||||
|
self::SHOW_EDITOR => $this->displayEditor(),
|
||||||
|
self::SHOW_GUIDE => $this->displayGuide(),
|
||||||
|
self::SHOW_CHANGELOG => $this->displayChangelog(),
|
||||||
|
default => trigger_error('GuidePage::generateContent - what content!?')
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
switch ($this->show)
|
||||||
|
{
|
||||||
|
case self::SHOW_NEW:
|
||||||
|
$this->displayNew();
|
||||||
|
break;
|
||||||
|
case self::SHOW_EDITOR:
|
||||||
|
$this->displayEditor();
|
||||||
|
break;
|
||||||
|
case self::SHOW_GUIDE:
|
||||||
|
$this->displayGuide();
|
||||||
|
break;
|
||||||
|
case self::SHOW_CHANGELOG:
|
||||||
|
$this->displayChangelog();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
trigger_error('GuidePage::generateContent - what content!?');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function displayNew() : void
|
||||||
|
{
|
||||||
|
// init required template vars
|
||||||
|
$this->editorFields = array(
|
||||||
|
'locale' => User::$localeId,
|
||||||
|
'status' => GUIDE_STATUS_DRAFT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function displayEditor() : void
|
||||||
|
{
|
||||||
|
// can't check in init as subject is unknown
|
||||||
|
if ($this->subject->getField('status') == GUIDE_STATUS_ARCHIVED)
|
||||||
|
$this->notFound(Lang::guide('guide'), Lang::guide('notFound'));
|
||||||
|
|
||||||
|
$status = GUIDE_STATUS_NONE;
|
||||||
|
$rev = DB::Aowow()->selectCell('SELECT `rev` FROM ?_articles WHERE `type` = ?d AND `typeId` = ?d ORDER BY `rev` DESC LIMIT 1', Type::GUIDE, $this->typeId);
|
||||||
|
$curStatus = DB::Aowow()->selectCell('SELECT `status` FROM ?_guides WHERE `id` = ?d ', $this->typeId);
|
||||||
|
if ($rev === null)
|
||||||
|
$rev = 0;
|
||||||
|
|
||||||
|
if ($this->save)
|
||||||
|
{
|
||||||
|
$rev++;
|
||||||
|
|
||||||
|
// insert Article
|
||||||
|
DB::Aowow()->query('INSERT INTO ?_articles (`type`, `typeId`, `locale`, `rev`, `editAccess`, `article`) VALUES (?d, ?d, ?d, ?d, ?d, ?)',
|
||||||
|
Type::GUIDE, $this->typeId, $this->_post['locale'], $rev, User::$groups, $this->_post['body']);
|
||||||
|
|
||||||
|
// link to Guide
|
||||||
|
$guideData = array(
|
||||||
|
'category' => $this->_post['category'],
|
||||||
|
'classId' => $this->_post['classId'],
|
||||||
|
'specId' => $this->_post['specId'],
|
||||||
|
'title' => $this->_post['title'],
|
||||||
|
'name' => $this->_post['name'],
|
||||||
|
'description' => $this->_post['description'] ?: Lang::trimTextClean((new Markup($this->_post['body']))->stripTags(), 120),
|
||||||
|
'locale' => $this->_post['locale'],
|
||||||
|
'roles' => User::$groups,
|
||||||
|
'status' => GUIDE_STATUS_DRAFT
|
||||||
|
);
|
||||||
|
|
||||||
|
DB::Aowow()->query('UPDATE ?_guides SET ?a WHERE `id` = ?d', $guideData, $this->typeId);
|
||||||
|
|
||||||
|
// new guide -> reload editor
|
||||||
|
if ($this->_get['id'] === 0)
|
||||||
|
header('Location: ?guide=edit&id='.$this->typeId, true, 302);
|
||||||
|
else
|
||||||
|
DB::Aowow()->query('INSERT INTO ?_guides_changelog (`id`, `rev`, `date`, `userId`, `msg`) VALUES (?d, ?d, ?d, ?d, ?)', $this->typeId, $rev, time(), User::$id, $this->_post['changelog']);
|
||||||
|
|
||||||
|
if ($this->_post['submit'])
|
||||||
|
{
|
||||||
|
$status = GUIDE_STATUS_REVIEW;
|
||||||
|
if ($curStatus != GUIDE_STATUS_REVIEW)
|
||||||
|
{
|
||||||
|
DB::Aowow()->query('UPDATE ?_guides SET `status` = ?d WHERE `id` = ?d', GUIDE_STATUS_REVIEW, $this->typeId);
|
||||||
|
DB::Aowow()->query('INSERT INTO ?_guides_changelog (`id`, `date`, `userId`, `status`) VALUES (?d, ?d, ?d, ?d)', $this->typeId, time(), User::$id, GUIDE_STATUS_REVIEW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// init required template vars
|
||||||
|
$this->editorFields = array(
|
||||||
|
'category' => $this->_post['category'] ?? $this->subject->getField('category'),
|
||||||
|
'title' => $this->_post['title'] ?? $this->subject->getField('title'),
|
||||||
|
'name' => $this->_post['name'] ?? $this->subject->getField('name'),
|
||||||
|
'description' => $this->_post['description'] ?? $this->subject->getField('description'),
|
||||||
|
'text' => $this->_post['body'] ?? $this->subject->getArticle(),
|
||||||
|
'status' => $status ?: $this->subject->getField('status'),
|
||||||
|
'classId' => $this->_post['classId'] ?? $this->subject->getField('classId'),
|
||||||
|
'specId' => $this->_post['specId'] ?? $this->subject->getField('specId'),
|
||||||
|
'locale' => $this->_post['locale'] ?? $this->subject->getField('locale'),
|
||||||
|
'rev' => $rev
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->extendGlobalData($this->subject->getJSGlobals());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function displayGuide() : void
|
||||||
|
{
|
||||||
|
if (!($this->subject->getField('cuFlags') & GUIDE_CU_NO_QUICKFACTS))
|
||||||
|
{
|
||||||
|
$qf = [];
|
||||||
|
if ($this->subject->getField('cuFlags') & CC_FLAG_STICKY)
|
||||||
|
$qf[] = '[span class=guide-sticky]'.Lang::guide('sticky').'[/span]';
|
||||||
|
|
||||||
|
$qf[] = Lang::guide('author').Lang::main('colon').'[url=?user='.$this->subject->getField('author').']'.$this->subject->getField('author').'[/url]';
|
||||||
|
|
||||||
|
if ($this->subject->getField('category') == 1)
|
||||||
|
{
|
||||||
|
$c = $this->subject->getField('classId');
|
||||||
|
$s = $this->subject->getField('specId');
|
||||||
|
if ($c > 0)
|
||||||
|
{
|
||||||
|
$this->extendGlobalIds(Type::CHR_CLASS, $c);
|
||||||
|
$qf[] = Util::ucFirst(Lang::game('class')).Lang::main('colon').'[class='.$c.']';
|
||||||
|
}
|
||||||
|
if ($s > -1)
|
||||||
|
$qf[] = Lang::guide('spec').Lang::main('colon').'[icon class="c'.$c.' icontiny" name='.Game::$specIconStrings[$c][$s].']'.Lang::game('classSpecs', $c, $s).'[/icon]';
|
||||||
|
}
|
||||||
|
|
||||||
|
// $qf[] = Lang::guide('patch').Lang::main('colon').'3.3.5'; // replace with date
|
||||||
|
$qf[] = Lang::guide('added').Lang::main('colon').'[tooltip name=added]'.date('l, G:i:s', $this->subject->getField('date')).'[/tooltip][span class=tip tooltip=added]'.date(Lang::main('dateFmtShort'), $this->subject->getField('date')).'[/span]';
|
||||||
|
|
||||||
|
switch ($this->subject->getField('status'))
|
||||||
|
{
|
||||||
|
case GUIDE_STATUS_APPROVED:
|
||||||
|
$qf[] = Lang::guide('views').Lang::main('colon').'[n5='.$this->subject->getField('views').']';
|
||||||
|
|
||||||
|
if (!($this->subject->getField('cuFlags') & GUIDE_CU_NO_RATING))
|
||||||
|
{
|
||||||
|
$this->guideRating = array(
|
||||||
|
$this->subject->getField('rating'), // avg rating
|
||||||
|
User::canUpvote() && User::canDownvote() ? 'true' : 'false',
|
||||||
|
$this->subject->getField('_self'), // my rating amt; 0 = no vote
|
||||||
|
$this->typeId // guide Id
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->subject->getField('nvotes') < 5)
|
||||||
|
$qf[] = Lang::guide('rating').Lang::main('colon').Lang::guide('noVotes');
|
||||||
|
else
|
||||||
|
$qf[] = Lang::guide('rating').Lang::main('colon').Lang::guide('votes', [round($this->rating['avg'], 1), $this->rating['n']]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GUIDE_STATUS_ARCHIVED:
|
||||||
|
$qf[] = Lang::guide('status', GUIDE_STATUS_ARCHIVED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$qf = '[ul][li]'.implode('[/li][li]', $qf).'[/li][/ul]';
|
||||||
|
|
||||||
|
if ($this->subject->getField('status') == GUIDE_STATUS_REVIEW && User::isInGroup(U_GROUP_STAFF) && $this->_get['rev'])
|
||||||
|
{
|
||||||
|
$this->addScript([JS_STRING, '
|
||||||
|
DomContentLoaded.addEvent(function() {
|
||||||
|
let send = function (status)
|
||||||
|
{
|
||||||
|
let message = "";
|
||||||
|
let id = $WH.g_getGets().guide;
|
||||||
|
if (status == 4) // rejected
|
||||||
|
{
|
||||||
|
while (message === "")
|
||||||
|
message = prompt("Please provide your reasoning.");
|
||||||
|
|
||||||
|
if (message === null)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({cache: false, url: "?admin=guide", type: "POST",
|
||||||
|
error: function() {
|
||||||
|
alert("Operation failed.");
|
||||||
|
},
|
||||||
|
success: function(json) {
|
||||||
|
if (json != 1)
|
||||||
|
alert("Operation failed.");
|
||||||
|
else
|
||||||
|
window.location.href = "?admin=guides";
|
||||||
|
},
|
||||||
|
data: { id: id, status: status, msg: message }
|
||||||
|
})
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
$WH.ge("btn-accept").onclick = send.bind(null, 3);
|
||||||
|
$WH.ge("btn-reject").onclick = send.bind(null, 4);
|
||||||
|
});
|
||||||
|
']);
|
||||||
|
|
||||||
|
$qf .= '[h3 style="text-align:center"]Admin[/h3]';
|
||||||
|
|
||||||
|
$qf .= '[div style="text-align:center"][url=# id="btn-accept" class=icon-tick]Approve[/url][url=# style="margin-left:20px" id="btn-reject" class=icon-delete]Reject[/url][/div]';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->redButtons[BUTTON_GUIDE_LOG] = true;
|
||||||
|
$this->redButtons[BUTTON_GUIDE_REPORT] = $this->subject->canBeReported();
|
||||||
|
|
||||||
|
$this->infobox = $qf ?? '';
|
||||||
|
$this->author = $this->subject->getField('author'); // add to g_pageInfo in GenericPage:prepareContent()
|
||||||
|
|
||||||
|
if ($this->subject->userCanView())
|
||||||
|
$this->redButtons[BUTTON_GUIDE_EDIT] = User::canWriteGuide() && $this->subject->getField('status') != GUIDE_STATUS_ARCHIVED;
|
||||||
|
|
||||||
|
// the article text itself is added by GenericPage::addArticle()
|
||||||
|
}
|
||||||
|
|
||||||
|
private function displayChangelog() : void
|
||||||
|
{
|
||||||
|
$this->addScript([JS_STRING, '
|
||||||
|
$(document).ready(function() {
|
||||||
|
var radios = $("input[type=radio]");
|
||||||
|
function limit(col, val) {
|
||||||
|
radios.each(function(i, e) {
|
||||||
|
if (col == e.name)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (col == "b")
|
||||||
|
e.disabled = (val <= parseInt(e.value));
|
||||||
|
else if (col == "a")
|
||||||
|
e.disabled = (val >= parseInt(e.value));
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
radios.each(function (i, e) {
|
||||||
|
e.onchange = limit.bind(this, e.name, parseInt(e.value));
|
||||||
|
|
||||||
|
if (i < 2 && e.name == "b") // first pair
|
||||||
|
$(e).trigger("click");
|
||||||
|
else if (e.value == 0 && e.name == "a") // last pair
|
||||||
|
$(e).trigger("click");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
']);
|
||||||
|
|
||||||
|
$buff = '<ul>';
|
||||||
|
$inp = fn($rev) => User::isInGroup(U_GROUP_STAFF) ? ($rev !== null ? '<input name="a" value="'.$rev.'" type="radio"/><input name="b" value="'.$rev.'" type="radio"/><b>' : '<b style="margin-left:28px;">') : '';
|
||||||
|
|
||||||
|
$logEntries = DB::Aowow()->select('SELECT a.`displayName` AS `name`, gcl.`date`, gcl.`status`, gcl.`msg`, gcl.`rev` FROM ?_guides_changelog gcl JOIN ?_account a ON a.`id` = gcl.`userId` WHERE gcl.`id` = ?d ORDER BY gcl.`date` DESC', $this->typeId);
|
||||||
|
foreach ($logEntries as $log)
|
||||||
|
{
|
||||||
|
if ($log['status'] != GUIDE_STATUS_NONE)
|
||||||
|
$buff .= '<li class="guide-changelog-status-change">'.$inp($log['rev']).Lang::guide('clStatusSet', [Lang::guide('status', $log['status'])]).Lang::main('colon').'</b>'.Util::formatTimeDiff($log['date'])."</li>\n";
|
||||||
|
else if ($log['msg'])
|
||||||
|
$buff .= '<li>'.$inp($log['rev']).Util::formatTimeDiff($log['date']).Lang::main('colon').'</b>'.$log['msg'].' <i class="q0">'.Lang::main('byUser', [$log['name'], 'style="text-decoration:underline"'])."</i></li>\n";
|
||||||
|
else
|
||||||
|
$buff .= '<li class="guide-changelog-minor-edit">'.$inp($log['rev']).Util::formatTimeDiff($log['date']).Lang::main('colon').'</b><i>'.Lang::guide('clMinorEdit').'</i> <i class="q0">'.Lang::main('byUser', [$log['name'], 'style="text-decoration:underline"'])."</i></li>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// append creation
|
||||||
|
$buff .= '<li class="guide-changelog-created">'.$inp(0).'<b>'.Lang::guide('clCreated').Lang::main('colon').'</b>'.Util::formatTimeDiff($this->subject->getField('date'))."</li>\n</ul>\n";
|
||||||
|
|
||||||
|
|
||||||
|
if (User::isInGroup(U_GROUP_STAFF))
|
||||||
|
$buff .= '<input type="button" value="Compare" onclick="alert(\'NYI\');"/>';
|
||||||
|
|
||||||
|
$this->name = lang::guide('clTitle', [$this->typeId, $this->subject->getField('title')]);
|
||||||
|
$this->extraHTML = $buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function initNew() : void
|
||||||
|
{
|
||||||
|
$this->addScript(
|
||||||
|
[JS_FILE, 'article-description.js'],
|
||||||
|
[JS_FILE, 'article-editing.js'],
|
||||||
|
[JS_FILE, 'guide-editing.js'],
|
||||||
|
[JS_FILE, 'fileuploader.js'],
|
||||||
|
[JS_FILE, 'toolbar.js'],
|
||||||
|
[JS_FILE, 'AdjacentPreview.js'],
|
||||||
|
[CSS_FILE, 'article-editing.css'],
|
||||||
|
[CSS_FILE, 'fileuploader.css'],
|
||||||
|
[CSS_FILE, 'guide-edit.css'],
|
||||||
|
[CSS_FILE, 'AdjacentPreview.css'],
|
||||||
|
|
||||||
|
[CSS_STRING, '#upload-result input[type=text] { padding: 0px 2px; font-size: 12px; }'],
|
||||||
|
[CSS_STRING, '#upload-result > span { display:block; height: 22px; }'],
|
||||||
|
[CSS_STRING, '#upload-result { display: inline-block; text-align:right; }'],
|
||||||
|
[CSS_STRING, '#upload-progress { display: inline-block; margin-right:8px; }']
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->articleUrl = 'new';
|
||||||
|
$this->tpl = 'guide-edit';
|
||||||
|
$this->name = Lang::guide('newTitle');
|
||||||
|
|
||||||
|
Lang::sort('guide', 'category');
|
||||||
|
|
||||||
|
$this->typeId = 0; // signals 'edit' to create new guide
|
||||||
|
}
|
||||||
|
|
||||||
|
private function initEdit() : bool
|
||||||
|
{
|
||||||
|
$this->addScript(
|
||||||
|
[JS_FILE, 'article-description.js'],
|
||||||
|
[JS_FILE, 'article-editing.js'],
|
||||||
|
[JS_FILE, 'guide-editing.js'],
|
||||||
|
[JS_FILE, 'fileuploader.js'],
|
||||||
|
[JS_FILE, 'toolbar.js'],
|
||||||
|
[JS_FILE, 'AdjacentPreview.js'],
|
||||||
|
[CSS_FILE, 'article-editing.css'],
|
||||||
|
[CSS_FILE, 'fileuploader.css'],
|
||||||
|
[CSS_FILE, 'guide-edit.css'],
|
||||||
|
[CSS_FILE, 'AdjacentPreview.css'],
|
||||||
|
|
||||||
|
[CSS_STRING, '#upload-result input[type=text] { padding: 0px 2px; font-size: 12px; }'],
|
||||||
|
[CSS_STRING, '#upload-result > span { display:block; height: 22px; }'],
|
||||||
|
[CSS_STRING, '#upload-result { display: inline-block; text-align:right; }'],
|
||||||
|
[CSS_STRING, '#upload-progress { display: inline-block; margin-right:8px; }']
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->articleUrl = 'edit';
|
||||||
|
$this->tpl = 'guide-edit';
|
||||||
|
$this->name = Lang::guide('editTitle');
|
||||||
|
$this->save = $this->_post['save'] || $this->_post['submit'];
|
||||||
|
|
||||||
|
// reject inconsistent guide data
|
||||||
|
if ($this->save)
|
||||||
|
{
|
||||||
|
// req: set data
|
||||||
|
if (!$this->_post['title'] || !$this->_post['name'] || !$this->_post['body'] || $this->_post['locale'] === null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// req: valid data
|
||||||
|
if (!in_array($this->_post['category'], $this->validCats) || !(CFG_LOCALES & (1 << $this->_post['locale'])))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// sanitize: spec / class
|
||||||
|
if ($this->_post['category'] == 1) // Classes
|
||||||
|
{
|
||||||
|
if ($this->_post['classId'] && !((1 << $this->_post['classId']) & CLASS_MASK_ALL))
|
||||||
|
$this->_post['classId'] = 0;
|
||||||
|
|
||||||
|
if (!in_array($this->_post['specId'], [-1, 0, 1, 2]))
|
||||||
|
$this->_post['specId'] = -1;
|
||||||
|
if ($this->_post['specId'] > -1 && !$this->_post['classId'])
|
||||||
|
$this->_post['specId'] = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->_post['classId'] = 0;
|
||||||
|
$this->_post['specId'] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->_get['id']) // edit existing guide
|
||||||
|
{
|
||||||
|
$this->typeId = $this->_get['id']; // just to display sensible not-found msg
|
||||||
|
if ($id = DB::Aowow()->selectCell('SELECT `id` FROM ?_guides WHERE `id` = ?d AND `status` <> ?d {AND `userId` = ?d}', $this->typeId, GUIDE_STATUS_ARCHIVED, User::isInGroup(U_GROUP_STAFF) ? DBSIMPLE_SKIP : User::$id))
|
||||||
|
$this->typeId = intVal($id);
|
||||||
|
}
|
||||||
|
else if ($this->_get['id'] === 0) // create new guide and load in editor
|
||||||
|
$this->typeId = DB::Aowow()->query('INSERT INTO ?_guides (`userId`, `date`, `status`) VALUES (?d, ?d, ?d)', User::$id, time(), GUIDE_STATUS_DRAFT);
|
||||||
|
|
||||||
|
return $this->typeId > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function editorFields(string $field, bool $asInt = false) : string|int
|
||||||
|
{
|
||||||
|
return $this->editorFields[$field] ?? ($asInt ? 0 : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateTooltip()
|
||||||
|
{
|
||||||
|
$power = new StdClass();
|
||||||
|
if (!$this->subject->error)
|
||||||
|
{
|
||||||
|
$power->{'name_'.User::$localeString} = $this->name;
|
||||||
|
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf($this->powerTpl, Util::toJSON($this->articleUrl ?: $this->typeId), User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generatePath() : void
|
||||||
|
{
|
||||||
|
if ($x = $this->subject?->getField('category'))
|
||||||
|
$this->path[] = $x;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateTitle() : void
|
||||||
|
{
|
||||||
|
if ($this->show == self::SHOW_EDITOR)
|
||||||
|
array_unshift($this->title, Lang::guide('editTitle').Lang::main('colon').$this->subject->getField('title'), Lang::guide('guides'));
|
||||||
|
if ($this->show == self::SHOW_NEW)
|
||||||
|
array_unshift($this->title, Lang::guide('newTitle'), Lang::guide('guides'));
|
||||||
|
else
|
||||||
|
array_unshift($this->title, $this->subject->getField('title'), Lang::guide('guides'));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function postCache() : void
|
||||||
|
{
|
||||||
|
// increment views of published guide; ignore caching
|
||||||
|
if ($this->subject?->getField('status') == GUIDE_STATUS_APPROVED)
|
||||||
|
DB::Aowow()->query('UPDATE ?_guides SET `views` = `views` + 1 WHERE `id` = ?d', $this->typeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
100
pages/guides.php
Normal file
100
pages/guides.php
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
// menuId ?:Category g_initPath()
|
||||||
|
// tabid 6:Guides g_initHeader()
|
||||||
|
class GuidesPage extends GenericPage
|
||||||
|
{
|
||||||
|
use TrListPage;
|
||||||
|
|
||||||
|
protected $type = Type::Guide;
|
||||||
|
protected $tpl = 'list-page-generic';
|
||||||
|
protected $path = [6];
|
||||||
|
protected $tabId = 6;
|
||||||
|
protected $mode = CACHE_TYPE_PAGE;
|
||||||
|
protected $validCats = [null, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||||
|
|
||||||
|
private $myGuides = false;
|
||||||
|
|
||||||
|
public function __construct($pageCall, $pageParam)
|
||||||
|
{
|
||||||
|
$this->getCategoryFromUrl($pageParam);
|
||||||
|
|
||||||
|
parent::__construct($pageCall, $pageParam);
|
||||||
|
|
||||||
|
if ($pageCall == 'my-guides')
|
||||||
|
{
|
||||||
|
if (!User::$id)
|
||||||
|
$this->error();
|
||||||
|
|
||||||
|
$this->name = Util::ucFirst(Lang::guide('myGuides'));
|
||||||
|
$this->myGuides = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$this->name = Util::ucFirst(Lang::guide('guides'));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateContent()
|
||||||
|
{
|
||||||
|
$hCols = ['patch']; // pointless: display date instead
|
||||||
|
$vCols = [];
|
||||||
|
$xCols = ['$Listview.extraCols.date']; // ok
|
||||||
|
|
||||||
|
if ($this->myGuides)
|
||||||
|
{
|
||||||
|
$conditions = [['userId', User::$id]];
|
||||||
|
$hCols[] = 'author';
|
||||||
|
$vCols[] = 'status';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$conditions = array(
|
||||||
|
['locale', User::$localeId],
|
||||||
|
['status', GUIDE_STATUS_ARCHIVED, '!'], // never archived guides
|
||||||
|
[
|
||||||
|
'OR',
|
||||||
|
['status', GUIDE_STATUS_APPROVED], // currently approved
|
||||||
|
['rev', 0, '>'] // has previously approved revision
|
||||||
|
]
|
||||||
|
);
|
||||||
|
if (isset($this->category[0]))
|
||||||
|
$conditions[] = ['category', $this->category];
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
$guides = new GuideList($conditions);
|
||||||
|
if (!$guides->error)
|
||||||
|
$data = array_values($guides->getListviewData());
|
||||||
|
|
||||||
|
$tabData = array(
|
||||||
|
'data' => $data,
|
||||||
|
'name' => Util::ucFirst(Lang::guide('guides')),
|
||||||
|
'hiddenCols' => $hCols,
|
||||||
|
'visibleCols' => $vCols,
|
||||||
|
'extraCols' => $xCols
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->lvTabs[] = [GuideList::$brickFile, $tabData];
|
||||||
|
|
||||||
|
$this->redButtons = [BUTTON_GUIDE_NEW => User::$id && User::canComment()];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateTitle()
|
||||||
|
{
|
||||||
|
array_unshift($this->title, $this->name);
|
||||||
|
if (isset($this->category[0]))
|
||||||
|
array_unshift($this->title, Lang::guide('category', $this->category[0]));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generatePath()
|
||||||
|
{
|
||||||
|
if (isset($this->category[0]))
|
||||||
|
$this->path[] = $this->category[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -12,14 +12,19 @@ class GuildPage extends GenericPage
|
|||||||
|
|
||||||
protected $lvTabs = [];
|
protected $lvTabs = [];
|
||||||
|
|
||||||
|
protected $type = Type::GUILD;
|
||||||
|
|
||||||
protected $tabId = 1;
|
protected $tabId = 1;
|
||||||
protected $path = [1, 5, 2];
|
protected $path = [1, 5, 2];
|
||||||
protected $tpl = 'roster';
|
protected $tpl = 'roster';
|
||||||
protected $js = ['profile_all.js', 'profile.js'];
|
protected $js = [[JS_FILE, 'profile_all.js'], [JS_FILE, 'profile.js']];
|
||||||
protected $css = [['path' => 'Profiler.css']];
|
protected $css = [[CSS_FILE, 'Profiler.css']];
|
||||||
|
|
||||||
public function __construct($pageCall, $pageParam)
|
public function __construct($pageCall, $pageParam)
|
||||||
{
|
{
|
||||||
|
if (!CFG_PROFILER_ENABLE)
|
||||||
|
$this->error();
|
||||||
|
|
||||||
$params = array_map('urldecode', explode('.', $pageParam));
|
$params = array_map('urldecode', explode('.', $pageParam));
|
||||||
if ($params[0])
|
if ($params[0])
|
||||||
$params[0] = Profiler::urlize($params[0]);
|
$params[0] = Profiler::urlize($params[0]);
|
||||||
@@ -92,7 +97,7 @@ class GuildPage extends GenericPage
|
|||||||
if ($this->doResync)
|
if ($this->doResync)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$this->addJS('?data=realms.weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
$this->addScript([JS_FILE, '?data=realms.weight-presets&locale='.User::$localeId.'&t='.$_SESSION['dataKey']]);
|
||||||
|
|
||||||
$this->redButtons[BUTTON_RESYNC] = [$this->subjectGUID, 'guild'];
|
$this->redButtons[BUTTON_RESYNC] = [$this->subjectGUID, 'guild'];
|
||||||
|
|
||||||
@@ -104,7 +109,7 @@ class GuildPage extends GenericPage
|
|||||||
// statistic calculations here
|
// statistic calculations here
|
||||||
|
|
||||||
// smuggle the guild ranks into the html
|
// 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))
|
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>';
|
$this->extraHTML = '<script type="text/javascript">var guild_ranks = '.Util::toJSON($ranks).';</script>';
|
||||||
|
|
||||||
|
|
||||||
@@ -113,7 +118,7 @@ class GuildPage extends GenericPage
|
|||||||
/**************/
|
/**************/
|
||||||
|
|
||||||
// tab: members
|
// tab: members
|
||||||
$member = new LocalProfileList(array(['p.guild', $this->subjectGUID]));
|
$member = new LocalProfileList(array(['p.guild', $this->subjectGUID], CFG_SQL_LIMIT_NONE));
|
||||||
if (!$member->error)
|
if (!$member->error)
|
||||||
{
|
{
|
||||||
$this->lvTabs[] = ['profile', array(
|
$this->lvTabs[] = ['profile', array(
|
||||||
@@ -125,15 +130,15 @@ class GuildPage extends GenericPage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function notFound($title = '', $msg = '')
|
public function notFound(string $title = '', string $msg = '') : void
|
||||||
{
|
{
|
||||||
return parent::notFound($title ?: Util::ucFirst(Lang::profiler('profiler')), $msg ?: Lang::profiler('notFound', 'guild'));
|
parent::notFound($title ?: Util::ucFirst(Lang::profiler('profiler')), $msg ?: Lang::profiler('notFound', 'guild'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleIncompleteData($teamGuid)
|
private function handleIncompleteData($teamGuid)
|
||||||
{
|
{
|
||||||
//display empty page and queue status
|
//display empty page and queue status
|
||||||
$newId = Profiler::scheduleResync(TYPE_GUILD, $this->realmId, $teamGuid);
|
$newId = Profiler::scheduleResync(Type::GUILD, $this->realmId, $teamGuid);
|
||||||
|
|
||||||
$this->doResync = ['guild', $newId];
|
$this->doResync = ['guild', $newId];
|
||||||
$this->initialSync();
|
$this->initialSync();
|
||||||
|
|||||||
@@ -10,13 +10,20 @@ class GuildsPage extends GenericPage
|
|||||||
{
|
{
|
||||||
use TrProfiler;
|
use TrProfiler;
|
||||||
|
|
||||||
|
protected $type = Type::GUILD;
|
||||||
|
|
||||||
protected $tabId = 1;
|
protected $tabId = 1;
|
||||||
protected $path = [1, 5, 2];
|
protected $path = [1, 5, 2];
|
||||||
protected $tpl = 'guilds';
|
protected $tpl = 'guilds';
|
||||||
protected $js = ['filters.js', 'profile_all.js', 'profile.js'];
|
protected $js = [[JS_FILE, 'filters.js'], [JS_FILE, 'profile_all.js'], [JS_FILE, 'profile.js']];
|
||||||
|
|
||||||
|
protected $_get = ['filter' => ['filter' => FILTER_UNSAFE_RAW]];
|
||||||
|
|
||||||
public function __construct($pageCall, $pageParam)
|
public function __construct($pageCall, $pageParam)
|
||||||
{
|
{
|
||||||
|
if (!CFG_PROFILER_ENABLE)
|
||||||
|
$this->error();
|
||||||
|
|
||||||
$this->getSubjectFromUrl($pageParam);
|
$this->getSubjectFromUrl($pageParam);
|
||||||
|
|
||||||
$this->filterObj = new GuildListFilter();
|
$this->filterObj = new GuildListFilter();
|
||||||
@@ -50,7 +57,7 @@ class GuildsPage extends GenericPage
|
|||||||
|
|
||||||
protected function generateContent()
|
protected function generateContent()
|
||||||
{
|
{
|
||||||
$this->addJS('?data=realms&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
|
$this->addScript([JS_FILE, '?data=realms&locale='.User::$localeId.'&t='.$_SESSION['dataKey']]);
|
||||||
|
|
||||||
$conditions = array(
|
$conditions = array(
|
||||||
['c.deleteInfos_Account', null],
|
['c.deleteInfos_Account', null],
|
||||||
@@ -62,7 +69,7 @@ class GuildsPage extends GenericPage
|
|||||||
|
|
||||||
// recreate form selection
|
// recreate form selection
|
||||||
$this->filter = $this->filterObj->getForm();
|
$this->filter = $this->filterObj->getForm();
|
||||||
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
|
$this->filter['query'] = $this->_get['filter'];
|
||||||
$this->filter['initData'] = ['type' => 'guilds'];
|
$this->filter['initData'] = ['type' => 'guilds'];
|
||||||
|
|
||||||
$tabData = array(
|
$tabData = array(
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
class HomePage extends GenericPage
|
class HomePage extends GenericPage
|
||||||
{
|
{
|
||||||
protected $tpl = 'home';
|
protected $tpl = 'home';
|
||||||
protected $js = ['home.js'];
|
protected $js = [[JS_FILE, 'home.js']];
|
||||||
protected $css = [['path' => 'home.css']];
|
protected $css = [[CSS_FILE, 'home.css']];
|
||||||
|
|
||||||
protected $featuredBox = [];
|
protected $featuredBox = [];
|
||||||
protected $oneliner = '';
|
protected $oneliner = '';
|
||||||
|
protected $homeTitle = '';
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -20,7 +21,7 @@ class HomePage extends GenericPage
|
|||||||
|
|
||||||
protected function generateContent()
|
protected function generateContent()
|
||||||
{
|
{
|
||||||
$this->addCSS(['string' => '.announcement { margin: auto; max-width: 1200px; padding: 0px 15px 15px 15px }']);
|
$this->addScript([CSS_STRING, '.announcement { margin: auto; max-width: 1200px; padding: 0px 15px 15px 15px }']);
|
||||||
|
|
||||||
// load oneliner
|
// load oneliner
|
||||||
if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_home_oneliner WHERE active = 1 LIMIT 1'))
|
if ($_ = DB::Aowow()->selectRow('SELECT * FROM ?_home_oneliner WHERE active = 1 LIMIT 1'))
|
||||||
@@ -52,8 +53,8 @@ class HomePage extends GenericPage
|
|||||||
|
|
||||||
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))
|
if ($_ = DB::Aowow()->selectCell('SELECT title FROM ?_home_titles WHERE active = 1 AND locale = ?d ORDER BY RAND() LIMIT 1', User::$localeId))
|
||||||
$this->title[0] .= Lang::main('colon').Util::localizedString($_, 'title');
|
$this->homeTitle = CFG_NAME.Lang::main('colon').$_;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function generatePath() {}
|
protected function generatePath() {}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// tabId 0: Database g_initHeader()
|
// tabId 0: Database g_initHeader()
|
||||||
class IconPage extends GenericPage
|
class IconPage extends GenericPage
|
||||||
{
|
{
|
||||||
use DetailPage;
|
use TrDetailPage;
|
||||||
|
|
||||||
protected $type = TYPE_ICON;
|
protected $type = Type::ICON;
|
||||||
protected $typeId = 0;
|
protected $typeId = 0;
|
||||||
protected $tpl = 'icon';
|
protected $tpl = 'icon';
|
||||||
protected $path = [0, 31];
|
protected $path = [0, 31];
|
||||||
@@ -25,11 +25,11 @@ class IconPage extends GenericPage
|
|||||||
|
|
||||||
$this->subject = new IconList(array(['id', $this->typeId]));
|
$this->subject = new IconList(array(['id', $this->typeId]));
|
||||||
if ($this->subject->error)
|
if ($this->subject->error)
|
||||||
$this->notFound(Util::ucFirst(Lang::game('icon')), Lang::icon('notFound'));
|
$this->notFound(Lang::game('icon'), Lang::icon('notFound'));
|
||||||
|
|
||||||
$this->extendGlobalData($this->subject->getJSGlobals());
|
$this->extendGlobalData($this->subject->getJSGlobals());
|
||||||
|
|
||||||
$this->name = Util::ucFirst($this->subject->getField('name'));
|
$this->name = $this->subject->getField('name');
|
||||||
$this->icon = $this->subject->getField('name', true, true);
|
$this->icon = $this->subject->getField('name', true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user