implementation of Sound DB

Client sounds are cross-referenced with as many other DB-Types as possible. Including, but not limited to:
 * Character VOs (Errors, Emotes)
 * Creature VOs (Boss Dialogue)
 * Zone Music and Ambience
 * Sounds triggerd by spells
 * Sounds from general item/spell usage, creature behavior

Restrictions:
 * only one locale is supported. Choose wisely!
This commit is contained in:
Sarjuuk 2017-03-06 15:16:34 +01:00 committed by GitHub
parent 8fcd8ea429
commit 20a1829317
54 changed files with 3454 additions and 169 deletions

1
.gitattributes vendored
View file

@ -1,4 +1,5 @@
*.php text eol=lf
*.js text eol=lf
*.css text eol=lf
*.sql text eol=lf

BIN
README.md

Binary file not shown.

View file

@ -352,6 +352,16 @@ abstract class BaseType
return $value;
}
public function getAllFields($field, $localized = false, $silent = false)
{
$data = [];
foreach ($this->iterate() as $__)
$data[$this->id] = $this->getField($field, $localized, $silent);
return $data;
}
public function getRandomId()
{
// ORDER BY RAND() is not optimal, so if anyone has an alternative idea..
@ -668,7 +678,7 @@ trait spawnHelper
public function getSpawns($mode)
{
// ony Creatures and GOs can be spawned
if (!self::$type || (self::$type != TYPE_NPC && self::$type != TYPE_OBJECT))
if (!self::$type || (self::$type != TYPE_NPC && self::$type != TYPE_OBJECT && self::$type != TYPE_SOUND))
return [];
switch ($mode)

View file

@ -24,6 +24,7 @@ define('TYPE_CLASS', 13);
define('TYPE_RACE', 14);
define('TYPE_SKILL', 15);
define('TYPE_CURRENCY', 17);
define('TYPE_SOUND', 19);
// internal types (not published to js)
define('TYPE_USER', 500);
define('TYPE_EMOTE', 501);
@ -42,7 +43,7 @@ define('SEARCH_TYPE_REGULAR', 0x10000000);
define('SEARCH_TYPE_OPEN', 0x20000000);
define('SEARCH_TYPE_JSON', 0x40000000);
define('SEARCH_MASK_OPEN', 0x007DC1FF); // open search
define('SEARCH_MASK_ALL', 0x07FFFFFF); // normal search
define('SEARCH_MASK_ALL', 0x0FFFFFFF); // normal search
// Databases
define('DB_AOWOW', 0);
@ -158,6 +159,7 @@ define('BUTTON_LINKS', 4);
define('BUTTON_FORUM', 5);
define('BUTTON_TALENT', 6);
define('BUTTON_EQUIP', 7);
define('BUTTON_PLAYLIST', 8);
// generic filter handler
define('FILTER_CR_BOOLEAN', 1);
@ -200,6 +202,9 @@ define('CC_FLAG_DELETED', 0x2);
define('CC_FLAG_OUTDATED', 0x4);
define('CC_FLAG_APPROVED', 0x8);
define('SOUND_TYPE_OGG', 1);
define('SOUND_TYPE_MP3', 2);
/*
* Game
*/

View file

@ -0,0 +1,137 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
class SoundList extends BaseType
{
use spawnHelper;
public static $type = TYPE_SOUND;
public static $brickFile = 'sound';
public static $dataTable = '?_sounds';
protected $queryBase = 'SELECT *, s.id AS ARRAY_KEY FROM ?_sounds s';
private $fileBuffer = [];
private static $fileTypes = array(
SOUND_TYPE_OGG => 'audio/ogg; codecs="vorbis"',
SOUND_TYPE_MP3 => 'audio/mpeg'
);
public function __construct($conditions = [])
{
parent::__construct($conditions);
// post processing
foreach ($this->iterate() as $id => &$_curTpl)
{
$_curTpl['files'] = [];
for ($i = 1; $i < 11; $i++)
{
if ($_curTpl['soundFile'.$i])
{
$this->fileBuffer[$_curTpl['soundFile'.$i]] = null;
$_curTpl['files'][] = &$this->fileBuffer[$_curTpl['soundFile'.$i]];
}
unset($_curTpl['soundFile'.$i]);
}
}
if ($this->fileBuffer)
{
$files = DB::Aowow()->select('SELECT id AS ARRAY_KEY, `id`, `file` AS title, `type` FROM ?_sounds_files sf WHERE id IN (?a)', array_keys($this->fileBuffer));
foreach ($files as $id => $data)
{
// skipp file extension
$data['title'] = substr($data['title'], 0, -4);
// enum to string
$data['type'] = self::$fileTypes[$data['type']];
// get real url
$data['url'] = STATIC_URL . '/wowsounds/' . $data['id'];
// v push v
$this->fileBuffer[$id] = $data;
}
}
}
public static function getName($id)
{
$this->getEntry($id);
return $this->getField('name');
}
public function getListviewData()
{
$data = [];
foreach ($this->iterate() as $__)
{
$data[$this->id] = array(
'id' => $this->id,
'type' => $this->getField('cat'),
'name' => $this->getField('name'),
'files' => array_values(array_filter($this->getField('files')))
);
}
return $data;
}
public function getJSGlobals($addMask = 0)
{
$data = [];
foreach ($this->iterate() as $__)
$data[self::$type][$this->id] = array(
'name' => Util::jsEscape($this->getField('name', true)),
'type' => $this->getField('cat'),
'files' => array_values(array_filter($this->getField('files')))
);
return $data;
}
public function renderTooltip() { }
}
class SoundListFilter extends Filter
{
// we have no criteria for this one...
protected function createSQLForCriterium(&$cr)
{
unset($cr);
$this->error = true;
return [1];
}
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']))
{
if ($_ = array_intersect((array)$_v['ty'], [1, 2, 3, 4, 6, 9, 10, 12, 13, 14, 16, 17, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 50, 52, 53]))
$parts[] = ['cat', $_];
else
{
$this->error = true;
unset($_v['ty']);
}
}
return $parts;
}
}
?>

View file

@ -1998,6 +1998,11 @@ class SpellList extends BaseType
for ($i = 0; $i < 11; $i++)
if ($mask & (1 << $i))
$data[TYPE_RACE][$i + 1] = $i + 1;
// play sound effect
for ($i = 1; $i < 4; $i++)
if ($this->getField('effect'.$i.'Id') == 132)
$data[TYPE_SOUND][$this->getField('effect'.$i.'MiscValue')] = $this->getField('effect'.$i.'MiscValue');
}
if ($addMask & GLOBALINFO_SELF)

View file

