* have creature emotes in the same system (on a negeative index) as SAI links were uselessly pointing to player emotes before
 * player emotes are now gendered
 * display two more cases of who points at whom when using a player emote
 * use and link event sound from emote
 * display more misc info
This commit is contained in:
Sarjuuk
2023-08-13 05:10:30 +02:00
parent 0f186576d3
commit 4d6fb4975e
20 changed files with 495 additions and 106 deletions

View File

@@ -652,7 +652,7 @@ trait spawnHelper
}
// guid < 0 are vehicle accessories. those are moved by moving the vehicle
if (User::isInGroup(U_GROUP_MODERATOR) && $worldPos && $s['guid'] > 0)
if (User::isInGroup(U_GROUP_MODERATOR) && $worldPos && $s['guid'] > 0 && isset($worldPos[$s['guid']]))
{
if ($points = Game::worldPosToZonePos($worldPos[$s['guid']]['mapId'], $worldPos[$s['guid']]['posX'], $worldPos[$s['guid']]['posY']))
{

View File

@@ -303,6 +303,8 @@ define('NPC_CU_DIFFICULTY_DUMMY', 0x02);
define('ITEM_CU_OT_ITEMLOOT', 0x01); // there are no sourceTypes for these two cases
define('ITEM_CU_OT_OBJECTLOOT', 0x02);
define('EMOTE_CU_MISSING_CMD', 0x01); // no alias in Globalstrings.lua and thus unusable
// as seen in wFlags
define('QUEST_CU_REPEATABLE', 0x01);
define('QUEST_CU_DAILY', 0x02);
@@ -1734,4 +1736,20 @@ define('MAP_TYPE_ARENA', 6);
define('MAP_TYPE_MMODE_RAID', 7);
define('MAP_TYPE_MMODE_RAID_HC', 8);
define('EMOTE_FLAG_ONLY_STANDING', 0x0001); // Only while standig
define('EMOTE_FLAG_USE_MOUNT', 0x0002); // Emote applies to mount
define('EMOTE_FLAG_NOT_CHANNELING', 0x0004); // Not while channeling
define('EMOTE_FLAG_ANIM_TALK', 0x0008); // Talk anim - talk
define('EMOTE_FLAG_ANIM_QUESTION', 0x0010); // Talk anim - question
define('EMOTE_FLAG_ANIM_EXCLAIM', 0x0020); // Talk anim - exclamation
define('EMOTE_FLAG_ANIM_SHOUT', 0x0040); // Talk anim - shout
define('EMOTE_FLAG_NOT_SWIMMING', 0x0080); // Not while swimming
define('EMOTE_FLAG_ANIM_LAUGH', 0x0100); // Talk anim - laugh
define('EMOTE_FLAG_CAN_LIE_ON_GROUND', 0x0200); // Ok while sleeping or dead
define('EMOTE_FLAG_NOT_FROM_CLIENT', 0x0400); // Disallow from client
define('EMOTE_FLAG_NOT_CASTING', 0x0800); // Not while casting
define('EMOTE_FLAG_END_MOVEMENT', 0x1000); // Movement ends
define('EMOTE_FLAG_INTERRUPT_ON_ATTACK', 0x2000); // Interrupt on attack
define('EMOTE_FLAG_ONLY_STILL', 0x4000); // Only while still
define('EMOTE_FLAG_NOT_FLYING', 0x8000); // Not while flying
?>

View File

@@ -339,9 +339,12 @@ class Game
$result = DB::AoWoW()->select('SELECT `id` AS ARRAY_KEY, `id`, `mapId`, `posX`, `posY` FROM dbc_areatrigger WHERE `id` IN (?a)', $guids);
break;
default:
trigger_error('Game::getWorldPosForGUID - instanced with unsupported TYPE '.$type, E_USER_WARNING);
trigger_error('Game::getWorldPosForGUID - instanced with unsupported TYPE #'.$type, E_USER_WARNING);
}
if ($diff = array_diff($guids, array_keys($result)))
trigger_error('Game::getWorldPosForGUID - no spawn points for TYPE #'.$type.' GUIDS: '.implode(', ', $diff), E_USER_WARNING);
return $result;
}

View File

@@ -905,7 +905,7 @@ class SmartAI
if ($time = $this->numRange('event', 1, true))
$footer = $time;
break;
case SAI_EVENT_RECEIVE_EMOTE: // 22 - On Receive Emote.
case SAI_EVENT_RECEIVE_EMOTE: // 22 - On Receive Player Emote.
$this->jsGlobals[Type::EMOTE][] = $e['param'][0];
if ($time = $this->numRange('event', 1, true))
@@ -1044,7 +1044,10 @@ class SmartAI
case SAI_ACTION_PLAY_EMOTE: // 5 -> any target
case SAI_ACTION_SET_EMOTE_STATE: // 17 -> any target
if ($a['param'][0])
{
$a['param'][0] *= -1; // handle creature emote
$this->jsGlobals[Type::EMOTE][] = $a['param'][0];
}
break;
case SAI_ACTION_FAIL_QUEST: // 6 -> any target
case SAI_ACTION_OFFER_QUEST: // 7 -> invoker
@@ -1152,6 +1155,7 @@ class SmartAI
if (empty($a['param'][$i]))
continue;
$a['param'][$i] *= -1; // handle creature emote
$buff[] = '[emote='.$a['param'][$i].']';
$this->jsGlobals[Type::EMOTE][] = $a['param'][$i];
}

View File

@@ -33,7 +33,7 @@ class EmoteList extends BaseType
$data[$this->id] = array(
'id' => $this->curTpl['id'],
'name' => $this->curTpl['cmd'],
'preview' => $this->getField('self', true) ?: ($this->getField('noTarget', true) ?: $this->getField('target', true))
'preview' => Util::parseHtmlText($this->getField('meToExt', true) ?: $this->getField('meToNone', true) ?: $this->getField('extToMe', true) ?: $this->getField('extToExt', true) ?: $this->getField('extToNone', true), true)
);
// [nyi] sounds

View File