@ -39,7 +39,7 @@ class Util
public static $typeClasses = array(
null, 'CreatureList', 'GameObjectList', 'ItemList', 'ItemsetList', 'QuestList', 'SpellList',
'ZoneList', 'FactionList', 'PetList', 'AchievementList', 'TitleList', 'WorldEventList', 'CharClassList',
'CharRaceList', 'SkillList', null, 'CurrencyList',
'CharRaceList', 'SkillList', null, 'CurrencyList', null, 'SoundList',
TYPE_EMOTE => 'EmoteList',
TYPE_ENCHANTMENT => 'EnchantmentList'
);
@ -47,6 +47,7 @@ class Util
public static $typeStrings = array( // zero-indexed
null, 'npc', 'object', 'item', 'itemset', 'quest', 'spell', 'zone', 'faction',
'pet', 'achievement', 'title', 'event', 'class', 'race', 'skill', null, 'currency',
null, 'sound',
TYPE_USER => 'user',
TYPE_EMOTE => 'emote',
TYPE_ENCHANTMENT => 'enchantment'

View file

@ -64,8 +64,8 @@ switch ($pageCall)
case 'search': // tool: searches
case 'skill':
case 'skills':
// case 'sound': // db: sounds for zone, creature, spell, ...
// case 'sounds':
case 'sound': // db: sounds for zone, creature, spell, ...
case 'sounds':
case 'spell':
case 'spells':
case 'talent': // tool: talent calculator

View file

@ -25,6 +25,7 @@ class Lang
private static $quest;
private static $race;
private static $skill;
private static $sound;
private static $spell;
private static $title;
private static $zone;

View file

@ -214,6 +214,8 @@ $lang = array(
'school' => "Magieart",
'skill' => "Fertigkeit",
'skills' => "Fertigkeiten",
'sound' => "Klang",
'sounds' => "Klänge",
'spell' => "Zauber",
'spells' => "Zauber",
'type' => "Art",
@ -675,6 +677,17 @@ $lang = array(
1 => "Verschiedenes", 2 => "Spieler gegen Spieler", 4 => "Classic", 21 => "Wrath of the Lich King", 22 => "Dungeon und Schlachtzug", 23 => "Burning Crusade", 41 => "Test", 3 => "Unbenutzt"
)
),
'sound' => array(
'notFound' => "Dieser Klang existiert nicht.",
'foundIn' => "Dieser Klang befindet sich in",
'goToPlaylist' => "Gehe zu meiner Playlist",
'cat' => array(
null, "Spells", "User Interface", "Footsteps", "Weapons Impacts", null, "Weapons Misses", null, null, "Pick Up/Put Down",
"NPC Combat", null, "Errors", "Nature", "Objects", null, "Death", "NPC Greetings", null, "Armor",
"Footstep Splash", "Water (Character)", "Water", "Tradeskills", "Misc Ambience", "Doodads", "Spell Fizzle", "NPC Loops", "Zone Music", "Emotes",
"Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "Meine Playlist"
)
),
'pet' => array(
'notFound' => "Diese Tierart existiert nicht.",
'exotic' => "Exotisch",

View file

@ -209,6 +209,8 @@ $lang = array(
'school' => "School",
'skill' => "skill",
'skills' => "Skills",
'sound' => "sound",
'sounds' => "Sounds",
'spell' => "spell",
'spells' => "Spells",
'type' => "Type",
@ -670,6 +672,17 @@ $lang = array(
1 => "Miscellaneous", 2 => "Player vs. Player", 4 => "Classic", 21 => "Wrath of the Lich King", 22 => "Dungeon and Raid", 23 => "Burning Crusade", 41 => "Test", 3 => "Unused"
)
),
'sound' => array(
'notFound' => "This sound doesn't exist.",
'foundIn' => "This sound can be found in",
'goToPlaylist' => "Go to My Playlist",
'cat' => array(
null, "Spells", "User Interface", "Footsteps", "Weapons Impacts", null, "Weapons Misses", null, null, "Pick Up/Put Down",
"NPC Combat", null, "Errors", "Nature", "Objects", null, "Death", "NPC Greetings", null, "Armor",
"Footstep Splash", "Water (Character)", "Water", "Tradeskills", "Misc Ambience", "Doodads", "Spell Fizzle", "NPC Loops", "Zone Music", "Emotes",
"Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "My Playlist"
)
),
'pet' => array(
'notFound' => "This pet family doesn't exist.",
'exotic' => "Exotic",

View file

@ -214,6 +214,8 @@ $lang = array(
'school' => "Escuela",
'skill' => "habilidad",
'skills' => "Habilidades",
'sound' => "sonido",
'sounds' => "Sonidos",
'spell' => "hechizo",
'spells' => "Hechizos",
'type' => "Tipo",
@ -676,6 +678,17 @@ $lang = array(
1 => "Miscelánea", 2 => "Jugador contra Jugador", 4 => "Clásico", 21 => "Wrath of the Lich King", 22 => "Mazmorra y banda", 23 => "Burning Crusade", 41 => "Prueba", 3 => "No las uso"
)
),
'sound' => array(
'notFound' => "Este sonido no existe.",
'foundIn' => "Este sonido se puede encontrar en",
'goToPlaylist' => "Ir a mi lista de reproducción",
'cat' => array(
null, "Spells", "User Interface", "Footsteps", "Weapons Impacts", null, "Weapons Misses", null, null, "Pick Up/Put Down",
"NPC Combat", null, "Errors", "Nature", "Objects", null, "Death", "NPC Greetings", null, "Armor",
"Footstep Splash", "Water (Character)", "Water", "Tradeskills", "Misc Ambience", "Doodads", "Spell Fizzle", "NPC Loops", "Zone Music", "Emotes",
"Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "Mi Lista de Reproducción"
)
),
'pet' => array(
'notFound' => "Esta familia de mascotas no existe.",
'exotic' => "Exótica",

View file

@ -214,6 +214,8 @@ $lang = array(
'school' => "École",
'skill' => "compétence",
'skills' => "Compétences",
'sound' => "son",
'sounds' => "Sons",
'spell' => "sort",
'spells' => "Sorts",
'type' => "Type",
@ -674,6 +676,17 @@ $lang = array(
1 => "Divers", 2 => "JcJ", 4 => "Classique", 21 => "Wrath of the Lich King", 22 => "Raid", 23 => "Burning Crusade", 41 => "Test", 3 => "Inutilisées"
)
),
'sound' => array(
'notFound' => "Ce son n'existe pas.",
'foundIn' => "Ce son se trouve dans",
'goToPlaylist' => "Aller à votre playlist",
'cat' => array(
null, "Spells", "User Interface", "Footsteps", "Weapons Impacts", null, "Weapons Misses", null, null, "Pick Up/Put Down",
"NPC Combat", null, "Errors", "Nature", "Objects", null, "Death", "NPC Greetings", null, "Armor",
"Footstep Splash", "Water (Character)", "Water", "Tradeskills", "Misc Ambience", "Doodads", "Spell Fizzle", "NPC Loops", "Zone Music", "Emotes",
"Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "Ma playlist"
)
),
'pet' => array(
'notFound' => "Cette famille de familiers n'existe pas.",
'exotic' => "Exotique",

View file

@ -214,6 +214,8 @@ $lang = array(
'school' => "Школа",
'skill' => "Уровень навыка",
'skills' => "Умения",
'sound' => "Звук",
'sounds' => "Звуки",
'spell' => "заклинание",
'spells' => "Заклинания",
'type' => "Тип",
@ -675,6 +677,17 @@ $lang = array(
1 => "Разное", 2 => "PvP", 4 => "World of Warcraft", 21 => "Wrath of the Lich King", 22 => "Подземелья и рейды", 23 => "Burning Crusade", 41 => "Test", 3 => "Неактивно"
)
),
'sound' => array(
'notFound' => "Этот звук не существует.",
'foundIn' => "Этот Звук может быть найден в следующих зонах:",
'goToPlaylist' => "Перейти к плейлисту",
'cat' => array(
null, "Spells", "User Interface", "Footsteps", "Weapons Impacts", null, "Weapons Misses", null, null, "Pick Up/Put Down",
"NPC Combat", null, "Errors", "Nature", "Objects", null, "Death", "NPC Greetings", null, "Armor",
"Footstep Splash", "Water (Character)", "Water", "Tradeskills", "Misc Ambience", "Doodads", "Spell Fizzle", "NPC Loops", "Zone Music", "Emotes",
"Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "Мой плейлист"
)
),
'pet' => array(
'notFound' => "Такой породы питомцев не существует.",
'exotic' => "Экзотический",

View file

@ -100,6 +100,28 @@ class EmotePage extends GenericPage
$this->lvTabs[] = ['achievement', ['data' => array_values($acv->getListviewData())]];
$this->extendGlobalData($acv->getJsGlobals());
// tab: sound
if ($em = DB::Aowow()->select('SELECT soundId AS ARRAY_KEY, BIT_OR(1 << (raceId - 1)) AS raceMask, BIT_OR(1 << (gender - 1)) AS gender FROM aowow_emotes_sounds WHERE emoteId = ?d GROUP BY soundId', $this->typeId))
{
$sounds = new SoundList(array(['id', array_keys($em)]));
if (!$sounds->error)
{
$this->extendGlobalData($sounds->getJSGlobals(GLOBALINFO_SELF));
$data = $sounds->getListviewData();
foreach($data as $id => &$d)
{
$d['races'] = $em[$id]['raceMask'];
$d['gender'] = $em[$id]['gender'];
}
$this->lvTabs[] = ['sound', array(
'data' => array_values($data),
// gender races
'extraCols' => ['$Listview.templates.title.columns[1]', '$Listview.templates.classs.columns[1]']
)];
}
}
}
}

View file

@ -129,6 +129,7 @@ class GenericPage
'reputationhistory' => ['template' => 'reputationhistory', 'id' => 'reputation', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_reputation' ],
'screenshot' => ['template' => 'screenshot', 'id' => 'screenshots', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_screenshots' ],
'skill' => ['template' => 'skill', 'id' => 'skills', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_skills' ],
'sound' => ['template' => 'sound', 'id' => 'sounds', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.types[19][2]' ],
'spell' => ['template' => 'spell', 'id' => 'spells', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_spells' ],
'title' => ['template' => 'title', 'id' => 'titles', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_titles' ],
'video' => ['template' => 'video', 'id' => 'videos', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_videos' ],
@ -641,6 +642,7 @@ class GenericPage
case TYPE_RACE: $jsg[TYPE_RACE] = ['g_races', [], []]; break;
case TYPE_SKILL: $jsg[TYPE_SKILL] = ['g_skills', [], []]; break;
case TYPE_CURRENCY: $jsg[TYPE_CURRENCY] = ['g_gatheredcurrencies', [], []]; break;
case TYPE_SOUND: $jsg[TYPE_SOUND] = ['g_sounds', [], []]; break;
// well, this is awkward
case TYPE_USER: $jsg[TYPE_USER] = ['g_users', [], []]; break;
case TYPE_EMOTE: $jsg[TYPE_EMOTE] = ['g_emotes', [], []]; break;
@ -681,6 +683,7 @@ class GenericPage
case TYPE_RACE: $obj = new CharRaceList($cnd); break;
case TYPE_SKILL: $obj = new SkillList($cnd); break;
case TYPE_CURRENCY: $obj = new CurrencyList($cnd); break;
case TYPE_SOUND: $obj = new SoundList($cnd); break;
// "um, eh":, he ums and ehs.
case TYPE_USER: $obj = new UserList($cnd); break;
case TYPE_EMOTE: $obj = new EmoteList($cnd); break;

View file

@ -953,6 +953,45 @@ class ItemPage extends genericPage
}
}
// tab: sounds
$soundIds = [];
if ($_class == ITEM_CLASS_WEAPON)
{
$scm = (1 << $_subClass);
if ($this->subject->getField('soundOverrideSubclass') > 0)
$scm = (1 << $this->subject->getField('soundOverrideSubclass'));
$soundIds = DB::Aowow()->selectCol('SELECT soundId FROM ?_items_sounds WHERE subClassMask & ?d', $scm);
}
$fields = ['pickUpSoundId', 'dropDownSoundId', 'sheatheSoundId', 'unsheatheSoundId'];
foreach ($fields as $f)
if ($x = $this->subject->getField($f))
$soundIds[] = $x;
if ($x = $this->subject->getField('spellVisualId'))
{
if ($spellSounds = DB::Aowow()->selectRow('SELECT * FROM ?_spell_sounds WHERE id = ?d', $x))
{
array_shift($spellSounds); // bye 'id'-field
foreach ($spellSounds as $ss)
if ($ss)
$soundIds[] = $ss;
}
}
if ($soundIds)
{
$sounds = new SoundList(array(['id', $soundIds]));
if (!$sounds->error)
{
$this->extendGlobalData($sounds->getJSGlobals(GLOBALINFO_SELF));
$this->lvTabs[] = ['sound', ['data' => array_values($sounds->getListviewData())]];
}
}
// // todo - tab: taught by
// use var $createdBy to find source of this spell
// id: 'taught-by-X',

View file

@ -18,6 +18,8 @@ class NpcPage extends GenericPage
protected $mode = CACHE_TYPE_PAGE;
protected $js = ['swfobject.js'];
private $soundIds = [];
public function __construct($pageCall, $id)
{
parent::__construct($pageCall, $id);
@ -581,7 +583,7 @@ class NpcPage extends GenericPage
{
$mode = ($_altIds[$id] + 1) * ($mapType == 1 ? -1 : 1);
if ($lootGO = DB::Aowow()->selectRow('SELECT o.id, o.lootId, o.name_loc0, o.name_loc2, o.name_loc3, o.name_loc6, o.name_loc8 FROM ?_loot_link l JOIN ?_objects o ON o.id = l.objectId WHERE l.npcId = ?d', $id))
array_splice($sourceFor, 1, 0, [[LOOT_GAMEOBJECT, $lootGO['lootId'], $langref[$mode], 'drops-object-'.abs($mode), [], 'note' => '$$WH.sprintf(LANG.lvnote_npcobjectsource, '.$lootGO['id'].', \''.Util::jsEscape(Util::localizedString($lootGO, 'name')).'\')']]);
array_splice($sourceFor, 1, 0, [[LOOT_GAMEOBJECT, $lootGO['lootId'], $langref[$mode], 'drops-object-'.abs($mode), [], 'note' => '$$WH.sprintf(LANG.lvnote_npcobjectsource, '.$lootGO['id'].', "'.Util::localizedString($lootGO, 'name').'")']]);
if ($lootId = $_altNPCs->getField('lootId'))
array_splice($sourceFor, 1, 0, [[LOOT_CREATURE, $lootId, $langref[$mode], 'drops-'.abs($mode), []]]);
}
@ -589,7 +591,7 @@ class NpcPage extends GenericPage
if ($lootGOs = DB::Aowow()->select('SELECT o.id, IF(npcId < 0, 1, 0) AS modeDummy, o.lootId, o.name_loc0, o.name_loc2, o.name_loc3, o.name_loc6, o.name_loc8 FROM ?_loot_link l JOIN ?_objects o ON o.id = l.objectId WHERE ABS(l.npcId) = ?d', $this->typeId))
foreach ($lootGOs as $idx => $lgo)
array_splice($sourceFor, 1, 0, [[LOOT_GAMEOBJECT, $lgo['lootId'], $mapType ? $langref[($mapType == 1 ? -1 : 1) + ($lgo['modeDummy'] ? 1 : 0)] : '$LANG.tab_drops', 'drops-object-'.$idx, [], 'note' => '$$WH.sprintf(LANG.lvnote_npcobjectsource, '.$lgo['id'].', \''.Util::jsEscape(Util::localizedString($lgo, 'name')).'\')']]);
array_splice($sourceFor, 1, 0, [[LOOT_GAMEOBJECT, $lgo['lootId'], $mapType ? $langref[($mapType == 1 ? -1 : 1) + ($lgo['modeDummy'] ? 1 : 0)] : '$LANG.tab_drops', 'drops-object-'.$idx, [], 'note' => '$$WH.sprintf(LANG.lvnote_npcobjectsource, '.$lgo['id'].', "'.Util::localizedString($lgo, 'name').'")']]);
$reqQuest = [];
foreach ($sourceFor as $sf)
@ -752,6 +754,58 @@ class NpcPage extends GenericPage
$this->lvTabs[] = ['creature', $tabData];
}
}
/* tab sounds:
* activity sounds => CreatureDisplayInfo.dbc => (CreatureModelData.dbc => ) CreatureSoundData.dbc
* AI => smart_scripts
* Dialogue VO => creature_text
* onClick VO => CreatureDisplayInfo.dbc => NPCSounds.dbc
*/
$ssActionLists = DB::World()->select('SELECT action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6 FROM smart_scripts WHERE entryorguid = ?d AND source_type = 0 AND action_type IN (80, 87, 88)', $this->typeId);
$actionListIds = [];
foreach ($ssActionLists as $sal)
{
$iMax = 0;
switch ($sal['action_type'])
{
case 80: $iMax = 1; break;
case 87: $iMax = 6; break;
case 88: $iMax = 2; break;
default: continue;
}
for ($i = 1; $i <= $iMax; $i++)
if ($sal['action_param'.$i])
$actionListIds[] = $sal['action_param'.$i];
}
// not going for a per guid basis. The infos are nested enough as is.
$smartScripts = DB::World()->selectCol('SELECT action_param1 FROM smart_scripts WHERE action_type = 4 AND ((source_type = 0 AND entryorguid = ?d) { OR (source_type = 9 AND entryorguid IN (?a)) } )', $this->typeId, $actionListIds ?: DBSIMPLE_SKIP);
$this->soundIds = array_merge($this->soundIds, $smartScripts);
// up to 4 possible displayIds .. for the love of things betwixt, just use the first!
$activitySounds = DB::Aowow()->selectRow('SELECT * FROM ?_creature_sounds WHERE id = ?d', $this->subject->getField('displayId1'));
array_shift($activitySounds); // remove id-column
$this->soundIds = array_merge($this->soundIds, array_values($activitySounds));
if ($this->soundIds)
{
$sounds = new SoundList(array(['id', $this->soundIds]));
if (!$sounds->error)
{
$data = $sounds->getListviewData();
foreach ($activitySounds as $activity => $id)
if (isset($data[$id]))
$data[$id]['activity'] = $activity; // no index, js wants a string :(
$tabData = ['data' => array_values($data)];
if ($activitySounds)
$tabData['visibleCols'] = ['activity'];
$this->extendGlobalData($sounds->getJSGlobals(GLOBALINFO_SELF));
$this->lvTabs[] = ['sound', $tabData];
}
}
}
protected function generateTooltip($asError = false)
@ -908,7 +962,8 @@ class NpcPage extends GenericPage
IFNULL(NULLIF(lbct.MaleText_loc2, ""), IFNULL(NULLIF(lbct.FemaleText_loc2, ""), IFNULL(lct.text_loc2, ""))) AS text_loc2,
IFNULL(NULLIF(lbct.MaleText_loc3, ""), IFNULL(NULLIF(lbct.FemaleText_loc3, ""), IFNULL(lct.text_loc3, ""))) AS text_loc3,
IFNULL(NULLIF(lbct.MaleText_loc6, ""), IFNULL(NULLIF(lbct.FemaleText_loc6, ""), IFNULL(lct.text_loc6, ""))) AS text_loc6,
IFNULL(NULLIF(lbct.MaleText_loc8, ""), IFNULL(NULLIF(lbct.FemaleText_loc8, ""), IFNULL(lct.text_loc8, ""))) AS text_loc8
IFNULL(NULLIF(lbct.MaleText_loc8, ""), IFNULL(NULLIF(lbct.FemaleText_loc8, ""), IFNULL(lct.text_loc8, ""))) AS text_loc8,
IF(bct.SoundId > 0, bct.SoundId, ct.sound) AS soundId
FROM
creature_text ct
LEFT JOIN
@ -927,6 +982,9 @@ class NpcPage extends GenericPage
$group = [];
foreach ($text as $t)
{
if ($t['soundId'])
$this->soundIds[] = $t['soundId'];
$msg = Util::localizedString($t, 'text');
if (!$msg)
continue;

View file

@ -31,6 +31,8 @@ class ObjectsPage extends GenericPage
protected function generateContent()
{
$this->addJS('?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
$conditions = [];
if (!User::isInGroup(U_GROUP_EMPLOYEE))

View file

@ -183,6 +183,24 @@ class RacePage extends GenericPage
'hiddenCols' => ['slot', 'type']
)];
}
// Sounds
if ($vo = DB::Aowow()->selectCol('SELECT soundId AS ARRAY_KEY, gender FROM ?_races_sounds WHERE raceId = ?d', $this->typeId))
{
$sounds = new SoundList(array(['id', array_keys($vo)]));
if (!$sounds->error)
{
$this->extendGlobalData($sounds->getJSGlobals(GLOBALINFO_SELF));
$data = $sounds->getListviewData();
foreach ($data as $id => &$d)
$d['gender'] = $vo[$id];
$this->lvTabs[] = ['sound', array(
'data' => array_values($data),
'extraCols' => ['$Listview.templates.title.columns[1]']
)];
}
}
}
}

View file

@ -52,7 +52,7 @@ class SearchPage extends GenericPage
'_searchProficiency', '_searchProfession', '_searchCompanion', '_searchMount', '_searchCreature',
'_searchQuest', '_searchAchievement', '_searchStatistic', '_searchZone', '_searchObject',
'_searchFaction', '_searchSkill', '_searchPet', '_searchCreatureAbility', '_searchSpell',
'_searchEmote', '_searchEnchantment'
'_searchEmote', '_searchEnchantment', '_searchSound'
);
public function __construct($pageCall, $pageParam)
@ -1359,9 +1359,35 @@ class SearchPage extends GenericPage
return false;
}
// private function _searchCharacter($cndBase) { } // 27 Characters $searchMask & 0x8000000
// private function _searchGuild($cndBase) { } // 28 Guilds $searchMask & 0x10000000
// private function _searchArenaTeam($cndBase) { } // 29 Arena Teams $searchMask & 0x20000000
private function _searchSound($cndBase) // 27 Sounds $searchMask & 0x8000000
{
$cnd = array_merge($cndBase, [$this->createLookup(['name'])]);
$sounds = new SoundList($cnd);
if ($data = $sounds->getListviewData())
{
if ($this->searchMask & SEARCH_TYPE_REGULAR)
$this->extendGlobalData($sounds->getJSGlobals());
$osInfo = [TYPE_SOUND, ' (Sound)', $sounds->getMatches()];
$result['data'] = array_values($data);
if ($sounds->getMatches() > $this->maxResults)
{
$result['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_soundsfound', $sounds->getMatches(), $this->maxResults);
$result['_truncated'] = 1;
}
return ['sound', $result, null, $osInfo];
}
return false;
}
// private function _searchCharacter($cndBase) { } // 28 Characters $searchMask & 0x10000000
// private function _searchGuild($cndBase) { } // 29 Guilds $searchMask & 0x20000000
// private function _searchArenaTeam($cndBase) { } // 30 Arena Teams $searchMask & 0x40000000
}
?>

369
pages/sound.php Normal file
View file

@ -0,0 +1,369 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// menuId 19: Sound g_initPath()
// tabId 0: Database g_initHeader()
class SoundPage extends GenericPage
{
use DetailPage;
protected $type = TYPE_SOUND;
protected $typeId = 0;
protected $tpl = 'sound';
protected $path = [0, 19];
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
private $cat = 0;
protected $special = false;
public function __construct($pageCall, $id)
{
parent::__construct($pageCall, $id);
// special case
if (!$id && isset($_GET['playlist']))
{
$this->special = true;
$this->name = Lang::sound('cat', 1000);
$this->cat = 1000;
$this->typeId = -1000;
}
// regular case
else
{
$this->typeId = intVal($id);
$this->subject = new SoundList(array(['id', $this->typeId]));
if ($this->subject->error)
$this->notFound(Lang::game('sound'), Lang::sound('notFound'));
$this->name = $this->subject->getField('name');
$this->cat = $this->subject->getField('cat');
}
}
protected function generatePath()
{
$this->path[] = $this->cat;
}
protected function generateTitle()
{
array_unshift($this->title, $this->name, Util::ucFirst(Lang::game('sound')));
}
protected function generateContent()
{
if ($this->special)
$this->generatePlaylistContent();
else
$this->generateDefaultContent();
}
private function generatePlaylistContent()
{
}
private function generateDefaultContent()
{
/****************/
/* Main Content */
/****************/
$this->addJS('?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
// get spawns
$map = null;
if ($spawns = $this->subject->getSpawns(SPAWNINFO_FULL))
{
$map = ['data' => ['parent' => 'mapper-generic'], 'mapperData' => &$spawns];
foreach ($spawns as $areaId => &$areaData)
$map['extra'][$areaId] = ZoneList::getName($areaId);
}
// get full path ingame for sound (workaround for missing PlaySoundKit())
$fullpath = DB::Aowow()->selectCell('SELECT IF(sf.`path`, CONCAT(sf.`path`, "\\\\", sf.`file`), sf.`file`) FROM ?_sounds_files sf JOIN ?_sounds s ON s.soundFile1 = sf.id WHERE s.id = ?d', $this->typeId);
$this->map = $map;
$this->headIcons = [$this->subject->getField('iconString')];
$this->redButtons = array(
BUTTON_WOWHEAD => true,
BUTTON_PLAYLIST => true,
BUTTON_LINKS => array(
'type' => TYPE_SOUND,
'typeId' => $this->typeId,
'sound' => str_replace('\\', '\\\\', $fullpath) // escape for wow client
)
);
$this->extendGlobalData($this->subject->getJSGlobals());
/**************/
/* Extra Tabs */
/**************/
// tab: Spells
// skipping (always empty): ready, castertargeting, casterstate, targetstate
$displayIds = DB::Aowow()->selectCol('
SELECT id FROM ?_spell_sounds WHERE
animation = ?d OR
precast = ?d OR
cast = ?d OR
impact = ?d OR
state = ?d OR
statedone = ?d OR
channel = ?d OR
casterimpact = ?d OR
targetimpact = ?d OR
missiletargeting = ?d OR
instantarea = ?d OR
persistentarea = ?d OR
missile = ?d OR
impactarea = ?d
', $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId);
$cnd = array(
'OR',
['AND', ['effect1Id', 132], ['effect1MiscValue', $this->typeId]],
['AND', ['effect2Id', 132], ['effect2MiscValue', $this->typeId]],
['AND', ['effect3Id', 132], ['effect3MiscValue', $this->typeId]]
);
if ($displayIds)
$cnd[] = ['spellVisualId', $displayIds];
$spells = new SpellList($cnd);
if (!$spells->error)
{
$data = $spells->getListviewData();
$this->extendGlobalData($spells->getJSGlobals(GLOBALINFO_SELF));
$this->lvTabs[] = ['spell', array(
'data' => array_values($data),
)];
}
// tab: Items
$subClasses = [];
if ($subClassMask = DB::Aowow()->selectCell('SELECT subClassMask FROM ?_items_sounds WHERE soundId = ?d', $this->typeId))
for ($i = 0; $i <= 20; $i++)
if ($subClassMask & (1 << $i))
$subClasses[] = $i;
$itemIds = DB::Aowow()->selectCol('
SELECT
id
FROM
?_items
WHERE
{spellVisualId IN (?a) OR }
pickUpSoundId = ?d OR
dropDownSoundId = ?d OR
sheatheSoundId = ?d OR
unsheatheSoundId = ?d {OR
(
IF (soundOverrideSubclass > 0, soundOverrideSubclass, subclass) IN (?a) AND
class = ?d
)}
', $displayIds ?: DBSIMPLE_SKIP, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $subClasses ?: DBSIMPLE_SKIP, ITEM_CLASS_WEAPON);
if ($itemIds)
{
$items = new ItemList(array(['id', $itemIds]));
if (!$items->error)
{
$this->extendGlobalData($items->getJSGlobals(GLOBALINFO_SELF));
$this->lvTabs[] = ['item', ['data' => array_values($items->getListviewData())]];
}
}
// tab: Zones
if ($zoneIds = DB::Aowow()->select('SELECT id, worldStateId, worldStateValue FROM ?_zones_sounds WHERE ambienceDay = ?d OR ambienceNight = ?d OR musicDay = ?d OR musicNight = ?d OR intro = ?d', $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId))
{
$zones = new ZoneList(array(['id', array_column($zoneIds, 'id')]));
if (!$zones->error)
{
$this->extendGlobalData($zones->getJSGlobals(GLOBALINFO_SELF));
$zoneData = $zones->getListviewData();
$parents = $zones->getAllFields('parentArea');
$tabData = [];
$pIds = array_filter(array_unique(array_values($parents)));
if ($pIds)
{
$pZones = new ZoneList(array(['id', $pIds]));
if (!$pZones->error)
{
$this->extendGlobalData($pZones->getJSGlobals(GLOBALINFO_SELF));
$pData = $pZones->getListviewData();
foreach ($parents as $child => $parent)
{
if (!$parent || empty($pData[$parent]))
continue;
if (!isset($pData[$parent]['subzones']))
$pData[$parent]['subzones'] = [];
$pData[$parent]['subzones'][] = $child;
unset($parents[$child]);
}
// these are original parents
foreach ($parents as $parent => $__)
if (empty($pData[$parent]))
$pData[$parent] = $zoneData[$parent];
$zoneData = $pData;
}
}
if (array_filter(array_column($zoneIds, 'worldStateId')))
{
$tabData['extraCols'] = ['$Listview.extraCols.condition'];
foreach ($zoneIds as $zData)
if ($zData['worldStateId'])
$zoneData[$zData['id']]['condition'][0][$this->typeId][] = [[CND_WORLD_STATE, $zData['worldStateId'], $zData['worldStateValue']]];
}
$tabData['data'] = array_values($zoneData);
$tabData['hiddenCols'] = ['territory'];
$this->lvTabs[] = ['zone', $tabData];
}
}
// tab: Races (VocalUISounds (containing error voice overs))
if ($vo = DB::Aowow()->selectCol('SELECT raceId FROM ?_races_sounds WHERE soundId = ?d GROUP BY raceId', $this->typeId))
{
$races = new CharRaceList(array(['id', $vo]));
if (!$races->error)
{
$this->extendGlobalData($races->getJSGlobals(GLOBALINFO_SELF));
$this->lvTabs[] = ['race', ['data' => array_values($races->getListviewData())]];
}
}
// tab: Emotes (EmotesTextSound (containing emote audio))
if ($em = DB::Aowow()->selectCol('SELECT emoteId FROM ?_emotes_sounds WHERE soundId = ?d GROUP BY emoteId', $this->typeId))
{
$races = new EmoteList(array(['id', $em]));
if (!$races->error)
{
$this->extendGlobalData($races->getJSGlobals(GLOBALINFO_SELF));
$this->lvTabs[] = ['emote', array(
'data' => array_values($races->getListviewData()),
'name' => Util::ucFirst(Lang::game('emotes'))
), 'emote'];
}
}
$ssQuery = '
SELECT
source_type AS ARRAY_KEY,
entryorguid AS ARRAY_KEY2,
0
FROM
smart_scripts
WHERE
(action_type = 4 AND action_param1 = ?d AND source_type <> 9) {
OR (action_type = 80 AND (action_param1 IN (?a)))
OR (action_type = 87 AND (action_param1 IN (?a) OR action_param2 IN (?a) OR action_param3 IN (?a) OR action_param4 IN (?a) OR action_param5 IN (?a) OR action_param6 IN (?a)))
OR (action_type = 88 AND (action_param1 IN (?a) OR action_param2 IN (?a)))
}
';
$ssActionLists = DB::World()->selectCol('SELECT entryorguid FROM smart_scripts WHERE action_type = 4 AND action_param1 = ?d AND source_type = 9', $this->typeId);
$smartScripts = DB::World()->selectCol($ssQuery, $this->typeId, $ssActionLists ?: DBSIMPLE_SKIP, $ssActionLists, $ssActionLists, $ssActionLists, $ssActionLists, $ssActionLists, $ssActionLists, $ssActionLists, $ssActionLists);
$creatureIds = DB::World()->selectCol('SELECT entry FROM creature_text ct LEFT JOIN broadcast_text bct ON bct.ID = ct.BroadCastTextId WHERE bct.SoundId = ?d OR ct.sound = ?d', $this->typeId, $this->typeId);
foreach ($smartScripts as $source => $ids)
{
switch($source)
{
case 0: // npc
// filter for guids (id < 0)
$creatureIds = array_merge($creatureIds, array_keys(array_filter($ids, function($x) { return $x > 0; })) );
break;
case 1: // gameobject
default:
break;
}
}
// tab: NPC (dialogues...?, generic creature sound)
// skipping (always empty): transforms, footsteps
$displayIds = DB::Aowow()->selectCol('
SELECT id FROM ?_creature_sounds WHERE
greeting = ?d OR
farewell = ?d OR
angry = ?d OR
exertion = ?d OR
exertioncritical = ?d OR
injury = ?d OR
injurycritical = ?d OR
death = ?d OR
stun = ?d OR
stand = ?d OR
aggro = ?d OR
wingflap = ?d OR
wingglide = ?d OR
alert = ?d OR
fidget = ?d OR
customattack = ?d OR
`loop` = ?d OR
jumpstart = ?d OR
jumpend = ?d OR
petattack = ?d OR
petorder = ?d OR
petdismiss = ?d OR
birth = ?d OR
spellcast = ?d OR
submerge = ?d OR
submerged = ?d
', $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId);
// broadcast_text <-> creature_text
if ($creatureIds || $displayIds)
{
$extra = [];
$cnds = [CFG_SQL_LIMIT_NONE, &$extra];
if (!User::isInGroup(U_GROUP_STAFF))
$cnds[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0];
if ($creatureIds)
$extra[] = ['id', $creatureIds];
if ($displayIds)
$extra[] = ['displayId1', $displayIds];
if (count($extra) > 1)
array_unshift($extra, 'OR');
else
$extra = array_pop($extra);
$npcs = new CreatureList($cnds);
if (!$npcs->error)
{
$this->addJS('?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']);
$this->extendGlobalData($npcs->getJSGlobals(GLOBALINFO_SELF));
$this->lvTabs[] = ['creature', ['data' => array_values($npcs->getListviewData())]];
}
}
}
}
?>

82
pages/sounds.php Normal file
View file

@ -0,0 +1,82 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// menuId 19: Sounds g_initPath()
// tabId 0: Database g_initHeader()
class SoundsPage extends GenericPage
{
use ListPage;
protected $type = TYPE_SOUND;
protected $tpl = 'sounds';
protected $path = [0, 19];
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
protected $validCats = [1, 2, 3, 4, 6, 9, 10, 12, 13, 14, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 50, 52, 53];
public function __construct($pageCall, $pageParam)
{
$this->filterObj = new SoundListFilter();
parent::__construct($pageCall, $pageParam);
$this->name = Util::ucFirst(Lang::game('sounds'));
}
protected function generateContent()
{
$this->addJs('filters.js');
$this->redButtons = array(
BUTTON_WOWHEAD => true,
BUTTON_PLAYLIST => true
);
$conditions = [];
if ($_ = $this->filterObj->getConditions())
$conditions[] = $_;
$this->filter = array_merge($this->filterObj->getForm('form'), $this->filter);
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : null;
$this->filter['fi'] = $this->filterObj->getForm();
$sounds = new SoundList($conditions);
$tabData = [];
if (!$sounds->error)
{
$tabData['data'] = array_values($sounds->getListviewData());
// create note if search limit was exceeded; overwriting 'note' is intentional
if ($sounds->getMatches() > CFG_SQL_LIMIT_DEFAULT)
{
$tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_soundsfound', $sounds->getMatches(), CFG_SQL_LIMIT_DEFAULT);
$tabData['_truncated'] = 1;
}
if ($this->filterObj->error)
$tabData['_errors'] = 1;
}
$this->lvTabs[] = ['sound', $tabData];
Lang::sort('sound', 'cat');
}
protected function generateTitle()
{
$form = $this->filterObj->getForm('form');
if (isset($form['ty']) && !is_array($form['ty']))
array_unshift($this->title, Lang::sound('cat', $form['ty']));
}
protected function generatePath()
{
$form = $this->filterObj->getForm('form');
if (isset($form['ty']) && !is_array($form['ty']))
$this->path[] = $form['ty'];
}
}
?>

View file

@ -1083,6 +1083,29 @@ class SpellPage extends GenericPage
$this->extendGlobalData($enchList->getJSGlobals());
}
// tab: sounds
$activitySounds = DB::Aowow()->selectRow('SELECT * FROM ?_spell_sounds WHERE id = ?d', $this->subject->getField('spellVisualId'));
array_shift($activitySounds); // remove id-column
if ($activitySounds)
{
$sounds = new SoundList(array(['id', $activitySounds]));
if (!$sounds->error)
{
$data = $sounds->getListviewData();
foreach ($activitySounds as $activity => $id)
if (isset($data[$id]))
$data[$id]['activity'] = $activity; // no index, js wants a string :(
$tabData = ['data' => array_values($data)];
if ($activitySounds)
$tabData['visibleCols'] = ['activity'];
$this->extendGlobalData($sounds->getJSGlobals(GLOBALINFO_SELF));
$this->lvTabs[] = ['sound', $tabData];
}
}
// find associated NPC, Item and merge results
// taughtbypets (unused..?)
// taughtbyquest (usually the spell casted as quest reward teaches something; exclude those seplls from taughtBySpell)
@ -1726,6 +1749,9 @@ class SpellPage extends GenericPage
$foo['name'] .= ' ('.$_.')';
break;
case 132: // Play Sound
$foo['sound'] = $effMV;
break;
case 123: // Send Taxi - effMV is taxiPathId. We only use paths for flightmasters for now, so spell-triggered paths are not in the table
default:
{
@ -1978,7 +2004,7 @@ class SpellPage extends GenericPage
}
// cases where we dont want 'Value' to be displayed
if (in_array($effAura, [11, 12, 36, 77]) || in_array($effId, []) || empty($foo['value']))
if (in_array($effAura, [11, 12, 36, 77]) || in_array($effId, [132]) || empty($foo['value']))
unset($foo['value']);
}

View file

@ -392,6 +392,8 @@ class ZonePage extends GenericPage
}
}
unset($data);
// append paths between nodes
if ($flightNodes)
{
@ -494,7 +496,7 @@ class ZonePage extends GenericPage
{
$this->lvTabs[] = ['quest', array(
'data' => array_values($questsLV),
'note' => '$$WH.sprintf(LANG.lvnote_zonequests, '.$this->subject->getField('mapId').', '.$this->typeId.', \''.Util::jsEscape($this->subject->getField('name', true)).'\', '.$this->typeId.')'
'note' => '$$WH.sprintf(LANG.lvnote_zonequests, '.$this->subject->getField('mapId').', '.$this->typeId.',"'.$this->subject->getField('name', true).'", '.$this->typeId.')'
)];
}
@ -685,6 +687,59 @@ class ZonePage extends GenericPage
$this->extendGlobalData($subZones->getJSGlobals(GLOBALINFO_SELF));
}
// tab: sound (including subzones; excluding parents)
$areaIds = [];
if (!$subZones->error)
$areaIds = $subZones->getFoundIDs();
$areaIds[] = $this->typeId;
$soundIds = [];
$zoneMusic = DB::Aowow()->select('
SELECT
x.soundId, x.worldStateId, x.worldStateValue
FROM (
SELECT ambienceDay AS soundId, worldStateId, worldStateValue FROM ?_zones_sounds WHERE id IN (?a) AND ambienceDay > 0 UNION
SELECT ambienceNight AS soundId, worldStateId, worldStateValue FROM ?_zones_sounds WHERE id IN (?a) AND ambienceNight > 0 UNION
SELECT musicDay AS soundId, worldStateId, worldStateValue FROM ?_zones_sounds WHERE id IN (?a) AND musicDay > 0 UNION
SELECT musicNight AS soundId, worldStateId, worldStateValue FROM ?_zones_sounds WHERE id IN (?a) AND musicNight > 0 UNION
SELECT intro AS soundId, worldStateId, worldStateValue FROM ?_zones_sounds WHERE id IN (?a) AND intro > 0
) x
GROUP BY
x.soundId, x.worldStateId, x.worldStateValue
', $areaIds, $areaIds, $areaIds, $areaIds, $areaIds);
if ($sSpawns = DB::Aowow()->selectCol('SELECT typeId FROM ?_spawns WHERE areaId = ?d AND type = ?d', $this->typeId, TYPE_SOUND))
$soundIds = array_merge($soundIds, $sSpawns);
if ($zoneMusic)
$soundIds = array_merge($soundIds, array_column($zoneMusic, 'soundId'));
if ($soundIds)
{
$music = new SoundList(array(['id', array_unique($soundIds)]));
if (!$music->error)
{
$data = $music->getListviewData();
$tabData = [];
if (array_filter(array_column($soundIds, 'worldStateId')))
{
$tabData['extraCols'] = ['$Listview.extraCols.condition'];
foreach ($soundIds as $sData)
if ($sData['worldStateId'])
$data[$sData['soundId']]['condition'][0][$this->typeId][] = [[CND_WORLD_STATE, $sData['worldStateId'], $sData['worldStateValue']]];
}
$tabData['data'] = array_values($data);
$this->lvTabs[] = ['sound', $tabData];
$this->extendGlobalData($music->getJSGlobals(GLOBALINFO_SELF));
}
}
}
protected function generatePath()

View file

@ -1136,6 +1136,7 @@ CREATE TABLE `aowow_items` (
`classBak` tinyint(3) NOT NULL,
`subClass` tinyint(3) NOT NULL DEFAULT '0',
`subClassBak` tinyint(3) NOT NULL,
`soundOverrideSubclass` tinyint(3) NOT NULL,
`subSubClass` tinyint(3) NOT NULL,
`name_loc0` varchar(127) NOT NULL DEFAULT '',
`name_loc2` varchar(127) DEFAULT NULL,
@ -1143,6 +1144,7 @@ CREATE TABLE `aowow_items` (
`name_loc6` varchar(127) DEFAULT NULL,
`name_loc8` varchar(127) DEFAULT NULL,
`displayId` mediumint(8) unsigned NOT NULL DEFAULT '0',
`spellVisualId` smallint(5) unsigned NOT NULL DEFAULT '0',
`quality` tinyint(3) unsigned NOT NULL DEFAULT '0',
`flags` bigint(20) NOT NULL DEFAULT '0',
`flagsExtra` int(10) unsigned NOT NULL DEFAULT '0',
@ -1253,6 +1255,7 @@ CREATE TABLE `aowow_items` (
`languageId` tinyint(3) unsigned NOT NULL DEFAULT '0',
`startQuest` mediumint(8) unsigned NOT NULL DEFAULT '0',
`lockId` mediumint(8) unsigned NOT NULL DEFAULT '0',
`material` tinyint(3) NOT NULL DEFAULT '0',
`randomEnchant` mediumint(8) NOT NULL DEFAULT '0',
`itemset` mediumint(8) unsigned NOT NULL DEFAULT '0',
`durability` smallint(5) unsigned NOT NULL DEFAULT '0',
@ -1278,6 +1281,10 @@ CREATE TABLE `aowow_items` (
`gemEnchantmentId` mediumint(8) NOT NULL,
`minMoneyLoot` int(10) unsigned NOT NULL DEFAULT '0',
`maxMoneyLoot` int(10) unsigned NOT NULL DEFAULT '0',
`pickUpSoundId` smallint(5) unsigned NOT NULL DEFAULT '0',
`dropDownSoundId` smallint(5) unsigned NOT NULL DEFAULT '0',
`sheatheSoundId` smallint(5) unsigned NOT NULL DEFAULT '0',
`unsheatheSoundId` smallint(5) unsigned NOT NULL DEFAULT '0',
`flagsCustom` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_name` (`name_loc0`),
@ -2119,6 +2126,7 @@ CREATE TABLE `aowow_spell` (
`iconId` smallint(5) unsigned NOT NULL,
`iconIdAlt` mediumint(9) NOT NULL,
`rankNo` tinyint(3) unsigned NOT NULL,
`spellVisualId` smallint(5) unsigned NOT NULL,
`name_loc0` varchar(85) NOT NULL,
`name_loc2` varchar(85) NOT NULL,
`name_loc3` varchar(85) NOT NULL,
@ -2420,6 +2428,138 @@ CREATE TABLE `aowow_zones` (
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
DROP TABLE IF EXISTS `aowow_zones_sounds`;
CREATE TABLE `aowow_zones_sounds` (
`id` smallint(5) unsigned NOT NULL,
`ambienceDay` smallint(5) unsigned NOT NULL,
`ambienceNight` smallint(5) unsigned NOT NULL,
`musicDay` smallint(5) unsigned NOT NULL,
`musicNight` smallint(5) unsigned NOT NULL,
`intro` smallint(5) unsigned NOT NULL,
`worldStateId` smallint(5) unsigned NOT NULL,
`worldStateValue` smallint(6) NOT NULL,
INDEX `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `aowow_creature_sounds`;
CREATE TABLE IF NOT EXISTS `aowow_creature_sounds` (
`id` smallint(5) unsigned NOT NULL COMMENT 'CreatureDisplayInfo.dbc/id',
`greeting` smallint(5) unsigned NOT NULL,
`farewell` smallint(5) unsigned NOT NULL,
`angry` smallint(5) unsigned NOT NULL,
`exertion` smallint(5) unsigned NOT NULL,
`exertioncritical` smallint(5) unsigned NOT NULL,
`injury` smallint(5) unsigned NOT NULL,
`injurycritical` smallint(5) unsigned NOT NULL,
`death` smallint(5) unsigned NOT NULL,
`stun` smallint(5) unsigned NOT NULL,
`stand` smallint(5) unsigned NOT NULL,
`footstep` smallint(5) unsigned NOT NULL,
`aggro` smallint(5) unsigned NOT NULL,
`wingflap` smallint(5) unsigned NOT NULL,
`wingglide` smallint(5) unsigned NOT NULL,
`alert` smallint(5) unsigned NOT NULL,
`fidget` smallint(5) unsigned NOT NULL,
`customattack` smallint(5) unsigned NOT NULL,
`loop` smallint(5) unsigned NOT NULL,
`jumpstart` smallint(5) unsigned NOT NULL,
`jumpend` smallint(5) unsigned NOT NULL,
`petattack` smallint(5) unsigned NOT NULL,
`petorder` smallint(5) unsigned NOT NULL,
`petdismiss` smallint(5) unsigned NOT NULL,
`birth` smallint(5) unsigned NOT NULL,
`spellcast` smallint(5) unsigned NOT NULL,
`submerge` smallint(5) unsigned NOT NULL,
`submerged` smallint(5) unsigned NOT NULL,
`transform` smallint(5) unsigned NOT NULL,
`transformanimated` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='!ATTENTION!\r\nthe primary key of this table is NOT a creatureId, but displayId\r\n\r\ncolumn names from LANG.sound_activities';
DROP TABLE IF EXISTS `aowow_emotes_sounds`;
CREATE TABLE IF NOT EXISTS `aowow_emotes_sounds` (
`emoteId` smallint(5) unsigned NOT NULL,
`raceId` tinyint(3) unsigned NOT NULL,
`gender` tinyint(1) unsigned NOT NULL,
`soundId` smallint(5) unsigned NOT NULL,
UNIQUE KEY `emoteId_raceId_gender_soundId` (`emoteId`,`raceId`,`gender`,`soundId`),
KEY `emoteId` (`emoteId`),
KEY `raceId` (`raceId`),
KEY `soundId` (`soundId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `aowow_races_sounds`;
CREATE TABLE IF NOT EXISTS `aowow_races_sounds` (
`raceId` tinyint(3) unsigned NOT NULL,
`soundId` smallint(5) unsigned NOT NULL,
`gender` tinyint(1) unsigned NOT NULL,
UNIQUE KEY `race_soundId_gender` (`raceId`,`soundId`,`gender`),
KEY `race` (`raceId`),
KEY `soundId` (`soundId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `aowow_sounds`;
CREATE TABLE IF NOT EXISTS `aowow_sounds` (
`id` smallint(5) unsigned NOT NULL,
`cat` tinyint(3) unsigned NOT NULL,
`name` varchar(100) NOT NULL,
`cuFlags` int(10) unsigned NOT NULL,
`soundFile1` smallint(5) unsigned DEFAULT NULL,
`soundFile2` smallint(5) unsigned DEFAULT NULL,
`soundFile3` smallint(5) unsigned DEFAULT NULL,
`soundFile4` smallint(5) unsigned DEFAULT NULL,
`soundFile5` smallint(5) unsigned DEFAULT NULL,
`soundFile6` smallint(5) unsigned DEFAULT NULL,
`soundFile7` smallint(5) unsigned DEFAULT NULL,
`soundFile8` smallint(5) unsigned DEFAULT NULL,
`soundFile9` smallint(5) unsigned DEFAULT NULL,
`soundFile10` smallint(5) unsigned DEFAULT NULL,
`flags` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `cat` (`cat`),
KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `aowow_sounds_files`;
CREATE TABLE IF NOT EXISTS `aowow_sounds_files` (
`id` smallint(6) NOT NULL COMMENT '<0 not found in client files',
`file` varchar(75) NOT NULL,
`path` varchar(75) NOT NULL COMMENT 'in client',
`type` tinyint(1) unsigned NOT NULL COMMENT '1: ogg; 2: mp3',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `aowow_spell_sounds`;
CREATE TABLE IF NOT EXISTS `aowow_spell_sounds` (
`id` smallint(5) unsigned NOT NULL COMMENT 'SpellVisual.dbc/id',
`animation` smallint(5) unsigned NOT NULL,
`ready` smallint(5) unsigned NOT NULL,
`precast` smallint(5) unsigned NOT NULL,
`cast` smallint(5) unsigned NOT NULL,
`impact` smallint(5) unsigned NOT NULL,
`state` smallint(5) unsigned NOT NULL,
`statedone` smallint(5) unsigned NOT NULL,
`channel` smallint(5) unsigned NOT NULL,
`casterimpact` smallint(5) unsigned NOT NULL,
`targetimpact` smallint(5) unsigned NOT NULL,
`castertargeting` smallint(5) unsigned NOT NULL,
`missiletargeting` smallint(5) unsigned NOT NULL,
`instantarea` smallint(5) unsigned NOT NULL,
`persistentarea` smallint(5) unsigned NOT NULL,
`casterstate` smallint(5) unsigned NOT NULL,
`targetstate` smallint(5) unsigned NOT NULL,
`missile` smallint(5) unsigned NOT NULL COMMENT 'not predicted by js',
`impactarea` smallint(5) unsigned NOT NULL COMMENT 'not predicted by js',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='!ATTENTION!\r\nthe primary key of this table is NOT a spellId, but spellVisualId\r\n\r\ncolumn names from LANG.sound_activities';
DROP TABLE IF EXISTS `aowow_items_sounds`;
CREATE TABLE `aowow_items_sounds` (
`soundId` smallint(5) unsigned NOT NULL,
`subClassMask` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`soundId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='actually .. its only weapon related sounds in here';
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
@ -2513,7 +2653,7 @@ UNLOCK TABLES;
LOCK TABLES `aowow_dbversion` WRITE;
/*!40000 ALTER TABLE `aowow_dbversion` DISABLE KEYS */;
INSERT INTO `aowow_dbversion` VALUES (1484926142,0,NULL,NULL);
INSERT INTO `aowow_dbversion` VALUES (1488745159,0,NULL,NULL);
/*!40000 ALTER TABLE `aowow_dbversion` ENABLE KEYS */;
UNLOCK TABLES;

View file

@ -328,6 +328,42 @@ class CLISetup
return false;
}
public static function nicePath(/* $file = '', ...$pathParts */)
{
$path = '';
switch (func_num_args())
{
case 0:
return '';
case 1:
$path = func_get_arg(0);
break;
default:
$args = func_get_args();
$file = array_shift($args);
$path = implode(DIRECTORY_SEPARATOR, $args).DIRECTORY_SEPARATOR.$file;
}
if (DIRECTORY_SEPARATOR == '/') // *nix
{
$path = str_replace('\\', '/', $path);
$path = preg_replace('/\/+/i', '/', $path);
}
else if (DIRECTORY_SEPARATOR == '\\') // win
{
$path = str_replace('/', '\\', $path);
$path = preg_replace('/\\\\+/i', '\\', $path);
}
else
CLISetup::log('Dafuq! Your directory separator is "'.DIRECTORY_SEPARATOR.'". Please report this!', CLISetup::LOG_ERROR);
if ($path[0] == DIRECTORY_SEPARATOR)
$path = substr($path, 1);
return $path;
}
/**************/
/* read input */
/**************/

View file

@ -44,16 +44,18 @@ class DBC
'achievement' => 'niiisxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxiiiiisxssxxsxsxxxxxxxxii',
'achievement_category' => 'nisxssxxsxsxxxxxxxxx',
'achievement_criteria' => 'niiiiiiiisxssxxsxsxxxxxxxxiixii',
'areatable' => 'niixixxxxxxsxssxxsxsxxxxxxxxixxxxxxx',
'areatable' => 'niixixxiiixsxssxxsxsxxxxxxxxixxxxxxx',
'battlemasterlist' => 'niixxxxxxixxxxxxxxxxxxxxxxxxixii',
'charbaseinfo' => 'bb',
'charstartoutfit' => 'nbbbXiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'chartitles' => 'nxsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxi',
'chrclasses' => 'nxixsxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsxixi',
'chrraces' => 'niixxxxixxxsxisxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi',
'creaturedisplayinfo' => 'nixixxssssxxxxxx',
'creaturedisplayinfo' => 'niiixxssssxxixxx',
'creaturedisplayinfoextra' => 'nxxxxxxxxxxxxxxxxxxxs',
'creaturefamily' => 'nxxxxixiiisxssxxsxsxxxxxxxxs',
'creaturemodeldata' => 'nxxxxxxxxxxxxixxxxxxxxxxxxxx',
'creaturesounddata' => 'niiiixiiiiiiiiixxxxixxxxixiiiiixxiiiix',
'currencytypes' => 'niix',
'dungeonmap' => 'niiffffi',
'durabilitycosts' => 'niiiiiiiiixiiiiiiiiiiixiiiixix',
@ -61,6 +63,7 @@ class DBC
'emotes' => 'nxixxxx',
'emotestext' => 'nsiixxxixixxxxxxxxx',
'emotestextdata' => 'nsxssxxsxsxxxxxxxx',
'emotestextsound' => 'niiii',
'faction' => 'nixxxxxxxxxxxxixxxiffixsxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxx',
'factiontemplate' => 'nixiiiiiiiiiii',
'gemproperties' => 'nixxi',
@ -77,17 +80,21 @@ class DBC
'holidays' => 'nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxxxxxxxiisxix',
'holidaydescriptions' => 'nsxssxxsxsxxxxxxxx',
'holidaynames' => 'nsxssxxsxsxxxxxxxx',
'itemdisplayinfo' => 'nssxxsxxxxxxxxxxxxxxxxxxx',
'itemdisplayinfo' => 'nssxxsxxxxxiixxxxxxxxxxxx',
'itemgroupsounds' => 'niixx',
'itemextendedcost' => 'niiiiiiiiiiiiiix',
'itemlimitcategory' => 'nsxssxxsxsxxxxxxxxii',
'itemrandomproperties' => 'nsiiiiisxssxxsxsxxxxxxxx',
'itemrandomsuffix' => 'nsxssxxsxsxxxxxxxxsiiiiiiiiii',
'itemset' => 'nsxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiiiii',
'itemsubclass' => 'iixxxxxxxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'lfgdungeons' => 'nsxssxxsxsxxxxxxxxiiiiiiixiixixixxxxxxxxxxxxxxxxx',
'lock' => 'niiiiixxxiiiiixxxiiiiixxxxxxxxxxx',
'mailtemplate' => 'nsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxx',
'map' => 'nsixisxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiffxixi',
'mapdifficulty' => 'niixxxxxxxxxxxxxxxxxxis',
'material' => 'nxxii',
'npcsounds' => 'niiix',
'powerdisplay' => 'nisbbb',
'questfactionreward' => 'niiiiiiiiii',
'questxp' => 'niiiiiiiiii',
@ -97,7 +104,10 @@ class DBC
'skillline' => 'nixsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxixxxxxxxxxxxxxxxxxx',
'skilllineability' => 'niiiixxixiiixx',
'skillraceclassinfo' => 'niiiiixx',
'spell' => 'niiiuuuuuuuuixixxxixxxxxxxxxiiixxxxiiiiiiiiiiiixxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiixxiixsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxiiiiiiiiiixxfffxxxiixiixifffii',
'soundambience' => 'nii',
'soundemitters' => 'nffxxxxiix',
'soundentries' => 'nisssssssssssxxxxxxxxxxsxixxxx',
'spell' => 'niiiuuuuuuuuixixxxixxxxxxxxxiiixxxxiiiiiiiiiiiixxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxsxssxxsxsxxxxxxxxiiiiiiiiiixxfffxxxiixiixifffii',
'spellcasttimes' => 'nixx',
'spelldescriptionvariables' => 'ns',
'spelldifficulty' => 'xiiii',
@ -110,15 +120,23 @@ class DBC
'spellrange' => 'nffffisxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxx',
'spellrunecost' => 'niiii',
'spellshapeshiftform' => 'nxsxssxxsxsxxxxxxxxiixxiixxiiiiiiii',
'spellvisual' => 'niiiiiixxxxiixiixxxxxxiiiixxxxxx',
'spellvisualkit' => 'nxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxxxxxx',
'talent' => 'niiiiiiiixxxxixxixxixii',
'talenttab' => 'nsxssxxsxsxxxxxxxxiiiiis',
'taxinodes' => 'niffxsxssxxsxsxxxxxxxxxx',
'taxipath' => 'niix',
'taxipathnode' => 'niiiffxxxxx',
'totemcategory' => 'nsxssxxsxsxxxxxxxxiu',
'vocaluisounds' => 'nxiiixx',
'weaponimpactsounds' => 'nixiiiiiiiiiiiiiiiiiiii',
'weaponswingsounds2' => 'nixi',
'worldmaparea' => 'niisffffxix', // 4.x - niisffffxixxxx
'worldmapoverlay' => 'niixxxxxsiiiixxxx', // 4.x - niixxxsiiiixxxx
'worldmaptransforms' => 'niffffiffi',
'worldstatezonesounds' => 'iiiiiiix',
'zoneintromusictable' => 'nxixx',
'zonemusic' => 'nxxxxxii'
);
@ -126,22 +144,25 @@ class DBC
'achievement' => 'Id,faction,map,previous,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,description_loc0,description_loc2,description_loc3,description_loc6,description_loc8,category,points,orderInGroup,flags,iconId,reward_loc0,reward_loc2,reward_loc3,reward_loc6,reward_loc8,reqCriteriaCount,refAchievement',
'achievement_category' => 'Id,parentCategory,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'achievement_criteria' => 'Id,refAchievementId,type,value1,value2,value3,value4,value5,value6,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,completionFlags,groupFlags,timeLimit,order',
'areatable' => 'Id,mapId,areaTable,flags,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,factionGroupMask',
'areatable' => 'Id,mapId,areaTable,flags,soundAmbience,zoneMusic,zoneIntroMusic,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,factionGroupMask',
'battlemasterlist' => 'Id,mapId,moreMapId,areaType,maxPlayers,minLevel,maxLevel',
'charbaseinfo' => 'raceId,classId',
'charstartoutfit' => 'Id,raceId,classId,gender,item1,item2,item3,item4,item5,item6,item7,item8,item9,item10,item11,item12,item13,item14,item15,item16,item17,item18,item19,item20',
'chartitles' => 'Id,male_loc0,male_loc2,male_loc3,male_loc6,male_loc8,female_loc0,female_loc2,female_loc3,female_loc6,female_loc8,bitIdx',
'chrclasses' => 'Id,powerType,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,fileString,flags,expansion',
'chrraces' => 'Id,flags,factionId,baseLanguage,fileString,side,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,expansion',
'creaturedisplayinfo' => 'Id,modelid,extraInfoId,skin1,skin2,skin3,iconString',
'creaturedisplayinfo' => 'Id,modelId,creatureSoundId,extraInfoId,skin1,skin2,skin3,iconString,npcSoundId',
'creaturedisplayinfoextra' => 'Id,textureString',
'creaturefamily' => 'Id,skillLine1,petFoodMask,petTalentType,categoryEnumID,name_loc0,name_loc2,name_loc3,name_lo6,name_loc8,iconString',
'creaturemodeldata' => 'Id,creatureSoundId',
'creaturesounddata' => 'Id,exertion,exertionCritical,injury,injuryCritical,death,stun,stand,footstepTerrainId,aggro,wingFlap,wingGlide,alert,fidget,customAttack,loop,jumpStart,jumpEnd,petAttack,petOrder,petDismiss,birth,spellcast,submerge,submerged',
'currencytypes' => 'Id,itemId,category',
'dungeonmap' => 'Id,mapId,floor,minY,maxY,minX,maxX,areaId',
'durabilitycosts' => 'Id,w0,w1,w2,w3,w4,w5,w6,w7,w8,w10,w11,w12,w13,w14,w15,w16,w17,w18,w19,w20,a1,a2,a3,a4,a6',
'durabilityquality' => 'Id,mod',
'emotes' => 'Id,animationId',
'emotestext' => 'Id,command,emoteId,targetId,noTargetId,selfId',
'emotestextsound' => 'Id,emotesTextId,raceId,gender,soundId',
'emotestextdata' => 'Id,text_loc0,text_loc2,text_loc3,text_loc6,text_loc8',
'faction' => 'Id,repIdx,repFlags1,parentFaction,spilloverRateIn,spilloverRateOut,spilloverMaxRank,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'factiontemplate' => 'Id,factionId,ourMask,friendlyMask,hostileMask,enemyFactionId1,enemyFactionId2,enemyFactionId3,enemyFactionId4,friendFactionId1,friendFactionId2,friendFactionId3,friendFactionId4',
@ -159,17 +180,21 @@ class DBC
'holidays' => 'Id,looping,nameId,descriptionId,textureString,scheduleType',
'holidaydescriptions' => 'Id,description_loc0,description_loc2,description_loc3,description_loc6,description_loc8',
'holidaynames' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'itemdisplayinfo' => 'Id,leftModelName,rightModelName,inventoryIcon1',
'itemdisplayinfo' => 'Id,leftModelName,rightModelName,inventoryIcon1,spellVisualId,groupSoundId',
'itemgroupsounds' => 'Id,pickUpSoundId,dropDownSoundId',
'itemextendedcost' => 'Id,reqHonorPoints,reqArenaPoints,reqArenaSlot,reqItemId1,reqItemId2,reqItemId3,reqItemId4,reqItemId5,itemCount1,itemCount2,itemCount3,itemCount4,itemCount5,reqPersonalRating',
'itemlimitcategory' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,count,isGem',
'itemrandomproperties' => 'Id,nameINT,enchantId1,enchantId2,enchantId3,enchantId4,enchantId5,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'itemrandomsuffix' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,nameINT,enchantId1,enchantId2,enchantId3,enchantId4,enchantId5,allocationPct1,allocationPct2,allocationPct3,allocationPct4,allocationPct5',
'itemset' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,spellId1,spellId2,spellId3,spellId4,spellId5,spellId6,spellId7,spellId8,itemCount1,itemCount2,itemCount3,itemCount4,itemCount5,itemCount6,itemCount7,itemCount8,reqSkillId,reqSkillLevel',
'itemsubclass' => 'class,subClass,weaponSize',
'lfgdungeons' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,levelMin,levelMax,targetLevel,targetLevelMin,targetLevelMax,mapId,difficulty,type,faction,expansion,groupId',
'lock' => 'Id,type1,type2,type3,type4,type5,properties1,properties2,properties3,properties4,properties5,reqSkill1,reqSkill2,reqSkill3,reqSkill4,reqSkill5',
'mailtemplate' => 'Id,subject_loc0,subject_loc2,subject_loc3,subject_loc6,subject_loc8,text_loc0,text_loc2,text_loc3,text_loc6,text_loc8',
'map' => 'Id,nameINT,areaType,isBG,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,parentMapId,parentX,parentY,expansion,maxPlayers',
'mapdifficulty' => 'Id,mapId,difficulty,nPlayer,nPlayerString',
'material' => 'Id,sheatheSoundId,unsheatheSoundId',
'npcsounds' => 'Id,greetSoundId,byeSoundId,angrySoundId',
'powerdisplay' => 'Id,realType,globalString,r,g,b',
'questfactionreward' => 'Id,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10',
'questxp' => 'Id,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10',
@ -179,7 +204,10 @@ class DBC
'skillline' => 'Id,categoryId,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,description_loc0,description_loc2,description_loc3,description_loc6,description_loc8,iconId',
'skilllineability' => 'Id,skillLineId,spellId,reqRaceMask,reqClassMask,reqSkillLevel,acquireMethod,skillLevelGrey,skillLevelYellow',
'skillraceclassinfo' => 'Id,skillLine,raceMask,classMask,flags,reqLevel',
'spell' => 'Id,category,dispelType,mechanic,attributes0,attributes1,attributes2,attributes3,attributes4,attributes5,attributes6,attributes7,stanceMask,stanceMaskNot,spellFocus,castTimeId,recoveryTime,recoveryTimeCategory,procChance,procCharges,maxLevel,baseLevel,spellLevel,durationId,powerType,powerCost,powerCostPerLevel,powerPerSecond,powerPerSecondPerLevel,rangeId,stackAmount,tool1,tool2,reagent1,reagent2,reagent3,reagent4,reagent5,reagent6,reagent7,reagent8,reagentCount1,reagentCount2,reagentCount3,reagentCount4,reagentCount5,reagentCount6,reagentCount7,reagentCount8,equippedItemClass,equippedItemSubClassMask,equippedItemInventoryTypeMask,effect1Id,effect2Id,effect3Id,effect1DieSides,effect2DieSides,effect3DieSides,effect1RealPointsPerLevel,effect2RealPointsPerLevel,effect3RealPointsPerLevel,effect1BasePoints,effect2BasePoints,effect3BasePoints,effect1Mechanic,effect2Mechanic,effect3Mechanic,effect1ImplicitTargetA,effect2ImplicitTargetA,effect3ImplicitTargetA,effect1ImplicitTargetB,effect2ImplicitTargetB,effect3ImplicitTargetB,effect1RadiusId,effect2RadiusId,effect3RadiusId,effect1AuraId,effect2AuraId,effect3AuraId,effect1Periode,effect2Periode,effect3Periode,effect1ValueMultiplier,effect2ValueMultiplier,effect3ValueMultiplier,effect1ChainTarget,effect2ChainTarget,effect3ChainTarget,effect1CreateItemId,effect2CreateItemId,effect3CreateItemId,effect1MiscValue,effect2MiscValue,effect3MiscValue,effect1MiscValueB,effect2MiscValueB,effect3MiscValueB,effect1TriggerSpell,effect2TriggerSpell,effect3TriggerSpell,effect1PointsPerComboPoint,effect2PointsPerComboPoint,effect3PointsPerComboPoint,effect1SpellClassMaskA,effect2SpellClassMaskA,effect3SpellClassMaskA,effect1SpellClassMaskB,effect2SpellClassMaskB,effect3SpellClassMaskB,effect1SpellClassMaskC,effect2SpellClassMaskC,effect3SpellClassMaskC,iconId,iconIdActive,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,rank_loc0,rank_loc2,rank_loc3,rank_loc6,rank_loc8,description_loc0,description_loc2,description_loc3,description_loc6,description_loc8,buff_loc0,buff_loc2,buff_loc3,buff_loc6,buff_loc8,powerCostPercent,startRecoveryCategory,startRecoveryTime,maxTargetLevel,spellFamilyId,spellFamilyFlags1,spellFamilyFlags2,spellFamilyFlags3,maxAffectedTargets,damageClass,effect1DamageMultiplier,effect2DamageMultiplier,effect3DamageMultiplier,toolCategory1,toolCategory2,schoolMask,runeCostId,powerDisplayId,effect1BonusMultiplier,effect2BonusMultiplier,effect3BonusMultiplier,spellDescriptionVariable,spellDifficulty',
'soundambience' => 'Id,soundIdDay,soundIdNight',
'soundemitters' => 'Id,posY,posX,soundId,mapId',
'soundentries' => 'Id,type,name,file1,file2,file3,file4,file5,file6,file7,file8,file9,file10,path,flags',
'spell' => 'Id,category,dispelType,mechanic,attributes0,attributes1,attributes2,attributes3,attributes4,attributes5,attributes6,attributes7,stanceMask,stanceMaskNot,spellFocus,castTimeId,recoveryTime,recoveryTimeCategory,procChance,procCharges,maxLevel,baseLevel,spellLevel,durationId,powerType,powerCost,powerCostPerLevel,powerPerSecond,powerPerSecondPerLevel,rangeId,stackAmount,tool1,tool2,reagent1,reagent2,reagent3,reagent4,reagent5,reagent6,reagent7,reagent8,reagentCount1,reagentCount2,reagentCount3,reagentCount4,reagentCount5,reagentCount6,reagentCount7,reagentCount8,equippedItemClass,equippedItemSubClassMask,equippedItemInventoryTypeMask,effect1Id,effect2Id,effect3Id,effect1DieSides,effect2DieSides,effect3DieSides,effect1RealPointsPerLevel,effect2RealPointsPerLevel,effect3RealPointsPerLevel,effect1BasePoints,effect2BasePoints,effect3BasePoints,effect1Mechanic,effect2Mechanic,effect3Mechanic,effect1ImplicitTargetA,effect2ImplicitTargetA,effect3ImplicitTargetA,effect1ImplicitTargetB,effect2ImplicitTargetB,effect3ImplicitTargetB,effect1RadiusId,effect2RadiusId,effect3RadiusId,effect1AuraId,effect2AuraId,effect3AuraId,effect1Periode,effect2Periode,effect3Periode,effect1ValueMultiplier,effect2ValueMultiplier,effect3ValueMultiplier,effect1ChainTarget,effect2ChainTarget,effect3ChainTarget,effect1CreateItemId,effect2CreateItemId,effect3CreateItemId,effect1MiscValue,effect2MiscValue,effect3MiscValue,effect1MiscValueB,effect2MiscValueB,effect3MiscValueB,effect1TriggerSpell,effect2TriggerSpell,effect3TriggerSpell,effect1PointsPerComboPoint,effect2PointsPerComboPoint,effect3PointsPerComboPoint,effect1SpellClassMaskA,effect2SpellClassMaskA,effect3SpellClassMaskA,effect1SpellClassMaskB,effect2SpellClassMaskB,effect3SpellClassMaskB,effect1SpellClassMaskC,effect2SpellClassMaskC,effect3SpellClassMaskC,spellVisualId1,spellVisualId2,iconId,iconIdActive,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,rank_loc0,rank_loc2,rank_loc3,rank_loc6,rank_loc8,description_loc0,description_loc2,description_loc3,description_loc6,description_loc8,buff_loc0,buff_loc2,buff_loc3,buff_loc6,buff_loc8,powerCostPercent,startRecoveryCategory,startRecoveryTime,maxTargetLevel,spellFamilyId,spellFamilyFlags1,spellFamilyFlags2,spellFamilyFlags3,maxAffectedTargets,damageClass,effect1DamageMultiplier,effect2DamageMultiplier,effect3DamageMultiplier,toolCategory1,toolCategory2,schoolMask,runeCostId,powerDisplayId,effect1BonusMultiplier,effect2BonusMultiplier,effect3BonusMultiplier,spellDescriptionVariable,spellDifficulty',
'spellcasttimes' => 'Id,baseTime',
'spelldescriptionvariables' => 'Id,vars',
'spellduration' => 'Id,baseTime',
@ -192,15 +220,23 @@ class DBC
'spellrange' => 'Id,rangeMinHostile,rangeMinFriend,rangeMaxHostile,rangeMaxFriend,rangeType,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'spellrunecost' => 'Id,costBlood,costUnholy,costFrost,runicPowerGain',
'spellshapeshiftform' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,flags,creatureType,displayIdA,displayIdH,spellId1,spellId2,spellId3,spellId4,spellId5,spellId6,spellId7,spellId8',
'spellvisual' => 'Id,precastKitId,castKitId,impactKitId,stateKitId,statedoneKitId,channelKitId,missileSoundId,animationSoundId,casterImpactKitId,targetImpactKitId,missileTargetingKitId,instantAreaKitId,impactAreaKitId,persistentAreaKitId',
'spellvisualkit' => 'Id,soundId',
'talent' => 'Id,tabId,row,column,rank1,rank2,rank3,rank4,rank5,reqTalent,reqRank,talentSpell,petCategory1,petCategory2',
'talenttab' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,iconId,raceMask,classMask,creatureFamilyMask,tabNumber,textureFile',
'taxinodes' => 'Id,mapId,posX,posY,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8',
'taxipath' => 'Id,startNodeId,endNodeId',
'taxipathnode' => 'Id,pathId,nodeIdx,mapId,posX,posY',
'totemcategory' => 'Id,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,category,categoryMask',
'vocaluisounds' => 'Id,raceId,soundIdMale,soundIdFemale',
'weaponimpactsounds' => 'Id,subClass,hit1,hit2,hit3,hit4,hit5,hit6,hit7,hit8,hit9,hit10,crit1,crit2,crit3,crit4,crit5,crit6,crit7,crit8,crit9,crit10',
'weaponswingsounds2' => 'Id,weaponSize,soundId',
'worldmaparea' => 'Id,mapId,areaId,nameINT,left,right,top,bottom,defaultDungeonMapId',
'worldmapoverlay' => 'Id,worldMapAreaId,areaTableId,textureString,w,h,x,y',
'worldmaptransforms' => 'Id,sourceMapId,minX,minY,maxX,maxY,targetMapId,offsetX,offsetY,dungeonMapId',
'worldstatezonesounds' => 'stateId,value,areaId,wmoAreaId,zoneIntroMusicId,zoneMusicId,soundAmbienceId',
'zoneintromusictable' => 'Id,soundId',
'zonemusic' => 'Id,soundIdDay,soundIdNight'
);
private $isGameTable = false;

View file

@ -48,7 +48,8 @@ class FileGen
'enchants' => [['items', 'spell', 'itemenchantment'], null],
'gems' => [['items', 'spell', 'itemenchantment'], null],
'profiler' => [['quests', 'quests_startend', 'spell', 'currencies', 'achievement', 'titles'], null],
'weightPresets' => [null, null]
'weightPresets' => [null, null],
'sounds' => [['sounds_files'], null]
);
public static $defaultExecTime = 30;
@ -60,7 +61,8 @@ class FileGen
'static/uploads/screenshots/temp',
'static/uploads/screenshots/thumb',
'static/uploads/temp/',
'static/download/searchplugins/'
'static/download/searchplugins/',
'static/wowsounds/'
);
public static $txtConstants = array(

View file

@ -0,0 +1,62 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
function sounds()
{
$ok = true;
// ALL files
$files = DB::Aowow()->selectCol('SELECT ABS(id) AS ARRAY_KEY, CONCAT(path, "/", `file`) FROM ?_sounds_files');
$nFiles = count($files);
$itr = $i = 0;
$nStep = 1000;
foreach ($files as $fileId => $filePath)
{
$i++;
$itr++;
if ($i == $step)
{
$i = 0;
CLISetup::log(' - '.$itr.'/'.$nFiles.' ('.(intVal(100 * $itr / $nFiles).'%) done'));
}
if (stristr($filePath, '.wav')) // expected file.wav.ogg
$filePath .= '.ogg';
else // expected file.mp3.mp3
$filePath .= '.mp3';
// just use the first locale available .. i there is no support for multiple audio files anyway
foreach (CLISetup::$expectedPaths as $locStr => $__)
{
// get your paths straight!
$p = CLISetup::nicePath($filePath, CLISetup::$srcDir, $locStr);
if (CLISetup::fileExists($p))
{
// copy over to static/wowsounds/
if (!copy($p, 'static/wowsounds/'.$fileId))
{
$ok = false;
CLISetup::log(' - could not copy '.CLISetup::bold($p).' into '.CLISetup::bold('static/wowsounds/'.$fileId), CLISetup::LOG_ERROR);
die();
}
continue 2;
}
}
CLISetup::log(' - did not find file: '.CLISetup::bold(CLISetup::nicePath($filePath, CLISetup::$srcDir, '<locale>')), CLISetup::LOG_WARN);
// flag as unusable in DB
DB::Aowow()->query('UPDATE ?_sounds_files SET id = ?d WHERE ABS(id) = ?d', -$fileId, $fileId);
}
return $ok;
}
?>

View file

@ -52,6 +52,7 @@ class SqlGen
'shapeshiftforms' => [null, null, null, null],
'skillline' => [null, null, null, null],
'emotes' => [null, null, null, null],
'sounds' => [null, null, null, null],
'itemenchantment' => [null, null, null, ['spell_enchant_proc_data']],
'achievement' => [null, null, null, ['dbc_achievement']],
'creature' => [null, null, null, ['creature_template', 'creature_template_locale', 'creature_classlevelstats', 'instance_encounters']],

View file

@ -9,10 +9,14 @@ if (!CLI)
$customData = array(
);
$reqDBC = ['emotes', 'emotestext', 'emotestextdata' /*, 'emotestextsound' */];
$reqDBC = ['emotes', 'emotestext', 'emotestextdata'];
function emotes(/*array $ids = [] */)
{
/**********/
/* Basics */
/**********/
$globStrPath = CLISetup::$srcDir.'%sInterface/FrameXML/GlobalStrings.lua';
$allOK = true;
$locPath = [];

View file

@ -33,9 +33,11 @@ function items(array $ids = [])
it.entry,
class, class as classBak,
subclass, subclass AS subClassBak,
SoundOverrideSubclass,
IFNULL(sg.id, 0) AS subSubClass,
name, IFNULL(li.name_loc2, ""), IFNULL(li.name_loc3, ""), IFNULL(li.name_loc6, ""), IFNULL(li.name_loc8, ""),
displayid,
0 AS spellVisualId,
Quality,
Flags, FlagsExtra,
BuyCount, BuyPrice, SellPrice,
@ -86,6 +88,7 @@ function items(array $ids = [])
LanguageID,
startquest,
lockid,
Material,
IF(RandomProperty > 0, RandomProperty, -RandomSuffix) AS randomEnchant,
itemset,
MaxDurability,
@ -107,6 +110,10 @@ function items(array $ids = [])
FoodType,
0 AS gemEnchantmentId,
minMoneyLoot, maxMoneyLoot,
0 AS pickUpSoundId,
0 AS dropDownSoundId,
0 AS sheatheSoundId,
0 AS unsheatheSoundId,
flagsCustom
FROM
item_template it

View file

@ -25,6 +25,10 @@ $reqDBC = ['chrraces', 'charbaseinfo'];
function races()
{
/**********/
/* Basics */
/**********/
$baseQuery = '
REPLACE INTO
?_races

View file

@ -0,0 +1,426 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
if (!CLI)
die('not in cli mode');
$customData = array(
15407 => ['cat' => 10] // UR_Algalon_Summon03 (this is not an item pickup)
);
$reqDBC = array(
// base emotes race
'soundentries', 'emotestextsound', 'vocaluisounds',
// creatures
'npcsounds', 'creaturesounddata', 'creaturedisplayinfo', 'creaturemodeldata',
// spells
'spell', 'spellvisual', 'spellvisualkit',
// zones
'soundambience', 'zonemusic', 'zoneintromusictable', 'worldstatezonesounds', 'areatable',
// items
'material', 'itemgroupsounds', 'itemdisplayinfo', 'weaponimpactsounds', 'itemsubclass', 'weaponswingsounds2' /*, 'sheathesoundlookups' data is redundant with material..? */
);
function sounds(/*array $ids = [] */)
{
/*
okay, here's the thing. WMOAreaTable.dbc references WMO-files to get its position in the world (AreTable) and has sparse information on the related AreaTables themself.
Though it has sets for ZoneAmbience, ZoneMusic and ZoneIntroMusic, these can't be linked for this very reason and are omitted for now.
content: e.g. Tavern Music
*/
// WMOAreaTable.dbc/Id => AreaTable.dbc/Id
$worldStateZoneSoundFix = array(
18153 => 2119,
18154 => 2119,
47321 => 4273, // The Spark of Imagination
43600 => 4273, // The Celestial Planetarium
47478 => 4273 // The Prison of Yogg-Saron
);
/***********/
/* M A I N */
/***********/
CLISetup::log(' - sounds main data');
// file extraction and conversion in build step. data here is purely structural
// reality check ... thats probably gigabytes worth of sound.. only growing in size with every locale added on top (RedRocketSite didn't do it. Should i then?)
// .wav => audio/ogg; codecs="vorbis"
// .mp3 => audio/mpeg
$query = '
SELECT Id AS `id`, `type` AS `cat`, `name`, 0 AS cuFlags,
`file1` AS soundFile1, `file2` AS soundFile2, `file3` AS soundFile3, `file4` AS soundFile4, `file5` AS soundFile5,
`file6` AS soundFile6, `file7` AS soundFile7, `file8` AS soundFile8, `file9` AS soundFile9, `file10` AS soundFile10,
path, flags
FROM dbc_soundentries
WHERE id > ?d LIMIT ?d
';
DB::Aowow()->query('TRUNCATE ?_sounds');
DB::Aowow()->query('TRUNCATE ?_sounds_files');
$lastMax = 0;
$soundFileIdx = 0;
$soundIndex = [];
while ($sounds = DB::Aowow()->select($query, $lastMax, SqlGen::$stepSize))
{
$newMax = max(array_column($sounds, 'id'));
CLISetup::log(' * sets '.($lastMax + 1).' - '.$newMax);
$lastMax = $newMax;
$groupSets = [];
foreach ($sounds as $s)
{
/* attention!
one sound can be used in 20 or more locations but may appear as multiple files,
because of different cases, path being attached to file and other shenanigans
build a usable path and create full index to compensate
25.6k raw files => expect ~21k filtered files
*/
$fileSets = [];
$hasDupes = false;
for ($i = 1; $i < 11; $i++)
{
$nicePath = CLISetup::nicePath($s['soundFile'.$i], $s['path']);
if ($s['soundFile'.$i] && array_key_exists($nicePath, $soundIndex))
{
$s['soundFile'.$i] = $soundIndex[$nicePath];
$hasDupes = true;
continue;
}
// convert to something web friendly => ogg
if (stristr($s['soundFile'.$i], '.wav'))
{
$soundIndex[$nicePath] = ++$soundFileIdx;
$fileSets[] = array(
$soundFileIdx,
strtolower($s['soundFile'.$i]),
strtolower($s['path']),
SOUND_TYPE_OGG
);
$s['soundFile'.$i] = $soundFileIdx;
}
// mp3 .. keep as is
else if (stristr($s['soundFile'.$i], '.mp3'))
{
$soundIndex[$nicePath] = ++$soundFileIdx;
$fileSets[] = array(
$soundFileIdx,
strtolower($s['soundFile'.$i]),
strtolower($s['path']),
SOUND_TYPE_MP3
);
$s['soundFile'.$i] = $soundFileIdx;
}
// i call bullshit
else if ($s['soundFile'.$i])
{
CLISetup::log(' - sound group #'.$s['id'].' "'.$s['name'].'" has invalid sound file "'.$s['soundFile'.$i].'" on index '.$i.'! Skipping...', CLISetup::LOG_WARN);
$s['soundFile'.$i] = null;
}
// empty case
else
$s['soundFile'.$i] = null;
}
if (!$fileSets && !$hasDupes)
{
CLISetup::log(' - sound group #'.$s['id'].' "'.$s['name'].'" contains no sound files! Skipping...', CLISetup::LOG_WARN);
continue;
}
else if ($fileSets)
DB::Aowow()->query('INSERT INTO ?_sounds_files VALUES (?a)', array_values($fileSets));
unset($s['path']);
$groupSets[] = array_values($s);
}
DB::Aowow()->query('REPLACE INTO ?_sounds VALUES (?a)', array_values($groupSets));
}
/******************/
/* VocalUI Sounds */
/******************/
CLISetup::log(' - linking to race');
DB::Aowow()->query('TRUNCATE ?_races_sounds');
DB::Aowow()->query('INSERT IGNORE INTO ?_races_sounds SELECT raceId, soundIdMale, 1 FROM dbc_vocaluisounds WHERE soundIdMale <> soundIdFemale AND soundIdMale > 0');
DB::Aowow()->query('INSERT IGNORE INTO ?_races_sounds SELECT raceId, soundIdFemale, 2 FROM dbc_vocaluisounds WHERE soundIdMale <> soundIdFemale AND soundIdFemale > 0');
// ps: im too dumb to union this
/***************/
/* Emote Sound */
/***************/
CLISetup::log(' - linking to emotes');
DB::Aowow()->query('TRUNCATE ?_emotes_sounds');
DB::Aowow()->query('INSERT IGNORE INTO ?_emotes_sounds SELECT emotesTextId, raceId, gender + 1, soundId FROM dbc_emotestextsound');
/*******************/
/* Creature Sounds */
/*******************/
CLISetup::log(' - linking to creatures');
// currently ommitting:
// * footsteps (matrix of: creature + terrain + humidity)
// * fidget2 through 5
// * customattack2 through 3
// in case of conflicting data CreatureDisplayInfo overrides CreatureModelData (seems to be more specialized (Thral > MaleOrc / Maiden > FemaleTitan))
DB::Aowow()->query('TRUNCATE ?_creature_sounds');
DB::Aowow()->query('
INSERT INTO
?_creature_sounds (`id`, `greeting`, `farewell`, `angry`, `exertion`, `exertioncritical`, `injury`, `injurycritical`, `death`, `stun`, `stand`, `aggro`, `wingflap`, `wingglide`, `alert`, `fidget`, `customattack`, `loop`, `jumpstart`, `jumpend`, `petattack`, `petorder`, `petdismiss`, `birth`, `spellcast`, `submerge`, `submerged`)
SELECT
cdi.Id,
IFNULL(ns.greetSoundId, 0),
IFNULL(ns.byeSoundId, 0),
IFNULL(ns.angrySoundId, 0),
IF(csdA.exertion, csdA.exertion, IFNULL(csdB.exertion, 0)),
IF(csdA.exertionCritical, csdA.exertionCritical, IFNULL(csdB.exertionCritical, 0)),
IF(csdA.injury, csdA.injury, IFNULL(csdB.injury, 0)),
IF(csdA.injuryCritical, csdA.injuryCritical, IFNULL(csdB.injuryCritical, 0)),
IF(csdA.death, csdA.death, IFNULL(csdB.death, 0)),
IF(csdA.stun, csdA.stun, IFNULL(csdB.stun, 0)),
IF(csdA.stand, csdA.stand, IFNULL(csdB.stand, 0)),
IF(csdA.aggro, csdA.aggro, IFNULL(csdB.aggro, 0)),
IF(csdA.wingFlap, csdA.wingFlap, IFNULL(csdB.wingFlap, 0)),
IF(csdA.wingGlide, csdA.wingGlide, IFNULL(csdB.wingGlide, 0)),
IF(csdA.alert, csdA.alert, IFNULL(csdB.alert, 0)),
IF(csdA.fidget, csdA.fidget, IFNULL(csdB.fidget, 0)),
IF(csdA.customAttack, csdA.customAttack, IFNULL(csdB.customAttack, 0)),
IF(csdA.loop, csdA.loop, IFNULL(csdB.loop, 0)),
IF(csdA.jumpStart, csdA.jumpStart, IFNULL(csdB.jumpStart, 0)),
IF(csdA.jumpEnd, csdA.jumpEnd, IFNULL(csdB.jumpEnd, 0)),
IF(csdA.petAttack, csdA.petAttack, IFNULL(csdB.petAttack, 0)),
IF(csdA.petOrder, csdA.petOrder, IFNULL(csdB.petOrder, 0)),
IF(csdA.petDismiss, csdA.petDismiss, IFNULL(csdB.petDismiss, 0)),
IF(csdA.birth, csdA.birth, IFNULL(csdB.birth, 0)),
IF(csdA.spellcast, csdA.spellcast, IFNULL(csdB.spellcast, 0)),
IF(csdA.submerge, csdA.submerge, IFNULL(csdB.submerge, 0)),
IF(csdA.submerged, csdA.submerged, IFNULL(csdB.submerged, 0))
FROM
dbc_creaturedisplayinfo cdi
LEFT JOIN
dbc_creaturemodeldata cmd ON cmd.Id = cdi.modelId
LEFT JOIN
dbc_creaturesounddata csdA ON cdi.creatureSoundId = csdA.Id
LEFT JOIN
dbc_creaturesounddata csdB ON cmd.creatureSoundId = csdB.Id
LEFT JOIN
dbc_npcsounds ns ON cdi.npcSoundId = ns.Id
');
/****************/
/* Spell Sounds */
/****************/
CLISetup::log(' - linking to spells');
// issues: (probably because of 335-data)
// * animate is probably wrong
// * missile and impactarea not in js
// * ready, castertargeting, casterstate and targetstate not in dbc
DB::Aowow()->query('TRUNCATE ?_spell_sounds');
DB::Aowow()->query('
INSERT INTO
?_spell_sounds (`Id`, `precast`, `cast`, `impact`, `state`, `statedone`, `channel`, `missile`, `animation`, `casterimpact`, `targetimpact`, `missiletargeting`, `instantarea`, `impactarea`, `persistentarea`)
SELECT
sv.Id,
IFNULL(svk1.soundId, 0),
IFNULL(svk2.soundId, 0),
IFNULL(svk3.soundId, 0),
IFNULL(svk4.soundId, 0),
IFNULL(svk5.soundId, 0),
IFNULL(svk6.soundId, 0),
missileSoundId,
animationSoundId,
IFNULL(svk7.soundId, 0),
IFNULL(svk8.soundId, 0),
IFNULL(svk9.soundId, 0),
IFNULL(svk10.soundId, 0),
IFNULL(svk11.soundId, 0),
IFNULL(svk12.soundId, 0)
FROM
dbc_spellvisual sv
LEFT JOIN
dbc_spellvisualkit svk1 ON svk1.Id = sv.precastKitId
LEFT JOIN
dbc_spellvisualkit svk2 ON svk2.Id = sv.castKitId
LEFT JOIN
dbc_spellvisualkit svk3 ON svk3.Id = sv.impactKitId
LEFT JOIN
dbc_spellvisualkit svk4 ON svk4.Id = sv.stateKitId
LEFT JOIN
dbc_spellvisualkit svk5 ON svk5.Id = sv.statedoneKitId
LEFT JOIN
dbc_spellvisualkit svk6 ON svk6.Id = sv.channelKitId
LEFT JOIN
dbc_spellvisualkit svk7 ON svk7.Id = sv.casterImpactKitId
LEFT JOIN
dbc_spellvisualkit svk8 ON svk8.Id = sv.targetImpactKitId
LEFT JOIN
dbc_spellvisualkit svk9 ON svk9.Id = sv.missileTargetingKitId
LEFT JOIN
dbc_spellvisualkit svk10 ON svk10.Id = sv.instantAreaKitId
LEFT JOIN
dbc_spellvisualkit svk11 ON svk11.Id = sv.impactAreaKitId
LEFT JOIN
dbc_spellvisualkit svk12 ON svk12.Id = sv.persistentAreaKitId
');
/***************/
/* Zone Sounds */
/***************/
CLISetup::log(' - linking to zones');
// omiting data from WMOAreaTable, as its at the moment impossible to link to actual zones
DB::Aowow()->query('TRUNCATE ?_zones_sounds');
DB::Aowow()->query('
INSERT INTO
?_zones_sounds (id, ambienceDay, ambienceNight, musicDay, musicNight, intro, worldStateId, worldStateValue)
SELECT
a.id,
IFNULL(sa1.soundIdDay, 0),
IFNULL(sa1.soundIdNight, 0),
IFNULL(zm1.soundIdDay, 0),
IFNULL(zm1.soundIdNight, 0),
IFNULL(zimt1.soundId, 0),
0,
0
FROM
dbc_areatable a
LEFT JOIN
dbc_soundambience sa1 ON sa1.id = a.soundAmbience
LEFT JOIN
dbc_zonemusic zm1 ON zm1.id = a.zoneMusic
LEFT JOIN
dbc_zoneintromusictable zimt1 ON zimt1.id = a.zoneIntroMusic
WHERE
a.soundAmbience > 0 OR a.zoneMusic > 0 OR a.zoneIntroMusic
UNION
SELECT
IF(wszs.areaId, wszs.areaId, wszs.wmoAreaId),
IFNULL(sa2.soundIdDay, 0),
IFNULL(sa2.soundIdNight, 0),
IFNULL(zm2.soundIdDay, 0),
IFNULL(zm2.soundIdNight, 0),
IFNULL(zimt2.soundId, 0),
wszs.stateId,
wszs.value
FROM
dbc_worldstatezonesounds wszs
LEFT JOIN
dbc_soundambience sa2 ON sa2.id = wszs.soundAmbienceId
LEFT JOIN
dbc_zonemusic zm2 ON zm2.id = wszs.zoneMusicId
LEFT JOIN
dbc_zoneintromusictable zimt2 ON zimt2.id = wszs.zoneIntroMusicId
WHERE
wszs.zoneMusicId > 0 AND (wszs.areaId OR wszs.wmoAreaId IN (?a))
', array_keys($worldStateZoneSoundFix));
// apply post-fix
foreach ($worldStateZoneSoundFix as $old => $new)
DB::Aowow()->query('UPDATE ?_zones_sounds SET id = ?d WHERE id = ?d', $new, $old);
/***************/
/* Item Sounds */
/***************/
CLISetup::log(' - linking to items');
DB::Aowow()->query('
UPDATE
?_items i
LEFT JOIN
dbc_itemdisplayinfo idi ON
idi.id = i.displayId
LEFT JOIN
dbc_itemgroupsounds igs ON
igs.id = idi.groupSoundId
LEFT JOIN
dbc_material m ON
m.id = i.material
SET
i.spellVisualId = IFNULL(idi.spellVisualId, 0),
i.pickUpSoundId = IFNULL(igs.pickUpSoundId, 0),
i.dropDownSoundId = IFNULL(igs.dropDownSoundId, 0),
i.sheatheSoundId = IFNULL(m.sheatheSoundId, 0),
i.unsheatheSoundId = IFNULL(m.unsheatheSoundId, 0)
');
DB::Aowow()->query('TRUNCATE ?_items_sounds');
$fields = ['hit', 'crit'];
foreach ($fields as $f)
{
for ($i = 1; $i <= 10; $i++)
{
DB::Aowow()->query('
INSERT INTO
?_items_sounds
SELECT
?#,
(1 << wis.subClass)
FROM
dbc_weaponimpactsounds wis
WHERE
?# > 0
ON DUPLICATE KEY UPDATE
subClassMask = subClassMask | (1 << wis.subClass)
', $f.$i, $f.$i);
}
}
DB::Aowow()->query('
INSERT INTO
?_items_sounds
SELECT
wss.soundId,
(1 << isc.subClass)
FROM
dbc_itemsubclass isc
JOIN
dbc_weaponswingsounds2 wss ON
wss.weaponSize = isc.weaponSize
WHERE
isc.class = 2
ON DUPLICATE KEY UPDATE
subClassMask = subClassMask | (1 << isc.subClass)
');
return true;
}
?>

View file

@ -23,7 +23,7 @@ if (!CLI)
$customData = array(
);
$reqDBC = ['worldmaparea', 'map', 'worldmaptransforms', 'dungeonmap', 'taxipathnode'];
$reqDBC = ['worldmaparea', 'map', 'dungeonmap', 'taxipathnode', 'soundemitters'];
function spawns() // and waypoints
{
@ -98,15 +98,19 @@ function spawns() // and waypoints
'FROM gameobject c',
' - assembling '.CLISetup::bold('gameobject').' spawns'];
$query[3] = ['SELECT c.guid, w.entry AS "npcOrPath", w.pointId AS "point", c.zoneId AS areaId, c.map, w.waittime AS "wait", w.location_y AS `posX`, w.location_x AS `posY` ' .
$query[3] = ['SELECT Id AS "guid", 19 AS "type", soundId AS typeId, 0 AS respawn, 0 AS phaseMask, 0 AS areaId, mapId AS "map", 0 AS pathId, posX, posY ' .
'FROM dbc_soundemitters',
' - assembling '.CLISetup::bold('sound emitter').' spawns'];
$query[4] = ['SELECT c.guid, w.entry AS "npcOrPath", w.pointId AS "point", c.zoneId AS areaId, c.map, w.waittime AS "wait", w.location_y AS `posX`, w.location_x AS `posY` ' .
'FROM creature c JOIN script_waypoint w ON c.id = w.entry',
' - assembling waypoints from '.CLISetup::bold('script_waypoint')];
$query[4] = ['SELECT c.guid, w.entry AS "npcOrPath", w.pointId AS "point", c.zoneId AS areaId, c.map, 0 AS "wait", w.position_y AS `posX`, w.position_x AS `posY` ' .
$query[5] = ['SELECT c.guid, w.entry AS "npcOrPath", w.pointId AS "point", c.zoneId AS areaId, c.map, 0 AS "wait", w.position_y AS `posX`, w.position_x AS `posY` ' .
'FROM creature c JOIN waypoints w ON c.id = w.entry',
' - assembling waypoints from '.CLISetup::bold('waypoints')];
$query[5] = ['SELECT c.guid, -w.id AS "npcOrPath", w.point, c.zoneId AS areaId, c.map, w.delay AS "wait", w.position_y AS `posX`, w.position_x AS `posY` ' .
$query[6] = ['SELECT c.guid, -w.id AS "npcOrPath", w.point, c.zoneId AS areaId, c.map, w.delay AS "wait", w.position_y AS `posX`, w.position_x AS `posY` ' .
'FROM creature c JOIN creature_addon ca ON ca.guid = c.guid JOIN waypoint_data w ON w.id = ca.path_id WHERE ca.path_id <> 0',
' - assembling waypoints from '.CLISetup::bold('waypoint_data')];
@ -118,7 +122,7 @@ function spawns() // and waypoints
'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) ' .
'HAVING (`posX` BETWEEN 0.1 AND 99.9 AND `posY` BETWEEN 0.1 AND 99.9) AND (dm.Id IS NULL OR ?d) ' .
'HAVING (`posX` BETWEEN 0.1 AND 99.9 AND `posY` BETWEEN 0.1 AND 99.9) ' . // AND (dm.Id IS NULL OR ?d) ' .
'ORDER BY quality ASC';
@ -149,7 +153,13 @@ function spawns() // and waypoints
$n = 0;
$sum = 0;
foreach (DB::World()->select($q[0]) as $spawn)
if ($idx == 3)
$queryResult = DB::Aowow()->select($q[0]);
else
$queryResult = DB::World()->select($q[0]);
foreach ($queryResult as $spawn)
{
if (!$n)
CLISetup::log(' * sets '.($sum + 1).' - '.($sum += SqlGen::$stepSize));
@ -167,20 +177,20 @@ function spawns() // and waypoints
$spawn['map'] = $transports[$spawn['map']]['mapId'];
}
$points = DB::Aowow()->select($queryPost, $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], 1, $spawn['map'], $spawn['areaId'], $spawn['areaId'], $spawn['areaId'] ? 1 : 0);
$points = DB::Aowow()->select($queryPost, $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], 1, $spawn['map'], $spawn['areaId'], $spawn['areaId'] /*, $spawn['areaId'] ? 1 : 0*/);
if (!$points) // retry: TC counts pre-instance subareas as instance-maps .. which have no map file
$points = DB::Aowow()->select($queryPost, $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], 0, $spawn['map'], 0, 0, 1);
$points = DB::Aowow()->select($queryPost, $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], $spawn['posX'], $spawn['posX'], $spawn['posY'], $spawn['posY'], 0, $spawn['map'], 0, 0 /*, 1*/);
if (!$points) // still impossible (there are areas that are intentionally off the map (e.g. the isles south of tanaris))
{
CLISetup::log('GUID '.$spawn['guid'].($idx < 3 ? '' : ' on path/point '.$spawn['npcOrPath'].'/'.$spawn['point']).' could not be matched to displayable area [A:'.$spawn['areaId'].'; X:'.$spawn['posY'].'; Y:'.$spawn['posX'].']', CLISetup::LOG_WARN);
CLISetup::log('GUID '.$spawn['guid'].($idx < 4 ? '' : ' on path/point '.$spawn['npcOrPath'].'/'.$spawn['point']).' could not be matched to displayable area [A:'.$spawn['areaId'].'; X:'.$spawn['posY'].'; Y:'.$spawn['posX'].']', CLISetup::LOG_WARN);
continue;
}
// if areaId is set, area was determined by TC .. we're fine .. mostly
$final = $spawn['areaId'] ? $points[0] : $checkCoords($points);
if ($idx < 3)
if ($idx < 4)
{
$set = array(
'guid' => $spawn['guid'],

View file

@ -85,6 +85,7 @@ function spell()
EffectSpellClassMaskA1, EffectSpellClassMaskA2, EffectSpellClassMaskA3,
EffectSpellClassMaskB1, EffectSpellClassMaskB2, EffectSpellClassMaskB3,
EffectSpellClassMaskC1, EffectSpellClassMaskC2, EffectSpellClassMaskC3,
0 AS spellVisualId1, 0 AS spellVisualId2,
0 AS iconId, 0 AS iconIdActive,
CONCAT("Serverside - ",Comment) AS name_loc0,CONCAT("Serverside - ",Comment) AS name_loc2,CONCAT("Serverside - ",Comment) AS name_loc3,CONCAT("Serverside - ",Comment) AS name_loc6,CONCAT("Serverside - ",Comment) AS name_loc8,
"" AS rank_loc0, "" AS rank_loc2, "" AS rank_loc3, "" AS rank_loc6, "" AS rank_loc8,
@ -176,6 +177,7 @@ function spell()
effect1BonusMultiplier, effect2BonusMultiplier, effect3BonusMultiplier,
iconId, 0 AS iconIdAlt,
0 AS rankId,
spellVisualId1,
name_loc0, name_loc2, name_loc3, name_loc6, name_loc8,
rank_loc0, rank_loc2, rank_loc3, rank_loc6, rank_loc8,
description_loc0, description_loc2, description_loc3, description_loc6, description_loc8,

View file

@ -1,107 +1,107 @@
-- TYPE_NPC:1
UPDATE aowow_creature a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 1 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_OBJECT:2
UPDATE aowow_objects a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 2 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_ITEM:3
UPDATE aowow_items a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 3 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_ITEMSET:4
UPDATE aowow_itemset a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 4 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_QUEST:5
UPDATE aowow_quests a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 5 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_SPELL:6
UPDATE aowow_spell a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 6 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_ZONE:7
UPDATE aowow_zones a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 7 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_FACTION:8
UPDATE aowow_factions a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 8 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_PET:9
UPDATE aowow_pet a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 9 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_ACHIEVEMENT:10
UPDATE aowow_achievement a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 10 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_TITLE:11
UPDATE aowow_titles a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 11 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_WORLDEVENT:12
UPDATE aowow_events a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 12 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_CLASS:13
UPDATE aowow_classes a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 13 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_RACE:14
UPDATE aowow_races a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 14 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_SKILL:15
UPDATE aowow_skillline a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 15 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_CURRENCY:17
UPDATE aowow_currencies a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 17 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_EMOTE:501
UPDATE aowow_emotes a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 501 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_ENCHANTMENT:502
UPDATE aowow_itemenchantment a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 502 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_NPC:1
UPDATE aowow_creature a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 1 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_OBJECT:2
UPDATE aowow_objects a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 2 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_ITEM:3
UPDATE aowow_items a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 3 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_ITEMSET:4
UPDATE aowow_itemset a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 4 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_QUEST:5
UPDATE aowow_quests a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 5 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_SPELL:6
UPDATE aowow_spell a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 6 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_ZONE:7
UPDATE aowow_zones a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 7 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_FACTION:8
UPDATE aowow_factions a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 8 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_PET:9
UPDATE aowow_pet a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 9 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_ACHIEVEMENT:10
UPDATE aowow_achievement a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 10 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_TITLE:11
UPDATE aowow_titles a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 11 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_WORLDEVENT:12
UPDATE aowow_events a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 12 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_CLASS:13
UPDATE aowow_classes a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 13 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_RACE:14
UPDATE aowow_races a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 14 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_SKILL:15
UPDATE aowow_skillline a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 15 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_CURRENCY:17
UPDATE aowow_currencies a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 17 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_EMOTE:501
UPDATE aowow_emotes a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 501 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;
-- TYPE_ENCHANTMENT:502
UPDATE aowow_itemenchantment a
JOIN (SELECT typeId, BIT_OR(`status`) AS `ccFlags` FROM aowow_screenshots WHERE `type` = 502 GROUP BY typeId) b ON a.id = b.typeId
SET a.cuFlags = a.cuFlags | 0x02000000
WHERE b.ccFlags & 0x8;

View file

@ -0,0 +1,23 @@
-- drop deprecatede dbc-tables
DROP TABLE IF EXISTS `dbc_areatable`;
DROP TABLE IF EXISTS `dbc_creaturedisplayinfo`;
DROP TABLE IF EXISTS `dbc_creaturemodeldata`;
DROP TABLE IF EXISTS `dbc_creaturesounddata`;
DROP TABLE IF EXISTS `dbc_emotestextsound`;
DROP TABLE IF EXISTS `dbc_itemdisplayinfo`;
DROP TABLE IF EXISTS `dbc_itemgroupsounds`;
DROP TABLE IF EXISTS `dbc_itemsubclass`;
DROP TABLE IF EXISTS `dbc_material`;
DROP TABLE IF EXISTS `dbc_npcsounds`;
DROP TABLE IF EXISTS `dbc_soundambience`;
DROP TABLE IF EXISTS `dbc_soundemitters`;
DROP TABLE IF EXISTS `dbc_soundentries`;
DROP TABLE IF EXISTS `dbc_spell`;
DROP TABLE IF EXISTS `dbc_spellvisual`;
DROP TABLE IF EXISTS `dbc_spellvisualkit`;
DROP TABLE IF EXISTS `dbc_vocaluisounds`;
DROP TABLE IF EXISTS `dbc_weaponimpactsounds`;
DROP TABLE IF EXISTS `dbc_weaponswingsounds2`;
DROP TABLE IF EXISTS `dbc_worldstatezonesound`;
DROP TABLE IF EXISTS `dbc_zoneintromusictable`;
DROP TABLE IF EXISTS `dbc_zonemusic`;

View file

@ -0,0 +1,164 @@
-- alterations
ALTER TABLE `aowow_spell`
ADD COLUMN `spellVisualId` smallint(5) unsigned NOT NULL AFTER `rankNo`;
ALTER TABLE `aowow_items`
ADD COLUMN `spellVisualId` smallint(5) unsigned NOT NULL DEFAULT '0' AFTER `displayId`,
ADD COLUMN `material` tinyint(3) NOT NULL DEFAULT '0' AFTER `lockId`,
ADD COLUMN `soundOverrideSubclass` tinyint(3) NOT NULL AFTER `subClassBak`,
ADD COLUMN `pickUpSoundId` smallint(5) unsigned NOT NULL DEFAULT '0' AFTER `maxMoneyLoot`,
ADD COLUMN `dropDownSoundId` smallint(5) unsigned NOT NULL DEFAULT '0' AFTER `pickUpSoundId`,
ADD COLUMN `sheatheSoundId` smallint(5) unsigned NOT NULL DEFAULT '0' AFTER `dropDownSoundId`,
ADD COLUMN `unsheatheSoundId` smallint(5) unsigned NOT NULL DEFAULT '0' AFTER `sheatheSoundId`;
-- additions
REPLACE INTO `aowow_articles` (`type`, `typeId`, `locale`, `article`, `quickInfo`)
VALUES (19, -1000, 0, 'Here you can set up a playlist of sounds and music. \n\nJust click the "Add" button near an audio control, then return to this page to listen to the list you\'ve created.', NULL);
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
DROP TABLE IF EXISTS `aowow_items_sounds`;
CREATE TABLE `aowow_items_sounds` (
`soundId` smallint(5) unsigned NOT NULL,
`subClassMask` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`soundId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='actually .. its only weapon related sounds in here';
DROP TABLE IF EXISTS `aowow_zones_sounds`;
CREATE TABLE `aowow_zones_sounds` (
`id` smallint(5) unsigned NOT NULL,
`ambienceDay` smallint(5) unsigned NOT NULL,
`ambienceNight` smallint(5) unsigned NOT NULL,
`musicDay` smallint(5) unsigned NOT NULL,
`musicNight` smallint(5) unsigned NOT NULL,
`intro` smallint(5) unsigned NOT NULL,
`worldStateId` smallint(5) unsigned NOT NULL,
`worldStateValue` smallint(6) NOT NULL,
INDEX `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `aowow_creature_sounds`;
CREATE TABLE IF NOT EXISTS `aowow_creature_sounds` (
`id` smallint(5) unsigned NOT NULL COMMENT 'CreatureDisplayInfo.dbc/id',
`greeting` smallint(5) unsigned NOT NULL,
`farewell` smallint(5) unsigned NOT NULL,
`angry` smallint(5) unsigned NOT NULL,
`exertion` smallint(5) unsigned NOT NULL,
`exertioncritical` smallint(5) unsigned NOT NULL,
`injury` smallint(5) unsigned NOT NULL,
`injurycritical` smallint(5) unsigned NOT NULL,
`death` smallint(5) unsigned NOT NULL,
`stun` smallint(5) unsigned NOT NULL,
`stand` smallint(5) unsigned NOT NULL,
`footstep` smallint(5) unsigned NOT NULL,
`aggro` smallint(5) unsigned NOT NULL,
`wingflap` smallint(5) unsigned NOT NULL,
`wingglide` smallint(5) unsigned NOT NULL,
`alert` smallint(5) unsigned NOT NULL,
`fidget` smallint(5) unsigned NOT NULL,
`customattack` smallint(5) unsigned NOT NULL,
`loop` smallint(5) unsigned NOT NULL,
`jumpstart` smallint(5) unsigned NOT NULL,
`jumpend` smallint(5) unsigned NOT NULL,
`petattack` smallint(5) unsigned NOT NULL,
`petorder` smallint(5) unsigned NOT NULL,
`petdismiss` smallint(5) unsigned NOT NULL,
`birth` smallint(5) unsigned NOT NULL,
`spellcast` smallint(5) unsigned NOT NULL,
`submerge` smallint(5) unsigned NOT NULL,
`submerged` smallint(5) unsigned NOT NULL,
`transform` smallint(5) unsigned NOT NULL,
`transformanimated` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='!ATTENTION!\r\nthe primary key of this table is NOT a creatureId, but displayId\r\n\r\ncolumn names from LANG.sound_activities';
DROP TABLE IF EXISTS `aowow_emotes_sounds`;
CREATE TABLE IF NOT EXISTS `aowow_emotes_sounds` (
`emoteId` smallint(5) unsigned NOT NULL,
`raceId` tinyint(3) unsigned NOT NULL,
`gender` tinyint(1) unsigned NOT NULL,
`soundId` smallint(5) unsigned NOT NULL,
UNIQUE KEY `emoteId_raceId_gender_soundId` (`emoteId`,`raceId`,`gender`,`soundId`),
KEY `emoteId` (`emoteId`),
KEY `raceId` (`raceId`),
KEY `soundId` (`soundId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `aowow_races_sounds`;
CREATE TABLE IF NOT EXISTS `aowow_races_sounds` (
`raceId` tinyint(3) unsigned NOT NULL,
`soundId` smallint(5) unsigned NOT NULL,
`gender` tinyint(1) unsigned NOT NULL,
UNIQUE KEY `race_soundId_gender` (`raceId`,`soundId`,`gender`),
KEY `race` (`raceId`),
KEY `soundId` (`soundId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `aowow_sounds`;
CREATE TABLE IF NOT EXISTS `aowow_sounds` (
`id` smallint(5) unsigned NOT NULL,
`cat` tinyint(3) unsigned NOT NULL,
`name` varchar(100) NOT NULL,
`cuFlags` int(10) unsigned NOT NULL,
`soundFile1` smallint(5) unsigned DEFAULT NULL,
`soundFile2` smallint(5) unsigned DEFAULT NULL,
`soundFile3` smallint(5) unsigned DEFAULT NULL,
`soundFile4` smallint(5) unsigned DEFAULT NULL,
`soundFile5` smallint(5) unsigned DEFAULT NULL,
`soundFile6` smallint(5) unsigned DEFAULT NULL,
`soundFile7` smallint(5) unsigned DEFAULT NULL,
`soundFile8` smallint(5) unsigned DEFAULT NULL,
`soundFile9` smallint(5) unsigned DEFAULT NULL,
`soundFile10` smallint(5) unsigned DEFAULT NULL,
`flags` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `cat` (`cat`),
KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `aowow_sounds_files`;
CREATE TABLE IF NOT EXISTS `aowow_sounds_files` (
`id` smallint(6) NOT NULL COMMENT '<0 not found in client files',
`file` varchar(75) NOT NULL,
`path` varchar(75) NOT NULL COMMENT 'in client',
`type` tinyint(1) unsigned NOT NULL COMMENT '1: ogg; 2: mp3',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `aowow_spell_sounds`;
CREATE TABLE IF NOT EXISTS `aowow_spell_sounds` (
`id` smallint(5) unsigned NOT NULL COMMENT 'SpellVisual.dbc/id',
`animation` smallint(5) unsigned NOT NULL,
`ready` smallint(5) unsigned NOT NULL,
`precast` smallint(5) unsigned NOT NULL,
`cast` smallint(5) unsigned NOT NULL,
`impact` smallint(5) unsigned NOT NULL,
`state` smallint(5) unsigned NOT NULL,
`statedone` smallint(5) unsigned NOT NULL,
`channel` smallint(5) unsigned NOT NULL,
`casterimpact` smallint(5) unsigned NOT NULL,
`targetimpact` smallint(5) unsigned NOT NULL,
`castertargeting` smallint(5) unsigned NOT NULL,
`missiletargeting` smallint(5) unsigned NOT NULL,
`instantarea` smallint(5) unsigned NOT NULL,
`persistentarea` smallint(5) unsigned NOT NULL,
`casterstate` smallint(5) unsigned NOT NULL,
`targetstate` smallint(5) unsigned NOT NULL,
`missile` smallint(5) unsigned NOT NULL COMMENT 'not predicted by js',
`impactarea` smallint(5) unsigned NOT NULL COMMENT 'not predicted by js',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='!ATTENTION!\r\nthe primary key of this table is NOT a spellId, but spellVisualId\r\n\r\ncolumn names from LANG.sound_activities';
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
UPDATE aowow_dbversion SET `build` = CONCAT(IFNULL(`build`, ''), ' sounds'), `sql` = CONCAT(IFNULL(`sql`, ''), ' spell creature sounds spawns');

View file

@ -114,7 +114,7 @@ h5 a.icontiny span { text-decoration:none !important; }
.entryc .quote, .comment-body .quote,
.text .quote, .text blockquote,
.quote-blizz, .quote-wh, .minibox {
.quote-blizz, .quote-wh {
background:#1b1b1b;
padding: 15px;
margin:15px 0;
@ -150,6 +150,14 @@ h5 a.icontiny span { text-decoration:none !important; }
overflow:auto;
}
div.audiomarkup
{
text-align:center;
display:inline-block;
font-size:13px;
line-height:normal
}
.quote-blizz,.quote-wh
{
clear:both;
@ -1826,6 +1834,10 @@ td.checked .listview-cb:hover {
background-color: #343434;
}
.listview-cleartext {
font-family:Verdana, "Open Sans", Arial, "Helvetica Neue", Helvetica, sans-serif;
}
.live-search {
position: absolute;
z-index: 100000001;
@ -3975,6 +3987,22 @@ div.captcha-center {
font-size: 11px;
}
.audio-controls td {
text-align:center
}
.audio-controls-title {
padding:0 15px 5px;
word-break:break-word;
word-wrap:break-word;
overflow-wrap:break-word
}
.audio-controls-pagination-track {
display:inline-block;
min-width:50px
}
/************************************************/
/* aowow: deprecated stuff that might be of use */

View file

@ -2249,6 +2249,138 @@ var Markup = {
return str.replace(/<small\b[\s\S]*?>([\s\S]*?)<\/small>/gi, '[small]$1[/small]');
}
},
sound: {
empty: true,
attr:
{
unnamed: { req: false, valid: /^[0-9]+$/ },
src: { req: false, valid: /\S+/ },
title: { req: false, valid: /\S+/ },
type: { req: false, valid: /\S+/ },
src2: { req: false, valid: /\S+/ },
type2: { req: false, valid: /\S+/ },
domain: { req: false, valid: /^(beta|mop|ptr|www|de|es|fr|ru|pt)$/ }
},
validate: function (attr)
{
if(attr.unnamed)
return true;
if(!attr.src)
return false;
return true;
},
toHtml: function (attr)
{
var
type,
src,
title,
href,
src2,
type2;
var domainInfo = Markup._getDatabaseDomainInfo(attr);
var url = domainInfo[0];
if (attr.unnamed)
{
if (!(attr.unnamed in g_sounds))
return '';
if (!g_sounds[attr.unnamed].hasOwnProperty("files"))
return '';
if (g_sounds[attr.unnamed].files.length == 0)
return '';
if (!g_sounds[attr.unnamed].files[0].hasOwnProperty('type'))
return '';
type = g_sounds[attr.unnamed].files[0].type;
src = g_sounds[attr.unnamed].files[0].url;
title = g_sounds[attr.unnamed].name ? g_sounds[attr.unnamed].name: g_sounds[attr.unnamed].files[0].title;
href = url + '?sound=' + attr.unnamed;
}
else
{
if (Markup.allow < MARKUP_CLASS_STAFF)
return '';
src = attr.src;
title = attr.title ? attr.title: '(Unknown)';
if (attr.hasOwnProperty('type'))
type = attr.type;
else
{
switch (attr.src.toLowerCase().substr(-4))
{
case '.mp3':
type = 'audio/mpeg';
break;
case '.ogg':
type = 'audio/ogg; codecs="vorbis"';
break;
}
}
if (attr.src2)
{
src2 = attr.src2;
if (attr.hasOwnProperty('type2'))
type2 = attr.type2;
else
{
switch (attr.src2.toLowerCase().substr(-4))
{
case '.mp3':
type2 = 'audio/mpeg';
break;
case '.ogg':
type2 = 'audio/ogg; codecs="vorbis"';
break;
}
}
}
}
var str = '<audio preload="none" controls="true"' + Markup._addGlobalAttributes(attr);
if (attr.unnamed)
str += ' rel="sound=' + attr.unnamed + '"';
str += ">";
if (!(/^(https?:)?\/\//).test(src))
src = g_staticUrl + "/wowsounds" + src;
str += '<source src="' + src + '"';
if (type)
str += ' type="' + type.replace(/"/g, "&quot;") + '"';
str += ">";
if (src2)
{
str += '<source src="' + src2 + '"';
if (type2)
str += ' type="' + type2.replace(/"/g, "&quot;") + '"';
str += ">";
}
str += "</audio>";
if (href)
str = '<div class="audiomarkup">' + str + '<br><a href="' + href + '">' + title + "</a></div>";
return str;
},
fromHtml: function (str)
{
var m = str.match(/<audio [^>]*\brel="sound=(\d+)/);
if (m)
return "[sound=" + m[1] + "]";
return str.replace(/<audio\b[\s\S]*?><source\b[\s\S]*\bsrc="([^"]*?)"[\s\S]*?<\/audio>/gi, '[sound src="$1"]');
}
},
span:
{
empty: false,

View file

@ -115,6 +115,25 @@ $WH.strcmp = function(a, b) {
return a < b ? -1 : 1;
}
$WH.stringCompare = function (a, b) {
if (a == b)
return 0;
if (a == null)
return -1;
if (b == null)
return 1;
var fa = parseFloat(a);
var fb = parseFloat(b);
if (!isNaN(fa) && !isNaN(fb) && fa != fb)
return fa < fb ? -1 : 1;
if (typeof a == 'string' && typeof b == 'string')
return a.localeCompare(b);
return a < b ? -1 : 1;
};
$WH.trim = function(str) {
return str.replace(/(^\s*|\s*$)/g, '');
}
@ -2110,9 +2129,173 @@ $WH.Tooltip = {
}
$WH.Tooltip.iconVisible = icon ? 1 : 0;
},
simple: function(element, text, className, fixed) {
if (fixed)
element.onmouseover = function(x) { $WH.Tooltip.show(element, text, false, false, className) };
else
{
element.onmouseover = function(x) { $WH.Tooltip.showAtCursor(x, text, false, false, className) };
element.onmousemove = $WH.Tooltip.cursorUpdate;
}
element.onmouseout = $WH.Tooltip.hide;
}
};
/* Aowow: totally incompatible with our styles. Only for reference use
$WH.g_createButton = function(text, href, opts) {
var aClass = 'btn btn-site';
var aTarget = '';
var aId = '';
var aStyle = '';
var UNUSED = '';
var classes = [];
var styles = [];
if (!opts)
opts = {};
if (!opts['no-margin'])
styles.push('margin-left:5px');
if (typeof href != 'string' || href === '')
href = 'javascript:;';
if (opts['new-window'])
aTarget = ' target="_blank"';
if (typeof opts.id == 'string')
aId = ' id="' + opts.id + '"';
if (typeof opts.size != 'undefined') {
switch (opts.size) {
case 'small':
case 'large':
classes.push('btn-' + opts.size);
break
}
}
else
classes.push('btn-small');
if (typeof opts['class'] == 'string')
classes.push(opts['class']);
if (typeof opts.type == 'string') {
switch (opts.type) {
case 'default':
case 'gray':
aClass = 'btn';
break;
default:
aClass = 'btn btn-' + opts.type
}
}
if (opts.disabled) {
classes.push('btn-disabled');
href = 'javascript:;';
}
if (classes.length)
aClass += ' ' + classes.join(' ');
if (aClass)
aClass = ' class="' + aClass + '"';
if (!(typeof opts['float'] != 'undefined' && !opts['float']))
styles.push('float:right');
if (typeof opts.style == 'string')
styles.push(opts.style);
if (styles.length)
aStyle = ' style="' + styles.join(';') + '"';
var a = '<a href="' + href + '"' + aTarget + aId + aClass + aStyle + '>' + (text || '') + '</a>';
var div = $WH.ce('div');
div.innerHTML = a;
var btn = div.childNodes[0];
if (typeof opts.click == 'function' && !opts.disabled)
btn.onclick = opts.click;
if (typeof opts.tooltip != 'undefined') {
if (opts.tooltip !== false)
btn.setAttribute('data-whattach', 'true');
if (opts.tooltip === false)
btn.rel = 'np';
else if (typeof opts.tooltip == 'string')
$WH.Tooltip.simple(btn, opts.tooltip, null, true);
else if (typeof opts.tooltip == 'object' && opts.tooltip['text'])
$WH.Tooltip.simple(btn, opts.tooltip['text'], opts.tooltip['class'], true);
}
return btn;
};
*/
$WH.g_createButton = function(text, href, opts)
{
var classes = [];
var styles = [];
var func = null;
if (!opts)
opts = {};
if (!opts['no-margin'])
styles.push('margin-left:5px');
if (typeof href != 'string' || href === '')
href = 'javascript:;';
if (typeof opts['class'] == 'string')
classes.push(opts['class']);
if (opts.disabled)
href = 'javascript:;';
if (typeof opts['float'] != 'undefined' && !opts['float'])
styles.push('float:inherit');
if (typeof opts.style == 'string')
styles.push(opts.style);
if (typeof opts.click == 'function' && !opts.disabled)
func = opts.click;
var btn = RedButton.create(text, !opts.disabled, func);
if (styles.length)
$(btn).attr('style', styles.join(';'));
if (classes.length)
$(btn).addClass(classes.join(' '));
btn.href = href;
if (opts['new-window'])
btn.target = '_blank';
if (typeof opts.id == 'string')
btn.id = opts.id;
if (typeof opts.tooltip != 'undefined') {
if (opts.tooltip === false)
btn.rel = 'np';
else if (typeof opts.tooltip == 'string')
$WH.Tooltip.simple(btn, opts.tooltip, null, true);
else if (typeof opts.tooltip == 'object' && opts.tooltip['text'])
$WH.Tooltip.simple(btn, opts.tooltip['text'], opts.tooltip['class'], true);
}
return btn;
}
/* Aowow: end replacement */
if ($WH.isset('$WowheadPower')) {
$WowheadPower.init();
}

View file

@ -1013,12 +1013,7 @@ function g_addTooltip(element, text, className) {
className = 'q';
}
element.onmouseover = function(d) {
$WH.Tooltip.showAtCursor(d, text, 0, 0, className);
};
element.onmousemove = $WH.Tooltip.cursorUpdate;
element.onmouseout = $WH.Tooltip.hide;
$WH.Tooltip.simple(element, text, className);
}
function g_addStaticTooltip(icon, text, className) {
@ -13960,6 +13955,104 @@ Listview.templates = {
}
},
sound: {
searchable: 1,
filtrable: 1,
columns: [
{
id: 'name',
name: LANG.name,
type: 'text',
align: 'left',
value: 'name',
compute: function (sound, td) {
var a = $WH.ce('a');
a.className = 'listview-cleartext';
a.href = '?sound=' + sound.id;
$WH.st(a, sound.name);
$WH.ae(td, a);
}
},
{
id: 'type',
name: LANG.type,
type: 'text',
compute: function (sound, td) {
var type = '';
if (!this.hasOwnProperty('soundtypecache')) {
var cache = {};
for (var i in mn_sounds)
if (mn_sounds[i][0] < 1000)
cache[mn_sounds[i][0]] = mn_sounds[i][1];
this.soundtypecache = cache;
}
if (this.soundtypecache.hasOwnProperty(sound.type))
type = this.soundtypecache[sound.type];
$WH.st(td, type);
},
sortFunc: function (a, b) {
if (!this.hasOwnProperty('soundtypecache')) {
var cache = {};
for (var i in mn_sounds)
if (mn_sounds[i][0] < 1000)
cache[mn_sounds[i][0]] = mn_sounds[i][1];
this.soundtypecache = cache;
}
var aType = (this.soundtypecache.hasOwnProperty(a.type)) ? this.soundtypecache[a.type] : '';
var bType = (this.soundtypecache.hasOwnProperty(b.type)) ? this.soundtypecache[b.type] : '';
return $WH.strcmp(aType, bType) || $WH.strcmp(a.name, b.name);
}
},
{
id: 'activity',
name: LANG.activity,
hidden: true,
type: 'text',
compute: function (sound, td) {
if (!sound.hasOwnProperty('activity'))
return '';
if (LANG.sound_activities.hasOwnProperty(sound.activity))
return LANG.sound_activities[sound.activity];
else
return sound.activity;
},
sortFunc: function (a, b) {
return $WH.strcmp(this.compute(a), this.compute(b));
}
},
{
id: 'sound',
name: LANG.types[19][2],
span: 2,
compute: function (sound, td, tr) {
var td2 = $WH.ce('td');
td2.className = 'nowrap';
$WH.ae(tr, td2);
td2.style.borderRight = 'none';
td.className = 'nowrap';
td.style.borderLeft = 'none';
var div = $WH.ce('div');
$WH.ae(td2, div);
(new AudioControls()).init(sound.files, div, { listview: this, trackdisplay: td });
}
}
],
getItemLink: function (sound) {
return '?sound=' + sound.id;
}
},
video: {
sort: [],
mode: 3, // Grid mode
@ -20623,7 +20716,13 @@ var Links = new function() {
var link = '';
if (opt.linkColor && opt.linkId && opt.linkName) {
link = g_getIngameLink(opt.linkColor, opt.linkId, opt.linkName);
}
if (opt.sound)
link = '/script PlaySoundFile("' + opt.sound + '", "master")';
// link = '/script PlaySoundKitID(' + opt.sound + ')'; Aowow: not available in 3.3.5
if (link) {
if (Dialog.templates.links.fields[Dialog.templates.links.fields.length - 2].id != 'ingamelink') {
Dialog.templates.links.fields.splice(Dialog.templates.links.fields.length - 1, 0, {
id: 'ingamelink',
@ -20858,6 +20957,342 @@ Announcement.prototype = {
}
};
var g_audiocontrols = {
__windowloaded: false,
};
var g_audioplaylist = {};
if (!window.JSON) {
window.JSON = {
parse: function (sJSON) {
return eval("(" + sJSON + ")");
},
stringify: function (obj) {
if (obj instanceof Object) {
var str = '';
if (obj.constructor === Array) {
for (var i = 0; i < obj.length; str += this.stringify(obj[i]) + ',', i++) {}
return '[' + str.substr(0, str.length - 1) + ']';
}
if (obj.toString !== Object.prototype.toString)
return '"' + obj.toString().replace(/"/g, '\\$&') + '"';
for (var e in obj)
str += '"' + e.replace(/"/g, '\\$&') + '":' + this.stringify(obj[e]) + ',';
return '{' + str.substr(0, str.length - 1) + '}';
}
return typeof obj === 'string' ? '"' + obj.replace(/"/g, '\\$&') + '"' : String(obj);
}
}
}
AudioControls = function () {
var fileIdx = -1;
var canPlay = false;
var looping = false;
var fullPlayer = false;
var autoStart = false;
var controls = {};
var playlist = [];
var url = '';
function updatePlayer(_self, itr, doPlay) {
var elAudio = $WH.ce('audio');
elAudio.preload = 'none';
elAudio.controls = 'true';
$(elAudio).click(function (s) { s.stopPropagation() });
elAudio.style.marginTop = '5px';
controls.audio.parentNode.replaceChild(elAudio, controls.audio);
controls.audio = elAudio;
$WH.aE(controls.audio, 'ended', setNextTrack.bind(_self));
if (doPlay) {
elAudio.preload = 'auto';
autoStart = true;
$WH.aE(controls.audio, 'canplaythrough', autoplay.bind(this));
}
if (!canPlay)
controls.table.style.visibility = 'visible';
var file;
do {
fileIdx += itr;
if (fileIdx > playlist.length - 1) {
fileIdx = 0;
if (!canPlay) {
var div = $WH.ce('div');
// div.className = 'minibox'; Aowow custom
div.className = 'minibox minibox-left';
$WH.st(div, $WH.sprintf(LANG.message_browsernoaudio, file.type));
controls.table.parentNode.replaceChild(div, controls.table);
return
}
}
if (fileIdx < 0)
fileIdx = playlist.length - 1;
file = playlist[fileIdx];
}
while (controls.audio.canPlayType(file.type) == '');
var elSource = $WH.ce('source');
elSource.src = file.url;
elSource.type = file.type;
$WH.ae(controls.audio, elSource);
if (controls.hasOwnProperty('title')) {
if (url) {
$WH.ee(controls.title);
var a = $WH.ce('a');
a.href = url;
$WH.st(a, '"' + file.title + '"');
$WH.ae(controls.title, a);
}
else
$WH.st(controls.title, '"' + file.title + '"');
}
if (controls.hasOwnProperty('trackdisplay'))
$WH.st(controls.trackdisplay, '' + (fileIdx + 1) + ' / ' + playlist.length);
if (!canPlay) {
canPlay = true;
for (var i = fileIdx + 1; i <= playlist.length - 1; i++) {
if (controls.audio.canPlayType(playlist[i].type)) {
$(controls.controlsdiv).children('a').removeClass('button-red-disabled');
break;
}
}
}
if (controls.hasOwnProperty('addbutton')) {
$(controls.addbutton).removeClass('button-red-disabled');
// $WH.st(controls.addbutton, LANG.add); Aowow: doesnt work with RedButtons
RedButton.setText(controls.addbutton, LANG.add);
}
}
function autoplay() {
if (!autoStart)
return;
autoStart = false;
controls.audio.play();
}
this.init = function (files, parent, opt) {
if (!$WH.is_array(files))
return;
if (files.length == 0)
return;
if ((parent.id == '') || g_audiocontrols.hasOwnProperty(parent.id)) {
var i = 0;
while (g_audiocontrols.hasOwnProperty('auto-audiocontrols-' + (++i))) {}
parent.id = 'auto-audiocontrols-' + i;
}
g_audiocontrols[parent.id] = this;
if (typeof opt == 'undefined')
opt = {};
looping = !!opt.loop;
if (opt.hasOwnProperty('url'))
url = opt.url;
playlist = files;
controls.div = parent;
if (!opt.listview) {
var tbl = $WH.ce('table', { className: 'audio-controls' });
controls.table = tbl;
controls.table.style.visibility = 'hidden';
$WH.ae(controls.div, tbl);
var tr = $WH.ce('tr');
$WH.ae(tbl, tr);
var td = $WH.ce('td');
$WH.ae(tr, td);
controls.audio = $WH.ce('div');
$WH.ae(td, controls.audio);
controls.title = $WH.ce('div', { className: 'audio-controls-title' });
$WH.ae(td, controls.title);
controls.controlsdiv = $WH.ce('div', { className: 'audio-controls-pagination' });
$WH.ae(td, controls.controlsdiv);
var prevBtn = createButton(LANG.previous, true);
$WH.ae(controls.controlsdiv, prevBtn);
$WH.aE(prevBtn, 'click', this.btnPrevTrack.bind(this));
controls.trackdisplay = $WH.ce('div', { className: 'audio-controls-pagination-track' });
$WH.ae(controls.controlsdiv, controls.trackdisplay);
var nextBtn = createButton(LANG.next, true);
$WH.ae(controls.controlsdiv, nextBtn);
$WH.aE(nextBtn, 'click', this.btnNextTrack.bind(this))
}
else {
fullPlayer = true;
var div = $WH.ce('div');
controls.table = div;
$WH.ae(controls.div, div);
controls.audio = $WH.ce('div');
$WH.ae(div, controls.audio);
controls.trackdisplay = opt.trackdisplay;
controls.controlsdiv = $WH.ce('span');
$WH.ae(div, controls.controlsdiv);
}
if (g_audioplaylist.isEnabled() && !opt.fromplaylist) {
var addBtn = createButton(LANG.add);
$WH.ae(controls.controlsdiv, addBtn);
$WH.aE(addBtn, 'click', this.btnAddToPlaylist.bind(this, addBtn));
controls.addbutton = addBtn;
if (fullPlayer)
addBtn.style.verticalAlign = '50%';
}
if (g_audiocontrols.__windowloaded)
this.btnNextTrack();
};
function setNextTrack() {
updatePlayer(this, 1, (looping || (fileIdx < (playlist.length - 1))));
}
this.btnNextTrack = function () {
updatePlayer(this, 1, (canPlay && (controls.audio.readyState > 1) && (!controls.audio.paused)));
};
this.btnPrevTrack = function () {
updatePlayer(this, -1, (canPlay && (controls.audio.readyState > 1) && (!controls.audio.paused)));
};
this.btnAddToPlaylist = function (_self) {
if (fullPlayer) {
for (var i = 0; i < playlist.length; i++)
g_audioplaylist.addSound(playlist[i]);
}
else
g_audioplaylist.addSound(playlist[fileIdx]);
_self.className += ' button-red-disabled';
// $WH.st(_self, LANG.added); // Aowow doesn't work with RedButtons
RedButton.setText(_self, LANG.added);
};
this.isPlaying = function () {
return !controls.audio.paused;
};
this.removeSelf = function () {
controls.table.parentNode.removeChild(controls.table);
delete g_audiocontrols[controls.div];
};
function createButton(text, disabled) {
return $WH.g_createButton(text, null, {
disabled: disabled,
'float': false,
style: 'margin:0 12px; display:inline-block'
});
}
};
$WH.aE(window, 'load', function () {
g_audiocontrols.__windowloaded = true;
for (var i in g_audiocontrols)
if (i.substr(0, 2) != '__')
g_audiocontrols[i].btnNextTrack();
});
AudioPlaylist = function () {
var enabled = false;
var playlist = [];
var player, container;
this.init = function () {
if (!$WH.localStorage.isSupported())
return;
enabled = true;
var tracks;
if (tracks = $WH.localStorage.get('AudioPlaylist'))
playlist = JSON.parse(tracks);
};
this.savePlaylist = function () {
if (!enabled)
return false;
$WH.localStorage.set('AudioPlaylist', JSON.stringify(playlist));
};
this.isEnabled = function () {
return enabled;
};
this.addSound = function (track) {
if (!enabled)
return false;
this.init();
playlist.push(track);
this.savePlaylist();
};
this.deleteSound = function (idx) {
if (idx < 0)
playlist = [];
else
playlist.splice(idx, 1);
this.savePlaylist();
if (!player.isPlaying()) {
player.removeSelf();
this.setAudioControls(container);
}
if (playlist.length == 0)
$WH.Tooltip.hide();
};
this.getList = function () {
var buf = [];
for (var i = 0; i < playlist.length; i++)
buf.push(playlist[i].title);
return buf;
};
this.setAudioControls = function (parent) {
if (!enabled)
return false;
container = parent;
player = new AudioControls();
player.init(playlist, container, { loop: true, fromplaylist: true });
};
};
g_audioplaylist = (new AudioPlaylist);
g_audioplaylist.init();
$WH.aE(window, 'load', function () {
if (!(window.JSON && $WH.localStorage.isSupported())) {
return;
@ -21452,6 +21887,7 @@ var
g_races = {},
g_skills = {},
g_gatheredcurrencies = {},
g_sounds = {},
g_enchantments = {},
g_emotes = {};
@ -21472,6 +21908,7 @@ var g_types = {
14: 'race',
15: 'skill',
17: 'currency',
19: 'sound',
501: 'emote',
502: 'enchantment'
};
@ -21683,7 +22120,7 @@ var ConditionList = new function() {
return 'unknown condition index ' + strIdx;
// these cases are not (yet) handled in detail
if ($WH.in_array([11, 13, 21, 24, 33, 34], strIdx) != -1)
if ($WH.in_array([13, 21, 24, 33, 34], strIdx) != -1)
return g_conditions[strIdx].replace(/\$([^\$:;]*):([^\$:;]*);/, '$' + (entry[0] > 0 ? 1 : 2));
switch (Math.abs(entry[0])) {
@ -21753,6 +22190,9 @@ var ConditionList = new function() {
case 35: param[0] = entry[2];
param[1] = g_operators[entry[3]];
break;
case 11: param[0] = entry[1];
param[1] = entry[2];
break;
case 26:
var pIndex = 0;
while (entry[1]) {

View file

@ -780,7 +780,38 @@ var mn_enchantments = [
[6,"DPS","?enchantments&filter=ty=6"],
[4,"Verteidigung","?enchantments&filter=ty=4"]
];
var mn_sounds = [
[1000, "Meine Playlist", "?sound&playlist"],
[, "Arten"],
[19,"Armor","?sounds&filter=ty=19"],
[16,"Death","?sounds&filter=ty=16"],
[25,"Doodads","?sounds&filter=ty=25"],
[52,"Emitters","?sounds&filter=ty=52"],
[29,"Emotes","?sounds&filter=ty=29"],
[12,"Errors","?sounds&filter=ty=12"],
[20,"Footstep Splash","?sounds&filter=ty=20"],
[3,"Footsteps","?sounds&filter=ty=3"],
[24,"Misc Ambience","?sounds&filter=ty=24"],
[10,"NPC Combat","?sounds&filter=ty=10"],
[17,"NPC Greetings","?sounds&filter=ty=17"],
[27,"NPC Loops","?sounds&filter=ty=27"],
[31,"Narration","?sounds&filter=ty=31"],
[30,"Narration Music","?sounds&filter=ty=30"],
[13,"Nature","?sounds&filter=ty=13"],
[14,"Objects","?sounds&filter=ty=14"],
[9,"Pick Up/Put Down","?sounds&filter=ty=9"],
[26,"Spell Fizzle","?sounds&filter=ty=26"],
[1,"Spells","?sounds&filter=ty=1"],
[23,"Tradeskills","?sounds&filter=ty=23"],
[2,"User Interface","?sounds&filter=ty=2"],
[53,"Vehicles","?sounds&filter=ty=53"],
[22,"Water","?sounds&filter=ty=22"],
[21,"Water (Character)","?sounds&filter=ty=21"],
[4,"Weapons Impacts","?sounds&filter=ty=4"],
[6,"Weapons Misses","?sounds&filter=ty=6"],
[50,"Zone Ambience","?sounds&filter=ty=50"],
[28,"Zone Music","?sounds&filter=ty=28"]
];
var mn_talentCalc = [
[6,"Todesritter","?talent#j",,{className:"c6",tinyIcon:"class_deathknight"}],
[11,"Druide","?talent#0",,{className:"c11",tinyIcon:"class_druid"}],
@ -839,6 +870,7 @@ var mn_database = [
[6,"Gebiete","?zones",mn_zones],
[0,"Gegenstände","?items",mn_items],
[12,"Klassen","?classes",mn_classes],
[19,"Klänge","?sounds",mn_sounds],
[4,"NPCs","?npcs",mn_npcs],
[5,"Objekte","?objects",mn_objects],
[3,"Quests","?quests",mn_quests],
@ -2292,7 +2324,7 @@ var g_conditions = {
8: 'Der Spieler hat $1$: nicht; beendet',
9: 'Der Spieler hat $1$: nicht; angenommen',
10: 'Der Spieler ist$: nicht; $1',
11: 'Die Spielwelt hat einen bestimmten Zustand$: nicht;', // nyi
11: 'WorldState #$1 ist$: nicht; $2',
12: '$1 ist$: nicht; aktiv',
13: 'Die Instanz hat einen bestimmten Zustand$: nicht;', // nyi
14: 'Der Spieler hat $nie :;mit $1 interagiert',
@ -2345,6 +2377,7 @@ var LANG = {
amount: "Menge",
abilities: "Fähigkeiten",
activity: "Aktivität",
add: "Hinzufügen",
animation: "Animation",
armor: "Rüstung",
text: "Text",
@ -2366,6 +2399,7 @@ var LANG = {
daily: "Täglich",
weekly: "Wöchentlich",
damage: "Schaden",
'delete': "Löschen",
diet: "Ernährung",
dps: "DPS",
earned: "Errungen",
@ -2627,6 +2661,7 @@ var LANG = {
lvnote_arenateamsfound2: "Insgesamt $1 Arena-Teams, $2 passende",
lvnote_currenciesfound: "$1 Währungen gefunden ($2 angezeigt)",
lvnote_enchantmentsfound: "$1 Verzauberungen gefunden ($2 angezeigt)",
lvnote_soundsfound: "$1 Klänge gefunden ($2 angezeigt)",
lvnote_createafilter: '<small><a href="$1">Filter erstellen</a></small>',
lvnote_filterresults: '<small><a href="$1">Diese Ergebnisse filtern</a></small>',
@ -2722,6 +2757,7 @@ var LANG = {
dialog_mouseovertoload: "Mouseover, um zu laden...",
message_ajaxnotsupported: "Bitte aktualisiert auf einen modernen Browser (zum Beispiel Firefox), welcher 'Ajax'-Anfragen unterstützt.",
message_browsernoaudio: "Entschuldigung, dein Webbrowser kann leider das benötigte Audioformat nicht wiedergeben: $1",
message_cantdeletecomment: "Dieser Kommentar wurde aufgrund seiner negativen Wertung automatisch bereinigt und kann nicht gelöscht werden.",
message_cantdetachcomment: "Dieser Kommentar wurde bereits abgetrennt.",
message_codenotentered: "Ihr habt den Code nicht eingegeben.",
@ -3215,6 +3251,7 @@ var LANG = {
15: ["Fertigkeit", "Fertigkeit", "Fertigkeiten", "Fertigkeiten"],
16: ["Statistik", "Statistik", "Statistiken", "Statistiken"],
17: ["Währung", "Währung", "Währungen", "Währungen"],
19: ["Klang", "Klang", "Klänge", "Klänge"],
501: ["Emote", "Emote", "Emotes", "Emotes"],
502: ["Verzauberung", "Verzauberung", "Verzauberungen", "Verzauberungen"]
},
@ -4378,6 +4415,54 @@ var LANG = {
calculators: "Rechner",
patch: "Patch",
sound_activities: {
greeting: "Begrüßung",
farewell: "Auf Wiedersehen",
angry: "Verärgert",
exertion: "Angriff",
exertioncritical: "Kritischer Treffer",
injury: "Verletzung",
injurycritical: "Kritische Verletzung",
death: "Tod",
stun: "Betäubt",
stand: "Stehen",
footstep: "Schritt",
aggro: "Bedrohung",
wingflap: "Flügelschlagen",
wingglide: "Gleiten",
alert: "Warnung",
fidget: "Herumzappeln",
customattack: "benutzerdefiniert",
loop: "Wiederholen",
jumpstart: "Springen",
jumpend: "Aufkommen",
petattack: "Begleiterangriff",
petorder: "Haustierbefehl",
petdismiss: "Tierfreigabe",
birth: "Erstellt",
spellcast: "Zauber",
submerge: "Abtauchen",
submerged: "Abgetaucht",
transform: "Transformieren",
transformanimated: "Transformieren",
animation: "Animation",
ready: "Bereit",
precast: "Vorgezaubert",
cast: "Zauber",
impact: "Einschlag",
state: "Status",
statedone: "Fertig",
channel: "Kanalisiert",
casterimpact: "Auswirkungen auf den Caster",
targetimpact: "Zielbeeinflussung",
castertargeting: "Dauer der Zauberplatzierung",
missiletargeting: "Geschoss-Zielfindung",
instantarea: "Kurzzeitige Fläche",
persistentarea: "Andauernde Fläche",
casterstate: "Caster-Zustand",
targetstate: "Zielzustand"
},
/* custom */
note_condition: "Jede einzelne, der hier aufgeführte Bedingungen, muss erfüllt sein um die Gesamtbedingung zu erfüllen.",
note_condition_group: "Eine beliebige, der hier aufgeführte Gruppen, muss vollständig erfüllt sein um die Gesamtbedingung zu erfüllen."

View file

@ -826,6 +826,38 @@ var mn_enchantments = [
[6,"DPS","?enchantments&filter=ty=6"],
[4,"Defense","?enchantments&filter=ty=4"]
];
var mn_sounds = [
[1000, "My Playlist", "?sound&playlist"],
[, "Types"],
[19,"Armor","?sounds&filter=ty=19"],
[16,"Death","?sounds&filter=ty=16"],
[25,"Doodads","?sounds&filter=ty=25"],
[52,"Emitters","?sounds&filter=ty=52"],
[29,"Emotes","?sounds&filter=ty=29"],
[12,"Errors","?sounds&filter=ty=12"],
[20,"Footstep Splash","?sounds&filter=ty=20"],
[3,"Footsteps","?sounds&filter=ty=3"],
[24,"Misc Ambience","?sounds&filter=ty=24"],
[10,"NPC Combat","?sounds&filter=ty=10"],
[17,"NPC Greetings","?sounds&filter=ty=17"],
[27,"NPC Loops","?sounds&filter=ty=27"],
[31,"Narration","?sounds&filter=ty=31"],
[30,"Narration Music","?sounds&filter=ty=30"],
[13,"Nature","?sounds&filter=ty=13"],
[14,"Objects","?sounds&filter=ty=14"],
[9,"Pick Up/Put Down","?sounds&filter=ty=9"],
[26,"Spell Fizzle","?sounds&filter=ty=26"],
[1,"Spells","?sounds&filter=ty=1"],
[23,"Tradeskills","?sounds&filter=ty=23"],
[2,"User Interface","?sounds&filter=ty=2"],
[53,"Vehicles","?sounds&filter=ty=53"],
[22,"Water","?sounds&filter=ty=22"],
[21,"Water (Character)","?sounds&filter=ty=21"],
[4,"Weapons Impacts","?sounds&filter=ty=4"],
[6,"Weapons Misses","?sounds&filter=ty=6"],
[50,"Zone Ambience","?sounds&filter=ty=50"],
[28,"Zone Music","?sounds&filter=ty=28"]
];
var mn_talentCalc = [
[6,"Death Knight","?talent#j",,{className:"c6",tinyIcon:"class_deathknight"}],
[11,"Druid","?talent#0",,{className:"c11",tinyIcon:"class_druid"}],
@ -888,6 +920,7 @@ var mn_database = [
[14,"Professions & Skills","?skills",mn_skills],
[3,"Quests","?quests",mn_quests],
[13,"Races","?races",mn_races],
[19,"Sounds","?sounds",mn_sounds],
[1,"Spells","?spells",mn_spells],
[10,"Titles","?titles",mn_titles],
[11,"World Events","?events",mn_holidays],
@ -2338,7 +2371,7 @@ var g_conditions = {
8: 'The Player has$: not; finished $1',
9: 'The Player has$: not; accepted $1',
10: 'The Player is$: not; $1',
11: 'The game word is$: not; in a certain state', // nyi
11: 'WorldState #$1 is$: not; $2',
12: '$1 must$: not; be active',
13: 'The instance $has:does not have; a certain state', // nyi
14: 'The Player has $never:; interacted with $1',
@ -2391,6 +2424,7 @@ var LANG = {
amount: "Amount",
abilities: "Abilities",
activity: "Activity",
add: "Add",
animation: "Animation",
armor: "Armor",
text: "Text",
@ -2412,6 +2446,7 @@ var LANG = {
daily: "Daily",
weekly: "Weekly",
damage: "Damage",
'delete': "Delete",
diet: "Diet",
dps: "DPS",
earned: "Earned",
@ -2674,6 +2709,7 @@ var LANG = {
lvnote_arenateamsfound2: "$1 total arena teams, $2 matching",
lvnote_currenciesfound: "$1 currencies found ($2 displayed)",
lvnote_enchantmentsfound: "$1 enchantments found ($2 displayed)",
lvnote_soundsfound: "$1 sounds found ($2 displayed)",
lvnote_createafilter: '<small><a href="$1">Create a filter</a></small>',
lvnote_filterresults: '<small><a href="$1">Filter these results</a></small>',
@ -2769,6 +2805,7 @@ var LANG = {
dialog_mouseovertoload: "Mouseover to load...",
message_ajaxnotsupported: "Please upgrade to a modern browser (such as Firefox) that supports 'Ajax' requests.",
message_browsernoaudio: "We're sorry, but your web browser cannot play the required audio format: $1",
message_cantdeletecomment: "This comment has been automatically purged due to a negative rating. It cannot be deleted.",
message_cantdetachcomment: "This comment has already been detached.",
message_codenotentered: "You did not enter the code.",
@ -3262,6 +3299,7 @@ var LANG = {
15: ["Skill", "skill", "Skills", "skills"],
16: ["Statistic", "statistic", "Statistics", "statistics"],
17: ["Currency", "currency", "Currencies", "currencies"],
19: ["Sound", "sound", "Sounds", "sounds"],
501: ["Emote", "emote", "Emotes", "emotes"],
502: ["Enchantment", "enchantment", "Enchantments", "enchantments"]
},
@ -4424,6 +4462,54 @@ var LANG = {
calculators: "Calculators",
patch: "Patch",
sound_activities: {
greeting: "Greeting",
farewell: "Farewell",
angry: "Angry",
exertion: "Attack",
exertioncritical: "Critical strike",
injury: "Injury",
injurycritical: "Critical injury",
death: "Death",
stun: "Stunned",
stand: "Stand",
footstep: "Footstep",
aggro: "Aggro",
wingflap: "Wing flap",
wingglide: "Glide",
alert: "Alert",
fidget: "Fidget",
customattack: "Custom",
loop: "Loop",
jumpstart: "Jump",
jumpend: "Jump landing",
petattack: "Pet attack",
petorder: "Pet order",
petdismiss: "Pet dismissal",
birth: "Created",
spellcast: "Spell",
submerge: "Submerge",
submerged: "Submerged",
transform: "Transform",
transformanimated: "Transform",
animation: "Animation",
ready: "Ready",
precast: "Precast",
cast: "Cast",
impact: "Impact",
state: "State",
statedone: "Done",
channel: "Channeled",
casterimpact: "Caster impact",
targetimpact: "Target impact",
castertargeting: "Caster targeting",
missiletargeting: "Missile targeting",
instantarea: "Instant area",
persistentarea: "Persistent area",
casterstate: "Caster state",
targetstate: "Target state"
},
/* custom */
note_condition: "Every one of these conditions must be met to satisfy the requirement.",
note_condition_group: "Any one of these groups must be met in full to satisfy the requirement."

View file

@ -780,6 +780,38 @@ var mn_enchantments = [
[6,"DPS","?enchantments&filter=ty=6"],
[4,"Defensa","?enchantments&filter=ty=4"]
];
var mn_sounds = [
[1000, "Mi Lista de Reproducción", "?sound&playlist"],
[, "Tipos"],
[19,"Armor","?sounds&filter=ty=19"],
[16,"Death","?sounds&filter=ty=16"],
[25,"Doodads","?sounds&filter=ty=25"],
[52,"Emitters","?sounds&filter=ty=52"],
[29,"Emotes","?sounds&filter=ty=29"],
[12,"Errors","?sounds&filter=ty=12"],
[20,"Footstep Splash","?sounds&filter=ty=20"],
[3,"Footsteps","?sounds&filter=ty=3"],
[24,"Misc Ambience","?sounds&filter=ty=24"],
[10,"NPC Combat","?sounds&filter=ty=10"],
[17,"NPC Greetings","?sounds&filter=ty=17"],
[27,"NPC Loops","?sounds&filter=ty=27"],
[31,"Narration","?sounds&filter=ty=31"],
[30,"Narration Music","?sounds&filter=ty=30"],
[13,"Nature","?sounds&filter=ty=13"],
[14,"Objects","?sounds&filter=ty=14"],
[9,"Pick Up/Put Down","?sounds&filter=ty=9"],
[26,"Spell Fizzle","?sounds&filter=ty=26"],
[1,"Spells","?sounds&filter=ty=1"],
[23,"Tradeskills","?sounds&filter=ty=23"],
[2,"User Interface","?sounds&filter=ty=2"],
[53,"Vehicles","?sounds&filter=ty=53"],
[22,"Water","?sounds&filter=ty=22"],
[21,"Water (Character)","?sounds&filter=ty=21"],
[4,"Weapons Impacts","?sounds&filter=ty=4"],
[6,"Weapons Misses","?sounds&filter=ty=6"],
[50,"Zone Ambience","?sounds&filter=ty=50"],
[28,"Zone Music","?sounds&filter=ty=28"]
];
var mn_talentCalc = [
[6,"Caballero de la muerte","?talent#j",,{className:"c6",tinyIcon:"class_deathknight"}],
[11,"Druida","?talent#0",,{className:"c11",tinyIcon:"class_druid"}],
@ -843,6 +875,7 @@ var mn_database = [
[3,"Misiones","?quests",mn_quests],
[13,"Razas","?races",mn_races],
[1,"Hechizos","?spells",mn_spells],
[19,"Sonidos","?sounds",mn_sounds],
[10,"Títulos","?titles",mn_titles],
[11,"Eventos del mundo","?events",mn_holidays],
[6,"Zonas","?zones",mn_zones],
@ -2293,7 +2326,7 @@ var g_conditions = {
8: 'El Jugador tiene$: no; finalizado $1',
9: 'El Jugador tiene$: no; aceptado $1',
10: 'El Jugador es$: no; $1',
11: 'El juego de palabras es$: no; en cierto estado', // nyi
11: 'WorldState #$1 es$: no; $2',
12: '$1 debe$: no; estar activo',
13: 'La instancia $debe:no debe; en cierto estado', // nyi
14: 'El Jugador tiene $nunca:; ha interactuado con $1',
@ -2345,6 +2378,7 @@ var LANG = {
amount: "Cantidad",
abilities: "Habilidades",
activity: "Actividad",
add: "Añadir",
animation: "Animación",
armor: "Armadura",
text: "Texto",
@ -2366,6 +2400,7 @@ var LANG = {
daily: "Diaria",
weekly: "Semanal",
damage: "Daño",
'delete': "Borrar",
diet: "Dieta",
dps: "DPS",
earned: "Logrados",
@ -2627,6 +2662,7 @@ var LANG = {
lvnote_arenateamsfound2: "$1 equipos de arena en total, $2 coincidente(s)",
lvnote_currenciesfound: "$1 monedas encontradas ($2 mostradas)",
lvnote_enchantmentsfound: "$1 encantamientos encontrados (mostrados $2)",
lvnote_soundsfound: "$1 sonidos encontrados ($2 mostrados)",
lvnote_createafilter: '<small><a href="$1">Crea un filtro</a></small>',
lvnote_filterresults: '<small><a href="$1">Filtrar estos resultados</a></small>',
@ -2722,6 +2758,7 @@ var LANG = {
dialog_mouseovertoload: "Pasa el ratón por encima para cargar...",
message_ajaxnotsupported: "Por favor, instale un navegador de internet más moderno (como Firefox) que pueda hacer peticiones 'Ajax'.",
message_browsernoaudio: "Lo sentimos pero tu navegador no puede reproducir el formato de audio requerido: $1",
message_cantdeletecomment: "Este comentario fue automaticamente eliminado debido a que tiene una valoración negativa. No puede ser borrado.",
message_cantdetachcomment: "Este comentario ya fue separado.",
message_codenotentered: "No introdujo el código.",
@ -3215,6 +3252,7 @@ var LANG = {
15: ["Habilidad", "habilidad", "Habilidades", "habilidades"],
16: ["Atributo", "atributo", "Atributos", "atributos"],
17: ["Monedas", "monedas", "Monedas", "monedas"],
19: ["Sonido", "sonido", "Sonidos", "sonidos"],
501: ["Emoción", "emoción", "Emociones", "emociones"],
502: ["Encantamiento", "encantamiento", "Encantamientos", "encantamientos"]
},
@ -4380,6 +4418,54 @@ var LANG = {
calculators: "Calculadoras",
patch: "Parche",
sound_activities: {
greeting: "Saludo",
farewell: "Adios",
angry: "Enojado",
exertion: "Ataque",
exertioncritical: "Golpe crítico",
injury: "Lesión",
injurycritical: "Herida Critica",
death: "Muerte",
stun: "Aturdido",
stand: "Parado",
footstep: "Paso",
aggro: "Aggro",
wingflap: "Aleteo",
wingglide: "Planear",
alert: "Alerta",
fidget: "Estar inquieto",
customattack: "Personalizado",
loop: "Repetir",
jumpstart: "Saltar",
jumpend: "Aterrizaje",
petattack: "Ataque de Mascota",
petorder: "Orden a la Mascota",
petdismiss: "Retiro de la Mascota",
birth: "Creado",
spellcast: "Hechizo",
submerge: "Sumergir",
submerged: "Sumergido",
transform: "Transformar",
transformanimated: "Transformar",
animation: "Animación",
ready: "Listo",
precast: "Antes de conjurar",
cast: "Lanzar",
impact: "Impacto",
state: "Estado",
statedone: "Listo",
channel: "Canalizado",
casterimpact: "Impacto en el taumaturgo",
targetimpact: "Impacto en el Objetivo",
castertargeting: "Objetivo del taumaturgo",
missiletargeting: "Focalización de un Misil",
instantarea: "Área instantánea",
persistentarea: "Área de permanencia",
casterstate: "Estado del taumaturgo",
targetstate: "Estado del Objetivo"
},
note_condition: "Cada una de estas condiciones se deben cumplir para satisfacer el requerimiento",
note_condition_group: "Cualquiera de estos grupos de cumplir en totalidad para satisfacer el requerimiento"
};

View file

@ -780,6 +780,38 @@ var mn_enchantments = [
[6,"DPS","?enchantments&filter=ty=6"],
[4,"Défense","?enchantments&filter=ty=4"]
];
var mn_sounds = [
[1000, "Ma playlist", "?sound&playlist"],
[, "Types"],
[19,"Armor","?sounds&filter=ty=19"],
[16,"Death","?sounds&filter=ty=16"],
[25,"Doodads","?sounds&filter=ty=25"],
[52,"Emitters","?sounds&filter=ty=52"],
[29,"Emotes","?sounds&filter=ty=29"],
[12,"Errors","?sounds&filter=ty=12"],
[20,"Footstep Splash","?sounds&filter=ty=20"],
[3,"Footsteps","?sounds&filter=ty=3"],
[24,"Misc Ambience","?sounds&filter=ty=24"],
[10,"NPC Combat","?sounds&filter=ty=10"],
[17,"NPC Greetings","?sounds&filter=ty=17"],
[27,"NPC Loops","?sounds&filter=ty=27"],
[31,"Narration","?sounds&filter=ty=31"],
[30,"Narration Music","?sounds&filter=ty=30"],
[13,"Nature","?sounds&filter=ty=13"],
[14,"Objects","?sounds&filter=ty=14"],
[9,"Pick Up/Put Down","?sounds&filter=ty=9"],
[26,"Spell Fizzle","?sounds&filter=ty=26"],
[1,"Spells","?sounds&filter=ty=1"],
[23,"Tradeskills","?sounds&filter=ty=23"],
[2,"User Interface","?sounds&filter=ty=2"],
[53,"Vehicles","?sounds&filter=ty=53"],
[22,"Water","?sounds&filter=ty=22"],
[21,"Water (Character)","?sounds&filter=ty=21"],
[4,"Weapons Impacts","?sounds&filter=ty=4"],
[6,"Weapons Misses","?sounds&filter=ty=6"],
[50,"Zone Ambience","?sounds&filter=ty=50"],
[28,"Zone Music","?sounds&filter=ty=28"]
];
var mn_talentCalc = [
[6,"Chevalier de la mort","?talent#j",,{className:"c6",tinyIcon:"class_deathknight"}],
[11,"Druide","?talent#0",,{className:"c11",tinyIcon:"class_druid"}],
@ -842,6 +874,7 @@ var mn_database = [
[14,"Métiers & compétences","?skills",mn_skills],
[3,"Quêtes","?quests",mn_quests],
[13,"Races","?races",mn_races],
[19,"Sons","?sounds", mn_sounds],
[1,"Sorts","?spells",mn_spells],
[10,"Titres","?titles",mn_titles],
[11,"Évènements mondiaux","?events",mn_holidays],
@ -2281,7 +2314,7 @@ var g_conditions = {
8: 'The Player has$: not; finished $1',
9: 'The Player has$: not; accepted $1',
10: 'The Player is$: not; $1',
11: 'The game word is$: not; in a certain state', // nyi
11: 'WorldState #$1 is$: not; $2',
12: '$1 must$: not; be active',
13: 'The instance $has:does not have; a certain state', // nyi
14: 'The Player has $never:; interacted with $1',
@ -2334,6 +2367,7 @@ var LANG = {
amount: "Montant",
abilities: "Techniques",
activity: "Activité",
add: "Ajouter",
animation: "Animation",
armor: "Armure",
text: "Texte",
@ -2355,6 +2389,7 @@ var LANG = {
daily: "Journalière",
weekly: "Chaque semaine",
damage: "Dégâts",
'delete': "Supprimer",
diet: "Alimentation",
dps: "DPS",
earned: "Accomplis",
@ -2617,6 +2652,7 @@ var LANG = {
lvnote_arenateamsfound2: "Total de $1 équipes d'aréna, $2 qui coïncides",
lvnote_currenciesfound: "$1 monnaies trouvées ($2 affichées)",
lvnote_enchantmentsfound: "$1 enchantements trouvés ($2 affichés)",
lvnote_soundsfound: "$1 sons trouvés (2$ affichés)",
lvnote_createafilter: '<small><a href="$1">Créer un filtre</a></small>',
lvnote_filterresults: '<small><a href="$1">Filtrer ces résultats</a></small>',
@ -2712,6 +2748,7 @@ var LANG = {
dialog_mouseovertoload: "Passez votre curseur de souris pour charger...",
message_ajaxnotsupported: "Veuillez utiliser un navigateur plus moderne (tel que Firefox) qui supporte les requêtes 'Ajax'.",
message_browsernoaudio: "Nous sommes désolés, mais votre navigateur ne peut pas lire le format audio obligatoire : $1",
message_cantdeletecomment: "Ce commentaire a été automatiquement effacé à cause d'une note négative. Il ne peut être supprimé.",
message_cantdetachcomment: "Ce commentaire a déjà été détaché.",
message_codenotentered: "Vous n'avez pas écrit le CAPTCHA.",
@ -3205,6 +3242,7 @@ var LANG = {
15: ["Compétence", "compétence", "Compétences", "compétences"],
16: ["Statistique", "statistique", "Statistiques", "statistiques"],
17: ["Monnaies", "monnaie", "Monnaies", "monnaies"],
19: ["Son", "Son", "Sons", "Sons"],
501: ["Emote", "emote", "Emotes", "emotes"],
502: ["Enchantement", "enchantement", "Enchantements", "enchantements"]
},
@ -4369,6 +4407,54 @@ var LANG = {
calculators: "Calculateurs",
patch: "Patch",
sound_activities: {
greeting: "Salutation",
farewell: "Adieu",
angry: "En colère",
exertion: "Attaque",
exertioncritical: "Coup critique",
injury: "Blessure",
injurycritical: "Blessure critique",
death: "Mort",
stun: "Étourdi",
stand: "Debout",
footstep: "Trace de pas",
aggro: "Menace",
wingflap: "Battement d'ailes",
wingglide: "Planer",
alert: "Alerte",
fidget: "Gigoter",
customattack: "Personnalisé",
loop: "Répéter",
jumpstart: "Sauter",
jumpend: "Atterissage",
petattack: "Attaque de Mascotte",
petorder: "Ordre au familier",
petdismiss: "Renvoi de Mascotte",
birth: "Créé",
spellcast: "Sort",
submerge: "Submerger",
submerged: "Submergé",
transform: "Transformer",
transformanimated: "Transformer",
animation: "Animation",
ready: "Prêt",
precast: "Préincantation",
cast: "Lancer",
impact: "Impact",
state: "État",
statedone: "Terminé",
channel: "Canalisée",
casterimpact: "Impact sur le lanceur",
targetimpact: "Impact sur la cible",
castertargeting: "Choix de la cible par le lanceur",
missiletargeting: "Missile en cours de ciblage",
instantarea: "Zone instantanée",
persistentarea: "Zone persistante",
casterstate: "État du lanceur",
targetstate: "État de la cible"
},
/* custom */
note_condition: "Every one of these conditions must be met to satisfy the requirement.",
note_condition_group: "Any one of these groups must be met in full to satisfy the requirement."

View file

@ -780,6 +780,38 @@ var mn_enchantments = [
[6,"УВС","?enchantments&filter=ty=6"],
[4,"Защита","?enchantments&filter=ty=4"]
];
var mn_sounds = [
[1000, "Мой плейлист", "?sound&playlist"],
[, "Типы"],
[19,"Armor","?sounds&filter=ty=19"],
[16,"Death","?sounds&filter=ty=16"],
[25,"Doodads","?sounds&filter=ty=25"],
[52,"Emitters","?sounds&filter=ty=52"],
[29,"Emotes","?sounds&filter=ty=29"],
[12,"Errors","?sounds&filter=ty=12"],
[20,"Footstep Splash","?sounds&filter=ty=20"],
[3,"Footsteps","?sounds&filter=ty=3"],
[24,"Misc Ambience","?sounds&filter=ty=24"],
[10,"NPC Combat","?sounds&filter=ty=10"],
[17,"NPC Greetings","?sounds&filter=ty=17"],
[27,"NPC Loops","?sounds&filter=ty=27"],
[31,"Narration","?sounds&filter=ty=31"],
[30,"Narration Music","?sounds&filter=ty=30"],
[13,"Nature","?sounds&filter=ty=13"],
[14,"Objects","?sounds&filter=ty=14"],
[9,"Pick Up/Put Down","?sounds&filter=ty=9"],
[26,"Spell Fizzle","?sounds&filter=ty=26"],
[1,"Spells","?sounds&filter=ty=1"],
[23,"Tradeskills","?sounds&filter=ty=23"],
[2,"User Interface","?sounds&filter=ty=2"],
[53,"Vehicles","?sounds&filter=ty=53"],
[22,"Water","?sounds&filter=ty=22"],
[21,"Water (Character)","?sounds&filter=ty=21"],
[4,"Weapons Impacts","?sounds&filter=ty=4"],
[6,"Weapons Misses","?sounds&filter=ty=6"],
[50,"Zone Ambience","?sounds&filter=ty=50"],
[28,"Zone Music","?sounds&filter=ty=28"]
];
var mn_talentCalc = [
[6,"Рыцарь смерти","?talent#j",,{className:"c6",tinyIcon:"class_deathknight"}],
[11,"Друид","?talent#0",,{className:"c11",tinyIcon:"class_druid"}],
@ -846,6 +878,7 @@ var mn_database = [
[10,"Звания","?titles",mn_titles],
[11,"Игровые события","?events",mn_holidays],
[6,"Местности","?zones",mn_zones],
[19,"Звуки","?sounds",mn_sounds],
[100,"Эмоции","?emotes",null],
[101,"Улучшения","?enchantments",mn_enchantments]
];
@ -2281,7 +2314,7 @@ var g_conditions = {
8: 'The Player has$: not; finished $1',
9: 'The Player has$: not; accepted $1',
10: 'The Player is$: not; $1',
11: 'The game word is$: not; in a certain state', // nyi
11: 'WorldState #$1 is$: not; $2',
12: '$1 must$: not; be active',
13: 'The instance $has:does not have; a certain state', // nyi
14: 'The Player has $never:; interacted with $1',
@ -2334,6 +2367,7 @@ var LANG = {
amount: "Количество",
abilities: "Способности",
activity: "Активность",
add: "Добавить",
animation: "Анимация",
armor: "Броня",
text: "Текст",
@ -2355,6 +2389,7 @@ var LANG = {
daily: "Ежедневно",
weekly: "Раз в неделю",
damage: "Урон",
'delete': "Удалить",
diet: "Рацион",
dps: "УВС",
earned: "Заработано",
@ -2617,6 +2652,7 @@ var LANG = {
lvnote_arenateamsfound2: "Команд арены: $1, подходящих: $2",
lvnote_currenciesfound: "Найдено валюты: $1 (показано: $2)",
lvnote_enchantmentsfound: "Найдено улучшения: $1 (показано: $2)",
lvnote_soundsfound: "$1 звуков найдено ($2 отображено)",
lvnote_createafilter: '<small><a href="$1">Применить фильтр</a></small>',
lvnote_filterresults: '<small><a href="$1">Отфильтровать результаты</a></small>',
@ -2712,6 +2748,7 @@ var LANG = {
dialog_mouseovertoload: "Наведите мышкой для загрузки...",
message_ajaxnotsupported: "Обновите ваш браузер на версию с поддержкой технологии 'Ajax'.",
message_browsernoaudio: "К сожалению, ваш браузер не может проигрывать этот аудио формат: $1",
message_cantdeletecomment: "Этот комментарий был автоматически удален из-за негативного рейтинга.",
message_cantdetachcomment: "Этот коментарий уже откреплен.",
message_codenotentered: "Вы не ввели CAPTCHA код.",
@ -3205,6 +3242,7 @@ var LANG = {
15: ["Уровень навыка", "навык", "Умения", "навыки"],
16: ["Статистика", "характеристика", "Характеристики", "характеристики"],
17: ["Валюта", "валюта", "Валюта", "валюта"],
19: ["Звук", "звук", "Звуки", "звуки"],
501: ["Эмоция", "эмоция", "Эмоции", "эмоции"],
502: ["Улучшение", "улучшение", "Улучшения", "улучшения"]
},
@ -4370,6 +4408,54 @@ var LANG = {
calculators: "Калькуляторы",
patch: "Обновление",
sound_activities: {
greeting: "Привет",
farewell: "Пока",
angry: "Злой",
exertion: "Атака",
exertioncritical: "Критический удар",
injury: "Ранение",
injurycritical: "Критическое ранение",
death: "Смерть",
stun: "Оглушен",
stand: "Стоять",
footstep: "След",
aggro: "Аггро",
wingflap: "Взмах крыльями",
wingglide: "Парить",
alert: "Предупреждение",
fidget: "[Fidget]",
customattack: "Свой",
loop: "Повторять",
jumpstart: "Прыгать",
jumpend: "Приземление",
petattack: "Атака питомца",
petorder: "Порядок питомцев",
petdismiss: "[Pet dismissal]",
birth: "Создано",
spellcast: "Заклинание",
submerge: "Погружаться",
submerged: "Погружённый",
transform: "Превратить",
transformanimated: "Превратить",
animation: "Анимация",
ready: "Готово",
precast: "Подготовка заклинания",
cast: "Применить",
impact: "Эффект",
state: "Состояние",
statedone: "Готово",
channel: "Направляемое",
casterimpact: "[Caster impact]",
targetimpact: "Влияние на цель",
castertargeting: "[Caster targeting]",
missiletargeting: "[Missile targeting]",
instantarea: "Зона мгновенного действия",
persistentarea: "Зона временного действия",
casterstate: "[Caster state]",
targetstate: "Состояние цели"
},
/* custom */
note_condition: "Every one of these conditions must be met to satisfy the requirement.",
note_condition_group: "Any one of these groups must be met in full to satisfy the requirement."

View file

@ -3,7 +3,7 @@ if (isset($this->map) && empty($this->map)):
echo Lang::zone('noMap');
elseif (!empty($this->map['data'])):
if ($this->type != TYPE_ZONE):
echo ' <div>'.($this->type == TYPE_OBJECT ? Lang::gameObject('foundIn') : Lang::npc('foundIn')).' <span id="locations">';
echo ' <div>'.($this->type == TYPE_OBJECT ? Lang::gameObject('foundIn') : ($this->type == TYPE_SOUND ? Lang::sound('foundIn') : Lang::npc('foundIn'))).' <span id="locations">';
$n = count($this->map['mapperData']);
$i = 0;

View file

@ -8,6 +8,11 @@ if (isset($this->redButtons[BUTTON_WOWHEAD])):
endif;
endif;
// go to my playlist
if (isset($this->redButtons[BUTTON_PLAYLIST])):
echo '<a href="?sound&playlist" class="button-red"><em><b><i>'.Lang::sound('goToPlaylist').'</i></b><span>'.Lang::sound('goToPlaylist').'</span></em></a>';
endif;
// ingame-links/markdown/ect
if (isset($this->redButtons[BUTTON_LINKS])):
if ($b = $this->redButtons[BUTTON_LINKS]):

View file

@ -0,0 +1,145 @@
<?php $this->brick('header'); ?>
<div class="main" id="main">
<div class="main-precontents" id="main-precontents"></div>
<div class="main-contents" id="main-contents">
<?php
$this->brick('announcement');
$this->brick('pageTemplate');
?>
<div class="text">
<?php
$this->brick('redButtons');
?>
<h1><?=$this->name; ?></h1>
<?php
$this->brick('article');
if ($this->special):
?>
<div id="playlistcontrols" style="margin: 20px"></div><div id="playlisttracks"></div>
<script type="text/javascript">//<![CDATA[
g_audioplaylist.setAudioControls($WH.ge('playlistcontrols'));
(function(){
var delline = function()
{
var li = this.parentNode;
var siblings = li.parentNode.childNodes;
for (var id = 0; id < siblings.length; id++)
if (siblings[id] === li)
break;
g_audioplaylist.deleteSound(id);
li.parentNode.removeChild(li);
}
var l = g_audioplaylist.getList();
var ol = $WH.ce('ol');
var s, li;
for (var x in l)
{
li = $WH.ce('li');
s = $WH.ce('span');
s.className = 'icon-delete';
s.style.cursor = 'pointer';
$WH.Tooltip.simple(s, LANG.delete, 'q2');
$WH.aE(s, 'click', delline);
$WH.ae(li, s);
s = $WH.ce('span');
$WH.st(s, l[x]);
$WH.ae(li, s);
$WH.ae(ol, li);
}
$WH.ae($WH.ge('playlisttracks'),ol);
})();
//]]></script></div>
<div class="clear"></div>
<?php
else:
if (!empty($this->map)):
$this->brick('mapper');
endif;
?>
<ol id="soundfilelist"></ol>
<div id="mainsound"></div>
<script type="text/javascript">//<![CDATA[
var soundpaths = g_sounds[<?=$this->typeId; ?>].files;
soundpaths.sort(function(a, b) { return $WH.stringCompare(a.title, b.title) || $WH.stringCompare(a.id, b.id); });
var sounddialog = new Dialog();
Dialog.templates.sound = {
title: LANG.types[19][0],
buttons: [['cancel', LANG.close]],
fields:
[
{
id: 'ingamelink',
type: 'text',
label: 'Ingame Link',
size: 40
}
],
onInit: function(form)
{
},
onShow: function(form) {
setTimeout(function() { $WH.safeSelect(form.ingamelink); }, 50);
setTimeout(Lightbox.reveal, 100);
}
};
function showSoundLink(idx)
{
var data = { 'ingamelink': '/script PlaySoundKitID(<?=$this->typeId; ?>)' };
sounddialog.show('sound', { data: data, onSubmit: function() { return false; } });
}
(new AudioControls()).init(soundpaths,$WH.ge('mainsound'));
(function(){
var ol = $WH.ge('soundfilelist');
for (var x = 0; x < soundpaths.length; x++)
{
var li = $WH.ce('li');
var a = $WH.ce('a');
a.href = 'javascript:;';
$WH.aE(a, 'click', (function(xy){return function(){showSoundLink(xy);}})(x));
$WH.st(a, soundpaths[x].title);
$WH.ae(li, a);
$WH.ae(ol, li);
}
})();
//]]></script>
<h2 class="clear"><?php echo Lang::main('related'); ?></h2>
</div>
<?php
$this->brick('lvTabs', ['relTabs' => true]);
$this->brick('contribute');
endif;
?>
<div class="clear"></div>
</div><!-- main-contents -->
</div><!-- main -->
<?php $this->brick('footer'); ?>

View file

@ -0,0 +1,60 @@
<?php
$this->brick('header');
$f = $this->filter; // shorthand
?>
<div class="main" id="main">
<div class="main-precontents" id="main-precontents"></div>
<div class="main-contents" id="main-contents">
<?php
$this->brick('announcement');
$this->brick('pageTemplate', ['fi' => empty($f['query']) ? null : ['query' => $f['query'], 'menuItem' => 101]]);
?>
<div class="text"><h1><?=$this->name; ?>&nbsp;<?=$this->brick('redButtons'); ?></h1></div>
<div id="fi" style="display: <?php echo empty($f['query']) ? 'none' : 'block' ?>;">
<form action="?sounds&filter" method="post" name="fi" onsubmit="return fi_submit(this)" onreset="return fi_reset(this)">
<div class="rightpanel">
<div style="float: left"><?php echo Util::ucFirst(Lang::game('type')).Lang::main('colon'); ?></div>
<small><a href="javascript:;" onclick="document.forms['fi'].elements['ty[]'].selectedIndex = -1; return false" onmousedown="return false"><?php echo Lang::main('clear'); ?></a></small>
<div class="clear"></div>
<select name="ty[]" size="6" multiple="multiple" class="rightselect">
<?php
foreach (Lang::sound('cat') as $i => $str):
if ($str && $i < 1000):
echo ' <option value="'.$i.'"'.(isset($f['ty']) && in_array($i, (array)$f['ty']) ? ' selected' : null).' >'.$str."</option>\n";
endif;
endforeach;
?>
</select>
</div>
<table>
<tr>
<td><?php echo Util::ucFirst(Lang::main('name')).Lang::main('colon'); ?></td>
<td colspan="2">
<table><tr>
<td>&nbsp;<input type="text" name="na" size="30" <?php echo isset($f['na']) ? 'value="'.Util::htmlEscape($f['na']).'" ' : null; ?>/></td>
</tr></table>
</td>
</tr><tr>
</table>
<div class="clear"></div>
<div class="padded">
<input type="submit" value="<?php echo Lang::main('applyFilter'); ?>" />
<input type="reset" value="<?php echo Lang::main('resetForm'); ?>" />
</div>
</form>
</div>
<div class="pad clear"></div>
<?php $this->brick('lvTabs'); ?>
<div class="clear"></div>
</div><!-- main-contents -->
</div><!-- main -->
<?php $this->brick('footer'); ?>

View file

@ -172,30 +172,51 @@ foreach ($this->effects as $i => $e):
<th><?=Lang::spell('_effect').' #'.($i + 1);?></th>
<td colspan="3" style="line-height: 17px">
<?php
echo ' '.$e['name'].'<small>' .
(isset($e['value']) ? '<br>'.Lang::spell('_value') .Lang::main('colon').$e['value'] : null) .
(isset($e['radius']) ? '<br>'.Lang::spell('_radius') .Lang::main('colon').$e['radius'].' '.Lang::spell('_distUnit') : null) .
(isset($e['interval']) ? '<br>'.Lang::spell('_interval').Lang::main('colon').$e['interval'] : null) .
(isset($e['mechanic']) ? '<br>'.Lang::game('mechanic') .Lang::main('colon').$e['mechanic'] : null);
echo ' '.$e['name'];
$smallBuf = '';
if (isset($e['value'])):
$smallBuf .= '<br>'.Lang::spell('_value').Lang::main('colon').$e['value'];
endif;
if (isset($e['radius'])):
$smallBuf .= '<br>'.Lang::spell('_radius').Lang::main('colon').$e['radius'].' '.Lang::spell('_distUnit');
endif;
if (isset($e['interval'])):
$smallBuf .= '<br>'.Lang::spell('_interval').Lang::main('colon').$e['interval'];
endif;
if (isset($e['mechanic'])):
$smallBuf .= '<br>'.Lang::game('mechanic') .Lang::main('colon').$e['mechanic'];
endif;
if (isset($e['procData'])):
echo '<br>';
$smallBuf .= '<br>';
if ($e['procData'][0] < 0):
echo sprintf(Lang::spell('ppm'), Lang::nf(-$e['procData'][0], 1));
$smallBuf .= sprintf(Lang::spell('ppm'), Lang::nf(-$e['procData'][0], 1));
elseif ($e['procData'][0] < 100.0):
echo Lang::spell('procChance').Lang::main('colon').$e['procData'][0].'%';
$smallBuf .= Lang::spell('procChance').Lang::main('colon').$e['procData'][0].'%';
endif;
if ($e['procData'][1]):
if ($e['procData'][0] < 100.0):
echo '<br>';
$smallBuf .= '<br>';
endif;
echo sprintf(Lang::game('cooldown'), $e['procData'][1]);
$smallBuf .= sprintf(Lang::game('cooldown'), $e['procData'][1]);
endif;
endif;
echo "</small>\n";
if ($smallBuf):
echo "<small>".$smallBuf."</small>\n";
endif;
if (isset($e['sound'])):
echo '<br/><div id="spelleffectsound-'.$i.'" style="display: inline-block"></div><script type="text/javascript">//<![CDATA[
$WH.aE(window,\'load\',function(){$WH.ge(\'spelleffectsound-'.$i.'\').innerHTML = Markup.toHtml(\'[sound='.$e['sound'].']\');});
//]]></script>';
endif;
if (isset($e['icon'])):
?>