@@ -750,9 +750,9 @@ abstract class Util
$from = array(
'/\|T([\w]+\\\)*([^\.]+)\.blp:\d+\|t/ui', // images (force size to tiny) |T<fullPath>:<size>|t
'/\|c(\w{6})\w{2}([^\|]+)\|r/ui', // color |c<RRGGBBAA><text>|r
'/\$g\s*([^:;]+)\s*:\s*([^:;]+)\s*(:?[^:;]*);/ui',// directed gender-reference $g:<male>:<female>:<refVariable>
'/\$g\s*([^:;]*)\s*:\s*([^:;]*)\s*(:?[^:;]*);/ui',// directed gender-reference $g<male>:<female>:<refVariable>
'/\$t([^;]+);/ui', // nonsense, that the client apparently ignores
'/\|\d\-?\d?\((\$\w)\)/ui', // and another modifier for something russian |3-6($r)
'/\|\d\-?\d?\(([\$\%]\w)\)/ui', // and another modifier for something russian |3-6($r)
'/<([^\"=\/>]+\s[^\"=\/>]+)>/ui', // emotes (workaround: at least one whitespace and never " or = between brackets)
'/\$(\d+)w/ui', // worldState(?)-ref found on some pageTexts $1234w
'/\$c/i', // class-ref

View File

@@ -627,7 +627,7 @@ $lang = array(
SAI_ACTION_SET_FACTION => ['Setze Fraktion von #target# (%1$d)?auf [faction=%7$d]:zurück;.', null],
SAI_ACTION_MORPH_TO_ENTRY_OR_MODEL => ['(%7$d)?Setze Aussehen zurück.:Nimm folgendes Erscheinungsbild an:;(%1$d)? [npc=%1$d]:;(%2$d)?[model npc=%2$d border=1 float=right][/model]:;', null],
SAI_ACTION_SOUND => ['Spiele Audio(%2$d)? für auslösenden Spieler:;:[div float=right width=270px][sound=%1$d][/div]', 'Abgespielt durch Welt.'],
SAI_ACTION_PLAY_EMOTE => ['Emote [emote=%1$d] zu #target#.', null],
SAI_ACTION_PLAY_EMOTE => ['(%1$d)?Emote [emote=%1$d] zu #target#.:Beende Emote;', null],
SAI_ACTION_FAIL_QUEST => ['[quest=%1$d] von #target# schlägt fehl.', null],
SAI_ACTION_OFFER_QUEST => ['(%2$d)?Füge [quest=%1$d] dem Log von #target# hinzu:Biete [quest=%1$d] #target# an;.', null],
SAI_ACTION_SET_REACT_STATE => ['#target# wird %7$s.', null],
@@ -638,7 +638,7 @@ $lang = array(
SAI_ACTION_THREAT_SINGLE_PCT => ['Ändere Bedrohung von #target# um %7$d%%.', null],
SAI_ACTION_THREAT_ALL_PCT => ['Ändere Bedrohung aller Ziele um %7$d%%.', null],
SAI_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS => ['Erfülle Entdeckungsereignis von [quest=%1$d] für #target#.', null],
SAI_ACTION_SET_EMOTE_STATE => ['Emote [emote=%1$d] kontinuierlich zu #target#.', null],
SAI_ACTION_SET_EMOTE_STATE => ['(%1$d)?Emote [emote=%1$d] kontinuierlich zu #target#:Beende Emote.;', null],
SAI_ACTION_SET_UNIT_FLAG => ['Setze (%2$d)?UnitFlags2:UnitFlags; %7$s.', null],
SAI_ACTION_REMOVE_UNIT_FLAG => ['Setze (%2$d)?UnitFlags2:UnitFlags; %7$s zurück.', null],
/* 20*/ SAI_ACTION_AUTO_ATTACK => ['(%1$d)?Beginne:Beende; automatische Angriffe gegen #target#.', null],
@@ -919,12 +919,35 @@ $lang = array(
),
'emote' => array(
'notFound' => "Dieses Emote existiert nicht.",
'self' => "An Euch selbst",
'target' => "An Andere mit Ziel",
'noTarget' => "An Andere ohne Ziel",
// 'self' => "An Euch selbst",
// 'target' => "An Andere mit Ziel",
// 'noTarget' => "An Andere ohne Ziel",
'targeted' => "Benutzt mit Ziel",
'untargeted' => "Benutzt ohne Ziel",
'isAnimated' => "Besitzt eine Animation",
'eventSound' => "Ereignis-Klang",
'aliases' => "Aliasse",
'noText' => "Dieses Emote besitzt keinen Text.",
'noCommand' => "Dieses Emote besitzt keinen /-Befehl. Es kann nicht benutzt werden.",
'flags' => array(
EMOTE_FLAG_ONLY_STANDING => "Nur im stehen",
EMOTE_FLAG_USE_MOUNT => "Emote benutzt das Reittier",
EMOTE_FLAG_NOT_CHANNELING => "Nicht beim kanalisieren",
EMOTE_FLAG_ANIM_TALK => "Talk anim - Reden",
EMOTE_FLAG_ANIM_QUESTION => "Talk anim - Fragen",
EMOTE_FLAG_ANIM_EXCLAIM => "Talk anim - Ausrufen",
EMOTE_FLAG_ANIM_SHOUT => "Talk anim - Schreien",
EMOTE_FLAG_NOT_SWIMMING => "Nicht beim schwimmen",
EMOTE_FLAG_ANIM_LAUGH => "Talk anim - Lachen",
EMOTE_FLAG_CAN_LIE_ON_GROUND => "Nutzbar im Schlaf/Tot",
EMOTE_FLAG_NOT_FROM_CLIENT => "Nur für Kreaturen",
EMOTE_FLAG_NOT_CASTING => "Nicht beim Zaubern",
EMOTE_FLAG_END_MOVEMENT => "Emote endet Bewegung",
EMOTE_FLAG_INTERRUPT_ON_ATTACK => "Unerbrochen durch Kampf",
EMOTE_FLAG_ONLY_STILL => "Nur in Ruhe",
EMOTE_FLAG_NOT_FLYING => "Nicht im Flug"
),
'state' => ['Einmalig', 'Stetiger Zustand', 'Stetiges Emote']
),
'enchantment' => array(
'details' => "Details",

View File

@@ -627,7 +627,7 @@ $lang = array(
SAI_ACTION_SET_FACTION => ['(%1$d)?Set faction of #target# to [faction=%7$d]:Reset faction of #target#;.', null],
SAI_ACTION_MORPH_TO_ENTRY_OR_MODEL => ['(%7$d)?Reset apperance.:Take the appearance of;(%1$d)? [npc=%1$d].:;(%2$d)?[model npc=%2$d border=1 float=right][/model]:;', null],
SAI_ACTION_SOUND => ['Play sound(%2$d)? to invoking player:;:[div float=right width=270px][sound=%1$d][/div]', 'Played by environment.'],
SAI_ACTION_PLAY_EMOTE => ['Emote [emote=%1$d] to #target#.', null],
SAI_ACTION_PLAY_EMOTE => ['(%1$d)?Emote [emote=%1$d] to #target#.: End Emote.;', null],
SAI_ACTION_FAIL_QUEST => ['Fail [quest=%1$d] for #target#.', null],
SAI_ACTION_OFFER_QUEST => ['(%2$d)?Add [quest=%1$d] to #target#\'s log:Offer [quest=%1$d] to #target#;.', null],
SAI_ACTION_SET_REACT_STATE => ['#target# becomes %7$s.', null],
@@ -638,7 +638,7 @@ $lang = array(
SAI_ACTION_THREAT_SINGLE_PCT => ['Modify #target#\'s threat by %7$d%%.', null],
SAI_ACTION_THREAT_ALL_PCT => ['Modify the threat of all targets by %7$d%%.', null],
SAI_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS => ['Exploration event of [quest=%1$d] is completed for #target#.', null],
SAI_ACTION_SET_EMOTE_STATE => ['Continuously emote [emote=%1$d] to #target#.', null],
SAI_ACTION_SET_EMOTE_STATE => ['(%1$d)?Continuously emote [emote=%1$d] to #target#.:End emote state;', null],
SAI_ACTION_SET_UNIT_FLAG => ['Set (%2$d)?UnitFlags2:UnitFlags; %7$s.', null],
SAI_ACTION_REMOVE_UNIT_FLAG => ['Unset (%2$d)?UnitFlags2:UnitFlags; %7$s.', null],
/* 20*/ SAI_ACTION_AUTO_ATTACK => ['(%1$d)?Start:Stop; auto attacking #target#.', null],
@@ -919,12 +919,35 @@ $lang = array(
),
'emote' => array(
'notFound' => "This Emote doesn't exist.",
'self' => "To Yourself",
'target' => "To others with a target",
'noTarget' => "To others without a target",
// 'self' => "To Yourself",
// 'target' => "To others with a target",
// 'noTarget' => "To others without a target",
'targeted' => "Used with target",
'untargeted' => "Used without target",
'isAnimated' => "Uses an animation",
'eventSound' => "Event Sound",
'aliases' => "Aliases",
'noText' => "This Emote has no text.",
'noCommand' => "This Emote has no /-command. It can not be triggered.",
'flags' => array( // gm stuff - translation nice but not essential
EMOTE_FLAG_ONLY_STANDING => "Only while standig",
EMOTE_FLAG_USE_MOUNT => "Emote applies to mount",
EMOTE_FLAG_NOT_CHANNELING => "Not while channeling",
EMOTE_FLAG_ANIM_TALK => "Talk anim - talk",
EMOTE_FLAG_ANIM_QUESTION => "Talk anim - question",
EMOTE_FLAG_ANIM_EXCLAIM => "Talk anim - exclamation",
EMOTE_FLAG_ANIM_SHOUT => "Talk anim - shout",
EMOTE_FLAG_NOT_SWIMMING => "Not while swimming",
EMOTE_FLAG_ANIM_LAUGH => "Talk anim - laugh",
EMOTE_FLAG_CAN_LIE_ON_GROUND => "Usable while sleeping or dead",
EMOTE_FLAG_NOT_FROM_CLIENT => "Creature only",
EMOTE_FLAG_NOT_CASTING => "Not while casting",
EMOTE_FLAG_END_MOVEMENT => "Emote ends movement",
EMOTE_FLAG_INTERRUPT_ON_ATTACK => "Interrupt on attacking",
EMOTE_FLAG_ONLY_STILL => "Only while still",
EMOTE_FLAG_NOT_FLYING => "Not while flying"
),
'state' => ['Oneshot', 'Continuous State', 'Continuous Emote']
),
'enchantment' => array(
'details' => "Details",

View File

@@ -627,7 +627,7 @@ $lang = array(
SAI_ACTION_SET_FACTION => ['(%1$d)?Set faction of #target# to [faction=%7$d]:Reset faction of #target#;.', null],
SAI_ACTION_MORPH_TO_ENTRY_OR_MODEL => ['(%7$d)?Reset apperance.:Take the appearance of;(%1$d)? [npc=%1$d].:;(%2$d)?[model npc=%2$d border=1 float=right][/model]:;', null],
SAI_ACTION_SOUND => ['Play sound(%2$d)? to invoking player:;:[div float=right width=270px][sound=%1$d][/div]', 'Played by environment.'],
SAI_ACTION_PLAY_EMOTE => ['Emote [emote=%1$d] to #target#.', null],
SAI_ACTION_PLAY_EMOTE => ['(%1$d)?Emote [emote=%1$d] to #target#.: End Emote.;', null],
SAI_ACTION_FAIL_QUEST => ['Fail [quest=%1$d] for #target#.', null],
SAI_ACTION_OFFER_QUEST => ['(%2$d)?Add [quest=%1$d] to #target#\'s log:Offer [quest=%1$d] to #target#;.', null],
SAI_ACTION_SET_REACT_STATE => ['#target# becomes %7$s.', null],
@@ -638,7 +638,7 @@ $lang = array(
SAI_ACTION_THREAT_SINGLE_PCT => ['Modify #target#\'s threat by %7$d%%.', null],
SAI_ACTION_THREAT_ALL_PCT => ['Modify the threat of all targets by %7$d%%.', null],
SAI_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS => ['Exploration event of [quest=%1$d] is completed for #target#.', null],
SAI_ACTION_SET_EMOTE_STATE => ['Continuously emote [emote=%1$d] to #target#.', null],
SAI_ACTION_SET_EMOTE_STATE => ['(%1$d)?Continuously emote [emote=%1$d] to #target#.:End emote state;', null],
SAI_ACTION_SET_UNIT_FLAG => ['Set (%2$d)?UnitFlags2:UnitFlags; %7$s.', null],
SAI_ACTION_REMOVE_UNIT_FLAG => ['Unset (%2$d)?UnitFlags2:UnitFlags; %7$s.', null],
/* 20*/ SAI_ACTION_AUTO_ATTACK => ['(%1$d)?Start:Stop; auto attacking #target#.', null],
@@ -919,12 +919,35 @@ $lang = array(
),
'emote' => array(
'notFound' => "Este emoticón no existe",
'self' => "Para Usted",
'target' => "Para otros con un objetivo",
'noTarget' => "Para otros sin un objetivo",
// 'self' => "Para Usted",
// 'target' => "Para otros con un objetivo",
// 'noTarget' => "Para otros sin un objetivo",
'targeted' => "[Used with target]",
'untargeted' => "[Used without target]",
'isAnimated' => "Usa una animación",
'eventSound' => "[Event Sound]",
'aliases' => "Aliases",
'noText' => "Este emoticón no tiene texto",
'noCommand' => "[This Emote has no /-command. It can not be triggered.]",
'flags' => array(
EMOTE_FLAG_ONLY_STANDING => "Only while standig",
EMOTE_FLAG_USE_MOUNT => "Emote applies to mount",
EMOTE_FLAG_NOT_CHANNELING => "Not while channeling",
EMOTE_FLAG_ANIM_TALK => "Talk anim - talk",
EMOTE_FLAG_ANIM_QUESTION => "Talk anim - question",
EMOTE_FLAG_ANIM_EXCLAIM => "Talk anim - exclamation",
EMOTE_FLAG_ANIM_SHOUT => "Talk anim - shout",
EMOTE_FLAG_NOT_SWIMMING => "Not while swimming",
EMOTE_FLAG_ANIM_LAUGH => "Talk anim - laugh",
EMOTE_FLAG_CAN_LIE_ON_GROUND => "Usable while sleeping or dead",
EMOTE_FLAG_NOT_FROM_CLIENT => "Creature only",
EMOTE_FLAG_NOT_CASTING => "Not while casting",
EMOTE_FLAG_END_MOVEMENT => "Emote ends movement",
EMOTE_FLAG_INTERRUPT_ON_ATTACK => "Interrupt on attacking",
EMOTE_FLAG_ONLY_STILL => "Only while still",
EMOTE_FLAG_NOT_FLYING => "Not while flying"
),
'state' => ['[Oneshot]', '[Continuous State]', '[Continuous Emote]']
),
'enchantment' => array(
'details' => "Detalles",

View File

@@ -627,7 +627,7 @@ $lang = array(
SAI_ACTION_SET_FACTION => ['(%1$d)?Set faction of #target# to [faction=%7$d]:Reset faction of #target#;.', null],
SAI_ACTION_MORPH_TO_ENTRY_OR_MODEL => ['(%7$d)?Reset apperance.:Take the appearance of;(%1$d)? [npc=%1$d].:;(%2$d)?[model npc=%2$d border=1 float=right][/model]:;', null],
SAI_ACTION_SOUND => ['Play sound(%2$d)? to invoking player:;:[div float=right width=270px][sound=%1$d][/div]', 'Played by environment.'],
SAI_ACTION_PLAY_EMOTE => ['Emote [emote=%1$d] to #target#.', null],
SAI_ACTION_PLAY_EMOTE => ['(%1$d)?Emote [emote=%1$d] to #target#.: End Emote.;', null],
SAI_ACTION_FAIL_QUEST => ['Fail [quest=%1$d] for #target#.', null],
SAI_ACTION_OFFER_QUEST => ['(%2$d)?Add [quest=%1$d] to #target#\'s log:Offer [quest=%1$d] to #target#;.', null],
SAI_ACTION_SET_REACT_STATE => ['#target# becomes %7$s.', null],
@@ -638,7 +638,7 @@ $lang = array(
SAI_ACTION_THREAT_SINGLE_PCT => ['Modify #target#\'s threat by %7$d%%.', null],
SAI_ACTION_THREAT_ALL_PCT => ['Modify the threat of all targets by %7$d%%.', null],
SAI_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS => ['Exploration event of [quest=%1$d] is completed for #target#.', null],
SAI_ACTION_SET_EMOTE_STATE => ['Continuously emote [emote=%1$d] to #target#.', null],
SAI_ACTION_SET_EMOTE_STATE => ['(%1$d)?Continuously emote [emote=%1$d] to #target#.:End emote state;', null],
SAI_ACTION_SET_UNIT_FLAG => ['Set (%2$d)?UnitFlags2:UnitFlags; %7$s.', null],
SAI_ACTION_REMOVE_UNIT_FLAG => ['Unset (%2$d)?UnitFlags2:UnitFlags; %7$s.', null],
/* 20*/ SAI_ACTION_AUTO_ATTACK => ['(%1$d)?Start:Stop; auto attacking #target#.', null],
@@ -919,12 +919,35 @@ $lang = array(
),
'emote' => array(
'notFound' => "[This Emote doesn't exist.]",
'self' => "Vers vous-même",
'target' => "Vers les autres avec une cible",
'noTarget' => "Vers les autres sans cible",
// 'self' => "Vers vous-même",
// 'target' => "Vers les autres avec une cible",
// 'noTarget' => "Vers les autres sans cible",
'targeted' => "[Used with target]",
'untargeted' => "[Used without target]",
'isAnimated' => "Utilise une animation",
'eventSound' => "[Event Sound]",
'aliases' => "Alias",
'noText' => "Cette émote n'a pas de texte.",
'noCommand' => "[This Emote has no /-command. It can not be triggered.]",
'flags' => array(
EMOTE_FLAG_ONLY_STANDING => "Only while standig",
EMOTE_FLAG_USE_MOUNT => "Emote applies to mount",
EMOTE_FLAG_NOT_CHANNELING => "Not while channeling",
EMOTE_FLAG_ANIM_TALK => "Talk anim - talk",
EMOTE_FLAG_ANIM_QUESTION => "Talk anim - question",
EMOTE_FLAG_ANIM_EXCLAIM => "Talk anim - exclamation",
EMOTE_FLAG_ANIM_SHOUT => "Talk anim - shout",
EMOTE_FLAG_NOT_SWIMMING => "Not while swimming",
EMOTE_FLAG_ANIM_LAUGH => "Talk anim - laugh",
EMOTE_FLAG_CAN_LIE_ON_GROUND => "Usable while sleeping or dead",
EMOTE_FLAG_NOT_FROM_CLIENT => "Creature only",
EMOTE_FLAG_NOT_CASTING => "Not while casting",
EMOTE_FLAG_END_MOVEMENT => "Emote ends movement",
EMOTE_FLAG_INTERRUPT_ON_ATTACK => "Interrupt on attacking",
EMOTE_FLAG_ONLY_STILL => "Only while still",
EMOTE_FLAG_NOT_FLYING => "Not while flying"
),
'state' => ['[Oneshot]', '[Continuous State]', '[Continuous Emote]']
),
'enchantment' => array(
'details' => "En détail",

View File

@@ -627,7 +627,7 @@ $lang = array(
SAI_ACTION_SET_FACTION => ['(%1$d)?Set faction of #target# to [faction=%7$d]:Reset faction of #target#;.', null],
SAI_ACTION_MORPH_TO_ENTRY_OR_MODEL => ['(%7$d)?Reset apperance.:Take the appearance of;(%1$d)? [npc=%1$d].:;(%2$d)?[model npc=%2$d border=1 float=right][/model]:;', null],
SAI_ACTION_SOUND => ['Play sound(%2$d)? to invoking player:;:[div float=right width=270px][sound=%1$d][/div]', 'Played by environment.'],
SAI_ACTION_PLAY_EMOTE => ['Emote [emote=%1$d] to #target#.', null],
SAI_ACTION_PLAY_EMOTE => ['(%1$d)?Emote [emote=%1$d] to #target#.: End Emote.;', null],
SAI_ACTION_FAIL_QUEST => ['Fail [quest=%1$d] for #target#.', null],
SAI_ACTION_OFFER_QUEST => ['(%2$d)?Add [quest=%1$d] to #target#\'s log:Offer [quest=%1$d] to #target#;.', null],
SAI_ACTION_SET_REACT_STATE => ['#target# becomes %7$s.', null],
@@ -638,7 +638,7 @@ $lang = array(
SAI_ACTION_THREAT_SINGLE_PCT => ['Modify #target#\'s threat by %7$d%%.', null],
SAI_ACTION_THREAT_ALL_PCT => ['Modify the threat of all targets by %7$d%%.', null],
SAI_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS => ['Exploration event of [quest=%1$d] is completed for #target#.', null],
SAI_ACTION_SET_EMOTE_STATE => ['Continuously emote [emote=%1$d] to #target#.', null],
SAI_ACTION_SET_EMOTE_STATE => ['(%1$d)?Continuously emote [emote=%1$d] to #target#.:End emote state;', null],
SAI_ACTION_SET_UNIT_FLAG => ['Set (%2$d)?UnitFlags2:UnitFlags; %7$s.', null],
SAI_ACTION_REMOVE_UNIT_FLAG => ['Unset (%2$d)?UnitFlags2:UnitFlags; %7$s.', null],
/* 20*/ SAI_ACTION_AUTO_ATTACK => ['(%1$d)?Start:Stop; auto attacking #target#.', null],
@@ -919,12 +919,35 @@ $lang = array(
),
'emote' => array(
'notFound' => "[This Emote doesn't exist.]",
'self' => "[To Yourself]",
'target' => "[To others with a target]",
'noTarget' => "[To others without a target]",
// 'self' => "[To Yourself]",
// 'target' => "[To others with a target]",
// 'noTarget' => "[To others without a target]",
'targeted' => "[Used with target]",
'untargeted' => "[Used without target]",
'isAnimated' => "[Uses an animation]",
'eventSound' => "[Event Sound]",
'aliases' => "[Aliases]",
'noText' => "[This Emote has no text.]",
'noCommand' => "[This Emote has no /-command. It can not be triggered.]",
'flags' => array(
EMOTE_FLAG_ONLY_STANDING => "Only while standig",
EMOTE_FLAG_USE_MOUNT => "Emote applies to mount",
EMOTE_FLAG_NOT_CHANNELING => "Not while channeling",
EMOTE_FLAG_ANIM_TALK => "Talk anim - talk",
EMOTE_FLAG_ANIM_QUESTION => "Talk anim - question",
EMOTE_FLAG_ANIM_EXCLAIM => "Talk anim - exclamation",
EMOTE_FLAG_ANIM_SHOUT => "Talk anim - shout",
EMOTE_FLAG_NOT_SWIMMING => "Not while swimming",
EMOTE_FLAG_ANIM_LAUGH => "Talk anim - laugh",
EMOTE_FLAG_CAN_LIE_ON_GROUND => "Usable while sleeping or dead",
EMOTE_FLAG_NOT_FROM_CLIENT => "Creature only",
EMOTE_FLAG_NOT_CASTING => "Not while casting",
EMOTE_FLAG_END_MOVEMENT => "Emote ends movement",
EMOTE_FLAG_INTERRUPT_ON_ATTACK => "Interrupt on attacking",
EMOTE_FLAG_ONLY_STILL => "Only while still",
EMOTE_FLAG_NOT_FLYING => "Not while flying"
),
'state' => ['[Oneshot]', '[Continuous State]', '[Continuous Emote]']
),
'enchantment' => array(
'details' => "Подробности",

View File

@@ -626,7 +626,7 @@ $lang = array(
SAI_ACTION_SET_FACTION => ['(%1$d)?Set faction of #target# to [faction=%7$d]:Reset faction of #target#;.', null],
SAI_ACTION_MORPH_TO_ENTRY_OR_MODEL => ['(%7$d)?Reset apperance.:Take the appearance of;(%1$d)? [npc=%1$d].:;(%2$d)?[model npc=%2$d border=1 float=right][/model]:;', null],
SAI_ACTION_SOUND => ['Play sound(%2$d)? to invoking player:;:[div float=right width=270px][sound=%1$d][/div]', 'Played by environment.'],
SAI_ACTION_PLAY_EMOTE => ['Emote [emote=%1$d] to #target#.', null],
SAI_ACTION_PLAY_EMOTE => ['(%1$d)?Emote [emote=%1$d] to #target#.: End Emote.;', null],
SAI_ACTION_FAIL_QUEST => ['Fail [quest=%1$d] for #target#.', null],
SAI_ACTION_OFFER_QUEST => ['(%2$d)?Add [quest=%1$d] to #target#\'s log:Offer [quest=%1$d] to #target#;.', null],
SAI_ACTION_SET_REACT_STATE => ['#target# becomes %7$s.', null],
@@ -637,7 +637,7 @@ $lang = array(
SAI_ACTION_THREAT_SINGLE_PCT => ['Modify #target#\'s threat by %7$d%%.', null],
SAI_ACTION_THREAT_ALL_PCT => ['Modify the threat of all targets by %7$d%%.', null],
SAI_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS => ['Exploration event of [quest=%1$d] is completed for #target#.', null],
SAI_ACTION_SET_EMOTE_STATE => ['Continuously emote [emote=%1$d] to #target#.', null],
SAI_ACTION_SET_EMOTE_STATE => ['(%1$d)?Continuously emote [emote=%1$d] to #target#.:End emote state;', null],
SAI_ACTION_SET_UNIT_FLAG => ['Set (%2$d)?UnitFlags2:UnitFlags; %7$s.', null],
SAI_ACTION_REMOVE_UNIT_FLAG => ['Unset (%2$d)?UnitFlags2:UnitFlags; %7$s.', null],
/* 20*/ SAI_ACTION_AUTO_ATTACK => ['(%1$d)?Start:Stop; auto attacking #target#.', null],
@@ -918,12 +918,35 @@ $lang = array(
),
'emote' => array(
'notFound' => "这个表情不存在。",
'self' => "对你自己",
'target' => "对别人并且选择了目标",
'noTarget' => "对别人并且不选择目标",
// 'self' => "对你自己",
// 'target' => "对别人并且选择了目标",
// 'noTarget' => "对别人并且不选择目标",
'targeted' => "[Used with target]",
'untargeted' => "[Used without target]",
'isAnimated' => "使用动画",
'eventSound' => "[Event Sound]",
'aliases' => "别名",
'noText' => "这个表情没有文字。",
'noCommand' => "[This Emote has no /-command. It can not be triggered.]",
'flags' => array(
EMOTE_FLAG_ONLY_STANDING => "Only while standig",
EMOTE_FLAG_USE_MOUNT => "Emote applies to mount",
EMOTE_FLAG_NOT_CHANNELING => "Not while channeling",
EMOTE_FLAG_ANIM_TALK => "Talk anim - talk",
EMOTE_FLAG_ANIM_QUESTION => "Talk anim - question",
EMOTE_FLAG_ANIM_EXCLAIM => "Talk anim - exclamation",
EMOTE_FLAG_ANIM_SHOUT => "Talk anim - shout",
EMOTE_FLAG_NOT_SWIMMING => "Not while swimming",
EMOTE_FLAG_ANIM_LAUGH => "Talk anim - laugh",
EMOTE_FLAG_CAN_LIE_ON_GROUND => "Usable while sleeping or dead",
EMOTE_FLAG_NOT_FROM_CLIENT => "Creature only",
EMOTE_FLAG_NOT_CASTING => "Not while casting",
EMOTE_FLAG_END_MOVEMENT => "Emote ends movement",
EMOTE_FLAG_INTERRUPT_ON_ATTACK => "Interrupt on attacking",
EMOTE_FLAG_ONLY_STILL => "Only while still",
EMOTE_FLAG_NOT_FLYING => "Not while flying"
),
'state' => ['[Oneshot]', '[Continuous State]', '[Continuous Emote]']
),
'enchantment' => array(
'details' => "细节",

View File

@@ -19,6 +19,11 @@ class EmotePage extends GenericPage
public function __construct($pageCall, $id)
{
/*
* id > 0: player text emote
* id < 0: creature emote
*/
parent::__construct($pageCall, $id);
$this->typeId = intVal($id);
@@ -46,15 +51,45 @@ class EmotePage extends GenericPage
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
// has Animation
if ($this->subject->getField('isAnimated'))
if ($this->subject->getField('isAnimated') && !$this->subject->getField('stateParam'))
{
$infobox[] = Lang::emote('isAnimated');
// anim state
$state = Lang::emote('state', $this->subject->getField('state'));
if ($this->subject->getField('state') == 1)
$state .= Lang::main('colon').Lang::unit('bytes1', 0, $this->subject->getField('stateParam'));
$infobox[] = $state;
}
if (User::isInGroup(U_GROUP_STAFF | U_GROUP_TESTER))
{
// player emote: point to internal data
if ($_ = $this->subject->getField('parentEmote'))
{
$this->extendGlobalIds(Type::EMOTE, $_);
$infobox[] = '[emote='.$_.']';
}
if ($flags = $this->subject->getField('flags'))
{
$box = Lang::game('flags').Lang::main('colon').'[ul]';
foreach (Lang::emote('flags') as $bit => $str)
if ($bit & $flags)
$box .= '[li][tooltip name=hint-'.$bit.']'.Util::asHex($bit).'[/tooltip][span class=tip tooltip=hint-'.$bit.']'.$str.'[/span][/li]';
$infobox[] = $box.'[/ul]';
}
}
/****************/
/* Main Content */
/****************/
$text = '';
if ($aliasses = DB::Aowow()->selectCol('SELECT command FROM ?_emotes_aliasses WHERE id = ?d AND locales & ?d', $this->typeId, 1 << User::$localeId))
if ($this->subject->getField('cuFlags') & EMOTE_CU_MISSING_CMD)
$text .= Lang::emote('noCommand').'[br][br]';
else if ($aliasses = DB::Aowow()->selectCol('SELECT command FROM ?_emotes_aliasses WHERE id = ?d AND locales & ?d', $this->typeId, 1 << User::$localeId))
{
$text .= '[h3]'.Lang::emote('aliases').'[/h3][ul]';
foreach ($aliasses as $a)
@@ -63,21 +98,43 @@ class EmotePage extends GenericPage
$text .= '[/ul][br][br]';
}
$texts = [];
if ($_ = $this->subject->getField('self', true))
$texts[Lang::emote('self')] = $_;
$target = $noTarget = [];
if ($_ = $this->subject->getField('extToExt', true))
$target[] = $this->prepare($_);
if ($_ = $this->subject->getField('extToMe', true))
$target[] = $this->prepare($_);
if ($_ = $this->subject->getField('meToExt', true))
$target[] = $this->prepare($_);
if ($_ = $this->subject->getField('extToNone', true))
$noTarget[] = $this->prepare($_);
if ($_ = $this->subject->getField('meToNone', true))
$noTarget[] =$this->prepare($_);
if ($_ = $this->subject->getField('target', true))
$texts[Lang::emote('target')] = $_;
if ($_ = $this->subject->getField('noTarget', true))
$texts[Lang::emote('noTarget')] = $_;
if (!$texts)
if (!$target && !$noTarget)
$text .= '[div][i class=q0]'.Lang::emote('noText').'[/i][/div]';
else
foreach ($texts as $h => $t)
$text .= '[pad][b]'.$h.'[/b][ul][li][span class=s4]'.preg_replace('/%\d?\$?s/', '<'.Util::ucFirst(Lang::main('name')).'>', $t).'[/span][/li][/ul]';
if ($target)
{
$text .= '[pad][b]'.Lang::emote('targeted').'[/b][ul]';
foreach ($target as $t)
$text .= '[li][span class=s4]'.$t.'[/span][/li]';
$text .= '[/ul]';
}
if ($noTarget)
{
$text .= '[pad][b]'.Lang::emote('untargeted').'[/b][ul]';
foreach ($noTarget as $t)
$text .= '[li][span class=s4]'.$t.'[/span][/li]';
$text .= '[/ul]';
}
// event sound
if ($_ = $this->subject->getField('soundId'))
{
$this->extendGlobalIds(Type::SOUND, $_);
$text .= '[h3]'.Lang::emote('eventSound').'[/h3][sound='.$_.']';
}
$this->extraText = $text;
$this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
@@ -102,7 +159,7 @@ class EmotePage extends GenericPage
$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))
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 ?_emotes_sounds WHERE -emoteId = ?d GROUP BY soundId', $this->typeId > 0 ? $this->subject->getField('parentEmote') : $this->typeId))
{
$sounds = new SoundList(array(['id', array_keys($em)]));
if (!$sounds->error)
@@ -123,6 +180,12 @@ class EmotePage extends GenericPage
}
}
}
private function prepare(string $emote) : string
{
$emote = Util::parseHtmlText($emote, true);
return preg_replace('/%\d?\$?s/', '<'.Util::ucFirst(Lang::main('name')).'>', $emote);
}
}
?>

View File

@@ -25,8 +25,12 @@ class EmotesPage extends GenericPage
protected function generateContent()
{
$cnd = [CFG_SQL_LIMIT_NONE];
if (!User::isInGroup(U_GROUP_STAFF))
$cnd[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0];
$tabData = array(
'data' => array_values((new EmoteList())->getListviewData()),
'data' => array_values((new EmoteList($cnd))->getListviewData()),
'name' => Util::ucFirst(Lang::game('emotes'))
);

View File

@@ -1315,7 +1315,7 @@ class SearchPage extends GenericPage
private function _searchEmote($cndBase) // 25 Emotes $searchMask & 0x2000000
{
$cnd = array_merge($cndBase, [$this->createLookup(['cmd', 'self_loc'.User::$localeId, 'target_loc'.User::$localeId, 'noTarget_loc'.User::$localeId])]);
$cnd = array_merge($cndBase, [$this->createLookup(['cmd', 'meToExt_loc'.User::$localeId, 'meToNone_loc'.User::$localeId, 'extToMe_loc'.User::$localeId, 'extToExt_loc'.User::$localeId, 'extToNone_loc'.User::$localeId])]);
$emote = new EmoteList($cnd);
if ($data = $emote->getListviewData())

View File

@@ -258,7 +258,7 @@ class SoundPage extends GenericPage
// tab: Emotes (EmotesTextSound (containing emote audio))
if ($em = DB::Aowow()->selectCol('SELECT emoteId FROM ?_emotes_sounds WHERE soundId = ?d GROUP BY emoteId', $this->typeId))
if ($em = DB::Aowow()->selectCol('SELECT emoteId FROM ?_emotes_sounds WHERE soundId = ?d GROUP BY emoteId UNION SELECT id FROM ?_emotes WHERE soundId = ?d', $this->typeId, $this->typeId))
{
$races = new EmoteList(array(['id', $em]));
if (!$races->error)

View File

@@ -675,28 +675,45 @@ DROP TABLE IF EXISTS `aowow_emotes`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `aowow_emotes` (
`id` smallint(5) unsigned NOT NULL,
`cmd` varchar(15) COLLATE utf8mb4_unicode_ci NOT NULL,
`isAnimated` tinyint(1) unsigned NOT NULL,
`cuFlags` int(10) unsigned NOT NULL,
`target_loc0` varchar(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`target_loc2` varchar(70) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`target_loc3` varchar(95) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`target_loc4` varchar(95) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`target_loc6` varchar(90) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`target_loc8` varchar(70) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`noTarget_loc0` varchar(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`noTarget_loc2` varchar(110) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`noTarget_loc3` varchar(85) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`noTarget_loc4` varchar(85) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`noTarget_loc6` varchar(75) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`noTarget_loc8` varchar(60) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`self_loc0` varchar(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`self_loc2` varchar(115) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`self_loc3` varchar(85) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`self_loc4` varchar(85) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`self_loc6` varchar(75) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`self_loc8` varchar(70) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`id` SMALLINT(5) SIGNED NOT NULL,
`cmd` VARCHAR(35) COLLATE utf8mb4_unicode_ci NOT NULL,
`isAnimated` TINYINT(1) UNSIGNED NOT NULL,
`flags` SMALLINT(5) UNSIGNED NOT NULL,
`parentEmote` SMALLINT(5) UNSIGNED NOT NULL,
`soundId` SMALLINT(5) SIGNED NOT NULL,
`state` TINYINT(1) UNSIGNED NOT NULL,
`stateParam` TINYINT(1) UNSIGNED NOT NULL,
`cuFlags` INT(10) UNSIGNED NOT NULL,
`extToExt_loc0` VARCHAR(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToExt_loc2` VARCHAR(113) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToExt_loc3` VARCHAR(91) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToExt_loc4` VARCHAR(71) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToExt_loc6` VARCHAR(89) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToExt_loc8` VARCHAR(123) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToMe_loc0` VARCHAR(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToMe_loc2` VARCHAR(113) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToMe_loc3` VARCHAR(91) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToMe_loc4` VARCHAR(71) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToMe_loc6` VARCHAR(89) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToMe_loc8` VARCHAR(123) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToExt_loc0` VARCHAR(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToExt_loc2` VARCHAR(113) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToExt_loc3` VARCHAR(91) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToExt_loc4` VARCHAR(71) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToExt_loc6` VARCHAR(89) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToExt_loc8` VARCHAR(123) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToNone_loc0` VARCHAR(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToNone_loc2` VARCHAR(113) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToNone_loc3` VARCHAR(91) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToNone_loc4` VARCHAR(71) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToNone_loc6` VARCHAR(89) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToNone_loc8` VARCHAR(123) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToNone_loc0` VARCHAR(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToNone_loc2` VARCHAR(113) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToNone_loc3` VARCHAR(91) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToNone_loc4` VARCHAR(71) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToNone_loc6` VARCHAR(89) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToNone_loc8` VARCHAR(123) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -3186,7 +3203,7 @@ UNLOCK TABLES;
LOCK TABLES `aowow_dbversion` WRITE;
/*!40000 ALTER TABLE `aowow_dbversion` DISABLE KEYS */;
INSERT INTO `aowow_dbversion` VALUES (1684849476,0,NULL,NULL);
INSERT INTO `aowow_dbversion` VALUES (1691940878,0,NULL,NULL);
/*!40000 ALTER TABLE `aowow_dbversion` ENABLE KEYS */;
UNLOCK TABLES;

View File

@@ -62,8 +62,8 @@ class DBC
'durabilitycosts' => 'niiiiiiiiixiiiiiiiiiiixiiiixix',
'durabilityquality' => 'nf',
'dungeonencounter' => 'niiiisxsssxsxsxxxxxxxxx',
'emotes' => 'nxixxxx',
'emotestext' => 'nsiixxxixixxxxxxxxx',
'emotes' => 'nsiiiii',
'emotestext' => 'nsiiiixixixiixxixxx',
'emotestextdata' => 'nsxsssxsxsxxxxxxxx',
'emotestextsound' => 'niiii',
'faction' => 'niiiiiiiiiiiiiixxxiffixsxsssxsxsxxxxxxxxxxxxxxxxxxxxxxxxx',
@@ -167,8 +167,8 @@ class DBC
'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',
'dungeonencounter' => 'id,map,mode,order,bit,name_loc0,name_loc2,name_loc3,name_loc4,name_loc6,name_loc8',
'emotes' => 'id,animationId',
'emotestext' => 'id,command,emoteId,targetId,noTargetId,selfId',
'emotes' => 'id,name,animationId,flags,state,stateParam,soundId',
'emotestext' => 'id,command,emoteId,etd0,etd1,etd2,etd4,etd6,etd8,etd9,etd12',
'emotestextsound' => 'id,emotesTextId,raceId,gender,soundId',
'emotestextdata' => 'id,text_loc0,text_loc2,text_loc3,text_loc4,text_loc6,text_loc8',
'faction' => 'id,repIdx,baseRepRaceMask1,baseRepRaceMask2,baseRepRaceMask3,baseRepRaceMask4,baseRepClassMask1,baseRepClassMask2,baseRepClassMask3,baseRepClassMask4,baseRepValue1,baseRepValue2,baseRepValue3,baseRepValue4,repFlags1,parentFaction,spilloverRateIn,spilloverRateOut,spilloverMaxRank,name_loc0,name_loc2,name_loc3,name_loc4,name_loc6,name_loc8',

View File

@@ -13,6 +13,71 @@ SqlGen::register(new class extends SetupScript
protected $dbcSourceFiles = ['emotes', 'emotestext', 'emotestextdata'];
private $textData = [];
private function mergeGenderedStrings(int $maleTextId, int $femaleTextId, int $locale) : string
{
$maleText = $this->textData[$maleTextId][$locale] ?? '';
$femaleText = $this->textData[$femaleTextId][$locale] ?? '';
if (!$maleText && !$femaleText)
return '';
else if (!$maleText)
return $femaleText;
else if (!$femaleText)
return $maleText;
else if ($maleText == $femaleText)
return $maleText;
$front = $back = [];
$m = explode(' ', $maleText);
$f = explode(' ', $femaleText);
$n = max(count($m), count($f));
// advance from left until diff -> store common string
// advance from right until diff -> store common string
// merge leftovers as gendered switch and recombine string
$i = 0;
for (; $i < $n; $i++)
{
if (!isset($m[$i]) || !isset($f[$i]))
break;
else if ($m[$i] != $f[$i])
break;
else
$front[] = $m[$i];
}
if ($i + 1 == $n) // loop completed all elements
return implode(' ', $m);
$m = array_reverse($m);
$f = array_reverse($f);
$j = 0;
for (; $j < $n - $i; $j++)
{
if (!isset($m[$j]) || !isset($f[$j]))
break;
else if ($m[$j] != $f[$j])
break;
else
$back[] = $m[$j];
}
$m = array_reverse($m);
$f = array_reverse($f);
$midM = array_slice($m, $i, count($m) - $i - $j);
$midF = array_slice($f, $i, count($f) - $i - $j);
$mid = '$g' . implode(' ', $midM ?? []) . ':' . implode(' ', $midF ?? []) . ';';
return implode(' ', array_merge($front, [$mid], array_reverse($back)));
}
public function generate(array $ids = []) : bool
{
/**********/
@@ -23,8 +88,13 @@ SqlGen::register(new class extends SetupScript
$allOK = true;
$locPath = [];
DB::Aowow()->query('TRUNCATE ?_emotes');
DB::Aowow()->query('TRUNCATE ?_emotes_aliasses');
/*********************/
/* Player controlled */
/*********************/
foreach (CLISetup::$localeIds as $lId)
{
foreach (CLISetup::$expectedPaths as $xp => $locId)
@@ -47,28 +117,43 @@ SqlGen::register(new class extends SetupScript
$allOK = false;
}
$_= DB::Aowow()->query('REPLACE INTO ?_emotes SELECT
et.id,
LOWER(et.command),
IF(e.animationId, 1, 0),
0, -- cuFlags
etdT.text_loc0, etdT.text_loc2, etdT.text_loc3, etdT.text_loc4, etdT.text_loc6, etdT.text_loc8,
etdNT.text_loc0, etdNT.text_loc2, etdNT.text_loc3, etdNT.text_loc4, etdNT.text_loc6, etdNT.text_loc8,
etdS.text_loc0, etdS.text_loc2, etdS.text_loc3, etdS.text_loc4, etdS.text_loc6, etdS.text_loc8
FROM
dbc_emotestext et
LEFT JOIN
dbc_emotes e ON e.id = et.emoteId
LEFT JOIN
dbc_emotestextdata etdT ON etdT.id = et.targetId
LEFT JOIN
dbc_emotestextdata etdNT ON etdNT.id = et.noTargetId
LEFT JOIN
dbc_emotestextdata etdS ON etdS.id = et.selfId'
);
/* EmotesText Data offsets
gender seenBy hasTarget mergedWith example
0 male others yes 8 %s raises <his/her> fist in anger at %s.
1 male self yes 9 %s raises <his/her> fist in anger at you.
2 self self yes You raise your fist in anger at %s.
4 male others no 12 %s raises <his/her> fist in anger.
6 self self no You raise your fist in anger.
8 female others yes 0 -
9 female self yes 1 -
12 female others no 4 -
*/
if (!$_)
$allOK = false;
$this->textData = DB::Aowow()->select('SELECT id AS ARRAY_KEY, text_loc0 AS "0", text_loc2 AS "2", text_loc3 AS "3", text_loc4 AS "4", text_loc6 AS "6", text_loc8 AS "8" FROM dbc_emotestextdata');
$texts = DB::Aowow()->select('SELECT et.id AS ARRAY_KEY, LOWER(command) AS `cmd`, IF(e.animationId, 1, 0) AS `anim`, -emoteId AS "parent", e.soundId, etd0, etd1, etd2, etd4, etd6, etd8, etd9, etd12 FROM dbc_emotestext et LEFT JOIN dbc_emotes e ON e.id = et.emoteId');
foreach ($texts AS $id => $t)
{
DB::Aowow()->query(
'INSERT INTO ?_emotes (
`id`, `cmd`, `isAnimated`, `parentEmote`, `soundId`,
`extToExt_loc0`, `extToMe_loc0`, `meToExt_loc0`, `extToNone_loc0`, `meToNone_loc0`,
`extToExt_loc2`, `extToMe_loc2`, `meToExt_loc2`, `extToNone_loc2`, `meToNone_loc2`,
`extToExt_loc3`, `extToMe_loc3`, `meToExt_loc3`, `extToNone_loc3`, `meToNone_loc3`,
`extToExt_loc4`, `extToMe_loc4`, `meToExt_loc4`, `extToNone_loc4`, `meToNone_loc4`,
`extToExt_loc6`, `extToMe_loc6`, `meToExt_loc6`, `extToNone_loc6`, `meToNone_loc6`,
`extToExt_loc8`, `extToMe_loc8`, `meToExt_loc8`, `extToNone_loc8`, `meToNone_loc8`)
VALUES
(?d, ?, ?d, ?d, ?d, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
$id, $t['cmd'], $t['anim'], $t['parent'], $t['soundId'],
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_EN), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_EN), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_EN), $this->textData[$t['etd2']][LOCALE_EN] ?? '', $this->textData[$t['etd6']][LOCALE_EN] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_FR), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_FR), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_FR), $this->textData[$t['etd2']][LOCALE_FR] ?? '', $this->textData[$t['etd6']][LOCALE_FR] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_DE), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_DE), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_DE), $this->textData[$t['etd2']][LOCALE_DE] ?? '', $this->textData[$t['etd6']][LOCALE_DE] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_CN), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_CN), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_CN), $this->textData[$t['etd2']][LOCALE_CN] ?? '', $this->textData[$t['etd6']][LOCALE_CN] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_ES), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_ES), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_ES), $this->textData[$t['etd2']][LOCALE_ES] ?? '', $this->textData[$t['etd6']][LOCALE_ES] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_RU), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_RU), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_RU), $this->textData[$t['etd2']][LOCALE_RU] ?? '', $this->textData[$t['etd6']][LOCALE_RU] ?? ''
);
}
// i have no idea, how the indexing in this file works.
// sometimes the \d+ after EMOTE is the emoteTextId, but not nearly often enough
@@ -78,23 +163,31 @@ SqlGen::register(new class extends SetupScript
if (preg_match('/^EMOTE(\d+)_CMD\d+\s=\s\"\/([^"]+)\";$/', $line, $m))
$aliasses[$m[1]][] = [$lId, $m[2]];
$emotes = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, cmd FROM ?_emotes');
foreach($emotes as $eId => $cmd)
{
foreach ($aliasses as $gsId => $data)
foreach ($aliasses as $data)
{
if (in_array($cmd, array_column($data, 1)))
{
foreach ($data as $d)
DB::Aowow()->query('INSERT IGNORE INTO ?_emotes_aliasses VALUES (?d, ?d, ?) ON DUPLICATE KEY UPDATE locales = locales | ?d', $eId, (1 << $d[0]), strtolower($d[1]), (1 << $d[0]));
break;
continue 2;
}
}
DB::Aowow()->query('UPDATE ?_emotes SET `cuFlags` = `cuFlags` | ?d WHERE `id` = ?d', CUSTOM_EXCLUDE_FOR_LISTVIEW | EMOTE_CU_MISSING_CMD, $eId);
}
/*********************/
/* Server controlled */
/*********************/
DB::Aowow()->query('INSERT INTO ?_emotes (`id`, `cmd`, `flags`, `isAnimated`, `parentEmote`, `soundId`, `state`, `stateParam`, `cuFlags`) SELECT -`id`, `name`, `flags`, IF(`animationId`, 1, 0), 0, `soundId`, `state`, `stateParam`, ?d FROM dbc_emotes WHERE 1', CUSTOM_EXCLUDE_FOR_LISTVIEW);
$this->reapplyCCFlags('emotes', Type::EMOTE);
return $allOK;

View File

@@ -0,0 +1,49 @@
DROP TABLE IF EXISTS `dbc_emotes`;
DROP TABLE IF EXISTS `dbc_emotestext`;
DROP TABLE IF EXISTS `dbc_emotestextdata`;
DROP TABLE IF EXISTS `aowow_emotes`;
CREATE TABLE `aowow_emotes` (
`id` SMALLINT(5) SIGNED NOT NULL,
`cmd` VARCHAR(35) COLLATE utf8mb4_unicode_ci NOT NULL,
`isAnimated` TINYINT(1) UNSIGNED NOT NULL,
`flags` SMALLINT(5) UNSIGNED NOT NULL,
`parentEmote` SMALLINT(5) UNSIGNED NOT NULL,
`soundId` SMALLINT(5) SIGNED NOT NULL,
`state` TINYINT(1) UNSIGNED NOT NULL,
`stateParam` TINYINT(1) UNSIGNED NOT NULL,
`cuFlags` INT(10) UNSIGNED NOT NULL,
`extToExt_loc0` VARCHAR(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToExt_loc2` VARCHAR(113) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToExt_loc3` VARCHAR(91) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToExt_loc4` VARCHAR(71) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToExt_loc6` VARCHAR(89) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToExt_loc8` VARCHAR(123) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToMe_loc0` VARCHAR(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToMe_loc2` VARCHAR(113) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToMe_loc3` VARCHAR(91) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToMe_loc4` VARCHAR(71) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToMe_loc6` VARCHAR(89) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToMe_loc8` VARCHAR(123) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToExt_loc0` VARCHAR(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToExt_loc2` VARCHAR(113) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToExt_loc3` VARCHAR(91) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToExt_loc4` VARCHAR(71) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToExt_loc6` VARCHAR(89) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToExt_loc8` VARCHAR(123) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToNone_loc0` VARCHAR(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToNone_loc2` VARCHAR(113) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToNone_loc3` VARCHAR(91) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToNone_loc4` VARCHAR(71) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToNone_loc6` VARCHAR(89) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`extToNone_loc8` VARCHAR(123) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToNone_loc0` VARCHAR(65) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToNone_loc2` VARCHAR(113) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToNone_loc3` VARCHAR(91) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToNone_loc4` VARCHAR(71) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToNone_loc6` VARCHAR(89) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`meToNone_loc8` VARCHAR(123) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
UPDATE `aowow_dbversion` SET `sql` = CONCAT(IFNULL(`sql`, ''), ' emotes');