/
<html> |
<head> |
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> |
</head> |
<body style="font-family: Arial; font-size: 16px; background-color: #101030; color: #FDFDFD; padding-left: 50px; padding-top: 20px;"> |
<form action="Morgaction.php" method="post" name="[object]"> |
<b><u>MorgDKP Import</b></u> |
<br> |
<br> |
Please copy the data string from MorgDKP into the box below and click parse.<br> |
<br> |
<br> |
<br><textarea style="width: 800px; height: 400px;" name="data" ></textarea> |
<br> |
<br> |
<input type="submit" value="Parse MorgDKP Data"><br> |
</form> |
</body> |
</html> |
<?php |
function converthtml($text) { |
$text = str_replace("â", "\\195\\162", $text); |
$text = str_replace("¡", "\\194\\161", $text); |
$text = str_replace("ª", "\\194\\170", $text); |
$text = str_replace("º", "\\194\\186", $text); |
$text = str_replace("¿", "\\194\\191", $text); |
$text = str_replace("À", "\\195\\128", $text); |
$text = str_replace("Á", "\\195\\129", $text); |
$text = str_replace("Â", "\\195\\130", $text); |
$text = str_replace("Ã", "\\195\\131", $text); |
$text = str_replace("Å", "\\195\\133", $text); |
$text = str_replace("Ç", "\\195\\135", $text); |
$text = str_replace("È", "\\195\\136", $text); |
$text = str_replace("É", "\\195\\137", $text); |
$text = str_replace("Ê", "\\195\\138", $text); |
$text = str_replace("Ë", "\\195\\139", $text); |
$text = str_replace("Ì", "\\195\\140", $text); |
$text = str_replace("Í", "\\195\\141", $text); |
$text = str_replace("Î", "\\195\\142", $text); |
$text = str_replace("Ï", "\\195\\143", $text); |
$text = str_replace("Ð", "\\195\\144", $text); |
$text = str_replace("Ñ", "\\195\\145", $text); |
$text = str_replace("Ò", "\\195\\146", $text); |
$text = str_replace("Ó", "\\195\\147", $text); |
$text = str_replace("Ô", "\\195\\148", $text); |
$text = str_replace("Õ", "\\195\\149", $text); |
$text = str_replace("Ø", "\\195\\152", $text); |
$text = str_replace("Ù", "\\195\\153", $text); |
$text = str_replace("Ú", "\\195\\154", $text); |
$text = str_replace("Û", "\\195\\155", $text); |
$text = str_replace("Ý", "\\195\\157", $text); |
$text = str_replace("à", "\\195\\160", $text); |
$text = str_replace("á", "\\195\\161", $text); |
$text = str_replace("ã", "\\195\\163", $text); |
$text = str_replace("å", "\\195\\165", $text); |
$text = str_replace("ç", "\\195\\167", $text); |
$text = str_replace("è", "\\195\\168", $text); |
$text = str_replace("é", "\\195\\169", $text); |
$text = str_replace("ê", "\\195\\170", $text); |
$text = str_replace("ë", "\\195\\171", $text); |
$text = str_replace("ì", "\\195\\172", $text); |
$text = str_replace("í", "\\195\\173", $text); |
$text = str_replace("î", "\\195\\174", $text); |
$text = str_replace("ï", "\\195\\175", $text); |
$text = str_replace("ð", "\\195\\176", $text); |
$text = str_replace("ñ", "\\195\\177", $text); |
$text = str_replace("ò", "\\195\\178", $text); |
$text = str_replace("ó", "\\195\\179", $text); |
$text = str_replace("ô", "\\195\\180", $text); |
$text = str_replace("õ", "\\195\\181", $text); |
$text = str_replace("ø", "\\195\\184", $text); |
$text = str_replace("ù", "\\195\\185", $text); |
$text = str_replace("ú", "\\195\\186", $text); |
$text = str_replace("û", "\\195\\187", $text); |
$text = str_replace("ý", "\\195\\189", $text); |
$text = str_replace("ÿ", "\\195\\191", $text); |
$text = str_replace("Ä", "\\195\\132", $text); |
$text = str_replace("Æ", "\\195\\134", $text); |
$text = str_replace("Ö", "\\195\\150", $text); |
$text = str_replace("Ü", "\\195\\156", $text); |
$text = str_replace("Þ", "\\195\\158", $text); |
$text = str_replace("ß", "\\195\\159", $text); |
$text = str_replace("ä", "\\195\\164", $text); |
$text = str_replace("æ", "\\195\\166", $text); |
$text = str_replace("ö", "\\195\\182", $text); |
$text = str_replace("ü", "\\195\\188", $text); |
$text = str_replace("þ", "\\195\\190", $text); |
$text = str_replace("&", "\\038", $text); |
$text = str_replace("!", "\\033", $text); |
$text = str_replace("#", "\\035", $text); |
$text = str_replace("$", "\\036", $text); |
$text = str_replace("%", "\\037", $text); |
$text = str_replace("?", "\\063", $text); |
$text = str_replace("@", "\\064", $text); |
return $text; |
} |
function converttext($text) { |
$text = str_replace("â", "â", $text); |
$text = str_replace("¡", "¡", $text); |
$text = str_replace("ª", "ª", $text); |
$text = str_replace("º", "º", $text); |
$text = str_replace("¿", "¿", $text); |
$text = str_replace("À", "Ã", $text); |
$text = str_replace("Á", "Ã?", $text); |
$text = str_replace("Â", "Ã", $text); |
$text = str_replace("Ã", "Ã", $text); |
$text = str_replace("Å", "Ã ", $text); |
$text = str_replace("Ç", "Ã", $text); |
$text = str_replace("È", "Ã", $text); |
$text = str_replace("É", "Ã", $text); |
$text = str_replace("Ê", "Ã", $text); |
$text = str_replace("Ë", "Ã", $text); |
$text = str_replace("Ì", "Ã", $text); |
$text = str_replace("Í", "Ã?", $text); |
$text = str_replace("Î", "Ã", $text); |
$text = str_replace("Ï", "Ã?", $text); |
$text = str_replace("Ð", "Ã?", $text); |
$text = str_replace("Ñ", "Ã", $text); |
$text = str_replace("Ò", "Ã", $text); |
$text = str_replace("Ó", "Ã", $text); |
$text = str_replace("Ô", "Ã", $text); |
$text = str_replace("Õ", "Ã", $text); |
$text = str_replace("Ø", "Ã", $text); |
$text = str_replace("Ù", "Ã", $text); |
$text = str_replace("Ú", "Ã", $text); |
$text = str_replace("Û", "Ã", $text); |
$text = str_replace("Ý", "Ã?", $text); |
$text = str_replace("à", "Ã ", $text); |
$text = str_replace("á", "á", $text); |
$text = str_replace("ã", "ã", $text); |
$text = str_replace("å", "Ã¥", $text); |
$text = str_replace("ç", "ç", $text); |
$text = str_replace("è", "è", $text); |
$text = str_replace("é", "é", $text); |
$text = str_replace("ê", "ê", $text); |
$text = str_replace("ë", "ë", $text); |
$text = str_replace("ì", "ì", $text); |
$text = str_replace("í", "Ã*", $text); |
$text = str_replace("î", "î", $text); |
$text = str_replace("ï", "ï", $text); |
$text = str_replace("ð", "ð", $text); |
$text = str_replace("ñ", "ñ", $text); |
$text = str_replace("ò", "ò", $text); |
$text = str_replace("ó", "ó", $text); |
$text = str_replace("ô", "ô", $text); |
$text = str_replace("õ", "õ", $text); |
$text = str_replace("ø", "ø", $text); |
$text = str_replace("ù", "ù", $text); |
$text = str_replace("ú", "ú", $text); |
$text = str_replace("û", "û", $text); |
$text = str_replace("ý", "ý", $text); |
$text = str_replace("ÿ", "ÿ", $text); |
$text = str_replace("Ä", "Ã", $text); |
$text = str_replace("Æ", "Ã", $text); |
$text = str_replace("Ö", "Ã", $text); |
$text = str_replace("Ü", "Ã", $text); |
$text = str_replace("Þ", "Ã", $text); |
$text = str_replace("ß", "Ã", $text); |
$text = str_replace("ä", "ä", $text); |
$text = str_replace("æ", "æ", $text); |
$text = str_replace("ö", "ö", $text); |
$text = str_replace("ü", "ü", $text); |
$text = str_replace("þ", "þ", $text); |
return $text; |
} |
function restoretext($text) { |
$text = str_replace("\\195\\162", "â", $text); |
$text = str_replace("\\194\\161", "¡", $text); |
$text = str_replace("\\194\\170", "ª", $text); |
$text = str_replace("\\194\\186", "º", $text); |
$text = str_replace("\\194\\191", "¿", $text); |
$text = str_replace("\\195\\128", "À", $text); |
$text = str_replace("\\195\\129", "Á", $text); |
$text = str_replace("\\195\\130", "Â", $text); |
$text = str_replace("\\195\\131", "Ã", $text); |
$text = str_replace("\\195\\133", "Å", $text); |
$text = str_replace("\\195\\135", "Ç", $text); |
$text = str_replace("\\195\\136", "È", $text); |
$text = str_replace("\\195\\137", "É", $text); |
$text = str_replace("\\195\\138", "Ê", $text); |
$text = str_replace("\\195\\139", "Ë", $text); |
$text = str_replace("\\195\\140", "Ì", $text); |
$text = str_replace("\\195\\141", "Í", $text); |
$text = str_replace("\\195\\142", "Î", $text); |
$text = str_replace("\\195\\143", "Ï", $text); |
$text = str_replace("\\195\\144", "Ð", $text); |
$text = str_replace("\\195\\145", "Ñ", $text); |
$text = str_replace("\\195\\146", "Ò", $text); |
$text = str_replace("\\195\\147", "Ó", $text); |
$text = str_replace("\\195\\148", "Ô", $text); |
$text = str_replace("\\195\\149", "Õ", $text); |
$text = str_replace("\\195\\152", "Ø", $text); |
$text = str_replace("\\195\\153", "Ù", $text); |
$text = str_replace("\\195\\154", "Ú", $text); |
$text = str_replace("\\195\\155", "Û", $text); |
$text = str_replace("\\195\\157", "Ý", $text); |
$text = str_replace("\\195\\160", "à", $text); |
$text = str_replace("\\195\\161", "á", $text); |
$text = str_replace("\\195\\163", "ã", $text); |
$text = str_replace("\\195\\165", "å", $text); |
$text = str_replace("\\195\\167", "ç", $text); |
$text = str_replace("\\195\\168", "è", $text); |
$text = str_replace("\\195\\169", "é", $text); |
$text = str_replace("\\195\\170", "ê", $text); |
$text = str_replace("\\195\\171", "ë", $text); |
$text = str_replace("\\195\\172", "ì", $text); |
$text = str_replace("\\195\\173", "í", $text); |
$text = str_replace("\\195\\174", "î", $text); |
$text = str_replace("\\195\\175", "ï", $text); |
$text = str_replace("\\195\\176", "ð", $text); |
$text = str_replace("\\195\\177", "ñ", $text); |
$text = str_replace("\\195\\178", "ò", $text); |
$text = str_replace("\\195\\179", "ó", $text); |
$text = str_replace("\\195\\180", "ô", $text); |
$text = str_replace("\\195\\181", "õ", $text); |
$text = str_replace("\\195\\184", "ø", $text); |
$text = str_replace("\\195\\185", "ù", $text); |
$text = str_replace("\\195\\186", "ú", $text); |
$text = str_replace("\\195\\187", "û", $text); |
$text = str_replace("\\195\\189", "ý", $text); |
$text = str_replace("\\195\\191", "ÿ", $text); |
$text = str_replace("\\195\\132", "Ä", $text); |
$text = str_replace("\\195\\134", "Æ", $text); |
$text = str_replace("\\195\\150", "Ö", $text); |
$text = str_replace("\\195\\156", "Ü", $text); |
$text = str_replace("\\195\\158", "Þ", $text); |
$text = str_replace("\\195\\159", "ß", $text); |
$text = str_replace("\\195\\164", "ä", $text); |
$text = str_replace("\\195\\166", "æ", $text); |
$text = str_replace("\\195\\182", "ö", $text); |
$text = str_replace("\\195\\188", "ü", $text); |
$text = str_replace("\\195\\190", "þ", $text); |
$text = str_replace("\\038", "&", $text); |
$text = str_replace("\\033","!", $text); |
$text = str_replace("\\035","#", $text); |
$text = str_replace( "\\036","$", $text); |
$text = str_replace( "\\037", "%",$text); |
$text = str_replace("\\063","?", $text); |
$text = str_replace("\\064", "@", $text); |
return $text; |
} |
function xmlstringtoarray($xml) { |
$parser = xml_parser_create("ISO-8859-1"); |
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false); |
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, false); |
xml_parse_into_struct($parser, $xml, $values, $index); |
xml_parser_free($parser); |
$return = array(); |
$stack = array(); |
foreach($values as $val) { |
if($val['type'] == "open") { |
array_push($stack, $val['tag']); |
} elseif($val['type'] == "close") { |
array_pop($stack); |
} elseif($val['type'] == "complete") { |
array_push($stack, $val['tag']); |
setArrayValue($return, $stack, $val['value']); |
array_pop($stack); |
} |
} |
return $return; |
} |
function setArrayValue(&$array, $stack, $value) { |
if ($stack) { |
$key = array_shift($stack); |
setArrayValue($array[$key], $stack, $value); |
return $array; |
} else { |
$array = $value; |
} |
} |
function FetchAliases($eqdkp, $table_prefix, $name) { |
if (mysql_select_db($eqdkp)) { |
$result = mysql_query("SELECT alias_id, alias_name, alias_member_id, member_name, member_id |
FROM " . $table_prefix . 'ctrt_aliases' . ", " . $table_prefix . 'members' . |
" WHERE member_id = alias_member_id AND member_name = '$name'"); |
$temp = array(); |
if ($result) { |
while ($row = mysql_fetch_array($result)) { |
$temp[] = array("alias_id"=>$row["alias_id"], |
"alias_name"=>stripslashes($row["alias_name"]), |
"alias_member_id"=>$row["alias_member_id"], |
"member_name"=>stripslashes($row["member_name"]), |
"member_id"=>$row["member_id"]); |
} |
} |
return $temp; |
} else mysql_error(); |
} |
function FetchAllAliases($eqdkp, $table_prefix) { |
if (mysql_select_db($eqdkp)) { |
$result = mysql_query("SELECT alias_id, alias_name, alias_member_id, member_name, member_id |
FROM " . $table_prefix . 'ctrt_aliases' . ", " . $table_prefix . 'members' . |
" WHERE member_id = alias_member_id"); |
$temp = array(); |
if ($result) { |
while ($row = mysql_fetch_array($result)) { |
$temp[] = array("alias_id"=>$row["alias_id"], |
"alias_name"=>stripslashes($row["alias_name"]), |
"alias_member_id"=>$row["alias_member_id"], |
"member_name"=>stripslashes($row["member_name"]), |
"member_id"=>$row["member_id"]); |
} |
} |
return $temp; |
} else mysql_error(); |
} |
function CreateAliasDB($eqdkp, $table_prefix) { |
if (mysql_select_db($eqdkp)) { |
$result = mysql_query("CREATE TABLE IF NOT EXISTS `". $table_prefix . 'ctrt_aliases' . "` ( |
`alias_id` smallint unsigned NOT NULL auto_increment, |
`alias_member_id` mediumint NOT NULL, |
`alias_name` varchar(50) NOT NULL, |
PRIMARY KEY (`alias_id`));"); |
if ($result) return true; |
return false; |
} else mysql_error(); |
} |
function CheckAlias($names, $eqdkp, $table_prefix) { |
$aliases = FetchAllAliases($eqdkp, $table_prefix); |
if (empty($aliases)) return $names; |
foreach ($names as $num => $alt) { |
$alt = rtrim($alt); |
$alt = ucwords($alt); |
foreach ($aliases as $alias) { |
if ($alt == $alias['alias_name']) { |
$names[$num] = $alias['member_name']; |
break; |
} |
} |
} |
return $names; |
} |
function FetchMember($eqdkp, $table_prefix, $name) { |
if (mysql_select_db($eqdkp)) { |
$result = mysql_query("SELECT member_name, member_id FROM " . $table_prefix . 'members' . " WHERE member_name = '$name'") |
or mysql_error(); |
while ($row = mysql_fetch_array($result)) { |
$temp = $row['member_id']; |
} |
return $temp; |
} else mysql_error(); |
} |
function FetchAllMembers($eqdkp, $table_prefix) { |
if (mysql_select_db($eqdkp)) { |
$result = mysql_query("SELECT * FROM " . $table_prefix . 'members' . " ORDER BY member_name") |
or mysql_error(); |
while ($row = mysql_fetch_array($result)) { |
$temp[stripslashes($row['member_name'])] = array('member_id'=>$row['member_id'], |
'member_earned'=>$row['member_earned'], |
'member_spent'=>$row['member_spent'], |
'member_adjustment'=>$row['member_adjustment'], |
'member_status'=>$row['member_status'], |
'member_firstraid'=>$row['member_firstraid'], |
'member_lastraid'=>$row['member_lastraid'], |
'member_raidcount'=>$row['member_raidcount'], |
'member_level'=>$row['member_level'], |
'member_race_id'=>$row['member_race_id'], |
'member_class_id'=>$row['member_class_id'], |
'member_rank_id'=>$row['member_rank_id']); |
} |
return $temp; |
} else mysql_error(); |
} |
function FetchAllEvents($eqdkp, $table_prefix) { |
if (mysql_select_db($eqdkp)) { |
$result = mysql_query("SELECT event_id, event_name, event_value FROM " . $table_prefix . 'events' . " ORDER BY event_name") |
or mysql_error(); |
while ($row = mysql_fetch_array($result)) { |
$temp[stripslashes($row['event_name'])] = array('event_id'=>$row['event_id'], 'event_value'=>$row['event_value'], 'event_name'=>$row['event_name']); |
} |
return $temp; |
} else mysql_error(); |
} |
function FetchAllRaces($eqdkp, $table_prefix) { |
if (mysql_select_db($eqdkp)) { |
$result = mysql_query("SELECT race_id, race_name FROM " . $table_prefix . 'races' ) |
or mysql_error(); |
while ($row = mysql_fetch_array($result)) { |
$temp[$row['race_name']] = $row['race_id']; |
} |
return $temp; |
} else mysql_error(); |
} |
function FetchAllClasses($eqdkp, $table_prefix) { |
if (mysql_select_db($eqdkp)) { |
$result = mysql_query("SELECT class_id, class_name FROM " . $table_prefix . 'classes' ) |
or mysql_error(); |
while ($row = mysql_fetch_array($result)) { |
$temp[$row['class_name']] = $row['class_id']; |
} |
return $temp; |
} else mysql_error(); |
} |
function AddNEWMember($membername, $otherdata, $data, $eqdkp, $table_prefix) { |
$user = $GLOBALS['DKPUSER']; |
$data['member_earned'] = '0'; |
$data['member_spent'] = '0'; |
if (mysql_select_db($eqdkp)) { |
$sql = "INSERT INTO " . $table_prefix . 'members' . " (" . join(',', array_keys($data)) . ") VALUES (" . join(',', array_values($data)) . ")"; |
//echo $sql; |
$result = mysql_query($sql); |
if (!$result) echo "!addnew" . mysql_error(); |
$log_action = array('header' => '{L_ACTION_MEMBER_ADDED}', |
'{L_NAME}' => addslashes($membername), |
'{L_EARNED}' => '0', |
'{L_SPENT}' => '0', |
'{L_ADJUSTMENT}' => $data['member_adjustment'], |
'{L_LEVEL}' => $data['member_level'], |
'{L_RACE}' => $otherdata['race'], |
'{L_CLASS}' => $otherdata['class'], |
'{L_ADDED_BY}' => addslashes($user)); |
LogAction($eqdkp, $table_prefix, $log_action); |
return true; |
} else echo mysql_error(); |
return false; |
} |
function UpdateEvent($eventname, $olddata, $eventdata, $eqdkp, $table_prefix) { |
$newval = $eventdata['value']; |
$eventid = $olddata['event_id']; |
$user = $GLOBALS['DKPUSER']; |
if (mysql_select_db($eqdkp)) { |
$sql = "UPDATE " . $table_prefix . 'events' . " SET event_name = '" . addslashes($eventname) . "', event_value = $newval, event_updated_by = '" |
. addslashes($user) . "' WHERE event_id = '$eventid'"; |
//echo $sql; |
$result = mysql_query($sql); |
if (!$result) echo "!upevent" . mysql_error(); |
$log_action = array('header' => '{L_ACTION_EVENT_UPDATED}', |
'id' => $eventid, |
'{L_NAME_BEFORE}' => addslashes($olddata['event_name']), |
'{L_VALUE_BEFORE}' => $olddata['event_value'], |
'{L_NAME_AFTER}' => addslashes($eventname), |
'{L_VALUE_AFTER}' => $newval, |
'{L_UPDATED_BY}' => addslashes($user)); |
LogAction($eqdkp, $table_prefix, $log_action); |
return true; |
} else echo mysql_error(); |
return false; |
} |
function CreateEvent($eventname, $eventdata, $eqdkp, $table_prefix) { |
$user = $GLOBALS['DKPUSER']; |
if (mysql_select_db($eqdkp)) { |
$sql = "INSERT INTO " . $table_prefix . 'events' . " (event_name, event_value, event_added_by) |
VALUES ('" . addslashes($eventname) . "','" . $eventdata['value'] . "','" . addslashes($user) . "')"; |
//echo $sql; |
$result = mysql_query($sql); |
if (!$result) echo "!createevent" . mysql_error(); |
$log_action = array('header' => '{L_ACTION_EVENT_ADDED}', |
'id' => mysql_insert_id(), |
'{L_NAME}' => addslashes($eventname), |
'{L_VALUE}' => $eventdata['value'], |
'{L_ADDED_BY}' => addslashes($user)); |
LogAction($eqdkp, $table_prefix, $log_action); |
return true; |
} else echo mysql_error(); |
return false; |
} |
function IsMulti($eqdkp, $table_prefix) { |
if (mysql_select_db($eqdkp)) { |
$sql = "SHOW TABLES FROM $eqdkp LIKE '" . $table_prefix . "plus_config'"; |
//echo $sql; |
$result = mysql_query($sql); |
$row = mysql_fetch_array($result); |
if ($row) return true; |
} |
return false; |
} |
function AddMultiAdjustment($name, $change, $eqdkp, $table_prefix, $key) { |
$user = $GLOBALS['DKPUSER']; |
$time = time(); |
$members = FetchAllMembers($eqdkp, $table_prefix); |
$name = rtrim($name); |
if (!$members[$name]) { |
$newmember = array('member_name'=>"'" . addslashes($name) . "'", |
'member_class_id'=>'0', |
'member_race_id'=>'0'); |
AddNEWMember($name, nil, $newmember, $eqdkp, $table_prefix); |
} |
if (mysql_select_db($eqdkp)) { |
if (IsMulti($eqdkp, $table_prefix)) { |
$sql = "INSERT INTO " . $table_prefix . 'adjustments' . " (adjustment_value, adjustment_date, member_name, adjustment_reason, adjustment_added_by, adjustment_group_key, raid_name) |
VALUES ('" . $change['value'] . "','$time','$name','" . $change['event'] . "','$user','$key','" . $change['event'] . "')"; |
} else { |
$sql = "INSERT INTO " . $table_prefix . 'adjustments' . " (adjustment_value, adjustment_date, member_name, adjustment_reason, adjustment_added_by, adjustment_group_key) |
VALUES ('" . $change['value'] . "','$time','$name','" . $change['event'] . "','$user','$key')"; |
} |
//echo $sql; |
$result = mysql_query($sql); |
if (!$result) echo "!addmultiadj" . mysql_error(); |
return true; |
} else echo mysql_error(); |
return false; |
} |
function UpdateMember($membername, $olddata, $change, $eqdkp, $table_prefix, $report) { |
$user = $GLOBALS['DKPUSER']; |
$listdata = array(); |
foreach ($change as $key => $value) { |
if ($value != '' and $olddata[$key] != $value) $listdata[] = $key . '=' . $value; |
} |
if (empty($listdata)) return; |
if (mysql_select_db($eqdkp)) { |
$sql = "UPDATE " . $table_prefix . 'members' . " SET " . join(',', $listdata) . " WHERE member_name = '" . addslashes($membername) . "'"; |
//echo $sql; |
$result = mysql_query($sql); |
if (!$result) echo "!updatemem" . mysql_error(); |
if ($report) { |
$log_action = array('header' => '{L_ACTION_MEMBER_UPDATED}', |
'{L_NAME_BEFORE}' => addslashes($membername), |
'{L_EARNED_BEFORE}' => $olddata['member_earned'], |
'{L_SPENT_BEFORE}' => $olddata['member_spent'], |
'{L_ADJUSTMENT_BEFORE}' => $olddata['member_adjustment'], |
'{L_LEVEL_BEFORE}' => $olddata['member_level'], |
'{L_RACE_BEFORE}' => $olddata['member_race_id'], |
'{L_CLASS_BEFORE}' => $olddata['member_class_id'], |
'{L_NAME_AFTER}' => addslashes($membername), |
'{L_EARNED_AFTER}' => !empty($change['member_earned']) ? $change['member_earned'] : $olddata['member_earned'], |
'{L_SPENT_AFTER}' => !empty($change['member_spent']) ? $change['member_spent'] : $olddata['member_spent'], |
'{L_ADJUSTMENT_AFTER}' => !empty($change['member_adjustment']) ? $change['member_adjustment'] : $olddata['member_adjustment'], |
'{L_LEVEL_AFTER}' => !empty($change['member_level']) ? $change['member_level'] : $olddata['member_level'], |
'{L_RACE_AFTER}' => !empty($change['member_race_id']) ? $change['member_race_id'] : $olddata['member_race_id'], |
'{L_CLASS_AFTER}' => !empty($change['member_class_id']) ? $change['member_class_id'] : $olddata['member_class_id'], |
'{L_UPDATED_BY}' => addslashes($user)); |
LogAction($eqdkp, $table_prefix, $log_action); |
} |
return true; |
} else echo mysql_error(); |
return false; |
} |
function CreateRaid($raid, $zonedata, $eventdata, $eqdkp, $table_prefix) { |
$user = $GLOBALS['DKPUSER']; |
$raiddate = TimestringtoTimestamp($raid['time']); |
if (mysql_select_db($eqdkp)) { |
$sql = "INSERT INTO " . $table_prefix . 'raids' . " (raid_name, raid_date, raid_note, raid_value, raid_added_by) |
VALUES ('" . addslashes($raid['name']) . "','$raiddate','" . addslashes($raid['note']) . "','" |
. $raid['value'] . "','" . addslashes($user) . "')"; |
//echo $sql; |
$result = mysql_query($sql); |
if (!$result) echo "!createraid" . mysql_error(); |
$raidid = mysql_insert_id(); |
$log_action = array('header' => '{L_ACTION_RAID_ADDED}', |
'id' => $raidid, |
'{L_EVENT}' => addslashes($raid['name']), |
'{L_ATTENDEES}' => implode(", ", $raid['attendees']), |
'{L_NOTE}' => addslashes($raid['note']), |
'{L_VALUE}' => $raid['value'], |
'{L_ADDED_BY}' => addslashes($user)); |
LogAction($eqdkp, $table_prefix, $log_action); |
return $raidid; |
} else echo mysql_error(); |
return false; |
} |
function AddRaidAttendees($raidid, $memberdata, $attendees, $eqdkp, $table_prefix) { |
$user = $GLOBALS['DKPUSER']; |
$values = array(); |
foreach ($attendees as $name) { |
$name =rtrim($name); |
$values[] = "('" . $raidid . "','" . addslashes($name) . "')"; |
} |
if (mysql_select_db($eqdkp)) { |
$sql = "INSERT INTO " . $table_prefix . 'raid_attendees' . " (raid_id, member_name) VALUES " . implode(', ', $values); |
//echo $sql; |
$result = mysql_query($sql); |
if (!$result) echo "!addraidattendees" . mysql_error(); |
} else echo mysql_error(); |
} |
function AddRaidItem($raid_id, $loot, $eqdkp, $table_prefix) { |
$user = $GLOBALS['DKPUSER']; |
$loottime = TimestringtoTimestamp($loot['Time']); |
$groupkey = gen_group_key($loot['ItemName'], $loottime, $raid_id); |
$loot['ItemName'] = addslashes($loot['ItemName']); |
$loot['Player'] = addslashes($loot['Player']); |
if (mysql_select_db($eqdkp)) { |
$sql = "INSERT INTO " . $table_prefix . 'items' . " (item_name, item_buyer, raid_id, item_value, item_date, item_added_by, item_group_key) |
VALUES ('" . rtrim($loot['ItemName']) . "','" . rtrim($loot['Player']) . "','$raid_id','" . $loot['Costs'] . |
"','$loottime','$user','$groupkey')"; |
//echo $sql; |
$result = mysql_query($sql); |
if (!$result) echo "!addraiditem" . mysql_error(); |
$log_action = array('header' => '{L_ACTION_ITEM_ADDED}', |
'{L_NAME}' => addslashes($loot['ItemName']), |
'{L_BUYERS}' => addslashes($loot['Player']), |
'{L_RAID_ID}' => $raid_id, |
'{L_VALUE}' => $loot['Costs'], |
'{L_ADDED_BY}' => addslashes($user)); |
LogAction($eqdkp, $table_prefix, $log_action); |
} else echo mysql_error(); |
} |
function LogAction($eqdkp, $table_prefix, $log_action) { |
$user = addslashes($GLOBALS['USERID']); |
$str_action = "\$log_action = array("; |
foreach ( $log_action as $k => $v ) |
{ |
$str_action .= "'" . $k . "' => '" . $v . "',"; |
} |
$action = substr($str_action, 0, strlen($str_action)- 1) . ");"; |
$action = addslashes($action); |
if (mysql_select_db($eqdkp)) { |
$sql = "INSERT INTO " . $table_prefix . 'logs' . " (log_date, log_type, log_action, log_ipaddress, log_sid, log_result, admin_id) |
VALUES ('" . time() . "','" . $log_action['header'] . "','$action','" . $_SERVER['REMOTE_ADDR'] . "','" |
. session_id() . "','{L_SUCCESS}','$user')"; |
//echo $sql; |
$result = mysql_query($sql); |
if (!$result) echo "!LOG" . mysql_error(); |
} else echo mysql_error(); |
} |
function TimestringtoTimestamp($timestring) { |
list($month, $day, $year, $hr, $mi, $s) = split('[/:-\ \]', $timestring); |
$stamp = mktime($hr, $mi, $s, $month, $day, $year); |
return $stamp; |
} |
function Arraydiff($arr1, $arr2) { |
$diff = array_diff_assoc($arr1, $arr2); |
foreach ($diff as $key => $value) { |
$arr2[$key] = $value; |
} |
return $arr2; |
} |
function array_merge_keys($arr1, $arr2) { |
foreach($arr2 as $k=>$v) { |
if (!array_key_exists($k, $arr1)) { |
$arr1[$k]=$v; |
} |
else { |
if (is_array($v)) { |
$arr1[$k]=array_merge_keys($arr1[$k], $arr2[$k]); |
} |
} |
} |
return $arr1; |
} |
function stripslashes_deep($value) |
{ |
$value = is_array($value) ? |
array_map('stripslashes_deep', $value) : |
stripslashes($value); |
return $value; |
} |
function gen_group_key($part1, $part2, $part3) { |
// Normalize data |
$part1 = htmlspecialchars(stripslashes($part1)); |
$part2 = htmlspecialchars(stripslashes($part2)); |
$part3 = htmlspecialchars(stripslashes($part3)); |
// Get the first 10-11 digits of each md5 hash |
$part1 = substr(md5($part1), 0, 10); |
$part2 = substr(md5($part2), 0, 11); |
$part3 = substr(md5($part3), 0, 11); |
// Group the hashes together and create a new hash based on uniqid() |
$group_key = $part1 . $part2 . $part3; |
$group_key = md5(uniqid($group_key)); |
return $group_key; |
} |
function CheckRace($member) { |
if ($member['race'] == "NightElf") $member['race'] = "Night Elf"; |
elseif ($member['race'] == "BloodElf") $member['race'] = "Blood Elf"; |
return $member; |
} |
function restoretext_deep($value) |
{ |
$value = is_array($value) ? |
array_map('restoretext', $value) : |
restoretext($value); |
return $value; |
} |
?> |
<?php |
session_start(); |
define('EQDKP_INC', true); |
define('IN_ADMIN', true); |
define('PLUGIN', 'ctrt'); |
$eqdkp_root_path = './../../'; |
$admin_path = $eqdkp_root_path . "admin/index.php?s=/"; |
require($eqdkp_root_path . 'config.php'); |
require($eqdkp_root_path . 'common.php'); |
require('Morgfunc.php'); |
function Addaliases($aliases) { |
global $Switches, $newalts; |
if (!empty($aliases)) { |
foreach ($aliases as $table) { |
$main = stripslashes(restoretext($table['main'])); |
$alt = stripslashes(restoretext($table['alt'])); |
$currentaliases = FetchAliases($table['eqdkp'], $table['prefix'], $main); |
$exists = false; |
$memberid = $currentaliases[0]['member_id'] OR false; |
if (!$memberid) { |
$memberid = FetchMember($table['eqdkp'], $table['prefix'], $main) OR false; |
if (!$memberid) $exists = true; |
} |
if (!$exists) { |
$newalts[] = array('alt'=>$alt, 'main'=>$main, 'eqdkp'=>$table['eqdkp'], 'prefix'=>$table['prefix'], 'id'=>$memberid, 'action'=>$table['action']); |
$Switches['alias'] = true; |
} else { |
$newalts[] = array('alt'=>$alt, 'main'=>$main, 'eqdkp'=>$table['eqdkp'], 'prefix'=>$table['prefix'], 'id'=>$memberid, 'action'=>'NO MAIN!'); |
$Switches['alias'] = true; |
} |
} |
} |
if (!empty($newalts)) $_SESSION['passalts'] = $newalts; |
} |
function ChangeDKP($changes) { |
global $needchanged, $Switches; |
if (!empty($changes)) { |
foreach ($changes as $change) { |
$name = stripslashes(restoretext($change['name'])); |
$change['members'] = CheckAlias($change['members'], $change['eqdkp'], $change['prefix']); |
$needchanged[] = array('addtype'=>$change['addtype'], 'name'=>$name, 'value'=>$change['value'], 'eqdkp'=>$change['eqdkp'], 'prefix'=>$change['prefix'], 'event'=>$change['event'], 'members'=>$change['members']); |
} |
} |
if (!empty($needchanged)) { |
$_SESSION['dkpchange'] = $needchanged; |
$Switches['dkpchange'] = true; |
} |
} |
function Addraids($raids) { |
global $RAID, $Switches; |
$i = 0; |
if (!empty($raids)) { |
foreach ($raids as $raid) { |
$RAID[$i]['zone'] = stripslashes($raid['zone']); |
$RAID[$i]['date'] = $raid['date']; |
$RAID[$i]['eqdkp'] = $raid['eqdkp']; |
$RAID[$i]['prefix'] = $raid['prefix']; |
foreach ($raid['Attendees'] as $attend) { |
$name = stripslashes(restoretext($attend['name'])); |
$RAID[$i]['attendees'][$name] = array('race'=>$attend['race'], 'class'=>$attend['class'], 'level'=>$attend['level']); |
} |
$eventindex = 0; |
$webevents = FetchAllEvents($raid['eqdkp'], $raid['prefix']); |
if ($raid['Bosskills']) { |
foreach ($raid['Bosskills'] as $boss) { |
$bossname = stripslashes(restoretext($boss['name'])); |
$bossnote = stripslashes(restoretext($boss['note'])); |
$attend = restoretext_deep($boss['attendees']); |
$attend = stripslashes_deep($attend); |
$attend = CheckAlias($attend, $raid['eqdkp'], $raid['prefix']); |
asort($attend); |
$attend = array_unique($attend); |
$RAID[$i]['events'][$eventindex] = array('name'=>$bossname, 'note'=>$bossnote,'value'=>$boss['value'], 'time'=>$boss['time'], 'attendees'=>$attend, 'trash'=>$boss['trash'], 'index'=>$eventindex); |
$eventindex++; |
} |
} |
$trashdone = false; |
if ($RAID[$i]['events']) { |
foreach ($RAID[$i]['events'] as $index => $event) { |
$trashcounter = 0; |
$lootnumber = 0; |
if ($raid['Loot']) { |
foreach ($raid['Loot'] as $loot) { |
$loot = restoretext_deep($loot); |
$loot = stripslashes_deep($loot); |
if ($event['note'] == $loot['Boss']) { |
$index = $event['index']; |
$isalias = CheckAlias(array('0' => $loot['Player']), $raid['eqdkp'], $raid['prefix']); |
$loot['Player'] = $isalias[0]; |
$RAID[$i]['loot'][$index][$lootnumber] = $loot; |
$lootnumber++; |
} |
if (!$trashdone and $loot['Boss'] == "Trash mob") { |
$isalias = CheckAlias(array('0' => $loot['Player']), $raid['eqdkp'], $raid['prefix']); |
$loot['Player'] = $isalias[0]; |
$RAID[$i]['loot']['Trash mob'][$trashcounter] = $loot; |
$trashcounter++; |
} |
} |
$trashdone = true; |
} |
} |
$i++; |
} |
} |
if (!empty($RAID)) { |
$_SESSION['RAID'] = $RAID; |
$Switches['raids'] = true; |
} |
} |
} |
$link = mysql_connect($dbhost, $dbuser, $dbpass); |
if (!$link) die('Could not connect: ' . mysql_error()); |
$retrieve = $_POST['data']; |
global $Switches, $newalts, $needchanged, $RAID, $DKP, $DKPUSER, $USERID; |
$DKPUSER = $user->data['username']; |
$USERID = $user->data['user_id']; |
$_SESSION['passalts'] = ""; |
$_SESSION['dkpchange'] = ""; |
$_SESSION['RAID'] = ""; |
$DKP = array(); |
$RAID = array(); |
$Switches = array(); |
$newalts = array(); |
$needchanged = array(); |
$temp = array(); |
$temp = converthtml($retrieve); |
$temp = xmlstringtoarray($temp); |
$DKP = $temp['MorgDKP']; |
//echo "<pre>"; |
//print_r($DKP); |
//echo "</pre>"; |
foreach ($DKP as $eventtype => $table) { |
switch ($eventtype) { |
case 'Aliases': |
Addaliases($table); |
break; |
case 'DKPChanges': |
ChangeDKP($table); |
break; |
case 'Raids': |
Addraids($table); |
break; |
} |
} |
?> |
<html> |
<head> |
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> |
<style type="text/css"> |
h1 {text-align: right; margin-right: 20px; font-size: 12px} |
</style> |
</head> |
<body style="font-family: Arial; font-size: 16px; background-color: #101030; color: #FDFDFD; padding-left: 100px; padding-right: 100px; padding-top: 20px;"> |
<form action="Morgresults.php" method="post" name="[object]"> |
<h1><a href="<?php echo $admin_path?>" target="_self" style="color: #FDFDFD;">Return to eqDKP Admin</a></h1> |
<b><u>MorgDKP Import</b></u> |
<br> |
<br> |
<?php if ($Switches['dkpchange']): ?> |
<u><b>DKP adjustments to be added to Database:</u></b><br><br> |
<table border="1" cellpadding="12"> |
<tr><td><strong>Member </strong></td><td><strong>Adjustment </strong></td><td><strong>Database </strong></td><td><strong>Event/Note </strong></td></tr> |
<?php $i = 0; |
while($needchanged[$i]): |
if ($needchanged[$i]['addtype'] == "Group" ) { |
$changevalue[$i]['members'] = implode("\n", $needchanged[$i]['members']);?> |
<tr><td><textarea style="width: 150px; height: 100px;" name="changevalue[<?php echo $i?>][members]" ><?php echo $changevalue[$i]['members']?></textarea></td><td><input name="changevalue[<?php echo $i?>][value]" size="3" value="<?php echo $needchanged[$i]['value']?>"></td><td><?php echo $needchanged[$i]['eqdkp']?></td><td><?php echo $needchanged[$i]['event']?></td></tr> |
<?php } else {?> |
<tr><td><input name="changevalue[<?php echo $i?>][members]" size="20" value="<?php echo $needchanged[$i]['name']?>"></td><td><input name="changevalue[<?php echo $i?>][value]" size="3" value="<?php echo $needchanged[$i]['value']?>"></td><td><?php echo $needchanged[$i]['eqdkp']?></td><td><?php echo $needchanged[$i]['event']?></td></tr> |
<?php } |
$i++; endwhile;?> |
</table> |
<hr> |
<?php endif; |
if ($Switches['alias']): ?> |
<u><b>Alias changes to Database:</u></b><br><br> |
<table border="1" cellpadding="12"> |
<tr><td><strong>Alt </strong></td><td><strong>Main </strong></td><td><strong>Database </strong></td><td><strong>Action </strong></td></tr> |
<?php $i = 0; |
while($newalts[$i]): ?> |
<tr><td><input name="altfield[<?php echo $i?>][alt]" value="<?php echo $newalts[$i]['alt']?>"></td><td><?php echo $newalts[$i]['main']?></td><td><?php echo $newalts[$i]['eqdkp']?></td><td><?php echo $newalts[$i]['action']?></td></tr> |
<?php $i++; endwhile;?> |
</table> |
<hr> |
<?php endif; |
if ($Switches['raids']): ?> |
<u><b>Raids to be added to Database:</u></b> |
<br><br> |
<?php $i = 0; |
while($RAID[$i]): ?> |
<b>Database: </b> <?php echo $RAID[$i]['eqdkp']?><br><br> |
<b>Zone</b> <input name="raidfield[<?php echo $i?>][zone]" value="<?php echo $RAID[$i]['zone']?>"> Use 0-sum DKP <input type="checkbox" name="raidfield[<?php echo $i?>][zsum]"><br><br> |
<?php $event = 0; |
while ($RAID[$i]['events'][$event]): ?> |
<b>Event</b> <input name="raidfield[<?php echo $i?>][events][<?php echo $event?>][name]" size="40" value="<?php echo $RAID[$i]['events'][$event]['name']?>"><br> |
<b>Note</b> <input name="raidfield[<?php echo $i?>][events][<?php echo $event?>][note]" size="40" value="<?php echo $RAID[$i]['events'][$event]['note']?>"><br> |
<b>Value</b> <input name="raidfield[<?php echo $i?>][events][<?php echo $event?>][value]" size="3" value="<?php echo $RAID[$i]['events'][$event]['value']?>"><br> |
<b>Time</b> <?php echo $RAID[$i]['events'][$event]['time']?><br><br> |
<?php $raidfield[$i]['events'][$event]['attendees'] = implode("\n", $RAID[$i]['events'][$event]['attendees']);?> |
<b>Attendees</b><br> <textarea style="width: 150px; height: 300px;" name="raidfield[<?php echo $i?>][events][<?php echo $event?>][attendees]"><?php echo $raidfield[$i]['events'][$event]['attendees'] ?></textarea><br> |
<?php $loot = 0; |
while ($RAID[$i]['loot'][$RAID[$i]['events'][$event]['index']][$loot]): |
$eventname = $RAID[$i]['events'][$event]['index']; ?> |
<br> |
<input name="raidfield[<?php echo $i?>][loot][<?php echo $eventname?>][<?php echo $loot?>][ItemName]" size="30" value="<?php echo $RAID[$i]['loot'][$eventname][$loot]['ItemName']?>"><br> |
|
<input name="raidfield[<?php echo $i?>][loot][<?php echo $eventname?>][<?php echo $loot?>][Costs]" size="30" value="<?php echo $RAID[$i]['loot'][$eventname][$loot]['Costs']?>"><br> |
|
<input name="raidfield[<?php echo $i?>][loot][<?php echo $eventname?>][<?php echo $loot?>][Player]" size="30" value="<?php echo $RAID[$i]['loot'][$eventname][$loot]['Player']?>"><br> |
<?php $loot++; endwhile; |
if ($RAID[$i]['loot']['Trash mob'][0] and $RAID[$i]['events'][$event]['trash'] == 2): |
$tloot = 0;?> |
<br> |
<?php while ($RAID[$i]['loot']['Trash mob'][$tloot]): ?> |
|
<input name="raidfield[<?php echo $i?>][loot][Trash mob][<?php echo $tloot?>][ItemName]" size="30" value="<?php echo $RAID[$i]['loot']['Trash mob'][$tloot]['ItemName']?>"><br> |
|
<input name="raidfield[<?php echo $i?>][loot][Trash mob][<?php echo $tloot?>][Costs]" size="30" value="<?php echo $RAID[$i]['loot']['Trash mob'][$tloot]['Costs']?>"><br> |
|
<input name="raidfield[<?php echo $i?>][loot][Trash mob][<?php echo $tloot?>][Player]" size="30" value="<?php echo $RAID[$i]['loot']['Trash mob'][$tloot]['Player']?>"><br><br> |
<?php $tloot++; endwhile; |
endif;?> |
<br> |
<hr> |
<?php $event++; endwhile; ?> |
<hr> |
<?php $i++;endwhile; |
endif; ?> |
<br> |
<br> |
<input type="submit" value="Enter final data"><br> |
<br> |
<b><u>Note:</b></u> If you delete the run event all trash drops will be automatically moved to one of the other events that are listed. If you don't want to record: 1) <b>Event</b> - delete it's name 2) <b>Item</b> - delete it's name or winner. |
</form> |
</body> |
</html> |
MorgDKP_DKP1 = { |
Timestamp = 300120082034, |
Pool = "Outlands", |
eqdkpsite = "aqdkp", |
prefix = "eqdkp_", |
Points = { |
["Aerovox"] = {earn = 41.00,spent = 40.00,adj = 0.00,bal = 1}, |
["Aestralx"] = {earn = 121.00,spent = 120.00,adj = 0.00,bal = 1}, |
["Aifos"] = {earn = 9.00,spent = 0.00,adj = 0.00,bal = 9}, |
["Alibaba"] = {earn = 7.00,spent = 0.00,adj = 0.00,bal = 7}, |
["Amellena"] = {earn = 10.00,spent = 0.00,adj = 0.00,bal = 10}, |
["Amelyana"] = {earn = 369.00,spent = 290.00,adj = -85.00,bal = -6}, |
["Amoriana"] = {earn = 42.00,spent = 0.00,adj = 0.00,bal = 42}, |
["Arik"] = {earn = 15.00,spent = 0.00,adj = 0.00,bal = 15}, |
["Arlin"] = {earn = 85.00,spent = 60.00,adj = 0.00,bal = 25}, |
["Arlus"] = {earn = 655.00,spent = 475.00,adj = 0.00,bal = 180}, |
["Avelline"] = {earn = 447.00,spent = 325.00,adj = 0.00,bal = 122}, |
["Avnas"] = {earn = 36.00,spent = 0.00,adj = 0.00,bal = 36}, |
["Bethsheba"] = {earn = 636.00,spent = 295.00,adj = 0.00,bal = 341}, |
["Blexmark"] = {earn = 9.00,spent = 0.00,adj = 0.00,bal = 9}, |
["Boing"] = {earn = 9.00,spent = 0.00,adj = 0.00,bal = 9}, |
["Bratac"] = {earn = 33.00,spent = 0.00,adj = 0.00,bal = 33}, |
["Breat"] = {earn = 331.00,spent = 95.00,adj = 0.00,bal = 236}, |
["Celine"] = {earn = 199.00,spent = 65.00,adj = 0.00,bal = 134}, |
["Chaku"] = {earn = 40.00,spent = 0.00,adj = 0.00,bal = 40}, |
["Charei"] = {earn = 16.00,spent = 0.00,adj = 0.00,bal = 16}, |
["Cheeseshaman"] = {earn = 93.00,spent = 30.00,adj = 0.00,bal = 63}, |
["Cobrap"] = {earn = 299.00,spent = 195.00,adj = 0.00,bal = 104}, |
["Daddyx"] = {earn = 276.00,spent = 120.00,adj = -156.00,bal = 0}, |
["Dangfangdang"] = {earn = 263.00,spent = 60.00,adj = 0.00,bal = 203}, |
["Daun"] = {earn = 18.00,spent = 0.00,adj = 0.00,bal = 18}, |
["Deilliann"] = {earn = 566.00,spent = 270.00,adj = 0.00,bal = 296}, |
["Delaurina"] = {earn = 201.00,spent = 265.00,adj = 0.00,bal = -64}, |
["Donnar"] = {earn = 523.00,spent = 460.00,adj = 0.00,bal = 63}, |
["Doommonger"] = {earn = 19.00,spent = 0.00,adj = 0.00,bal = 19}, |
["Dorchleit"] = {earn = 58.00,spent = 0.00,adj = 0.00,bal = 58}, |
["Elanas"] = {earn = 18.00,spent = 0.00,adj = 0.00,bal = 18}, |
["Eljente"] = {earn = 668.00,spent = 105.00,adj = 0.00,bal = 563}, |
["Ema"] = {earn = 778.00,spent = 260.00,adj = 0.00,bal = 518}, |
["Eqthelious"] = {earn = 249.00,spent = 225.00,adj = -24.00,bal = 0}, |
["Esmeysuzial"] = {earn = 14.00,spent = 0.00,adj = 0.00,bal = 14}, |
["Extinguish"] = {earn = 9.00,spent = 0.00,adj = 0.00,bal = 9}, |
["Felian"] = {earn = 118.00,spent = 120.00,adj = 0.00,bal = -2}, |
["Firebaerd"] = {earn = 799.00,spent = 545.00,adj = 0.00,bal = 254}, |
["Fobainist"] = {earn = 548.00,spent = 225.00,adj = 0.00,bal = 323}, |
["Friedchicken"] = {earn = 299.00,spent = 180.00,adj = -105.00,bal = 14}, |
["Gazaus"] = {earn = 177.00,spent = 0.00,adj = 0.00,bal = 177}, |
["Grantm"] = {earn = 87.00,spent = 0.00,adj = -87.00,bal = 0}, |
["Grothgarn"] = {earn = 25.00,spent = 0.00,adj = 0.00,bal = 25}, |
["Haplo"] = {earn = 9.00,spent = 0.00,adj = 0.00,bal = 9}, |
["Hoadley"] = {earn = 14.00,spent = 0.00,adj = 0.00,bal = 14}, |
["Hoofhoof"] = {earn = 16.00,spent = 0.00,adj = 0.00,bal = 16}, |
["Hotstuff"] = {earn = 907.00,spent = 520.00,adj = 0.00,bal = 387}, |
["Icelight"] = {earn = 654.00,spent = 360.00,adj = 0.00,bal = 294}, |
["Icewalker"] = {earn = 7.00,spent = 0.00,adj = 0.00,bal = 7}, |
["Illilorn"] = {earn = 49.00,spent = 0.00,adj = 0.00,bal = 49}, |
["Infaredbeam"] = {earn = 127.00,spent = 120.00,adj = 0.00,bal = 7}, |
["Ironboy"] = {earn = 36.00,spent = 0.00,adj = 0.00,bal = 36}, |
["Jamjam"] = {earn = 7.00,spent = 0.00,adj = 0.00,bal = 7}, |
["Jany"] = {earn = 7.00,spent = 0.00,adj = 0.00,bal = 7}, |
["Jaycen"] = {earn = 336.00,spent = 210.00,adj = 0.00,bal = 126}, |
["Kahuano"] = {earn = 10.00,spent = 0.00,adj = 0.00,bal = 10}, |
["Kainnen"] = {earn = 28.00,spent = 65.00,adj = 0.00,bal = -37}, |
["Kaladen"] = {earn = 390.00,spent = 160.00,adj = -230.00,bal = 0}, |
["Karsten"] = {earn = 20.00,spent = 0.00,adj = 0.00,bal = 20}, |
["Khoss"] = {earn = 328.00,spent = 60.00,adj = -238.00,bal = 30}, |
["Killmasta"] = {earn = 273.00,spent = 120.00,adj = 0.00,bal = 153}, |
["Kobaiashi"] = {earn = 344.00,spent = 115.00,adj = 0.00,bal = 229}, |
["Kodama"] = {earn = 802.00,spent = 635.00,adj = 0.00,bal = 167}, |
["Krondrax"] = {earn = 55.00,spent = 35.00,adj = 0.00,bal = 20}, |
["Llyranel"] = {earn = 340.00,spent = 240.00,adj = 0.00,bal = 100}, |
["Lokiwolf"] = {earn = 81.00,spent = 120.00,adj = 0.00,bal = -39}, |
["Loxi"] = {earn = 634.00,spent = 350.00,adj = 0.00,bal = 284}, |
["Magdalena"] = {earn = 393.00,spent = 60.00,adj = 0.00,bal = 333}, |
["Malachi"] = {earn = 737.00,spent = 225.00,adj = 0.00,bal = 512}, |
["Manicotti"] = {earn = 23.00,spent = 0.00,adj = 0.00,bal = 23}, |
["Massmurder"] = {earn = 9.00,spent = 0.00,adj = -9.00,bal = 0}, |
["Mckenna"] = {earn = 268.00,spent = 165.00,adj = -103.00,bal = 0}, |
["Medeii"] = {earn = 82.00,spent = 0.00,adj = 0.00,bal = 82}, |
["Mistymind"] = {earn = 69.00,spent = 45.00,adj = 0.00,bal = 24}, |
["Morbia"] = {earn = 15.00,spent = 0.00,adj = 0.00,bal = 15}, |
["Morgalm"] = {earn = 1074.00,spent = 280.00,adj = 0.00,bal = 794}, |
["Mychemro"] = {earn = 485.00,spent = 300.00,adj = 0.00,bal = 185}, |
["Myrrin"] = {earn = 290.00,spent = 125.00,adj = 0.00,bal = 165}, |
["Neruid"] = {earn = 27.00,spent = 0.00,adj = 0.00,bal = 27}, |
["Newstranger"] = {earn = 34.00,spent = 130.00,adj = 0.00,bal = -96}, |
["Nienor"] = {earn = 13.00,spent = 0.00,adj = 0.00,bal = 13}, |
["Nightraptor"] = {earn = 809.00,spent = 215.00,adj = 0.00,bal = 594}, |
["Norber"] = {earn = 40.00,spent = 0.00,adj = 0.00,bal = 40}, |
["Nosh"] = {earn = 9.00,spent = 0.00,adj = 0.00,bal = 9}, |
["Ochie"] = {earn = 488.00,spent = 265.00,adj = 0.00,bal = 223}, |
["Panman"] = {earn = 186.00,spent = 0.00,adj = 0.00,bal = 186}, |
["Peggysuzy"] = {earn = 21.00,spent = 0.00,adj = 0.00,bal = 21}, |
["Preast"] = {earn = 9.00,spent = 0.00,adj = 0.00,bal = 9}, |
["Pynt"] = {earn = 276.00,spent = 120.00,adj = 0.00,bal = 156}, |
["Quicksilverx"] = {earn = 281.00,spent = 90.00,adj = 0.00,bal = 191}, |
["Raian"] = {earn = 25.00,spent = 0.00,adj = 0.00,bal = 25}, |
["Ravennite"] = {earn = 85.00,spent = 45.00,adj = 0.00,bal = 40}, |
["Rebelyo"] = {earn = 16.00,spent = 0.00,adj = 0.00,bal = 16}, |
["Renz"] = {earn = 67.00,spent = 70.00,adj = 0.00,bal = -3}, |
["Sekmet"] = {earn = 30.00,spent = 0.00,adj = 0.00,bal = 30}, |
["Shortlock"] = {earn = 48.00,spent = 0.00,adj = 0.00,bal = 48}, |
["Skih"] = {earn = 476.00,spent = 105.00,adj = 0.00,bal = 371}, |
["Slickrunner"] = {earn = 7.00,spent = 0.00,adj = 0.00,bal = 7}, |
["Smaldorf"] = {earn = 244.00,spent = 60.00,adj = 0.00,bal = 184}, |
["Sorella"] = {earn = 887.00,spent = 390.00,adj = 0.00,bal = 497}, |
["Squibe"] = {earn = 41.00,spent = 30.00,adj = 0.00,bal = 11}, |
["Stohaan"] = {earn = 63.00,spent = 0.00,adj = 0.00,bal = 63}, |
["Swordmaster"] = {earn = 14.00,spent = 0.00,adj = 0.00,bal = 14}, |
["Sylenas"] = {earn = 9.00,spent = 0.00,adj = 0.00,bal = 9}, |
["Taihou"] = {earn = 7.00,spent = 0.00,adj = -7.00,bal = 0}, |
["Taisch"] = {earn = 983.00,spent = 265.00,adj = 0.00,bal = 718}, |
["Tammyfay"] = {earn = 269.00,spent = 95.00,adj = 0.00,bal = 174}, |
["Tandese"] = {earn = 799.00,spent = 320.00,adj = 0.00,bal = 479}, |
["Teppistella"] = {earn = 7.00,spent = 0.00,adj = 0.00,bal = 7}, |
["Tigraine"] = {earn = 552.00,spent = 355.00,adj = 0.00,bal = 197}, |
["Tonnpa"] = {earn = 92.00,spent = 0.00,adj = 0.00,bal = 92}, |
["Twigge"] = {earn = 685.00,spent = 165.00,adj = 0.00,bal = 520}, |
["Ubin"] = {earn = 56.00,spent = 0.00,adj = 0.00,bal = 56}, |
["Vorge"] = {earn = 338.00,spent = 230.00,adj = -55.00,bal = 53}, |
["Vulkmarr"] = {earn = 31.00,spent = 120.00,adj = 0.00,bal = -89}, |
["Warpigwench"] = {earn = 14.00,spent = 0.00,adj = 0.00,bal = 14}, |
["Wempsey"] = {earn = 69.00,spent = 30.00,adj = 0.00,bal = 39}, |
["Winterbrook"] = {earn = 853.00,spent = 465.00,adj = 0.00,bal = 388}, |
["Zeropal"] = {earn = 729.00,spent = 470.00,adj = 0.00,bal = 259}, |
["Zoul"] = {earn = 1128.00,spent = 390.00,adj = 0.00,bal = 738}, |
["Zulander"] = {earn = 21.00,spent = 35.00,adj = 0.00,bal = -14} |
}, |
Aliases = { |
["Bethnei"] = "Bethsheba", |
["Bose"] = "Gazaus", |
["Denhaan"] = "Stohaan", |
["Fobain"] = "Fobainist", |
["Fobainmage"] = "Fobainist", |
["Fobainpally"] = "Fobainist", |
["Fobainwarloc"] = "Fobainist", |
["Genevieve"] = "Loxi", |
["Graycen"] = "Jaycen", |
["Hebridaire"] = "Taisch", |
["Holychicken"] = "Friedchicken", |
["Jaynie"] = "Panman", |
["Jeandra"] = "Deilliann", |
["Kaiselyn"] = "Kaladen", |
["Kellessa"] = "Avelline", |
["Loraelai"] = "Hotstuff", |
["Mckennapriest"] = "Mckenna", |
["Missfobain"] = "Fobainist", |
["Mogha"] = "Morgalm", |
["Moonmichelle"] = "Celine", |
["Nerunter"] = "Neruid", |
["Nightraven"] = "Winterbrook", |
["Oldidcithog"] = "Shortlock", |
["Saigas"] = "Tigraine", |
["Sakuraya"] = "Celine", |
["Shaollyr"] = "Llyranel", |
["Shiveget"] = "Vorge", |
["Snowlock"] = "Winterbrook", |
["Sorphrasia"] = "Sorella", |
["Thorvard"] = "Vulkmarr", |
["Trinny"] = "Peggysuzy", |
["Vladamir"] = "Krondrax" |
}, |
Events = { |
["Al'ar"] = {id = 78,value = 3.00}, |
["Al'ar Attempt"] = {id = 102,value = 1.00}, |
["Anetheron"] = {id = 95,value = 3.00}, |
["Archimonde"] = {id = 98,value = 3.00}, |
["Azgalor"] = {id = 97,value = 3.00}, |
["Black Temple Run"] = {id = 82,value = 7.00}, |
["Black Temple Start"] = {id = 81,value = 2.00}, |
["Essence of Souls"] = {id = 90,value = 3.00}, |
["Fathom-Lord Karathress"] = {id = 70,value = 3.00}, |
["Fathom-Lord Karathress Attempt"] = {id = 106,value = 1.00}, |
["Gruul the Dragonkiller"] = {id = 59,value = 3.00}, |
["Gruul's Lair Run"] = {id = 63,value = 7.00}, |
["Gruul's Lair Start"] = {id = 62,value = 2.00}, |
["Gurtogg Bloodboil"] = {id = 87,value = 3.00}, |
["High Astromancer Solarian"] = {id = 79,value = 3.00}, |
["High Astromancer Solarian Attempt"] = {id = 104,value = 1.00}, |
["High King Maulgar"] = {id = 60,value = 3.00}, |
["High Warlord Naj'entus"] = {id = 85,value = 3.00}, |
["Hydross the Unstable"] = {id = 69,value = 3.00}, |
["Hyjal Run"] = {id = 84,value = 7.00}, |
["Hyjal Start"] = {id = 83,value = 2.00}, |
["Illidan Stormrage"] = {id = 93,value = 3.00}, |
["Illidari Council"] = {id = 92,value = 3.00}, |
["Kael'thas Sunstrider"] = {id = 80,value = 3.00}, |
["Kaz'rogal"] = {id = 96,value = 3.00}, |
["Lady Vashj"] = {id = 73,value = 3.00}, |
["Lady Vashj Attempt"] = {id = 107,value = 1.00}, |
["Leotheras the Blind"] = {id = 72,value = 3.00}, |
["Leotheras the Blind Attempt"] = {id = 105,value = 1.00}, |
["Magtheridon"] = {id = 66,value = 3.00}, |
["Magtheridon Attempt"] = {id = 100,value = 1.00}, |
["Magtheridon's Lair Run"] = {id = 65,value = 7.00}, |
["Magtheridon's Lair Start"] = {id = 64,value = 2.00}, |
["Morogrim Tidewalker"] = {id = 71,value = 3.00}, |
["Mother Shahraz"] = {id = 91,value = 3.00}, |
["Nagrand Start"] = {id = 103,value = 0.00}, |
["Rage Winterchill"] = {id = 94,value = 3.00}, |
["Serpentshrine Cavern Attempt"] = {id = 101,value = 1.00}, |
["Serpentshrine Cavern Run"] = {id = 68,value = 7.00}, |
["Serpentshrine Cavern Start"] = {id = 67,value = 2.00}, |
["Shade of Akama"] = {id = 89,value = 3.00}, |
["Supremus"] = {id = 86,value = 3.00}, |
["Tempest Keep Run"] = {id = 75,value = 7.00}, |
["Tempest Keep Start"] = {id = 76,value = 2.00}, |
["Teron Gorefiend"] = {id = 88,value = 3.00}, |
["The Lurker Below"] = {id = 74,value = 3.00}, |
["The Lurker Below Attempt"] = {id = 99,value = 1.00}, |
["Void Reaver"] = {id = 77,value = 3.00} |
}, |
} |
<?php |
define('EQDKP_INC', true); |
define('IN_ADMIN', true); |
define('PLUGIN', 'ctrt'); |
$eqdkp_root_path = './../../'; |
$root_path = './../../../'; |
$admin_path = $eqdkp_root_path . "admin/index.php?s=/"; |
require('Morgfunc.php'); |
function CommonOutput() { |
global $data, $table_prefix, $events, $poolname, $eventlist; |
$result = mysql_query("SELECT alias_id, alias_name, alias_member_id, member_name |
FROM " . CTRT_ALIASES_TABLE . ", " . $table_prefix . 'members' . |
" WHERE member_id = alias_member_id ORDER BY alias_name"); |
if ($result) { |
$data .= "Aliases = {\n\t\t"; |
$c = 0; |
while ($row = mysql_fetch_array($result)) { |
if ($c > 0) $data .= ",\n\t\t"; |
$alias = converttext($row['alias_name']); |
$member = converttext($row['member_name']); |
$data .= "[\"$alias\"] = \"$member\""; |
$c++; |
} |
} else $data .= "Aliases = {"; |
if (!empty($eventlist)) { |
$data .= "\n\t},\n\tEvents = {\n\t\t"; |
$c = 0; |
foreach ($eventlist as $event => $eventdata) { |
if (empty($events) or $events[$event]['pool'] == $poolname) { |
$event = converttext($event); |
if ($c > 0) $data .= ",\n\t\t"; |
$data .= "[\"$event\"] = {id = {$eventdata['event_id']},value = {$eventdata['event_value']}}"; |
$c++; |
} |
} |
} else $data .= "\n\t},\n\tEvents = {"; |
$data .= "\n\t},"; |
$data .= "\n}\n"; |
$SaveLoc = 'DKPInfo.lua'; |
if (is_writable($SaveLoc)) { |
if (!$handle = fopen($SaveLoc, 'w')) { |
echo "Cannot open file ($SaveLoc)"; |
exit; |
} //else echo "opened file $SaveLoc"; |
if (fwrite($handle, $data) === FALSE) { |
echo "Cannot write to file ($SaveLoc)"; |
exit; |
} //else echo "Wrote to file $SaveLoc"; |
fclose($handle); |
} else echo "The file $SaveLoc is not writable"; |
} |
$retrieve = $_REQUEST['retrieve']; |
$data = ''; |
$timezones = array('Pacific'=>'America/Vancouver', 'Eastern'=>'America/New_York','Central'=>'America/Regina','Mountain'=>'America/Phoenix','AEST'=>'Australia/Melbourne', 'CET'=>'Europe/Berlin'); |
$php_version = phpversion(); |
if ($retrieve) { |
$eqDKP = $_REQUEST['eqDKP']; |
$DBName = $_REQUEST['DBName']; |
$tzone = $_REQUEST['tzone']; |
for ($c = 1; $c <= 5; $c++) { |
setcookie("DKPcook$c", $eqDKP[$c], time()+3600*24*365); |
setcookie("DBNamecook$c", $DBName[$c], time()+3600*24*365); |
} |
setcookie("TZonecook", $tzone, time()+3600*24*365); |
$DKP = array(); |
$c = 1; |
while (!empty($eqDKP[$c])) { |
$DKP[$c] = $eqDKP[$c]; |
$c++; |
} |
$offset = 0; |
if ($tzone and $php_version > 5) date_default_timezone_set($timezones[$tzone]); |
foreach ($DKP as $i => $pool) { |
require($root_path . $pool . '/config.php'); |
$link = mysql_connect($dbhost, $dbuser, $dbpass); |
if (!$link) { |
die('Could not connect: ' . mysql_error()); |
} //else echo "connected " . $dbhost; |
define('CTRT_ALIASES_TABLE', ($table_prefix . 'ctrt_aliases')); |
if (!mysql_select_db($dbname)) { |
die('Could not connect: ' . $dbname . mysql_error()); |
} //else echo "Connected " . $dbname; |
$events = array(); |
$pools = array(); |
$eventlist = FetchAllEvents($dbname, $table_prefix); |
$resultmulti = mysql_query("SELECT config_value FROM " . $table_prefix . "plus_config WHERE config_name = 'pk_multidkp'"); |
$result = mysql_query("SELECT * FROM " . $table_prefix . 'multidkp'); |
if ($resultmulti) { |
while ($row = mysql_fetch_array($result)) { |
$pools[$row['multidkp_id']] = $row['multidkp_name']; |
} |
$offset += count($pools) - 1; |
$result = mysql_query("SELECT * FROM " . $table_prefix . 'multidkp2event'); |
while ($row = mysql_fetch_array($result)) { |
$events[$row['multidkp2event_eventname']] = array( 'pool'=>$pools[$row['multidkp2event_multi_id']], |
'value'=>$eventlist[$row['multidkp2event_eventname']]['event_value']); |
} |
if (!$pools[1]) $pools[1] = $DBName[1] or "DKP"; |
foreach ($pools as $pluspoolnum => $poolname) { |
if ($i == 1) { |
$dkpnum = $pluspoolnum; |
} else $dkpnum = $i + $pluspoolnum; |
$data .= "MorgDKP_DKP$dkpnum = {\n\tTimestamp = " . strftime("%d%m%Y%H%M") . ",\n\tPool = \"$poolname\",\n\teqdkpsite = \"$dbname\",\n\tprefix = \"$table_prefix\",\n\tPoints = {\n\t\t"; |
$result = mysql_query("SELECT * FROM " . $table_prefix . 'members' . " ORDER BY member_name"); |
$c = 0; |
while ($row = mysql_fetch_array($result)) { |
if ($c > 0) $data .= ",\n\t\t"; |
$member = $row['member_name']; |
$sql = "SELECT " . $table_prefix . 'raids' .".raid_name, SUM(raid_value) FROM " . |
$table_prefix . 'raid_attendees' . " LEFT JOIN " . $table_prefix . 'raids' . " ON ". $table_prefix . 'raid_attendees' . |
".raid_id=" . $table_prefix . 'raids' . ".raid_id WHERE ". $table_prefix . 'raid_attendees' . ".member_name = '" . |
$member . "' GROUP by " . $table_prefix . 'raids' . ".raid_name"; |
$earnedresult = mysql_query($sql); |
$earned = 0; |
while ($earnedrow = mysql_fetch_array($earnedresult)) { |
if ($events[$earnedrow['raid_name']]['pool'] == $poolname) $earned += $earnedrow[1]; |
} |
$sql = "SELECT ". $table_prefix . 'raids' . ".raid_name, SUM(". $table_prefix . 'items' .".item_value) FROM " . |
$table_prefix . 'items' . " LEFT JOIN " . $table_prefix . 'raids' . " ON " . $table_prefix . 'items' . ".raid_id=" . |
$table_prefix . 'raids' . ".raid_id WHERE " . $table_prefix . 'items' . ".item_buyer = '" . $member . |
"' GROUP by " . $table_prefix . 'raids' . ".raid_name;"; |
$spentresult = mysql_query($sql); |
$spent = 0; |
while ($spentrow = mysql_fetch_array($spentresult)) { |
if ($events[$spentrow['raid_name']]['pool'] == $poolname) $spent += $spentrow[1]; |
} |
$adjust = 0; |
$sql = "SELECT adjustment_reason, adjustment_value, raid_name FROM " . $table_prefix . 'adjustments' . |
" WHERE member_name = '" . $member . "';"; |
$adjresult = mysql_query($sql); |
while ($adjrow = mysql_fetch_array($adjresult)) { |
if ($events[$adjrow['raid_name']]['pool'] == $poolname) $adjust += $adjrow['adjustment_value']; |
} |
$balance = $earned - $spent + $adjust; |
$member = converttext($member); |
$data .= "[\"$member\"] = {earn = $earned,spent = $spent,adj = $adjust,bal = $balance}"; |
$c++; |
} |
$data .= "\n\t},\n\t"; |
CommonOutput(); |
} |
} else { |
$dkpnum = $i + $offset; |
$data .= "MorgDKP_DKP$dkpnum = {\n\tTimestamp = " . strftime("%d%m%Y%H%M") . ",\n\tPool = \"$DBName[$i]\",\n\teqdkpsite = \"$dbname\",\n\tprefix = \"$table_prefix\",\n\tPoints = {\n\t\t"; |
$result = mysql_query("SELECT * FROM " . $table_prefix . 'members' . " ORDER BY member_name"); |
$c = 0; |
while ($row = mysql_fetch_array($result)) { |
if ($c > 0) $data .= ",\n\t\t"; |
$balance = $row['member_earned'] - $row['member_spent'] + $row['member_adjustment']; |
$member = converttext($row['member_name']); |
$data .= "[\"$member\"] = {earn = {$row['member_earned']},spent = {$row['member_spent']},adj = {$row['member_adjustment']},bal = $balance}"; |
$c++; |
} |
$data .= "\n\t},\n\t"; |
CommonOutput(); |
} |
} |
} |
?> |
<html> |
<head> |
<style type="text/css"> |
h1 {text-align: right; margin-right: 50px; font-size: 12px} |
</style> |
</head> |
<body style="font-family: Arial; font-size: 16px; background-color: #101030; color: #FDFDFD; padding-left: 50px; padding-top: 20px;"> |
<form method="post"> |
<input type="hidden" name="retrieve" value="1"> |
<h1><a href="<?php echo $admin_path?>" target="_self" style="color: #FDFDFD;">Return to eqDKP Admin</a></h1> |
<b><u>MorgDKP Export</b></u> |
<br> |
<br> |
<?php if ($php_version > 5) {?> |
Please select the timezone of your WOW server: |
<?php if ($TZonecook) { ?> |
<input type="radio" name="tzone" checked="yes" value="<?php echo $TZonecook?>"><?php echo $TZonecook?> |
<?php } |
foreach ($timezones as $tzonename => $string) { |
if ($tzonename != $TZonecook) {?> |
<input type="radio" name="tzone" value="<?php echo $tzonename?>"><?php echo $tzonename?> |
<?php } |
}?> |
<br>No selection will use the timezone set on your website which may or may not be accurate.<br><br> |
<?php }?> |
Please enter the directory names of up to 5 eqDKP installs (pools) to download.<br> |
Example: http://sodalityoftheconstant.com/<b>aqdkp</b>/listmembers.php? (ie enter aqdkp and AQ40 below)<br> |
<b><u>NOTE:</b></u> eqdkp+ users only need to enter the directory name. Pool names will be the same as you set up on your website IF you are using multiple pools. All pools will be done automatically.<br><br> |
1. <input name="eqDKP[1]" value="<?php echo $DKPcook1?>"> In Game Database Name = <input name="DBName[1]" value="<?php echo $DBNamecook1?>"><br> |
2. <input name="eqDKP[2]" value="<?php echo $DKPcook2?>"> In Game Database Name = <input name="DBName[2]" value="<?php echo $DBNamecook2?>"><br> |
3. <input name="eqDKP[3]" value="<?php echo $DKPcook3?>"> In Game Database Name = <input name="DBName[3]" value="<?php echo $DBNamecook3?>"><br> |
4. <input name="eqDKP[4]" value="<?php echo $DKPcook4?>"> In Game Database Name = <input name="DBName[4]" value="<?php echo $DBNamecook4?>"><br> |
5. <input name="eqDKP[5]" value="<?php echo $DKPcook5?>"> In Game Database Name = <input name="DBName[5]" value="<?php echo $DBNamecook5?>"> |
<br> |
<br> |
<br><textarea style="width: 800px; height: 140px;" name="mydata" onClick="select();"><?php echo $data ?></textarea> |
<br> |
<br> |
<input type="submit" value="Export EQdkp Data"><br> |
<br> |
<br><a href="DKPInfo.lua" target="_self" style="color: #FDFDFD; margin-left: 50px; font-size: 18px">Click or right-click this link and save to WOW/Interface/Addons/MorgDKP</a> |
</form> |
</body> |
</html> |
<?php |
session_start(); |
define('EQDKP_INC', true); |
define('IN_ADMIN', true); |
define('PLUGIN', 'ctrt'); |
$eqdkp_root_path = './../../'; |
$admin_path = $eqdkp_root_path . "admin/index.php?s=/"; |
require($eqdkp_root_path . 'config.php'); |
require($eqdkp_root_path . 'common.php'); |
require('Morgfunc.php'); |
function InsertAliases($alts) { |
foreach ($alts as $tab) { |
if ($tab['alt']) { |
CreateAliasDB($tab['eqdkp'], $tab['prefix']); |
if (mysql_select_db($tab['eqdkp'])) { |
if ($tab['action'] == "ADD") { |
$sql = "INSERT INTO " . $tab['prefix'] . 'ctrt_aliases' . " (alias_id, alias_member_id, alias_name) |
VALUES ('','" . $tab['id'] . "','" . stripslashes($tab['alt']) . "')"; |
//echo $sql; |
$result = mysql_query($sql); |
if ($result) { |
$GLOBALS['DATAOUT'] .= "Added alias: " . stripslashes($tab['alt']) . " of " . stripslashes($tab['main']) . " to database: " . $tab['eqdkp'] . "\n"; |
$log_action = array('header' => '{L_ACTION_CTRT_ALIAS_ADDED}', |
'{L_CTRT_LABEL_ALIAS_NAME}' => $tab['alt'], |
'{L_CTRT_LABEL_MEMBER_NAME}' => $tab['main'], |
'{L_ADDED_BY}' => addslashes($GLOBALS['DKPUSER'])); |
LogAction($tab['eqdkp'], $tab['prefix'], $log_action); |
} else mysql_error(); |
} |
if ($tab['action'] == "DELETE") { |
$sql = "DELETE FROM " . $tab['prefix'] . 'ctrt_aliases' . " WHERE alias_name = '" . stripslashes($tab['alt'] . "'"); |
//echo $sql; |
$result = mysql_query($sql); |
if ($result) { |
$GLOBALS['DATAOUT'] .= "Deleted alias: " . stripslashes($tab['alt']) . " of " . stripslashes($tab['main']) . " from database: " . $tab['eqdkp'] . "\n"; |
$log_action = array('header' => '{L_ACTION_CTRT_ALIAS_DELETED}', |
'{L_CTRT_LABEL_ALIAS_NAME}' => $tab['alt'], |
'{L_CTRT_LABEL_MEMBER_NAME}' => $tab['main'], |
'{L_ADDED_BY}' => addslashes($GLOBALS['DKPUSER'])); |
LogAction($tab['eqdkp'], $tab['prefix'], $log_action); |
} else mysql_error(); |
} |
} else mysql_error(); |
} |
} |
$GLOBALS['DATAOUT'] .= "\n"; |
} |
function AdjustDKP($changes, $parsedata) { |
foreach ($changes as $changeid=>$change) { |
$change = Arraydiff($parsedata[$changeid], $change); |
$change['members'] = ucwords($change['members']); |
$change['members'] = rtrim($change['members']); |
$change['members'] = explode("\n", $change['members']); |
$change['value'] = $parsedata[$changeid]['value']; |
$change['members'] = CheckAlias($change['members'], $change['eqdkp'], $change['prefix']); |
$change['members'] = array_unique($change['members']); |
if ($change['value']) { |
$user = $GLOBALS['DKPUSER']; |
$grp_key = gen_group_key(time(), stripslashes($change['event']), $change['value']); |
if ($change['name'] == "Group") { |
$counter = 0; |
foreach ($change['members'] as $name) { |
$adjusted = AddMultiAdjustment($name, $change, $change['eqdkp'], $change['prefix'], $grp_key); |
$counter++; |
} |
$log_action = array('header' => '{L_ACTION_INDIVADJ_ADDED}', |
'{L_ADJUSTMENT}' => $change['value'], |
'{L_REASON}' => $change['event'], |
'{L_MEMBERS}' => implode(", ", $change['members']), |
'{L_EVENT}' => $change['event'], |
'{L_ADDED_BY}' =>addslashes($user)); |
$GLOBALS['DATAOUT'] .= "Added group adjustment to $counter members by " . $change['value'] . " DKP in database: " . $change['eqdkp'] . "\n"; |
} else { |
AddMultiAdjustment($change['name'], $change, $change['eqdkp'], $change['prefix'], $grp_key); |
$log_action = array('header' => '{L_ACTION_INDIVADJ_ADDED}', |
'{L_ADJUSTMENT}' => $change['value'], |
'{L_REASON}' => $change['event'], |
'{L_MEMBERS}' => $change['name'], |
'{L_EVENT}' => $change['event'], |
'{L_ADDED_BY}' =>addslashes($user)); |
$GLOBALS['DATAOUT'] .= "Added member adjustment: " . $change['name'] . " by " . $change['value'] . " DKP in database: " . $change['eqdkp'] . "\n"; |
} |
if ($adjusted) LogAction($change['eqdkp'], $change['prefix'], $log_action); |
} |
} |
$GLOBALS['DATAOUT'] .= "\n"; |
} |
function UpdateRaidData($parsedata) { |
$RAID = $GLOBALS['RAID']; |
foreach ($RAID as $raidnum => $raid) { |
$GLOBALS['DATAOUT'] .= "Updates to raid database: " . $raid['eqdkp'] . "\n"; |
$eqdkp = $raid['eqdkp']; |
$prefix = $raid['prefix']; |
$oldraids = FetchAllEvents($eqdkp, $prefix); |
$races = FetchAllRaces($eqdkp, $prefix); |
$classes = FetchAllClasses($eqdkp, $prefix); |
$members = FetchAllMembers($eqdkp, $prefix); |
$aliases = FetchAllAliases($eqdkp, $prefix); |
$trashdone = array(); |
$trashdone[$raidnum] = false; |
foreach ($raid['attendees'] as $name => $attendees) { |
$isalias = CheckAlias(array('0' => $name), $eqdkp, $prefix); |
if ($name == $isalias[0]) { |
$attendees = CheckRace($attendees); |
if (!$members[$name]) { |
$newmember = array('member_name'=>"'" . addslashes($name) . "'", |
'member_firstraid'=>TimestringtoTimestamp($raid['date']), |
'member_lastraid'=>TimestringtoTimestamp($raid['date']), |
'member_raidcount'=>'1', |
'member_adjustment'=>'0'); |
if ($attendees['level']) $newmember['member_level'] = $attendees['level']; |
if ($attendees['class']) { |
$newmember['member_class_id'] = $classes[$attendees['class']]; |
if (empty($newmember['member_class_id'])) $newmember['member_class_id'] = '0'; |
} |
if ($attendees['race']) { |
$newmember['member_race_id'] = $races[$attendees['race']]; |
if (empty($newmember['member_race_id'])) $newmember['member_race_id'] = '0'; |
} |
if (AddNEWMember($name, $attendees, $newmember, $eqdkp, $prefix)) { |
$GLOBALS['DATAOUT'] .= "Added new member: $name " . $attendees['level'] . " " . $attendees['race'] . " " . $attendees['class'] . "\n"; |
} |
} else { |
if ($races[$attendees['race']] != $members[$name]['member_race_id'] or $classes[$attendees['class']] != $members[$name]['member_class_id'] or $attendees['level'] != $members[$name]['member_level']) { |
$changed = array('member_level'=>$attendees['level'], |
'member_class_id'=>$classes[$attendees['class']], |
'member_race_id'=>$races[$attendees['race']]); |
if (UpdateMember($name, $members[$name], $changed, $eqdkp, $prefix, 1)) { |
$GLOBALS['DATAOUT'] .= "Updated member: $name " . $attendees['level'] . " " . $attendees['race'] . " " . $attendees['class'] . "\n"; |
} |
} |
} |
} |
} |
$members = FetchAllMembers($eqdkp, $prefix); |
foreach ($raid['events'] as $eventid => $event) { |
$event_id = $oldraids[$event['name']]['event_id']; |
if ($event_id) { |
$oldraiddata = $oldraids[$event['name']]; |
$oldname = $event['name']; |
} |
$event = Arraydiff($parsedata[$raidnum]['events'][$eventid], $event); |
$event['attendees'] = ucwords($event['attendees']); |
$event['attendees'] = rtrim($event['attendees']); |
$event['attendees'] = explode("\n", $event['attendees']); |
$event['attendees'] = CheckAlias($event['attendees'], $eqdkp, $prefix); |
$event['attendees'] = array_unique($event['attendees']); |
$RAID[$raidnum]['events'][$eventid] = $event; |
if (!empty($event['name']) and !empty($event['attendees'][0])) { |
$eventname = stripslashes($event['name']); |
foreach ($event['attendees'] as $anum => $aname) { |
$aname = rtrim($aname); |
if (!$members[$aname]) { |
$newmember = array('member_name'=>"'" . addslashes($aname) . "'", |
'member_firstraid'=>TimestringtoTimestamp($raid['date']), |
'member_lastraid'=>TimestringtoTimestamp($raid['date']), |
'member_raidcount'=>'1', |
'member_adjustment'=>'0'); |
if (AddNEWMember($aname, '', $newmember, $eqdkp, $prefix)) { |
$GLOBALS['DATAOUT'] .= "Added new member: $aname\n"; |
} |
} |
} |
if (empty($event['value'])) $event['value'] = 0; |
if ($oldraids[$eventname]) { |
if ($oldraids[$eventname]['event_value'] != $event['value']) { |
UpdateEvent($eventname, $oldraids[$eventname], $event, $eqdkp, $prefix); |
$GLOBALS['DATAOUT'] .= "Updated event: $eventname to " . $event['value'] . " DKP.\n"; |
} |
} else { |
if (!$event_id) { |
CreateEvent($eventname, $event, $eqdkp, $prefix); |
$GLOBALS['DATAOUT'] .= "Created new event: $eventname for " . $event['value'] . " DKP.\n"; |
} else { |
UpdateEvent($eventname, $oldraiddata, $event, $eqdkp, $prefix); |
$GLOBALS['DATAOUT'] .= "Updated event: $oldname to $eventname.\n"; |
} |
} |
if (!empty($raid['loot'][$event['index']])) { |
$event['zsum'] = 0; |
foreach ($raid['loot'][$event['index']] as $lootid => $eventloot) { |
$parsedindex = $event['index']; |
$eventloot = Arraydiff($parsedata[$raidnum]['loot'][$parsedindex][$lootid], $eventloot); |
$eventloot['ItemName'] = ucwords($eventloot['ItemName']); |
$eventloot['Player'] = ucwords($eventloot['Player']); |
$event['zsum'] += $eventloot['Costs']; |
$raid['loot'][$event['index']][$lootid] = $eventloot; |
} |
} |
if (!empty($raid['loot']['Trash mob']) and !$trashdone[$raidnum] and $event['trash'] == 2) { |
$raid['zsumtrash'] = 0; |
foreach ($raid['loot']['Trash mob'] as $lootid => $eventloot) { |
$eventloot = Arraydiff($parsedata[$raidnum]['loot']['Trash mob'][$lootid], $eventloot); |
$eventloot['ItemName'] = ucwords($eventloot['ItemName']); |
$eventloot['Player'] = ucwords($eventloot['Player']); |
$raid['zsumtrash'] += $eventloot['Costs']; |
$raid['loot']['Trash mob'][$lootid] = $eventloot; |
} |
} |
$members = FetchAllMembers($eqdkp, $prefix); |
$oldraids = FetchAllEvents($eqdkp, $prefix); |
$changed = array(); |
if ($parsedata[$raidnum]['zsum']) { |
if ($event['zsum'] > 0) { |
$newval = intval($event['zsum']/count($event['attendees'])); |
$event['value'] = $newval; |
$RAID[$raidnum]['event'][$eventid]['value'] = $newval; |
} else $event['value'] = 0; |
if (!$trashdone[$raidnum]) { |
$num = count($raid['attendees']); |
$newval = intval($raid['zsumtrash']/$num); |
foreach ($raid['attendees'] as $zname => $attendees) { |
if (!$changed[$zname]['member_earned']) { |
$changed[$zname]['member_earned'] = $members[$zname]['member_earned'] + newval; |
} else $changed[$zname]['member_earned'] += $newval; |
} |
$GLOBALS['DATAOUT'] .= "Added $newval DKP to $num attendees for trash drops.\n"; |
} |
} |
foreach ($event['attendees'] as $atenname) { |
$atenname = rtrim($atenname); |
$changed[$atenname]['member_lastraid'] = TimestringtoTimestamp($raid['date']); |
$changed[$atenname]['member_raidcount'] = $members[$atenname]['member_raidcount'] + 1; |
if (!$changed[$atenname]['member_earned']) { |
$changed[$atenname]['member_earned'] = $members[$atenname]['member_earned'] + $event['value']; |
} else $changed[$atenname]['member_earned'] += $event['value']; |
} |
$raidid = CreateRaid($event, $raid, $oldraids[$eventname], $eqdkp, $prefix); |
if ($raidid) { |
AddRaidAttendees($raidid, $members, $event['attendees'], $eqdkp, $prefix); |
$GLOBALS['DATAOUT'] .= "Added raid: $eventname worth " . $event['value'] . " DKP with " . count($event['attendees']) . " attendees.\n"; |
if ($raid['loot'][$event['index']]) { |
foreach ($raid['loot'][$event['index']] as $lootdata) { |
if (!empty($lootdata['ItemName']) and !empty($lootdata['Player'])) { |
$isalias = CheckAlias(array('0' => $lootdata['Player']), $eqdkp, $prefix); |
$lootdata['Player'] = $isalias[0]; |
AddRaidItem($raidid, $lootdata, $lootdata['eqdkp'], $lootdata['prefix']); |
$changed[$lootdata['Player']]['member_spent'] = $members[$lootdata['Player']]['member_spent'] + $lootdata['Costs']; |
$GLOBALS['DATAOUT'] .= "Added item: " . $lootdata['ItemName'] . " worth " . $lootdata['Costs'] . " DKP to " . $lootdata['Player'] . " Database: " . $lootdata['eqdkp'] . ".\n"; |
} |
} |
} |
if (!$trashdone[$raidnum] and !empty($raid['loot']['Trash mob']) and $event['trash'] == 2) { |
$trashdone[$raidnum] = true; |
foreach ($raid['loot']['Trash mob'] as $trashid => $trashloot) { |
if (!empty($trashloot['ItemName']) and !empty($trashloot['Player'])) { |
$isalias = CheckAlias(array('0' => $trashloot['Player']), $eqdkp, $prefix); |
$trashloot['Player'] = $isalias[0]; |
AddRaidItem($raidid, $trashloot, $trashloot['eqdkp'], $trashloot['prefix']); |
if ($changed[$trashloot['Player']]['member_spent']) { |
$newval = $changed[$trashloot['Player']]['member_spent'] + $trashloot['Costs']; |
} else $newval = $members[$trashloot['Player']]['member_spent'] + $trashloot['Costs']; |
$changed[$trashloot['Player']]['member_spent'] = $newval; |
$GLOBALS['DATAOUT'] .= "Added item: " . $trashloot['ItemName'] . " worth " . $trashloot['Costs'] . " DKP to " . $trashloot['Player'] . " Database: " . $trashloot['eqdkp'] . ".\n"; |
} |
} |
} |
foreach ($changed as $cname => $cdata) { |
UpdateMember($cname, $members[$cname], $cdata, $eqdkp, $prefix, 0); |
} |
} |
} |
} |
$GLOBALS['DATAOUT'] .= "\n"; |
} |
} |
global $DKPUSER, $USERID, $DATAOUT, $RAID; |
$DKPUSER = $user->data['username']; |
$USERID = $user->data['user_id']; |
$DATAOUT = ""; |
$RAID = $_SESSION['RAID']; |
if (isset($_POST['altfield'])) { |
$altarray = $_POST['altfield']; |
$newalts = $_SESSION['passalts']; |
$newalts = array_merge_keys($altarray, $newalts); |
InsertAliases($newalts); |
} |
if (isset($_POST['raidfield'])) { |
$raidfields = $_POST['raidfield']; |
$raidfields = stripslashes_deep($raidfields); |
//echo "<pre>"; |
//print_r($RAID); |
//print_r($raidfields); |
//echo "</pre>"; |
UpdateRaidData($raidfields); |
} |
if (isset($_POST['changevalue'])) { |
$needchanged = $_SESSION['dkpchange']; |
$valuearray = $_POST['changevalue']; |
AdjustDKP($needchanged, $valuearray); |
} |
?> |
<html> |
<head> |
<style type="text/css"> |
h1 {text-align: right; margin-right: 50px; font-size: 12px} |
</style> |
</head> |
<body style="font-family: Arial; font-size: 16px; background-color: #101030; color: #FDFDFD; text-align: left; padding-left: 50px; padding-top: 20px;"> |
<h1><a href="<?php echo $admin_path?>" target="_self" style="color: #FDFDFD;">Return to eqDKP Admin</a></h1> |
<b><u>MorgDKP Import</u><br> |
<br> |
<br> |
Changes made to eqDKP database:</b> |
<pre> |
<?php echo $DATAOUT; ?> |
</pre> |
</body> |
</html> |
<?php |
// no direct usage |
if (!defined('EQDKP_INC')) |
{ |
die('You cannot access this file directly.'); |
} |
// declare the plugin class |
class morgdkp_Plugin_Class extends EQdkp_Plugin |
{ |
function morgdkp_Plugin_Class($pm) |
{ |
global $eqdkp_root_path, $user, $SID; |
// wire ourselves in |
$this->eqdkp_plugin($pm); |
$this->pm->get_language_pack('morgdkp'); |
// setup plugin details |
$this->add_data(array( |
'name' => 'MorgDKP', |
'code' => 'morgdkp', |
'path' => 'morgdkp', |
'contact' => 'Morgalm at WOWInterface', |
'template_path' => 'plugins/morgexport/templates/', |
'version' => '1.0.0') |
); |
// wire in our menus |
$this->add_menu('admin_menu', $this->gen_admin_menu()); |
} |
function gen_admin_menu() |
{ |
// make sure we are installed |
if ($this->pm->check(PLUGIN_INSTALLED, 'morgdkp')) |
{ |
global $db, $user, $SID; |
$admin_menu = array('morgdkp' => array( 0 => $user->lang['morgdkp_adminmenu_title'], |
1 => array('link' => $eqdkp_root_path . 'plugins/' . $this->get_data('path') . '/Morgexport.php' . $SID, 'text' => $user->lang['morgexport'], 'check' => 'u_raid_list'), |
2 => array('link' => $eqdkp_root_path . 'plugins/' . $this->get_data('path') . '/Morgimport.php' . $SID, 'text' => $user->lang['morgimport'], 'check' => 'u_raid_list')) |
); |
} |
return $admin_menu; |
} |
} |
?> |
<?php |
$lang['morgexport'] = "Export Standings"; |
$lang['morgimport'] = "Import Raids"; |
$lang['morgdkp_adminmenu_title'] = "MorgDKP"; |
?> |
<?php |
$lang['morgexport'] = "Export Standings"; |
$lang['morgimport'] = "Import Raids"; |
$lang['morgdkp_adminmenu_title'] = "MorgDKP"; |
?> |
{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fmodern\fprq1\fcharset0 Courier New;}{\f1\fnil\fcharset0 Rockwell;}{\f2\fnil\fcharset0 Courier New;}{\f3\fnil Rockwell;}{\f4\fnil\fcharset0 Verdana;}{\f5\fnil\fcharset2 Symbol;}} |
{\colortbl ;\red0\green0\blue0;} |
{\stylesheet{ Normal;}{\s1 heading 1;}{\s2 heading 2;}} |
{\*\generator Msftedit 5.41.21.2507;}\viewkind4\uc1\pard\cf1\lang4105\b\f0\fs20 Full documentation at http://www3.telus.net/MorgDKP/\par |
____________________________________________________\par |
\par |
\pard\nowidctlpar\lang1033\kerning28\ul\f1\fs24 Description:\ulnone\par |
\pard\fi-540\li1260\fs28\par |
\pard\nowidctlpar\fi-540\li1260\fs24 MorgBid \b0\fs22 is a fairly simple mod that allows a window to pop up to so that raid members can vote NEED, TAKE (greed), or PASS on loot in endgame instances. Every member of the raid must have MorgBid installed in order to vote. MorgBid also has a BidWar mode that allows members to bid on items in an auction style setting.\par |
\pard\fi-540\li1260\b\par |
\pard\nowidctlpar\fi-540\li1260\fs24 MorgDKP\fs28 \b0\fs22 is a full featured mod that allows the master looter (ML) to control the loot distribution process. Only one member is required to have this mod, that being the master looter. MorgDKP is also capable of tracking DKP and outputting the DKP string for import into eqDKP using a custom php import script.\par |
\pard\cf0\lang4105\kerning0\f2\fs20\par |
\par |
\pard\nowidctlpar\cf1\lang1033\kerning28\ul\b\f1\fs24 MorgDKP Features:\par |
\pard\nowidctlpar\fi-360\li1080\ulnone\b0\fs22\par |
\pard{\pntext\f5\'B7\tab}{\*\pn\pnlvlblt\pnf5\pnindent285{\pntxtb\'B7}}\nowidctlpar\fi-285\li1005 Allows ML to query raid for interest in loot.\par |
{\pntext\f5\'B7\tab}Tracks DKP including raid attendees, start bonus, and all drops. \par |
{\pntext\f5\'B7\tab}Options for different DKP systems including zero\f3 -\f1 sum, relational, and random.\par |
{\pntext\f5\'B7\tab}Options to award DKP/unit of time, include a start bonus, and include custom events such as boss attempts.\par |
{\pntext\f5\'B7\tab}BidWar mode for item auctions.\par |
{\pntext\f5\'B7\tab}Custom php script to export eqDKP data into MorgDKP.\par |
{\pntext\f5\'B7\tab}Custom php import to eqDKP allowing multiple raids in one import string as well as ability to add DKP changes/decays and add aliases. \par |
{\pntext\f5\'B7\tab}Raid tracking interface allows editing of all raid events and attendees as well as DKP changes and aliases. \par |
{\pntext\f5\'B7\tab}Allows a ML and disenchanter (DE) to be set so that they are not charged for loot. (Toggle)\par |
{\pntext\f5\'B7\tab}Remembers what raid members have equipped and will not send a query to them for loot they already have. (Exceptions for some non\f3 -\f1 unique items included.)\par |
{\pntext\f5\'B7\tab}Displays query results in raid channel.\par |
{\pntext\f5\'B7\tab}Displays top 5 DKP members for the moused over item in the tooltip.\par |
{\pntext\f5\'B7\tab}Automatically hands out items to the winning player if the loot window is still open. Note: It asks with the standard blizzard confirmation dialogue.\par |
{\pntext\f5\'B7\tab}Allows ML to easily set which classes are eligible and DKP value. Also remembers these values.\par |
{\pntext\f5\'B7\tab}Scans for base installs of MorgBid in the current raid. Automatically outputs a link to MorgBid site on click.\par |
{\pntext\f5\'B7\tab}Allows ML to record BOE items before trading them to member.\par |
{\pntext\f5\'B7\tab}Can load up to 5 separate DKP pools. Ie. MC1, MC2, BWL, AQ40, NAXX. These raids can be named whatever you wish. \par |
{\pntext\f5\'B7\tab}multiPool feature allows up to 5 DKP pools to be used in one raid. (ie separate pool for class items)\par |
{\pntext\f5\'B7\tab}Can change loot threshold on the fly.\par |
{\pntext\f5\'B7\tab}Item history for easy recall of current raid item winners.\par |
{\pntext\f5\'B7\tab}Allows raid members to whisper ML for current DKP for own class or specified classes in all 5 DKP pools.\par |
{\pntext\f5\'B7\tab}Lets you know it is working by displaying boss kills, raid changes, and looting events.\par |
{\pntext\f5\'B7\tab}Automatically links items to raid chat and shows item tablet on looting.\f4\fs20\par |
\f1\fs22{\pntext\f5\'B7\tab}Edit item values from item history (Allow you to track DKP without being ML)\f4\fs20\par |
\f1\fs22{\pntext\f5\'B7\tab}Whsiper system for those crazy people who hate mods:P\f4\fs20\par |
\f1\fs22{\pntext\f5\'B7\tab}Fubar support\f4\fs20\par |
\pard\cf0\lang4105\kerning0\f2\par |
\par |
\pard\nowidctlpar\cf1\lang1033\kerning28\ul\b\f1\fs28 Installation:\par |
\ulnone\b0\par |
\pard\nowidctlpar\fi-285\li1005\b\fs22 1. \b0 Install MorgDKP/MorgBid. Unzip into WoW addons directory or run .exe.\par |
\pard{\pntext\f1 2.\tab}{\*\pn\pnlvlbody\pnf1\pnindent285\pnstart2\pndec{\pntxta.}} |
\nowidctlpar\s2\fi-285\li1005 Copy the \b plugins\b0 folder from the MorgDKP directory to your eqDKP folder on your website using an ftp program. Note: admin access to the website will be required. \line (ie. http://sodalityoftheconstant.com/aqdkp/)\par |
{\pntext\f1 3.\tab}Enter the admin menu of your eqDKP website and click \b manage plugins. \b0 Install the MorgDKP plugin. Refresh the admin menu and you will see \b MorgDKP Export\b0 and \b MorgDKP Import\b0 options are now present.\par |
\pard{\pntext\f1 4.\tab}{\*\pn\pnlvlbody\pnf1\pnindent285\pnstart4\pndec{\pntxta.}} |
\s2\fi-285\li1005 Click \b MorgDKP Export. \b0 Follow the instructions to enter the website name of the pool and the name you wish it to be called in WoW. Cookies will remember these setting for your next visit. Right click the link to save it to your MorgDKP folder.\par |
{\pntext\f1 5.\tab}Enter WoW and confirm that MorgDKP is loaded in the addons menu.\par |
\pard{\pntext\f1 6.\tab}{\*\pn\pnlvlbody\pnf1\pnindent285\pnstart6\pndec{\pntxta.}} |
\s2\fi-285\li1005 Either use the fubar tablet or right click menu and choose \b Main DKP Pool\b0 option and click one of your pools to set as default. The DKP will be loaded and you should see a confirmation. If you get any errors then we have a problem:P\par |
{\pntext\f1 7.\tab}Enjoy tracking raids:)\par |
\pard\cf0\lang4105\kerning0\f2\fs20\par |
\par |
\pard\s2\tqdec\tx0\tqdec\tx1260\cf1\lang1033\kerning28\ul\b\f1\fs28 QUICKSTART\par |
\pard\nowidctlpar\s2\fi-360\li1080\tqdec\tx0\tqdec\tx720\ulnone\fs22\par |
1. \b0 Update DKP before loading WOW using web based php script. Alternately \b ALT\f3 -\f1 TAB\b0 out of WOW to update and then reloadui.\par |
\b 2. Enable MOD \b0 and \b Enable ML/DE mode \b0\par |
\b 3. \b0 Set \b Main DKP pool\b0 for desired raid. \par |
\b 4. MorgBid Base\b0 check. \b LEFT \endash CLICK\b0 to whisper non\f3 -\f1 users. Repeat as necessary until everyone has MorgBid or it is pull time. \par |
\b 5. Add Twink\b0 if any members are on alts. Can be done through right click menu or \b Raid \b0 Tracking tablet. Good idea to remind them to whisper you to check DKP when on an alt. \par |
\b 6. \b0 Make sure you are the \b Master Looter \b0 and set the \b Disenchanter\b0 if not already set. \par |
\b 7. Start Raid\b0 manually OR enter instance.\par |
\b 8. \b0 Enjoy wiping out those mobs and distributing loot with MorgDKP.\par |
\b 9. End Raid\b0 when the raid is over and before the raid disbands. \par |
\b 10. Export Raid\b0 if desired and use \b MorgDKP Export\b0 in admin menu to update DKP. This step doesn\rquote t have to be done for every raid anymore. You can run any number of raids and import them all at once.\par |
\pard\cf0\lang4105\kerning0\f2\fs20\par |
\par |
} |
local L = AceLibrary("AceLocale-2.2"):new("MorgDKP") |
L:RegisterTranslations("deDE", function() return { |
cmd1 = "/mdkp", |
cmd2 = "/MorgDKP", |
Bar_Hint = "L-Klick: Ank\195\188ndigen.\nR-Klick: Schlie\195\159en.", |
Bar_Hint_DKPlist = "L-Click: Send to raid.\nR-Click: Close tablet.", |
Bar_Hint_Version = "L-Klick: Sendet tells.\nR-Klick: Fenster schlie\195\159en.", |
BidWarBar_Hint = "L-Klick: Ank\195\188ndigen.\nR-Klick: Fenster schlie\195\159en.", |
add = "Hinzugef/195/188gt ", |
adddkp = "DKP hinzuf\195\188gen", |
adddkpdesc = "Einem Mitglied DKP hinzufügen. \nFormat: <charname> <punkte>", |
addnewchar = "Neuen Charakter angelegt ", |
aliasadd = "Alias hinzugef/195/188gt: ", |
attadded = " teilnehmer hinzugef/195/188gt.", |
attend = " Teilnehmer.", |
bosskill = " get/195/182tet um ", |
bwarsteps = "BidWar Schritte", |
bwarstepsdesc = "Legt die H/195/182he der DKP Schritte fest f/195/188r den BidWar Modus. Gibt den Wert an die MorgBid Clients weiter.", |
charpoints = "Du musst den String korrekt formatieren: <Charakter> <Punkte>", |
classlist = "Klassen", |
closemenu = "schlie/195/159en", |
denchanter = "Entzauberer", |
denchanterdesc = "Der Spieler, der Items entzaubert.", |
dkp = "DKP Funktionen", |
dkpdesc = "Funktionen im Zusammenhang mit DKP-Tracking.", |
dkpp = " DKP Punkte: ", |
dkpstand = "DKP Stand f/195/188r ", |
doresult = "Ergebnisse f/195/188r: ", |
enablebidwar = "BidWar", |
enablebidwardesc = "Aktiviert BidWar Modus. Dieser Modus erlaubt Spieler, um Items zu bieten. Die MorgDKP Tafel benutzt Gebote auch f\195\188r NICHT-Mitglieder DKP.", |
enablemlde = "PM/VZ Mode aktivieren", |
enablemldedesc = "Ist diese Option aktiviert, wird kein Loot f\195\188r den Pl\195\188ndermeister und Verzauberer aufgezeichnet.", |
enablerelationaldkp = "Relationales DKP", |
enablerelationaldkpdesc = "Aktiviert RDKP zur Berechnung des Bekommen/Verbraucht Anteils.", |
enablezerosum = "0-Summe", |
enablezerosumdesc = "Aktiviert Nullsummen DKP Systeme.", |
endraid = "Beende Raid", |
endraiddesc = "Schlie\195\159t die Raid Datenbank und gibt den DKP string f\195\188r Bosskills und erlangten Loot aus.", |
fubarhint = "CLICK: MorgBid Base query.\nSHIFT-CLICK: Toggle active.\nALT-CLICK: Toggle ML/DE\nCTRL-CLICK: Raid Tracker.", |
giveboe = "BOE zuweisen", |
giveboedesc = "Gibt einem Spieler im Raid ein BOE Item und zeichnet dies in der Raid Loot Datenbank auf.", |
itemhistory = "Item History", |
itemhistorydesc = "Zeigt alle Items, die in diesem Raid gelootet wurden. \nAchtung: Nur seit der letzte Raid gestartet worden ist.", |
joinraid = " ist dem Raid beigetreten um ", |
leftraid = " hat den Raid verlassen um ", |
listdkp = "List DKP", |
listdkpdesc = "Lists the DKP of the selected classes in tablet.", |
logquality = "Aufzeichnungsqualit\195\164t", |
logqualitydesc = "Alles unter diesem Qualit\195\164tsstand wird NICHT aufgezeichnet.", |
lootdistro = "W/195/164hlbare Items:", |
lootquery = "%s an %s geben, bist du sicher?", |
manualitem = "Item h/195/182ndisch hinzuf/195/188gen", |
manualitemdesc = "F/195/188gt ein Item aus dem Inventar hinzu. N/195/188tzlich f/195/188r manche BOE Items und Items die du nicht looten kannst.", |
mloot = "Pl\195\188ndermeister", |
mlootdesc = "Der Spieler, die Pl\195\188ndermeister ist. Das Addon versucht es automatisch einzustellen.", |
morgbidcheck = "MorgBid Basis", |
morgbidcheckdesc = "Ermittelt die MorgBid User Basis. \nAuch n\195\188tzlich um die DKP auf Twinks zu checken.", |
morgtitle = "MorgDKP", |
mvquery = "MorgBid Version Abfrage", |
needraid = "Du kannst diese Funktion nicht au/195/159erhalb eine Raidgruppe verwenden.", |
newdkp = " Neue DKP: ", |
noitem = "Item existiert nicht!", |
nolootrec = "PM Modus ist aktiviert, damit wird kein Loot f/195/188r PM/VZ aufgezeichnet.", |
nomain = "Dieser Mainchar existiert nicht. Keine /195/132nderungen wurden durchgef/195/188hrt.", |
noquery = "Entweder sind keine Klassen selektiert oder kein Mitglied braucht dieses Item.", |
noraid = "Es existiert gerade kein Raid.", |
notexi = " existiert nicht.", |
olddkp = ": Alte DKP: ", |
playfrom = " Spieler von ", |
pointsto = " Punkte jedem ", |
query = "abfragen", |
queryraid = "Raid Abfrage", |
queryraiddesc = "Fragt die Raidmitglieder, ob Interesse an dem Item besteht.", |
querysent = "MorgBid Anfrage gesendet: ", |
raidatt = " Raidteilnehmer.", |
raidstartadd = " teilnehmer bei Raidstart.", |
receive = "erh/195/164lt ", |
removed = "Entfernt ", |
rightclickclose = "Rechtsklick zum schlie\195\159en.", |
roundbid = "Gebote f/195/188r diese Runde: ", |
setitempoints = "Item Punkte festsetzen", |
setitempointsdesc = "DKP Kosten f\195\188r das gew\195\164hlte Item.", |
startraid = "Starte Raid", |
startraiddesc = "Resettet die Raid Datenbank, um eine neue Raidaufzeichnung zu beginnen. \nGibt auch den DKP string f\195\188r den Start Bonus aus.", |
sub = "Entfernt ", |
subdkp = "DKP entfernen", |
subdkpdesc = "Entfernt DKP von einem Raidmitglied. \nFormat: <charname> <punkte>", |
to = " an ", |
transfer = "/195/188bertragen ", |
twinkaltmain = "Du musst den String korrekt formatieren: <twinkalt> <twinkmain>", |
twinks = "Twink hinzuf\195\188gen", |
twinksdesc = "F\195\188gt einen Spieler zum Raid hinzu, der mit einem Twink dabei ist und mit dem Main DKP Punkte hat. \n Format: <twink> <main>", |
updatedkp = "Update DKP Punkte ", |
updatemorgbid = "Bitte MorgBid updaten. http://www3.telus.net/MorgDKP/MorgBid3.6.exe. Danke :)", |
validname = "Du musst einen g/195/188ltigen Namen eingeben.", |
valuehint = "Mausrad hoch/Linksklick - Betrag erh/195/182hen.\nMausrad runter/Rechtsklick - Betrag verringern.\nSHIFT-Taste - Betrag um +/-1 /195/164ndern\nALT-Taste - Betrag um +/-20 /195/164ndern", |
--need loc |
Bar_Hint_Sync = "|c000070ddL-Click:|r Sync with.\n|c000070ddSHIFT-Click:|r Sync all.\n|c000070ddR-Click:|r Close tablet.", |
Bar_Hint_Waitlist = "|c000070ddL-Click:|r Invite.\n|c000070ddCTRL-Click:|r Remove.\n|c000070ddR-Click:|r Close tablet.", |
AcceptLeaderRequest = "%s is requesting leader status. Disable your MorgDKP?", |
AcceptSYNC = "Accept sync data from %s?", |
ad = "Add", |
alias = "Aliases", |
aliasexists = "Alias name already exihists", |
All = "All", |
alreadybid = "Sorry this is a silent auction and you have already placed your bid.", |
auctionbegin = "Beginning auction for %s: ID = %s", |
autozone = "Autozone", |
autozonedesc = "Automatically start a raid when zoning into a trackable zone.", |
badformat = "Can't add an event with incomplete information.", |
bidaccepted = "Your response has been accepted: %s", |
bidformat = "Bid Format = mbid ID [need/take/pass/bid value]", |
bidwaroptions = "BidWar Options", |
bidwaroptionsdesc = "Different BidWar options.", |
bossattemptmode = "Boss Attempt Mode", |
bossattemptmodedesc = "Enable's a mode where a boss attempt is recorded when you die via a confirmation dialogue.", |
broadlead = "Broadcast Leader", |
broadleaddesc = "Broadcast leader status to raid.", |
changedcost = "Changed item cost from %s to %s for %s.", |
classmain = "Main", |
classalt = "Offspec", |
cleardb = "Clear raid database?", |
clearraid = "Clear Raid DB", |
clearraiddesc = "Clear the raid database.", |
cleared = "Cleared the MorgDKP Raid database.", |
convert = "Convert DB", |
convertdesc = "Convert pre MorgDKP 6.0 database to work with MorgDKP 6.0 and above.", |
converted = "Converted old MorgDKP Database.", |
complete = "COMPLETED", |
custom = "Custom event", |
customdesc = "Add a custom raid event. This will record all attendees when you click the event menu by adding Attempt to the end of the boss name. You can change event name value through raid tracker.", |
customname = "Custom name", |
deletechar = "Deleting %s from MorgDKP database.", |
deleteimportfile = "Please delete the ItemData.lua file from the MorgDKP directory now.", |
devmode = "Developer mode", |
disablemod = "Disable MOD", |
disablemoddesc = "Send MorgDKP to STANDBY mode.", |
dkpaward = "DKP Award/Time", |
dkpawarddesc = "Enable DKP awarding per unit of time in minutes to raid members who have been present at least for that amount of time.", |
dkpchange = "DKP Changes", |
dkplisten = "DKP Listener", |
dkplistendesc = "When you are in a tracked zone you will track DKP but you will not get the loot popup window or link to raid. You will act like a backup raidlog.", |
dkpsys = "Adjust DKP", |
dkptypes = "DKP Types", |
dkptypesdesc = "Different DKP variations.", |
dkpword = " DKP ", |
enablejustenough = "Just Enough", |
enablejustenoughdesc = "Enable BidWar mode where the winner is charged the 2nd highest bid value for the item.", |
enablepercent = "Percent", |
enablepercentdesc = "Enable percent DKP system. Items will cost a percentage of the members total DKP.", |
enablerandom = "Random", |
enablerandomdesc = "Enable random rolling for items.", |
enablesilentauction = "Silent Auction", |
enablesilentauctiondesc = "Enable BidWar mode with only one round of bidding and no reporting to raid chat.", |
enablewait = "Award DKP", |
enablewaitdesc = "Award DKP to the current members of the waitlist.", |
enablewhisper = "Bidding Whispers", |
enablewhisperdesc = "Enable whisper system - sends whispers to everyone (even if they have MorgBid) so they can reply and bid using whispers.", |
endraidadd = "End %s", |
endandadd = "and add these attendees?", |
endbidding = "Bidding is now closed.", |
eventformat = "Event format", |
eventformatdesc = "Format for the event names that are automatically recorded. Format = <zone> <boss>. Choose one or two in any order.", |
events = "Events", |
exceedoverbid = "You have exceeded the overbid amount of %s. Your bid has been reset to the maximum.", |
from = " from ", |
fubarhintdisabled = "On STANDBY.\n|c000070ddClick:|r to enable.", |
fubaropts = "Fubar Options", |
highbidder = "New high bidder for %s: %s = %s", |
ignorelist = "Ignored items", |
ignorelistdesc = "List of currently ignored items. Click to remove ignored item.", |
importdkp = "Import DKP", |
importdkpdesc = "Import DKP string from website. Note: UI will be reloaded.", |
ImportdefaultDB = "Import saved item database?", |
invalidformat = "Sorry your response format is incorrect or no item with that ID is up for bidding. Format = mbid ID [need/take/pass/bid value]", |
Menu = "FuBar Options", |
mldefunc = "ML/DE mode", |
morgbidmaxwhisper = "Current bid for ID: %s = %s (Reply format: mbid ID [pass/bid value])", |
morgbidwhisper = "%s: ID = %s DKP/Bid value = %s (Reply format: mbid ID [need/take/pass/bid value])", |
multi = "multiPool", |
multidesc = "Enable more than one DKP pool for rolling on items. When starting auction you have to choose the alternate pool to use or it will be main pool that is used.", |
noauction = "This item is not currently up for bid.", |
normal = "Standard", |
onerun = "Single Run event", |
onerundesc = "Use one event for entire raid. Boss kills will not be tracked separately.", |
option = "Options", |
otheroptions = "Other Options", |
otheroptionsdesc = "Miscellaneous DKP/tracking options.", |
overbidmax = "Overbid", |
overbidmaxdesc = "Maximum to allow members to bid above their present DKP.", |
pending = "PENDING...", |
percenttake = "% Take Mode", |
percenttakedesc = "When using the percent DKP system this option enables TAKE looting. This means if the winning member rolled TAKE he will not be charged x% DKP he will instead be charged the base price of the item (Set using original itempoints.", |
pool = "DKP Pool", |
pooldesc = "Set DKP Pool to be primary (or only if not multiPool) DKP pool.", |
pooluse = "Pool", |
poolusedesc = "Choose DKP pool to use for this item roll.", |
pools = "Currently loaded DKP pools....", |
raiddbfunc = "Import DKP standings", |
raiddbfuncdesc = "Import DKP string from website. Note: UI will be reloaded.", |
raids = "Raids", |
raidtrack = "Raid Tracking", |
raidtrackdesc = "Opens the raid tracking functions window.", |
recordbossattempt = "Record boss attempt for %s?", |
requestsync = "Requesting database sync...", |
rollingbegin = "Now querying for %s ID = %s DKP %s....", |
rundkp = "Export Raid", |
rundkpdesc = "Output raid data for Morgimport\nDatabase reset is recommended after or raid logs may get large.", |
runevent = "Sorry deleteing the run event is not allowed as trash drops are recorded in this event.", |
runrewardtime = "Minimum Run Time", |
runrewardtimedesc = "Minimum time in minutes a member must be in the raid before they recieve run DKP. ie 30 min", |
sentsync = "Transmitted item database over sync channel.", |
startformat = "Start format", |
startformatdesc = "Format of start event name: <[zone]> <text>. Example: [zone] Start", |
startruntrack = "Start Event", |
startruntrackdesc = "Track raidstart event.", |
statusoff = "|c009d9d9dOFF|r", |
statuson = "|c001eff00ON|r", |
syncdb = "Sync Item DB", |
syncdbdesc = "Sync your item database with another MorgDKP user. Note: replaces your item database and any values you have added. Use with caution.", |
syncdone = "Database transfer complete and %s items were transferred.", |
syncquery = "SYNC", |
syncrequest = "%s has requested a database sync.", |
syncstart = "Querying MorgDKP databases available...", |
syncwait = "Waiting for sync data from %s", |
transferitem = "Transferred item from %s to %s: Cost = %s.", |
trashformat = "Trash format", |
trashformatdesc = "Format of trash event name: <[zone]> <text>. Example: [zone] Run", |
waitadd = "Added you to the waitlist.", |
waitbossamt = "Waitlist boss DKP", |
waitbossamtdesc = "Amount of DKP to award to the waitlist per boss kill.", |
waitmain = "Please log on to your main for an invite to the raid. Whisper me when online.", |
waitoptsdesc = "Options related to the waitlist.", |
waitsub = "Removed you from the waitlist.", |
waitlist = "Waitlist", |
waitlistdesc = "Options related to the waitlist.", |
waitstartamt = "Waitlist start DKP", |
waitstartamtdesc = "Amount of start bonus DKP to award to the waitlist at the start of the run.", |
waitrunamt = "Waitlist run DKP", |
waitrunamtdesc = "Amount of run DKP to award to the waitlist. Applied at start of run.", |
waitotimeamt = "Waitlist DKP/time", |
waitotimeamtdesc = "Amount of DKP/time to award to the waitlist. Note: Only works if you are awarding DKP/time to the raid.", |
whisperformat = "Please whisper: dkplist [poolname] [class] [class] .... [all]", |
MORGTRACKER_LADYVASHJP2_YELL = "The time is now! Leave none standing!", |
MORGTRACKER_LADYVASHJP3_YELL = "You may want to take cover.", |
MORGTRACKER_RAGEENTERS_YELL = "The Legion's final conquest has begun! Once again the subjugation of this world is within our grasp. Let none survive!", |
MORGTRACKER_ANETHERONENTERS_YELL = "You are defenders of a doomed world! Flee here, and perhaps you will prolong your pathetic lives!", |
MORGTRACKER_KAZROGALENTERS_YELL = "Cry for mercy! Your meaningless lives will soon be forfeit.", |
MORGTRACKER_AZGALORENTERS_YELL = "Abandon all hope! The legion has returned to finish what was begun so many years ago. This time there will be no escape!", |
MORGTRACKER_ERADOR_YELL = "These are the hallmarks...", |
--need loc |
Romulo = "Romulo", |
Julianne = "Julianne", |
RomuloandJulianne = "Romulo & Julianne", |
Chessevent = "Schach Event", |
DEFAULTBOSS = "Trash mob", |
WorldBoss = "World Boss", |
NEW = "NEW", |
NONE = "NONE", |
MORGTRACKER_MAJORDOMO_YELL = "Unm\195\182glich! Haltet ein, Sterbliche... Ich gebe auf! Ich gebe auf!", |
MORGTRACKER_ROMULO_YELL="Welch' Teufel bist du, dass du mich so folterst?", |
MORGTRACKER_CHESS_EMOTE = "The halls of Karazhan shake, as the curse binding the doors of the Gamesman's Hall is lifted.", --need loc |
MORGTRACKER_LOOT_RECEIVES1 = "([^%s]+) bekommt Beute: (.+)%.", |
MORGTRACKER_LOOT_RECEIVES1_COUNT = "([^%s]+) erh\195\164lt Beute: (|c%x+|Hitem:%d+:%d+:%d+:%d+|h%[.-%]|h|r)x(%d+)%.", |
MORGTRACKER_LOOT_RECEIVES2 = "Ihr erhaltet Beute: (.+)%.", |
MORGTRACKER_LOOT_RECEIVES2_COUNT = "Ihr erhaltet Beute: (|c%x+|Hitem:%d+:%d+:%d+:%d+|h%[.-%]|h|r)x(%d+)%.", |
MORGTRACKER_MASTERLOOT = "([^%s]+) ist nun Pl/195/188ndermeister", |
MorgTracker_IgnoreMobs = { |
["Sohn der Flamme"] = true, |
["Onyxia-Welpe"] = true, |
["Kil'rek"] = true, |
["Amani Dragonhawk Spirit"] = true, |
}, |
classcount = { |
["PALADIN"] = 8, |
["HEXENMEISTER"] = 7, |
["MAGIER"] = 13, |
["DRUID"] = 12, |
["KRIEGER"] = 7, |
["J\195\132GER"] = 9, |
["PRIESTER"] = 11, |
["SCHURKE"] = 11, |
["SCHAMANE"] = 8, |
["NEED"] = 10, |
["TAKE"] = 10, |
["PASS"] = 11, |
["PENDING"] = 5 |
}, |
} end) |
MorgDKP_Items = { |
[16957] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33356] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28726] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[33388] = { |
["classes"] = { |
["Warrior"] = true, |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
}, |
}, |
[29253] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28750] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[28766] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[33468] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28782] = { |
["classes"] = { |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Shaman"] = true, |
}, |
}, |
[17069] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28830] = { |
["classes"] = { |
["Warrior"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 35, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[12662] = { |
["classes"] = { |
["Warrior"] = false, |
["Paladin"] = false, |
["Shaman"] = false, |
["Rogue"] = false, |
["Mage"] = false, |
["Druid"] = false, |
["Priest"] = true, |
["All"] = false, |
["Warlock"] = false, |
["Hunter"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29924] = { |
["classes"] = { |
["Warrior"] = true, |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[19720] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33293] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Shaman"] = true, |
}, |
}, |
[33489] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[33357] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29756] = { |
["classes"] = { |
["Hunter"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33389] = { |
["classes"] = { |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Shaman"] = true, |
}, |
}, |
[30020] = { |
["classes"] = { |
["Warlock"] = false, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 30, |
["altclasses"] = { |
["Warlock"] = true, |
}, |
}, |
[33421] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[28503] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[28511] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = false, |
["Mage"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30052] = { |
["classes"] = { |
["Warrior"] = false, |
["Druid"] = false, |
["Shaman"] = false, |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[30060] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[30068] = { |
["classes"] = { |
["Hunter"] = false, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 65, |
["altclasses"] = { |
["Paladin"] = true, |
["Hunter"] = true, |
}, |
}, |
[33469] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33533] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30092] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
["Shaman"] = true, |
["Paladin"] = true, |
}, |
}, |
[33054] = { |
["classes"] = { |
["Warrior"] = false, |
["Paladin"] = true, |
["Shaman"] = false, |
["Rogue"] = false, |
["Mage"] = false, |
["Druid"] = true, |
["Priest"] = false, |
["All"] = false, |
["Hunter"] = false, |
["Warlock"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Warlock"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Mage"] = true, |
["Druid"] = false, |
}, |
}, |
[30619] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 35, |
["altclasses"] = { |
}, |
}, |
[30627] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Druid"] = false, |
["Paladin"] = true, |
}, |
}, |
[28591] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28599] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29764] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 30, |
["altclasses"] = { |
}, |
}, |
[28654] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[30667] = { |
["classes"] = { |
["Warlock"] = false, |
["Shaman"] = true, |
["Mage"] = false, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[19433] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30028] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Druid"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 30, |
["altclasses"] = { |
["Paladin"] = false, |
}, |
}, |
[33214] = { |
["classes"] = { |
["Warrior"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
}, |
["pool"] = "BWL", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[17413] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28663] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28671] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28734] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[33805] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30739] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33326] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[16958] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16966] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28727] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29757] = { |
["classes"] = { |
["Rogue"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29765] = { |
["classes"] = { |
["Warlock"] = true, |
["Mage"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 60, |
["altclasses"] = { |
}, |
}, |
[28751] = { |
["classes"] = { |
["Paladin"] = false, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[30084] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
}, |
}, |
[28767] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
}, |
}, |
[28583] = { |
["classes"] = { |
["Hunter"] = false, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33453] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30324] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[34029] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["Hunter"] = true, |
["Warlock"] = true, |
["All"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30100] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
}, |
}, |
[16806] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28823] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 35, |
["altclasses"] = { |
}, |
}, |
[17078] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[19903] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30626] = { |
["classes"] = { |
["Warlock"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Mage"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Druid"] = false, |
["Shaman"] = false, |
}, |
}, |
[28567] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[17110] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28566] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[28647] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28655] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28590] = { |
["classes"] = { |
["Warrior"] = false, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = false, |
["Mage"] = false, |
["Warlock"] = false, |
["Priest"] = true, |
["All"] = false, |
["Druid"] = true, |
["Hunter"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29925] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Paladin"] = false, |
}, |
}, |
[30067] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
["Shaman"] = true, |
["Druid"] = true, |
}, |
}, |
[33483] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[25350] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28518] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[29965] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 65, |
["altclasses"] = { |
}, |
}, |
[30643] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33327] = { |
["classes"] = { |
}, |
["pool"] = "BWL", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28743] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[33055] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Hunter"] = true, |
["Paladin"] = true, |
}, |
}, |
[25414] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30021] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 85, |
["altclasses"] = { |
}, |
}, |
[30029] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Shaman"] = true, |
}, |
}, |
[28504] = { |
["classes"] = { |
["Warrior"] = false, |
["Hunter"] = true, |
["Rogue"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Rogue"] = true, |
["Warrior"] = true, |
}, |
}, |
[32944] = { |
["classes"] = { |
["Rogue"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
["Warrior"] = true, |
}, |
}, |
[30053] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[30061] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Shaman"] = true, |
["Rogue"] = false, |
["Hunter"] = false, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
}, |
[24304] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28512] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30085] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[18811] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28568] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30620] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 35, |
["altclasses"] = { |
}, |
}, |
[28584] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = false, |
["Shaman"] = true, |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
}, |
}, |
[28592] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[19402] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28608] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[33471] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30668] = { |
["classes"] = { |
["Mage"] = true, |
["Warlock"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28528] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Rogue"] = false, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28600] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33216] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28656] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16911] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[32249] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[19354] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16935] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16943] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16951] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16959] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28735] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28728] = { |
["classes"] = { |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
}, |
[29758] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28744] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[28752] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16919] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28768] = { |
["classes"] = { |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[24576] = { |
["classes"] = { |
}, |
["pool"] = "BWL", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30109] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[29923] = { |
["classes"] = { |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 35, |
["altclasses"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
}, |
[28800] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 65, |
["altclasses"] = { |
}, |
}, |
[32385] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["Hunter"] = true, |
["All"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30740] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[1074] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28672] = { |
["classes"] = { |
["Warrior"] = false, |
["Druid"] = false, |
["Shaman"] = false, |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[29766] = { |
["classes"] = { |
["Rogue"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 60, |
["altclasses"] = { |
}, |
}, |
[28824] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 50, |
["altclasses"] = { |
}, |
}, |
[17103] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28799] = { |
["classes"] = { |
["Warlock"] = true, |
["Priest"] = true, |
["Mage"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[29966] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 65, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[28569] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28633] = { |
["classes"] = { |
["Warlock"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Mage"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29918] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 65, |
["altclasses"] = { |
["Shaman"] = true, |
["Druid"] = true, |
}, |
}, |
[24305] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28521] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[19722] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33281] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33297] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[2672] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33329] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[31332] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33058] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["Hunter"] = true, |
["Warlock"] = true, |
["All"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[28593] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[19435] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[19802] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30030] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 30, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[28505] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29763] = { |
["classes"] = { |
["Rogue"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 60, |
["altclasses"] = { |
}, |
}, |
[18812] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28529] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = false, |
["Shaman"] = true, |
["Rogue"] = false, |
["Mage"] = false, |
["Warlock"] = false, |
["Priest"] = false, |
["Hunter"] = false, |
["Druid"] = false, |
["All"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Rogue"] = true, |
["Druid"] = true, |
["Paladin"] = true, |
}, |
}, |
[28773] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 20, |
["altclasses"] = { |
}, |
}, |
[28545] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[19866] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33474] = { |
["classes"] = { |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Rogue"] = true, |
}, |
}, |
[19371] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30629] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Paladin"] = false, |
}, |
}, |
[19395] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28601] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28609] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33490] = { |
["classes"] = { |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Shaman"] = true, |
}, |
}, |
[33522] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30677] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28741] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[28649] = { |
["classes"] = { |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[28657] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29755] = { |
["classes"] = { |
["Mage"] = true, |
["Warlock"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 75, |
["altclasses"] = { |
}, |
}, |
[28673] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28522] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33298] = { |
["classes"] = { |
["Rogue"] = true, |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[16944] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33354] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[30246] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
}, |
}, |
[30242] = { |
["classes"] = { |
["Rogue"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 90, |
["altclasses"] = { |
}, |
}, |
[28729] = { |
["classes"] = { |
["Warrior"] = false, |
["Warlock"] = false, |
["Rogue"] = true, |
["Mage"] = false, |
["Paladin"] = false, |
["Hunter"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Hunter"] = true, |
}, |
}, |
[29759] = { |
["classes"] = { |
["Warlock"] = true, |
["Mage"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28745] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Shaman"] = true, |
["Rogue"] = false, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
}, |
[28753] = { |
["classes"] = { |
["Druid"] = false, |
["Shaman"] = false, |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
["Paladin"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Druid"] = true, |
}, |
}, |
[16828] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30302] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[7976] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28785] = { |
["classes"] = { |
["Warrior"] = false, |
["Paladin"] = false, |
["Shaman"] = true, |
["Rogue"] = false, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["Hunter"] = false, |
["Warlock"] = true, |
["All"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28565] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[28801] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Paladin"] = true, |
["Shaman"] = false, |
}, |
}, |
[30729] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28506] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28825] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 50, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[30047] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 65, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[30055] = { |
["classes"] = { |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 60, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[33491] = { |
["classes"] = { |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Rogue"] = true, |
}, |
}, |
[28530] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[19859] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30673] = { |
["classes"] = { |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30665] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[33203] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[21456] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30446] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[16852] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30641] = { |
["classes"] = { |
["Warrior"] = true, |
["Hunter"] = false, |
["Paladin"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[33283] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = false, |
["Druid"] = false, |
}, |
}, |
[33299] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28589] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29983] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 60, |
["altclasses"] = { |
["Paladin"] = false, |
}, |
}, |
[28581] = { |
["classes"] = { |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Rogue"] = true, |
}, |
}, |
[30058] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[30098] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Shaman"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
}, |
[30090] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Shaman"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 85, |
["altclasses"] = { |
}, |
}, |
[30023] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[30050] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
}, |
}, |
[25440] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28514] = { |
["classes"] = { |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
}, |
}, |
[18813] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30063] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[28658] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30079] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
["Shaman"] = true, |
["Druid"] = true, |
}, |
}, |
[19335] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30095] = { |
["classes"] = { |
["Warlock"] = true, |
["Mage"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
}, |
}, |
[18861] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28578] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28586] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[28594] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[28602] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[28610] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[21464] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28525] = { |
["classes"] = { |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
}, |
[19436] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28517] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[32227] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[22526] = { |
["classes"] = { |
}, |
["pool"] = "BWL", |
["points"] = 10, |
["altclasses"] = { |
}, |
}, |
[28666] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28674] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Shaman"] = true, |
}, |
}, |
[33300] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Shaman"] = true, |
}, |
}, |
[23069] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16945] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33332] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30247] = { |
["classes"] = { |
["Mage"] = true, |
["Hunter"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
}, |
}, |
[30303] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28730] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Shaman"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
}, |
[23628] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[25169] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
["Priest"] = true, |
["All"] = true, |
["Druid"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28754] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28762] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Mage"] = true, |
["Druid"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = false, |
["Paladin"] = false, |
["Shaman"] = false, |
["Rogue"] = false, |
["Mage"] = false, |
["Druid"] = false, |
["Priest"] = false, |
["Hunter"] = false, |
["Warlock"] = false, |
["All"] = false, |
}, |
}, |
[30814] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28778] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[33492] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = false, |
["Rogue"] = false, |
["Mage"] = false, |
["Druid"] = false, |
["Priest"] = false, |
["All"] = false, |
["Hunter"] = true, |
["Warlock"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33971] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28802] = { |
["classes"] = { |
["Warlock"] = true, |
["Priest"] = false, |
["Mage"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 60, |
["altclasses"] = { |
}, |
}, |
[25744] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33476] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[28826] = { |
["classes"] = { |
["Warrior"] = false, |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Warrior"] = true, |
["Hunter"] = true, |
}, |
}, |
[28810] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 50, |
["altclasses"] = { |
}, |
}, |
[28746] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28770] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[17105] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[18646] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[3300] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29984] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 35, |
["altclasses"] = { |
["Shaman"] = true, |
["Paladin"] = false, |
}, |
}, |
[30056] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 95, |
["altclasses"] = { |
["Shaman"] = true, |
["Druid"] = true, |
}, |
}, |
[29920] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[29553] = { |
["classes"] = { |
["Paladin"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 47, |
["altclasses"] = { |
}, |
}, |
[30447] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[30080] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = false, |
["Mage"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
}, |
}, |
[30104] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
["Paladin"] = false, |
}, |
}, |
[33285] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[25339] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["All"] = true, |
["Warlock"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33828] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[27429] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[18423] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16898] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30008] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[33286] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[25425] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 20, |
["altclasses"] = { |
}, |
}, |
[28747] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[28507] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[28515] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[28523] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30064] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 65, |
["altclasses"] = { |
["Shaman"] = true, |
["Druid"] = true, |
}, |
}, |
[19852] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[21904] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[31342] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30096] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
["Paladin"] = false, |
}, |
}, |
[16818] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28579] = { |
["classes"] = { |
["Warrior"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Hunter"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
["Hunter"] = true, |
}, |
}, |
[28587] = { |
["classes"] = { |
["Paladin"] = false, |
["Shaman"] = false, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
}, |
[24507] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[19405] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28611] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16866] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33463] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28524] = { |
["classes"] = { |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Hunter"] = true, |
}, |
}, |
[33206] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[32228] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28659] = { |
["classes"] = { |
["Warrior"] = false, |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
}, |
}, |
[16914] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28675] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16930] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33830] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33829] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Paladin"] = true, |
}, |
}, |
[30240] = { |
["classes"] = { |
["Priest"] = true, |
["Druid"] = true, |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
}, |
}, |
[30248] = { |
["classes"] = { |
["Rogue"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
}, |
}, |
[28508] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29753] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29761] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30280] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28755] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
["Druid"] = true, |
}, |
}, |
[28763] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28771] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33478] = { |
["classes"] = { |
["Warrior"] = true, |
["Hunter"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33494] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[28795] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[28803] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 50, |
["altclasses"] = { |
}, |
}, |
[32388] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["Hunter"] = true, |
["Warlock"] = true, |
["All"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33303] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[28827] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 50, |
["altclasses"] = { |
["Shaman"] = true, |
}, |
}, |
[33590] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Hunter"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28516] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33495] = { |
["classes"] = { |
["Warrior"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
}, |
}, |
[17106] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30081] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
["Paladin"] = false, |
}, |
}, |
[19374] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33591] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[5194] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["All"] = true, |
["Warlock"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29921] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 95, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[33496] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
}, |
[5200] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["All"] = true, |
["Warlock"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33480] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[32516] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 65, |
["altclasses"] = { |
}, |
}, |
[29458] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29977] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
}, |
}, |
[29985] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 60, |
["altclasses"] = { |
}, |
}, |
[28772] = { |
["classes"] = { |
["Warrior"] = false, |
["Hunter"] = true, |
["Rogue"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Rogue"] = true, |
}, |
}, |
[28612] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28756] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28748] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30025] = { |
["classes"] = { |
["Rogue"] = true, |
["Warrior"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Warrior"] = true, |
["Hunter"] = true, |
["Shaman"] = false, |
}, |
}, |
[28740] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[25442] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30049] = { |
["classes"] = { |
["Warrior"] = false, |
["Paladin"] = false, |
["Shaman"] = false, |
["Rogue"] = false, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["All"] = false, |
["Warlock"] = true, |
["Hunter"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Shaman"] = true, |
}, |
}, |
[30057] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 65, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[30065] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 95, |
["altclasses"] = { |
}, |
}, |
[28732] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[16803] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30097] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[28572] = { |
["classes"] = { |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
}, |
}, |
[19382] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[19390] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[19398] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28604] = { |
["classes"] = { |
["Priest"] = true, |
["Druid"] = true, |
["Shaman"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Shaman"] = true, |
}, |
}, |
[28101] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30664] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[16835] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30249] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
}, |
}, |
[28660] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28652] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16907] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16947] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30720] = { |
["classes"] = { |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[30728] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16859] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33831] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[30241] = { |
["classes"] = { |
["Warlock"] = true, |
["Mage"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
}, |
}, |
[16963] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28588] = { |
["classes"] = { |
["Priest"] = true, |
["Shaman"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29754] = { |
["classes"] = { |
["Rogue"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 75, |
["altclasses"] = { |
}, |
}, |
[29762] = { |
["classes"] = { |
["Hunter"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 60, |
["altclasses"] = { |
}, |
}, |
[30281] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33432] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28764] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Hunter"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = false, |
}, |
}, |
[33464] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28780] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[30321] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28796] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 60, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[28804] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 60, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[29554] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["All"] = true, |
["Warlock"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[18815] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28828] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = false, |
["Shaman"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
["Druid"] = true, |
}, |
}, |
[33592] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30448] = { |
["classes"] = { |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[33191] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[33640] = { |
["classes"] = { |
["Warrior"] = true, |
["Shaman"] = true, |
["Rogue"] = false, |
["Hunter"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
}, |
[30304] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33446] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28731] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = false, |
["Priest"] = true, |
["Paladin"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
}, |
[2409] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28603] = { |
["classes"] = { |
["Warlock"] = true, |
["Shaman"] = false, |
["Priest"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[18870] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30449] = { |
["classes"] = { |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[33493] = { |
["classes"] = { |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[30024] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 35, |
["altclasses"] = { |
["Shaman"] = true, |
["Druid"] = true, |
}, |
}, |
[33317] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[32515] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 65, |
["altclasses"] = { |
["Paladin"] = false, |
}, |
}, |
[32267] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
}, |
}, |
[28453] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Shaman"] = true, |
}, |
}, |
[13107] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30239] = { |
["classes"] = { |
["Rogue"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 65, |
["altclasses"] = { |
}, |
}, |
[28477] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16921] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30026] = { |
["classes"] = { |
["Shaman"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[29760] = { |
["classes"] = { |
["Rogue"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28509] = { |
["classes"] = { |
["Warrior"] = false, |
["Druid"] = false, |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = true, |
["Druid"] = true, |
}, |
}, |
[33465] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33481] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[30066] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[30183] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["Hunter"] = true, |
["All"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 5, |
["altclasses"] = { |
}, |
}, |
[30082] = { |
["classes"] = { |
["Rogue"] = true, |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
["Hunter"] = true, |
}, |
}, |
[29068] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16812] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28573] = { |
["classes"] = { |
["Warrior"] = true, |
["Hunter"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[18872] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16836] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28597] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = false, |
["Shaman"] = false, |
["Rogue"] = false, |
["Mage"] = false, |
["Druid"] = false, |
["Priest"] = false, |
["Hunter"] = false, |
["Warlock"] = false, |
["All"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[19407] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30127] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28621] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[19431] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28570] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33497] = { |
["classes"] = { |
["Warlock"] = true, |
["Shaman"] = false, |
["Priest"] = true, |
["Mage"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Warrior"] = false, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = false, |
["Mage"] = false, |
["Druid"] = true, |
["Priest"] = false, |
["All"] = false, |
["Warlock"] = false, |
["Hunter"] = false, |
}, |
}, |
[28653] = { |
["classes"] = { |
["Warlock"] = true, |
["Shaman"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["Hunter"] = true, |
["Mage"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28661] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28669] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
}, |
}, |
[16924] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16932] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16940] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33322] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16956] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30250] = { |
["classes"] = { |
["Mage"] = true, |
["Hunter"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
}, |
}, |
[20038] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28733] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29252] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28749] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = false, |
["Shaman"] = false, |
["Rogue"] = false, |
["Mage"] = false, |
["Druid"] = false, |
["Priest"] = false, |
["All"] = false, |
["Warlock"] = false, |
["Hunter"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[28757] = { |
["classes"] = { |
["Rogue"] = true, |
["Hunter"] = false, |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[28765] = { |
["classes"] = { |
["Warrior"] = false, |
["Paladin"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33466] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[29767] = { |
["classes"] = { |
["Priest"] = true, |
["Druid"] = true, |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 60, |
["altclasses"] = { |
}, |
}, |
[33498] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28797] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[19387] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28777] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Hunter"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30062] = { |
["classes"] = { |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 65, |
["altclasses"] = { |
["Shaman"] = true, |
}, |
}, |
[33473] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[30022] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Paladin"] = false, |
["Shaman"] = false, |
["Rogue"] = true, |
["Hunter"] = true, |
}, |
}, |
[28585] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[22721] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33328] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[34845] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["All"] = true, |
["Warlock"] = true, |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[21220] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[19003] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[33211] = { |
["classes"] = { |
["Rogue"] = true, |
["Hunter"] = false, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
}, |
[28742] = { |
["classes"] = { |
["Priest"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30450] = { |
["classes"] = { |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 35, |
["altclasses"] = { |
}, |
}, |
[29947] = { |
["classes"] = { |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 70, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Hunter"] = true, |
}, |
}, |
[30245] = { |
["classes"] = { |
["Rogue"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
}, |
}, |
[30101] = { |
["classes"] = { |
["Rogue"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 95, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
["Druid"] = true, |
}, |
}, |
[33102] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Mage"] = true, |
["Druid"] = true, |
["Priest"] = true, |
["All"] = true, |
["Hunter"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28520] = { |
["classes"] = { |
["Hunter"] = false, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[28454] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30644] = { |
["classes"] = { |
["Rogue"] = true, |
["Druid"] = false, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
["Druid"] = true, |
}, |
}, |
[33215] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[25412] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[29949] = { |
["classes"] = { |
["Hunter"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 80, |
["altclasses"] = { |
["Rogue"] = true, |
["Warrior"] = true, |
}, |
}, |
[30027] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 40, |
["altclasses"] = { |
}, |
}, |
[28502] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[28510] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[33467] = { |
["classes"] = { |
["Warlock"] = true, |
["Mage"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[30059] = { |
["classes"] = { |
["Warrior"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["Hunter"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
}, |
}, |
[19336] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[2070] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30083] = { |
["classes"] = { |
["Warrior"] = true, |
["Druid"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 45, |
["altclasses"] = { |
["Paladin"] = false, |
}, |
}, |
[19360] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16813] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[16830] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28582] = { |
["classes"] = { |
["Paladin"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[19392] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30642] = { |
["classes"] = { |
["Priest"] = true, |
["Paladin"] = true, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28606] = { |
["classes"] = { |
["Warrior"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[19337] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30666] = { |
["classes"] = { |
["Priest"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[30674] = { |
["classes"] = { |
["Rogue"] = false, |
["Druid"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Rogue"] = true, |
["Shaman"] = true, |
}, |
}, |
[28519] = { |
["classes"] = { |
["Hunter"] = true, |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28631] = { |
["classes"] = { |
["Shaman"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Paladin"] = true, |
}, |
}, |
[16901] = { |
["classes"] = { |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28662] = { |
["classes"] = { |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
}, |
}, |
[28670] = { |
["classes"] = { |
["Priest"] = true, |
["Mage"] = true, |
["Warlock"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 0, |
["altclasses"] = { |
["Druid"] = true, |
["Shaman"] = true, |
}, |
}, |
[28822] = { |
["classes"] = { |
["Druid"] = true, |
["Shaman"] = true, |
["Priest"] = true, |
["Paladin"] = true, |
}, |
["pool"] = "Outlands", |
["points"] = 35, |
["altclasses"] = { |
}, |
}, |
} |
-- ****************************************************************** |
-- ****************************************************************** |
-- ** MorgDKP ** |
-- ****************************************************************** |
-- ****************************************************************** |
-- |
local L = AceLibrary("AceLocale-2.2"):new("MorgDKP") |
local BC = AceLibrary("Babble-Class-2.2") |
local BZ = LibStub("LibBabble-Zone-3.0"):GetLookupTable() |
local BB = LibStub("LibBabble-Boss-3.0"):GetLookupTable() |
local dewdrop = AceLibrary("Dewdrop-2.0") |
local rosterlib = AceLibrary("Roster-2.1") |
local roster = rosterlib.roster |
local tablet = AceLibrary("Tablet-2.0") |
MorgDKP = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0", "AceHook-2.1", "AceConsole-2.0","AceComm-2.0", "AceDB-2.0") |
MorgDKP.version = "6.88" |
MorgDKP.commPrefix = "MorgDKP" |
MorgDKP.commVersion = 6.2 |
StaticPopupDialogs["MorgLoot"] = { |
text = TEXT(L["lootquery"]), |
button1 = TEXT(YES), |
button2 = TEXT(NO), |
OnAccept = function() |
MorgDKP:GiveOutLoot() |
end, |
timeout = 0, |
whileDead = 1, |
hideOnEscape = 1, |
} |
StaticPopupDialogs["BossAttempt"] = { |
text = TEXT(L["recordbossattempt"]), |
button1 = TEXT(YES), |
button2 = TEXT(NO), |
OnAccept = function() |
MorgDKP:CustomEvent() |
end, |
timeout = 0, |
whileDead = 1, |
hideOnEscape = 1, |
} |
StaticPopupDialogs["MorgAcceptSYNC"] = { |
text = TEXT(L["AcceptSYNC"]), |
button1 = TEXT(YES), |
button2 = TEXT(NO), |
OnAccept = function() |
MorgDKP:AcceptSyncData() |
end, |
OnCancel = function() |
MorgDKP:DenySyncData() |
end, |
timeout = 0, |
whileDead = 1, |
hideOnEscape = 1, |
} |
StaticPopupDialogs["MorgImport"] = { |
text = TEXT(L["ImportdefaultDB"]), |
button1 = TEXT(YES), |
button2 = TEXT(NO), |
OnAccept = function() |
MorgDKP:ImportMorgItems() |
end, |
timeout = 0, |
whileDead = 1, |
hideOnEscape = 1, |
} |
StaticPopupDialogs["MorgAcceptLeader"] = { |
text = TEXT(L["AcceptLeaderRequest"]), |
button1 = TEXT(YES), |
button2 = TEXT(NO), |
OnAccept = function() |
MorgDKP:AcceptLeader() |
end, |
OnCancel = function() |
MorgDKP:DenyLeader() |
end, |
timeout = 0, |
whileDead = 1, |
hideOnEscape = 1, |
} |
MorgTracker_ZoneBosses = { |
[BZ["Molten Core"]] = {[1] = BB["Lucifron"], |
[2] = BB["Magmadar"], |
[3] = BB["Gehennas"], |
[4] = BB["Garr"], |
[5] = BB["Baron Geddon"], |
[6] = BB["Shazzrah"], |
[7] = BB["Sulfuron Harbinger"], |
[8] = BB["Golemagg the Incinerator"], |
[9] = BB["Majordomo Executus"], |
[10] = BB["Ragnaros"]}, |
[BZ["Blackwing Lair"]] = {[1] = BB["Razorgore the Untamed"], |
[2] = BB["Vaelastrasz the Corrupt"], |
[3] = BB["Broodlord Lashlayer"], |
[4] = BB["Firemaw"], |
[5] = BB["Ebonroc"], |
[6] = BB["Flamegor"], |
[7] = BB["Chromaggus"], |
[8] = BB["Nefarian"]}, |
[BZ["Zul'Gurub"]] = {[1] = BB["High Priestess Jeklik"], |
[2] = BB["High Priest Venoxis"], |
[3] = BB["High Priestess Mar'li"], |
[4] = BB["High Priest Thekal"], |
[5] = BB["High Priestess Arlokk"], |
[6] = BB["Hakkar"], |
[7] = BB["Bloodlord Mandokir"], |
[8] = BB["Jin'do the Hexxer"], |
[9] = BB["Gahz'ranka"], |
[10] = BB["Hazza'rah"], |
[11] = BB["Gri'lek"], |
[12] = BB["Renataki"], |
[13] = BB["Wushoolay"]}, |
[BZ["Ruins of Ahn'Qiraj"]] = {[1] = BB["Kurinnaxx"], |
[2] = BB["General Rajaxx"], |
[3] = BB["Ayamiss the Hunter"], |
[4] = BB["Buru the Gorger"], |
[5] = BB["Moam"], |
[6] = BB["Ossirian the Unscarred"]}, |
[BZ["Ahn'Qiraj"]] = { [1] = BB["The Prophet Skeram"], |
[2] = BB["Fankriss the Unyielding"], |
[3] = BB["Battleguard Sartura"], |
[4] = BB["Princess Huhuran"], |
[5] = BB["Emperor Vek'lor"], |
[6] = BB["Emperor Vek'nilash"], |
[7] = BB["C'Thun"], |
[8] = BB["Vem"], |
[9] = BB["Princess Yauj"], |
[10] = BB["Lord Kri"], |
[11] = BB["Viscidus"], |
[12] = BB["Ouro"]}, |
[BZ["Naxxramas"]] = {[1] = BB["Patchwerk"], |
[2] = BB["Grobbulus"], |
[3] = BB["Gluth"], |
[4] = BB["Thaddius"], |
[5] = BB["Instructor Razuvious"], |
[6] = BB["Gothik the Harvester"], |
[7] = BB["Highlord Mograine"], |
[8] = BB["Thane Korth'azz"], |
[9] = BB["Lady Blaumeux"], |
[10] = BB["Sir Zeliek"], |
[11] = BB["Noth the Plaguebringer"], |
[12] = BB["Heigan the Unclean"], |
[13] = BB["Loatheb"], |
[14] = BB["Anub'Rekhan"], |
[15] = BB["Grand Widow Faerlina"], |
[16] = BB["Maexxna"], |
[17] = BB["Sapphiron"], |
[18] = BB["Kel'Thuzad"]}, |
[BZ["Karazhan"]] = {[1] = BB["Attumen the Huntsman"], |
[2] = BB["Moroes"], |
[3] = BB["Maiden of Virtue"], |
[4] = BB["Netherspite"], |
[5] = BB["Nightbane"], |
[6] = BB["Prince Malchezaar"], |
[7] = BB["Shade of Aran"], |
[8] = BB["Terestian Illhoof"], |
[9] = BB["The Curator"], |
[10] = BB["Romulo & Julianne"], |
[11] = BB["The Big Bad Wolf"], |
[12] = BB["The Crone"], |
[13] = BB["Chess Event"], |
[14] = BB["Rokad the Ravager"], |
[15] = BB["Hyakiss the Lurker"], |
[16] = BB["Shadikith the Glider"]}, |
[BZ["Serpentshrine Cavern"]] = {[1] = BB["Hydross the Unstable"], |
[2] = BB["Fathom-Lord Karathress"], |
[3] = BB["The Lurker Below"], |
[4] = BB["Morogrim Tidewalker"], |
[5] = BB["Leotheras the Blind"], |
[6] = BB["Lady Vashj"]}, |
[BZ["Tempest Keep"]] = {[1] = BB["Al'ar"], |
[2] = BB["Void Reaver"], |
[3] = BB["High Astromancer Solarian"], |
[4] = BB["Kael'thas Sunstrider"]}, |
[BZ["Hyjal Summit"]] = {[1] = BB["Rage Winterchill"], |
[2] = BB["Anetheron"], |
[3] = BB["Kaz'rogal"], |
[4] = BB["Azgalor"], |
[5] = BB["Archimonde"]}, |
[BZ["Black Temple"]] = { [1] = BB["High Warlord Naj'entus"], |
[2] = BB["Supremus"], |
[3] = BB["Gurtogg Bloodboil"], |
[4] = BB["Teron Gorefiend"], |
[5] = BB["Shade of Akama"], |
[6] = BB["Reliquary of Souls"], |
[7] = BB["Mother Shahraz"], |
[8] = BB["Illidari Council"], |
[9] = BB["Illidan Stormrage"]}, |
[BZ["Zul'Aman"]] = {[1] = BB["Akil'zon"], |
[2] = BB["Halazzi"], |
[3] = BB["Jan'alai"], |
[4] = BB["Hex Lord Malacrass"], |
[5] = BB["Nalorakk"], |
[6] = BB["Zul'jin"]}, |
[L["WorldBoss"]] = { [1] = BB["Emeriss"], |
[2] = BB["Lethon"], |
[3] = BB["Ysondre"], |
[4] = BB["Taerar"], |
[5] = BB["Azuregos"], |
[6] = BB["Doom Lord Kazzak"], |
[7] = BB["Doomwalker"]}, |
[BZ["Onyxia's Lair"]] = {[1] = BB["Onyxia"]}, |
[BZ["Gruul's Lair"]] = {[1] = BB["High King Maulgar"],[2] = BB["Gruul the Dragonkiller"]}, |
[BZ["Magtheridon's Lair"]] = {[1] = BB["Magtheridon"]}, |
[BZ["Sunwell Plateau"]] = { [1] = BB["Kalecgos"], |
[2] = BB["Brutallus"], |
[3] = BB["Felmyst"], |
[4] = BB["The Eredar Twins"], |
[5] = BB["M'uru"], |
[6] = BB["Kil'jaeden"]} |
} |
function MorgDKP:OnInitialize() |
MorgDKP:RegisterDB("MorgDKPDB") |
MorgDKP:RegisterDefaults('account', { |
items = { }, |
info = { }, |
defaults = { |
zerosum = nil, |
bidwar = nil, |
whisper = nil, |
relational = nil, |
random = nil, |
silent = nil, |
InRaid = nil, |
raidend = nil, |
quality = 4, |
raidnum = 0, |
bidstep = 5, |
startrun = 1, |
raidnum = 0, |
raidlist = { [1] = L["NONE"] }, |
raidmembers = {[1] = UnitName("player")}, |
lootframex = UIParent:GetWidth() / 2, |
lootframey = UIParent:GetHeight() / 2, |
raid = nil, |
custom = L["NEW"], |
menuzone = L["WorldBoss"], |
autozone = 1, |
multiPool = nil, |
dbupdated = 0, |
dkpaward = nil, |
dkpsched = 3600, |
dkpamount = 1, |
dbpassword = "SyncDBPassword", |
overbid = 50, |
justenough = nil, |
OneEvent = nil, |
Waitlist = {members = {}, join = {} }, |
waitstart = 2, |
waitrun = 0, |
waitaward = nil, |
waitotime = 0, |
waitboss = 0, |
percent = 0, |
percenttake = nil, |
attemptmode = nil, |
eventformat = "<boss>", |
startformat = "<zone> Start", |
trashformat = "<zone> Run", |
runrewardtime = 1800, |
dkplistener = nil, |
leadbroadcast = nil, |
restoreautozone = nil, |
devmode = nil, |
ignore = { [1] = "|cffa335ee|Hitem:22450:0:0:0:0:0:0:0|h[Void Crystal]|h|r", [2] = "|cffa335ee|Hitem:29434:0:0:0:0:0:0:0|h[Badge of Justice]|h|r", |
[3] = "|cffa335ee|Hitem:18562:0:0:0:0:0:0:0|h[Elementium Ore]|h|r", [4] = "|cff0070dd|Hitem:22448:0:0:0:0:0:0:0|h[Small Prismatic Shard]|h|r", |
[5] = "|cff0070dd|Hitem:22449:0:0:0:0:0:0:0|h[Large Prismatic Shard]|h|r", [6] = "|cff0070dd|Hitem:14344:0:0:0:0:0:0:0|h[Large Brilliant Shard]|h|r", |
[7] = "|cffff8000|Hitem:30317:0:0:0:0:0:0:0|h[Cosmic Infuser]|h|r", [8] = "|cffff8000|Hitem:30316:0:0:0:0:0:0:0|h[Devastation]|h|r", |
[9] = "|cffff8000|Hitem:30312:0:0:0:0:0:0:0|h[Infinity Blade]|h|r",[10] = "|cffff8000|Hitem:30318:0:0:0:0:0:0:0|h[Netherstrand Longbow]|h|r", |
[11] = "|cffff8000|Hitem:30313:0:0:0:0:0:0:0|h[Staff of Disintegration]|h|r", [12] = "|cffff8000|Hitem:30311:0:0:0:0:0:0:0|h[Warp Slicer]|h|r", |
[13] = "|cffff8000|Hitem:30314:0:0:0:0:0:0:0|h[Phaseshift Bulwark]|h|r", [14] = "|cffff8000|Hitem:30320:0:0:0:0:0:0:0|h[Bundle of Nether Spikes]|h|r", |
[15] = "|cffff8000|Hitem:30319:0:0:0:0:0:0:0|h[Nether Spike]|h|r" } |
}, |
raidlog = { |
raidstart = L["pending"], |
raidend = L["pending"], |
raidexport = L["pending"], |
playerinfo = { }, |
join = { }, |
leave = { }, |
bosskills = { }, |
loot = { } |
} |
}) |
self:DoOptions() |
MorgDKP:RegisterChatCommand({L["cmd1"], L["cmd2"]}, MorgDKP.opts) |
self:SetCommPrefix("MorgDKP") |
end |
function MorgDKP:OnEnable(called) |
if called then self:ToggleActive(false) return end |
self.items = { } |
self.TT = { } |
self.querytooltips = { } |
self.origitempoints = { } |
self.queryneeded = nil |
self.killed = { } |
self.MLmode = true |
self.hasitem = nil |
self.requestsync = nil |
self.repliedleader = nil |
self.random = {} |
self.given = nil |
self.Fonts = { |
['GameFontNormal'] = {['Font'] = { GameFontNormal:GetFont() }}, |
['GameFontNormalSmall'] = {['Font'] = { GameFontNormalSmall:GetFont() }}, |
} |
if self.db.account.defaults.dbupdated ~= 3 then |
self:ConvertDB() |
self.db.account.defaults.dbupdated = 3 |
end |
if MorgDKP_Items then StaticPopup_Show ("MorgImport") end |
self:ToggleDKPAward() |
if UnitInRaid("player") and self.db.account.defaults.InRaid then |
if not self:IsEventScheduled("MorgDKP_Attendance") then self:ScheduleRepeatingEvent("MorgDKP_Attendance", self.CheckAttendance, 60, self ) end |
end |
if self.db.account.defaults.restoreautozone then |
self.db.account.defaults.autozone = true |
self.db.account.defaults.restoreautozone = nil |
end |
self:UpdateRaidlist() |
self:TogglePlayerDies(self.db.account.defaults.attemptmode) |
self:RegisterEvent("CHAT_MSG_ADDON", "OnAddonMsg") |
self:RegisterEvent("CHAT_MSG_LOOT", "OnLootMsg") |
self:RegisterEvent("LOOT_OPENED", "OnOpen") |
self:RegisterEvent("RosterLib_UnitChanged", "ProcessRosterChange") |
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED", "CombatLogEvent") |
self:RegisterEvent("CHAT_MSG_MONSTER_YELL", "HostileYell") |
self:RegisterEvent("CHAT_MSG_MONSTER_EMOTE", "HostileEmote") |
self:RegisterEvent("GUILD_ROSTER_UPDATE", "GuildUpdate") |
self:RegisterComm(self.commPrefix, "GUILD", "OnCommReceive") |
self:RegisterComm(self.commPrefix, "GROUP", "OnCommReceive") |
self:HookStuff() |
end |
function MorgDKP:OnDisable() |
self:UnhookAll() |
self:TogglePlayerDies() |
if self:IsEventScheduled("MorgDKP_Award") then self:CancelScheduledEvent("MorgDKP_Award") end |
if self:IsEventScheduled("MorgDKP_Attendance") then self:CancelScheduledEvent("MorgDKP_Attendance") end |
MorgDKPFu:ChangeState() |
end |
function MorgDKP:TogglePlayerDies(switch) |
if switch then self:RegisterEvent("PLAYER_DEAD", "LeaderDied") |
elseif self:IsEventRegistered("PLAYER_DEAD") then self:UnregisterEvent("PLAYER_DEAD") end |
end |
function MorgDKP:ToggleDKPAward() |
local ON = self:IsEventScheduled("MorgDKP_Award") |
if self.db.account.defaults.InRaid and self.db.account.defaults.dkpaward then |
if not ON then self:ScheduleRepeatingEvent("MorgDKP_Award", self.RecurrentReward, self.db.account.defaults.dkpsched, self ) end |
self:Print("AWARD ON") |
return |
end |
if ON then self:CancelScheduledEvent("MorgDKP_Award") self:Print("AWARD OFF") end |
end |
function MorgDKP:IsRaided() |
if not UnitInRaid("player") then |
DEFAULT_CHAT_FRAME:AddMessage(L["needraid"]) |
return false |
end |
return true |
end |
function MorgDKP:IsValid() |
if self.db.account.defaults.random then |
self.db.account.defaults.bidwar = nil |
self.db.account.defaults.relational = nil |
self.db.account.defaults.zerosum = nil |
self.db.account.defaults.multiPool = nil |
self.db.account.defaults.percent = 0 |
end |
if self.db.account.defaults.bidwar or self.db.account.defaults.relational or self.db.account.defaults.zerosum or self.db.account.defaults.multiPool or self.db.account.defaults.percent > 0 then return true |
else return false end |
end |
function MorgDKP:PlayerinDB(playname, playclass) |
if not self.db.account.info[playname] then |
self.db.account.info[playname] = { } |
self.db.account.info[playname][self.db.account.defaults.raid] = {points = 0, earned = 0, spent = 0} |
self.db.account.info[playname].raidloot = 0 |
self.db.account.info[playname].lastupdate = self:GetServerTime() |
end |
if not self.db.account.info[playname].aliases then self.db.account.info[playname].aliases = { } end |
if playclass and not self.db.account.info[playname].class then |
self.db.account.info[playname].class = playclass |
self.db.account.info[playname].lastupdate = self:GetServerTime() |
end |
end |
function MorgDKP:PointsPoolExists(playname, pool) |
self:PlayerinDB(playname) |
if not self.db.account.info[playname][pool] then |
self.db.account.info[playname][pool] = {points = 0, earned = 0, spent = 0} |
self.db.account.info[playname].lastupdate = self:GetServerTime() |
end |
end |
function MorgDKP:IteminDB(item) |
if not self.db.account.items[item] then |
self.db.account.items[item] = {points = 0, classes = {}, altclasses = {} } |
end |
if not self.db.account.items[item].points then self.db.account.items[item].points = 0 end |
if not self.db.account.items[item].pool then self.db.account.items[item].pool = self.db.account.defaults.raid end |
end |
function MorgDKP:GiveOutLoot() |
for ci = 1, GetNumRaidMembers() do |
if GetMasterLootCandidate(ci) == Lootwinner then |
for li = 1, GetNumLootItems() do |
local lootIcon, lootName, lootQuantity, rarity = GetLootSlotInfo(li) |
if lootName == Lootitem then |
GiveMasterLoot(li, ci) |
return |
end |
end |
end |
end |
end |
function MorgDKP:MakeDewDropMenu(frame, itemlink) |
if itemlink == nil then return end |
_, _, qid = string.find(itemlink, "Hitem:(%d+)") |
local id = tonumber(qid) |
if( id ) then |
-- make sure it's there |
self:IteminDB(id) |
-- get cursor pos |
local x,y = GetCursorPosition() |
myid, mylink = id,itemlink |
-- build the menu |
self.hasitem = 1 |
dewdrop:Open(frame, |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.opts) |
end, |
'cursorX', true, |
'cursorY', true |
) |
end |
end |
function MorgDKP:GiveBOE(id, link) |
if not self.db.account.items[id] then DEFAULT_CHAT_FRAME:AddMessage(L["noitem"]); return end |
if not charstring then DEFAULT_CHAT_FRAME:AddMessage(L["validname"]) return end |
if self.MLmode and (charstring == self.db.account.defaults.mlooter or charstring == self.db.account.defaults.disenchanter) then |
DEFAULT_CHAT_FRAME:AddMessage(L["nolootrec"]) |
return |
end |
MorgDKP:RecordLoot(link, charstring) |
end |
function MorgDKP:CheckRaid(namequery) |
for pname, data in pairs(roster) do |
if pname == namequery then |
return true |
end |
end |
return nil |
end |
function MorgDKP:CheckPool(item) |
local POOL = self.db.account.defaults.raid |
if self.db.account.defaults.multiPool then |
if self.db.account.items[item] then |
POOL = self.db.account.items[item].pool |
end |
end |
return POOL |
end |
function MorgDKP:AddTwink(twinkstring) |
_, _, twink2, twink1 = string.find(twinkstring, "(%a+) (%a+)") |
if twink1 == nil or twink2 == nil then |
DEFAULT_CHAT_FRAME:AddMessage(L["twinkaltmain"]) |
return |
end |
local POOL = self.db.account.defaults.raid |
twinkmain = string.upper(string.sub(twink1,1,1))..string.sub(twink1,2,-1) |
twinkalt = string.upper(string.sub(twink2,1,1))..string.sub(twink2,2,-1) |
mainpoints = 0 |
if self.db.account.info[twinkmain] then mainpoints = self.db.account.info[twinkmain][POOL].points |
else DEFAULT_CHAT_FRAME:AddMessage(L["nomain"]) return end |
for _, data in pairs(self.db.account.defaults.eqDKP[self.db.account.defaults.raid].Aliases) do |
if data.alt == twinkalt then |
DEFAULT_CHAT_FRAME:AddMessage(L["aliasexists"]) |
return |
end |
end |
local var = nil |
if self.db.account.info[twinkalt] then |
DEFAULT_CHAT_FRAME:AddMessage(L["transfer"]..tostring(mainpoints)..L["dkpp"]..twinkmain..L["to"]..twinkalt) |
var = 1 |
end |
if not var then |
DEFAULT_CHAT_FRAME:AddMessage(L["addnewchar"]..twinkalt.." with "..tostring(mainpoints)..L["dkpp"]) |
end |
self:PlayerinDB(twinkalt) |
self.db.account.info[twinkalt][POOL] = { points = mainpoints, |
earned = self.db.account.info[twinkmain][POOL].earned, |
spent = self.db.account.info[twinkmain][POOL].spent} |
self.db.account.info[twinkalt].raidloot = 0 |
if not self:DoesAliasExist(twinkmain, twinkalt, self.db.account.defaults.raid) then table.insert(self.db.account.info[twinkmain].aliases, {raid = self.db.account.defaults.raid, alt = twinkalt}) end |
local update = self:GetServerTime() |
self.db.account.info[twinkmain].lastupdate = update |
self.db.account.info[twinkalt].lastupdate = update |
if not self.db.account.raidlog.aliases[self.db.account.defaults.raid] then self.db.account.raidlog.aliases[self.db.account.defaults.raid] = { } end |
table.insert( self.db.account.raidlog.aliases[self.db.account.defaults.raid], { alt = twinkalt, |
main = twinkmain, |
eqdkp = self.db.account.defaults.eqDKP[self.db.account.defaults.raid].eqDKPsite, |
action = "ADD" }) |
table.insert(self.db.account.defaults.eqDKP[self.db.account.defaults.raid].Aliases, {alt = twinkalt, main = twinkmain}) |
end |
function MorgDKP:EventFormat(formatstring) |
if not formatstring then return end |
if string.find(formatstring, "[zone]") or string.find(formatstring, "[boss]") then |
self.db.account.defaults.eventformat = formatstring |
return |
end |
DEFAULT_CHAT_FRAME:AddMessage(L["eventformatdesc"]) |
end |
function MorgDKP:StartFormat(formatstring) |
if not formatstring then return end |
self.db.account.defaults.startformat = formatstring |
end |
function MorgDKP:TrashFormat(formatstring) |
if not formatstring then return end |
self.db.account.defaults.trashformat = formatstring |
end |
function MorgDKP:SetRunTime(amttime) |
local seconds = math.floor(tonumber(amttime) * 60) |
if seconds > 0 and seconds < 21600 then |
self.db.account.defaults.runrewardtime = seconds |
end |
end |
function MorgDKP:ChangeDKP() |
if not self.db.account.defaults.InRaid then DEFAULT_CHAT_FRAME:AddMessage(L["needraid"]) return end |
local POOL = self.db.account.defaults.raid |
local Runname = self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[self:GetRunEvent()].note |
local _, _, char, points = string.find(charstring, "(%a+) (%d+)") |
if char == nil or points == nil then |
DEFAULT_CHAT_FRAME:AddMessage(L["charpoints"]) |
return |
end |
local character = string.upper(string.sub(char,1,1))..string.sub(char,2,-1) |
local pointval = tonumber(points) |
local type = L["add"] |
if MorgDKP.db.account.info[character] then |
mainpoints = MorgDKP.db.account.info[character][POOL].points |
oldmainpoints = mainpoints |
if adding then mainpoints = mainpoints + pointval |
else mainpoints = mainpoints - pointval |
type = L["sub"] |
pointval = 0 - pointval |
end |
DEFAULT_CHAT_FRAME:AddMessage(type..points..L["dkpp"]..character..L["olddkp"]..tostring(oldmainpoints)..L["newdkp"]..tostring(mainpoints)) |
self.db.account.info[character][POOL].points = mainpoints |
self.db.account.info[character].lastupdate = self:GetServerTime() |
if not self.db.account.raidlog.dkpevents[POOL] then self.db.account.raidlog.dkpevents[POOL] = { } end |
table.insert(self.db.account.raidlog.dkpevents[POOL], { name = character, |
value = pointval, |
members = {[1] = character}, |
eqdkp = self.db.account.defaults.eqDKP[self.db.account.defaults.raid].eqDKPsite, |
prefix = self.db.account.defaults.eqDKP[POOL].prefix, |
addtype = "individual", |
event = Runname}) |
return |
end |
DEFAULT_CHAT_FRAME:AddMessage(character..L["notexi"]) |
end |
function MorgDKP:GetPlayersNeedItem(item) |
if not UnitInRaid("player") then return end |
local POOL = self:CheckPool(item) |
needquery = self:HasItem(item) |
if not needquery then return end |
reportpoints = { } |
for qname in pairs(needquery) do |
self:PointsPoolExists(qname, POOL) |
table.insert(reportpoints, {name = qname, points = self.db.account.info[qname][POOL].points, priority = needquery[qname].priority}) |
end |
table.sort(reportpoints, function(a,b) |
if a.priority == b.priority then |
return a.points>b.points |
else return a.priority < b.priority |
end |
end) |
return reportpoints |
end |
function MorgDKP:Scan() |
local SLOTS = { |
"HeadSlot", |
"NeckSlot", |
"ShoulderSlot", |
"BackSlot", |
"ChestSlot", |
"WristSlot", |
"HandsSlot", |
"WaistSlot", |
"LegsSlot", |
"FeetSlot", |
"Finger0Slot", |
"Finger1Slot", |
"Trinket0Slot", |
"Trinket1Slot", |
"MainHandSlot", |
"SecondaryHandSlot", |
"RangedSlot" |
} |
for i = 1, GetNumRaidMembers() do |
local name = UnitName("raid"..i) |
local class = UnitClass("raid"..i) |
self:PlayerinDB(name, class) |
if not self.db.account.info[name].items then self.db.account.info[name].items = { } end |
if CheckInteractDistance(name, 1) then |
NotifyInspect(name) |
for _,slot in pairs(SLOTS) do |
local itemLink = GetInventoryItemLink(name, GetInventorySlotInfo(slot)) |
if itemLink then |
local _, _, itemCode = strfind(itemLink, "(%d+):") |
itemCode = tonumber(itemCode) |
if not self:ItemRecorded(itemCode, name) then |
table.insert(self.db.account.info[name].items, itemCode) |
if self.db.account.defaults.devmode then |
self:Print("Added ".. name .. " slot: ".. slot ..";item ".. itemLink ..";ID: " .. itemCode) |
end |
end |
elseif self.db.account.defaults.devmode then self:Print(name.."'s slot: "..slot.."; no item") |
end |
end |
if self.db.account.defaults.devmode then self:Print("Scanned "..name) end |
end |
end |
end |
function MorgDKP:ItemRecorded(item, name) |
for _, ID in pairs(self.db.account.info[name].items) do |
if item == ID then |
return true |
end |
end |
return false |
end |
function MorgDKP:OnLootMsg() |
if not UnitInRaid("player") or not self.db.account.defaults.InRaid then return end |
local sPlayer, sLink; |
local iStart, iEnd, sPlayerName, sItem = string.find( arg1, L["MORGTRACKER_LOOT_RECEIVES1"] ) |
if sPlayerName then |
_, _, _, _, itemCount = string.find( arg1, L["MORGTRACKER_LOOT_RECEIVES1_COUNT"] ) |
sPlayer = sPlayerName |
sLink = sItem |
else |
local iStart, iEnd, sItem = string.find( arg1, L["MORGTRACKER_LOOT_RECEIVES2"] ) |
if iStart then |
sPlayer = UnitName("player") |
sLink = sItem |
_, _, _, itemCount = string.find( arg1, L["MORGTRACKER_LOOT_RECEIVES2_COUNT"] ) |
end |
end |
itemCount = tonumber(itemCount) |
if not itemCount then |
itemCount = 1 |
end |
-- Make sure there is a link |
if self.MLmode and (sPlayer == self.db.account.defaults.mlooter or sPlayer == self.db.account.defaults.disenchanter) and not self.given then return |
else self.given = nil end |
if not MorgDKP:CheckRaid(sPlayer) then return end |
if sLink and sPlayer then |
MorgDKP:RecordLoot(sLink, sPlayer) |
end |
end |
-- Code by Kaelten (split & explode) |
function MorgDKP:Split(string, sep) |
if (not string) then error("Bad String", 2) end |
local x = strfind(string , sep) or 0 |
return (tonumber(strsub(string, 1, x-1)) or strsub(string, 1, x-1)), (tonumber(strsub(string, x+1)) or strsub(string, x+1)) |
end |
function MorgDKP:Explode(string, sep) |
if (not string) then return nil end |
local a, b = self:Split(string, sep) |
if (not b or b == "") then return a; end |
if (not strfind(b or "", sep)) then return a, b; end |
return a, self:Explode(b, sep) |
end |
function MorgDKP:RecordLoot(item, player) |
if self.db.account.defaults.raidnum < 1 then DEFAULT_CHAT_FRAME:AddMessage(L["noraid"]) return end |
local _, _, sColor = string.find(item, "|c(%x+)") |
local _,_, itemId = string.find(item, "item:(%d+):") |
itemId = tonumber(itemId) |
local IGNORE = nil |
for _, ignorelink in pairs(self.db.account.defaults.ignore) do |
local _,_, ignoreid = string.find(ignorelink, "item:(%d+):") |
ignoreid = tonumber(ignoreid) |
if ignoreid == itemId then IGNORE = true break end |
end |
if IGNORE then return end |
local sName, iLink, iQuality, _, _, class, subclass, _, iEquipLoc, iconGIF = GetItemInfo(itemId) |
if iQuality < self.db.account.defaults.quality then return end |
local lootTime = date("%m/%d/%y %H:%M:%S") |
local lastboss = self.db.account.raidlog[self.db.account.defaults.raidnum].lastboss |
local lastmob = self.db.account.raidlog[self.db.account.defaults.raidnum].lastmob |
local BossMob |
if self.db.account.raidlog.lootbuffer and self.db.account.raidlog.lootbuffer[sName] ~= nil then |
BossMob = self.db.account.raidlog.lootbuffer[sName] |
else |
if lastboss == lastmob then BossMob = lastboss |
else BossMob = lastmob end |
end |
local match = nil |
for _, bossname in pairs(MorgTracker_ZoneBosses[self.db.account.defaults.menuzone]) do |
if BossMob == bossname then |
match = 1 |
break |
end |
end |
if not BossMob or self.db.account.defaults.OneEvent or not match then BossMob = L["DEFAULTBOSS"] end |
self:IteminDB(itemId) |
local points |
local POOL = self:CheckPool(itemId) |
self:PointsPoolExists(player, POOL) |
points = self.db.account.info[player][POOL].points |
itempoints = self.db.account.items[itemId].points or 0 |
if self.db.account.defaults.percent > 0 then |
itempoints = math.floor((points * self.db.account.defaults.percent/100) + 0.5) |
if self.db.account.defaults.percenttake then |
if self.querytooltips[itemId] then |
for i,v in pairs(self.querytooltips[itemId]) do |
if v[1] == player then |
if v[3] == "TAKE" then itempoints = self.origitempoints[itemId] end |
break |
end |
end |
end |
end |
end |
Zone = GetRealZoneText() |
table.insert(self.db.account.raidlog[self.db.account.defaults.raidnum].loot, |
{ |
["ItemName"] = sName, |
["ItemLink"] = iLink, |
["Quality"] = iQuality, |
["ID"] = itemId, |
["Icon"] = iconGIF, |
["Class"] = class, |
["SubClass"] = subclass, |
["Color"] = sColor, |
["Count"] = itemCount, |
["Player"] = player, |
["Costs"] = itempoints, |
["Time"] = lootTime, |
["Zone"] = Zone, |
["Boss"] = BossMob, |
["eqdkp"] = self.db.account.defaults.eqDKP[POOL].eqDKPsite, |
["prefix"] = self.db.account.defaults.eqDKP[POOL].prefix |
} |
) |
points = points - itempoints |
self.db.account.info[player][POOL].points = points |
self.db.account.info[player][POOL].spent = self.db.account.info[player][POOL].spent + itempoints |
self.db.account.info[player].raidloot = 1 |
self.db.account.info[player].lastupdate = self:GetServerTime() |
if self.db.account.defaults.zerosum and (tonumber(itempoints) > 0) then self:AddZeroSumPoints(itempoints, POOL) end |
DEFAULT_CHAT_FRAME:AddMessage(player..L["receive"]..item.." for "..tostring(itempoints).." DKP") |
if iEquipLoc ~="" then |
if not self.db.account.info[player].items then |
self.db.account.info[player].items = { } |
end |
if not self:ItemRecorded(itemId, player) then |
table.insert(self.db.account.info[player].items, itemId) |
end |
end |
if self.db.account.defaults.bidwar then self.db.account.items[itemId].points = 0 end |
end |
function MorgDKP:PrepareRaidmembers() |
--Rebuild raid members |
self.db.account.defaults.raidmembers = { } |
local raidmembers = { } |
for name, data in pairs(roster) do |
if (data.class ~= "PET") then table.insert(raidmembers, name) end |
end |
table.sort(raidmembers, function(a,b) |
if a < b then return true |
else return false end |
end) |
for _ ,name in pairs(raidmembers) do |
table.insert(self.db.account.defaults.raidmembers, name) |
end |
MorgDKP:ReclaimAll() |
--Update ML |
local lootmethod, masterlooterPartyID, masterlooterRaidID = GetLootMethod() |
local lootmaster |
if lootmethod == "master" then |
if masterlooterPartyID then |
if masterlooterPartyID == 0 then lootmaster = UnitName("player") |
else lootmaster = UnitName("party"..masterlooterPartyID) end |
else lootmaster = UnitName("raid"..masterlooterRaidID) |
end |
self.db.account.defaults.mlooter = lootmaster |
self.lootmaster = lootmaster |
else self.db.account.defaults.mlooter = lootmethod |
end |
self:ReclaimML() |
end |
function MorgDKP:AddZeroSumPoints(points, pool) |
addpoints = math.floor((points/GetNumRaidMembers()) + 0.5) |
local counter = 0 |
local update = self:GetServerTime() |
for name in pairs(roster) do |
if name and name ~= "" and name ~= "UNKNOWN" then |
local tbl = roster[name] |
if tbl.class ~= "PET" and tbl.oldclass ~= "PET" then |
self.db.account.info[name][pool].points = self.db.account.info[name][pool].points + addpoints |
self.db.account.info[name][pool].earned = self.db.account.info[name][pool].earned + addpoints |
self.db.account.info[name].lastupdate = update |
counter = counter + 1 |
end |
end |
end |
DEFAULT_CHAT_FRAME:AddMessage(L["add"]..tostring(addpoints)..L["pointsto"]..tostring(counter)..L["attend"]) |
end |
function MorgDKP:ListDKP(listtext) |
if not listtext then return end |
listtext = "listdkp "..listtext |
dkplist = self:FillDKPTable(nil, nil, listtext, nil) |
local item = "listdkp" |
local title = L["listdkp"] |
local hint = L["Bar_Hint_DKPlist"] |
local id = nil |
self.querytooltips[item] = dkplist |
self:Onlinemembers(true) |
self:CreateQueryTooltip(id, item, title, hint) |
end |
function MorgDKP:Onlinemembers(skip) |
local Onlinemembers = self:GetOnlineGuildMembers() |
for i = 1, GetNumRaidMembers() do |
local name, _, subgroup, _, _, _, _, online, _, _, _ = GetRaidRosterInfo(i) |
if subgroup and online then Onlinemembers[name] = 2 end |
end |
for index, data in pairs(self.querytooltips["listdkp"]) do |
if Onlinemembers[data[1]] then self.querytooltips["listdkp"][index][2] = Onlinemembers[data[1]] |
else self.querytooltips["listdkp"][index][2] = nil end |
end |
if not skip then tablet:Refresh("listdkp") end |
end |
function MorgDKP:GetOnlineGuildMembers() |
local numGuildMembers = GetNumGuildMembers() |
local Onlinemembers = { } |
for i = 1, numGuildMembers do |
local name, _, _, _, _, _, _, _, online, _ = GetGuildRosterInfo(i) |
if online then Onlinemembers[name] = 1 end |
end |
return Onlinemembers |
end |
function MorgDKP:GuildUpdate() |
if not self.querytooltips["listdkp"] then return end |
self:Onlinemembers() |
end |
function MorgDKP:FillDKPTable(sender, senderclass, txt, raided) |
local POOL = self.db.account.defaults.raid |
dkplist = { } |
local args = {self:Explode(txt, " ")} |
for _, name in pairs(self.db.account.defaults.raidlist) do |
if string.upper(name) == string.upper(args[2]) then |
POOL = name |
end |
end |
if string.find(string.upper(txt), "ALL") then |
txt = "dkplist Paladin Warlock Druid Mage Priest Rogue Hunter Warrior Shaman" |
end |
if senderclass then |
if not string.find(string.upper(txt), string.upper(senderclass)) then |
txt = txt .. " "..senderclass |
end |
end |
local args = {self:Explode(txt, " ")} |
numargs = #args |
for i = 2, numargs do |
local class = string.upper(args[i]) |
if raided then |
for pname, data in pairs(roster) do |
if data.class ~= "PET" then |
pclass = BC[string.upper(string.sub(data.class,1,1))..string.lower(string.sub(data.class,2,-1))] |
local realClass = BC[data.class] |
if string.upper(pclass) == class then |
self:PointsPoolExists(pname, POOL) |
local points = self:PointsFormat(pname, POOL) or 0 |
table.insert(dkplist, {pname, pclass, realClass, points}) |
end |
end |
end |
else |
for pname, data in pairs(self.db.account.info) do |
if data.class and string.upper(data.class) == class then |
self:PointsPoolExists(pname, POOL) |
local points = self:PointsFormat(pname, POOL) or 0 |
table.insert(dkplist, {pname, data.class, data.class, points}) |
end |
end |
end |
end |
table.sort(dkplist, function(a,b) |
if a[4] > b[4] then return true |
else return false end |
end) |
if sender then SendChatMessage(L["dkpstand"]..POOL..":", "WHISPER", nil, sender) end |
return dkplist |
end |
function MorgDKP:PointsFormat(name, POOL) |
local points |
if self.db.account.defaults.relational then |
if self.db.account.info[name][POOL].spent == 0 then self.db.account.info[name][POOL].spent = 1 end |
if self.db.account.info[name][POOL].earned == 0 then self.db.account.info[name][POOL].earned = 1 end |
points = string.format("%.2f", (self.db.account.info[name][POOL].earned /self.db.account.info[name][POOL].spent )) |
else points = self.db.account.info[name][POOL].points end |
return tonumber(points) |
end |
function MorgDKP:ShowPools(txt, sender) |
SendChatMessage(L["pools"], "WHISPER", nil, sender) |
local counter = 1 |
for _, name in pairs(self.db.account.defaults.raidlist) do |
SendChatMessage(tostring(counter)..". "..name, "WHISPER", nil, sender) |
counter = counter + 1 |
end |
SendChatMessage(L["whisperformat"], "WHISPER", nil, sender) |
end |
## Interface: 20400 |
## Author: Morg & Fryguy |
## Title: MorgDKP - |cffffffffv|r|cff00ff006.88|r |
## Notes: Inspects all members of raid and saves in database, as well as lists people's dkp values |
## DefaultState: 1 |
## SavedVariables: MorgDKPDB, MorgDKPFuBarDB |
## Dependencies: |
## OptionalDeps: Ace2, LibBabble-Boss-3.0, LibBabble-Zone-3.0, LibBabble-Class-3.0, DewdropLib |
## X-Embeds: Ace2, LibBabble-Boss-3.0, LibBabble-Zone-3.0, LibBabble-Class-3.0, DewdropLib |
## X-Category: Raid |
libs\AceLibrary\AceLibrary.lua |
libs\AceOO-2.0\AceOO-2.0.lua |
libs\AceEvent-2.0\AceEvent-2.0.lua |
libs\AceConsole-2.0\AceConsole-2.0.lua |
libs\AceComm-2.0\AceComm-2.0.lua |
libs\AceAddon-2.0\AceAddon-2.0.lua |
libs\AceHook-2.1\AceHook-2.1.lua |
libs\AceDB-2.0\AceDB-2.0.lua |
libs\AceDebug-2.0\AceDebug.lua |
libs\AceLocale-2.2\AceLocale-2.2.lua |
libs\DewDrop-2.0\DewDrop-2.0.lua |
libs\Babble-Class-2.2\Babble-Class-2.2.lua |
libs\LibBabble-Boss-3.0\lib.xml |
libs\LibBabble-Zone-3.0\lib.xml |
libs\Tablet-2.0\Tablet-2.0.lua |
libs\Roster-2.1\Roster-2.1.lua |
libs\FuBarPlugin-2.0\FuBarPlugin-2.0.lua |
MorgDKP-enUS.lua |
MorgDKP-deDE.lua |
MorgDKP.lua |
DKPInfo.lua |
ItemData.lua |
BidQuery.lua |
Points.lua |
Hooks.lua |
DKPTracker.lua |
MorgDKPOptions.lua |
LootTablet.lua |
RaidFunctions.lua |
MorgDKPFu.lua |
MorgDKP.xml |
-- ****************************************************************** |
-- ****************************************************************** |
-- ** RaidFunctions ** |
-- ****************************************************************** |
-- ****************************************************************** |
-- |
local L = AceLibrary("AceLocale-2.2"):new("MorgDKP") |
local dewdrop = AceLibrary("Dewdrop-2.0") |
local BC = AceLibrary("Babble-Class-2.2") |
local MorgDKP_classes = { [1] = BC["Paladin"], [2] = BC["Warrior"], [3] = BC["Hunter"], [4] = BC["Rogue"], [5] = BC["Druid"], [6] = BC["Mage"], [7] = BC["Warlock"], [8] = BC["Priest"], [9] = BC["Shaman"], [10] = L["All"]} |
local MorgDKP_Quality = {[0] = "|c009d9d9d", [1] = "|c00ffffff", [2] = "|c001eff00", [3] = "|c000070dd", [4] = "|c00a335ee", [5] = "|c00ff8000", [6] = "|c00e6cc80"} |
StaticPopupDialogs["MorgClearRaids"] = { |
text = TEXT(L["cleardb"]), |
button1 = TEXT(YES), |
button2 = TEXT(NO), |
OnAccept = function() |
MorgDKP:ClearRaidDB() |
end, |
timeout = 0, |
whileDead = 1, |
hideOnEscape = 1, |
} |
function MorgDKP:ExportRaids() |
self:OutputRaid(self.db.account.raidlog) |
self.db.account.raidlog.raidexport = L["complete"] |
StaticPopup_Show ("MorgClearRaids") |
end |
function MorgDKP:ExportCurrentRaid() |
if not self.raidid then return end |
self:OutputRaid(self.db.account.raidlog, self.raidid) |
end |
function MorgDKP:ClearRaidDB() |
self.db.account.raidlog = { } |
self.db.account.defaults.raidnum = 0 |
self.db.account.raidlog[self.db.account.defaults.raidnum] = {} |
self.db.account.raidlog.lootbuffer = { } |
self.db.account.raidlog.raidstart = L["pending"] |
self.db.account.raidlog.raidend = L["pending"] |
self.db.account.raidlog.raidexport = L["pending"] |
self.db.account.raidlog.dkpevents = {} |
self.db.account.raidlog.aliases = { } |
self.db.account.defaults.InRaid = nil |
DEFAULT_CHAT_FRAME:AddMessage(L["cleared"]) |
end |
function MorgDKP:CustomEvent() |
if not self:IsRaided() then return end |
if not self.db.account.defaults.InRaid then |
DEFAULT_CHAT_FRAME:AddMessage(L["noraid"]) |
return |
end |
if not self.db.account.defaults.custom then self.db.account.defaults.custom = L["NEW"] end |
if self.db.account.defaults.custom == L["NONE"] then return end |
local event = self.db.account.defaults.custom |
if self.db.account.defaults.custom == L["NEW"] then event = event .. " Event" |
else event = event .. " Attempt" end |
self:LogBossKill(date("%m/%d/%y %H:%M:%S"), event, 1, event) |
end |
function MorgDKP:RaidTablet() |
if not MorgDKP_Raid:IsShown() then |
PanelTemplates_SetNumTabs(MorgDKP_Raid, 5) |
PanelTemplates_SetTab(MorgDKP_Raid, 1) |
MorgDKP_RaidsPage1:Show() |
MorgDKP_RaidsPage2:Hide() |
MorgDKP_RaidsPage3:Hide() |
MorgDKP_RaidsPage4:Hide() |
MorgDKP_RaidsPage5:Hide() |
MorgDKP_Raid:Show() |
end |
self:ShowDefaultRaid() |
end |
function MorgDKP:SetupDropMenu() |
local Raidmenu = { } |
for raidindex = 1, self.db.account.defaults.raidnum do |
Raidmenu[raidindex] = "Raid"..raidindex |
end |
Raidmenu[#Raidmenu + 1] = "Close" |
self:CreateDropdownmenu(Raidmenu, 0) |
end |
function MorgDKP:ShowDropMenu(frame) |
dewdrop:Open(frame, |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.Dropdownmenu) |
end, |
'cursorX', true, |
'cursorY', true |
) |
end |
function MorgDKP:ShowDefaultRaid() |
self:ClearRaidFrame() |
if self.db.account.defaults.raidnum == 0 then return end |
MorgDKP_RaidsPage1Raid:SetText("Raid"..self.db.account.defaults.raidnum) |
self:ChangeRaidsFrame(self.db.account.defaults.raidnum) |
end |
function MorgDKP:CreateDropdownmenu(menu, action) |
MorgDKP.Dropdownmenu = { |
type = "text", |
name = L["ad"], |
desc = L["ad"], |
get = function(v) return v end, |
set = function(v) self:HandleDropDialogue(v, menu, action) end, |
validate = menu |
} |
end |
function MorgDKP:ClearRaidFrame() |
MorgDKP_RaidsPage1Name:SetText("") |
MorgDKP_RaidsPage1Name:Hide() |
MorgDKP_RaidsPage1RaidNameLabel:Hide() |
MorgDKP_RaidsPage1Note:SetText("") |
MorgDKP_RaidsPage1Note:Hide() |
MorgDKP_RaidsPage1RaidNoteLabel:Hide() |
MorgDKP_RaidsPage1Value:SetText("") |
MorgDKP_RaidsPage1Value:Hide() |
MorgDKP_RaidsPage1RaidValueLabel:Hide() |
MorgDKP_RaidsPage1Attendees:SetText("") |
MorgDKP_RaidsPage1Attendees:Hide() |
MorgDKP_RaidsPage1RaidAttendeesLabel:Hide() |
MorgDKP_RaidsPage1Delete:Hide() |
MorgDKP_RaidsPage1Update:Hide() |
MorgDKP_RaidsPage1ExportCurrent:Hide() |
MorgDKP_RaidsPage1Add:Hide() |
MorgDKP_RaidsPage1Clear:Hide() |
MorgDKP_RaidsPage1ItemLabel:Hide() |
MorgDKP_RaidsPage1ItemWinner:Hide() |
MorgDKP_RaidsPage1ItemWinnerLabel:Hide() |
MorgDKP_RaidsPage1ItemValue:Hide() |
MorgDKP_RaidsPage1ItemValueLabel:Hide() |
MorgDKP_RaidsPage1DeleteItem:Hide() |
MorgDKP_RaidsPage1EventChoose:Hide() |
self:ScrollBar_Clear(MorgDKP_RaidsPage1) |
self:ScrollBar2_Clear() |
self.editevent = nil |
self.scrolldata2 = nil |
end |
function MorgDKP:CloseRaidtracker() |
self.scrolldata = nil |
self.scrolldata2 = nil |
end |
function MorgDKP:HandleDropDialogue(value, data, action) |
dewdrop:Close() |
if value == "Close" then return end |
if action == 0 then --RAIDS |
_, _, raidnum = string.find(value, "Raid(%d+)") |
raidnum = tonumber(raidnum) |
MorgDKP_RaidsPage1Raid:SetText(value) |
self:ClearRaidFrame() |
self:ChangeRaidsFrame(raidnum) |
elseif action == 2 then --DKP |
MorgDKP_RaidsPage3Members:Hide() |
MorgDKP_RaidsPage3Value:SetText("0") |
MorgDKP_RaidsPage3Members:SetText("") |
self:ChangeDKPFrame(value) |
elseif action == 3 then --ALIASES |
self:ChangeAliasFrame(value) |
end |
end |
function MorgDKP:ChangeRaidsFrame(raidid) |
MorgDKP_RaidsPage1RaidNameLabel:Show() |
MorgDKP_RaidsPage1Name:Show() |
MorgDKP_RaidsPage1RaidNoteLabel:Show() |
MorgDKP_RaidsPage1Note:Show() |
MorgDKP_RaidsPage1RaidValueLabel:Show() |
MorgDKP_RaidsPage1Value:Show() |
MorgDKP_RaidsPage1RaidAttendeesLabel:Show() |
MorgDKP_RaidsPage1Attendees:Show() |
MorgDKP_RaidsPage1EventChoose:Show() |
if not self.editevent then MorgDKP_RaidsPage1Add:Show() end |
self.raidid = raidid |
self.editevent = nil |
local numevents = #self.db.account.raidlog[raidid].bosskills |
self.scrolldata = { } |
if numevents > 0 then |
self.maxitems = 9 |
for event, eventdata in pairs(self.db.account.raidlog[raidid].bosskills) do |
self.scrolldata[event] = { name = eventdata.name, value = eventdata.value, time = eventdata.time, attendees = eventdata.attendees, note = eventdata.note, trash = eventdata.trash} |
end |
self.scrollframe = MorgDKP_RaidsPage1 |
self:ScrollBar_Update() |
end |
end |
function MorgDKP:TextEscapePressed(frame) |
frame:ClearFocus() |
end |
function MorgDKP:TextEnterPressed(frame) |
local f = frame |
local name = f:GetName() |
f:ClearFocus() |
if name == "MorgDKP_RaidsPage1Note" then |
if not self.raidid or not self.editevent then return end |
self.db.account.raidlog[self.raidid].bosskills[self.editevent].note = f:GetText() |
self:ChangeRaidsFrame(self.raidid) |
elseif name == "MorgDKP_RaidsPage1Name" then |
if not self.raidid or not self.editevent then return end |
self.db.account.raidlog[self.raidid].bosskills[self.editevent].name = f:GetText() |
self:ChangeRaidsFrame(self.raidid) |
elseif name == "MorgDKP_RaidsPage1Value" then |
if not self.raidid or not self.editevent then return end |
local newvalue = tonumber(f:GetText()) |
local oldvalue = self.scrolldata[self.editevent].value |
local attendees = self.scrolldata[self.editevent].attendees |
local POOL = self:GetPool(self.raidid) |
self:AwardDKP(newvalue, oldvalue, POOL, attendees) |
self.db.account.raidlog[self.raidid].bosskills[self.editevent].value = newvalue |
self:ChangeRaidsFrame(self.raidid) |
elseif name == "MorgDKP_RaidsPage1ItemWinner" then |
local winner = f:GetText() |
winner = string.upper(string.sub(winner,1,1))..string.lower(string.sub(winner,2,-1)) |
local oldwinner = self.scrolldata2[self.edititem].winner |
local cost = self.scrolldata2[self.edititem].value |
local POOL = self:CheckPool(self.db.account.raidlog[self.raidid].loot[self.scrolldata2[self.edititem].index].ID) |
self:AdjustDKPPoints(winner, oldwinner, POOL, cost) |
self.db.account.raidlog[self.raidid].loot[self.scrolldata2[self.edititem].index].Player = winner |
self.scrolldata2[self.edititem].winner = winner |
elseif name == "MorgDKP_RaidsPage1ItemValue" then |
local newcost = tonumber(f:GetText()) |
local winner = self.scrolldata2[self.edititem].winner |
local oldcost = self.scrolldata2[self.edititem].value |
local POOL = self:CheckPool(self.db.account.raidlog[self.raidid].loot[self.scrolldata2[self.edititem].index].ID) |
self:AdjustDKPPoints(winner, winner, POOL, newcost, oldcost) |
if self.db.account.defaults.zerosum then |
local diff = oldcost - newcost |
local addpoints = math.floor((diff/#self.db.account.raidlog[self.raidid].bosskills[self.editevent].attendees) + 0.5) |
self:AwardDKP(0, addpoints, POOL, self.db.account.raidlog[self.raidid].bosskills[self.editevent].attendees) |
end |
self.db.account.raidlog[self.raidid].loot[self.scrolldata2[self.edititem].index].Costs = newcost |
self.scrolldata2[self.edititem].value = newcost |
elseif name == "MorgDKP_RaidsPage2Value" then |
local value = tonumber(f:GetText()) |
self.db.account.items[self.edititemid].points = value |
self:UpdateItemValues() |
elseif name == "MorgDKP_RaidsPage5DKP" then self.db.account.defaults.dkpamount = math.floor(tonumber(f:GetText()) + 0.5) |
elseif name == "MorgDKP_RaidsPage5Time" then self.db.account.defaults.dkpsched = math.floor((tonumber(f:GetText()) * 60) + 0.5) |
elseif name == "MorgDKP_RaidsPage5SyncPW" then self.db.account.defaults.dbpassword = f:GetText() |
elseif name == "MorgDKP_RaidsPage5EventFormat" then self:EventFormat(f:GetText()) |
elseif name == "MorgDKP_RaidsPage5StartFormat" then self:StartFormat(f:GetText()) |
elseif name == "MorgDKP_RaidsPage5TrashFormat" then self:TrashFormat(f:GetText()) |
elseif name == "MorgDKP_RaidsPage5RunTime" then self:SetRunTime(f:GetText()) |
elseif name == "MorgDKP_RaidsPage5PTakeNum" then |
value = tonumber(f:GetText()) |
if value >= 0 and value <= 100 then self.db.account.defaults.percent = value end |
elseif name == "MorgDKP_RaidsPage5OverBID" then self.db.account.defaults.overbid = math.floor(tonumber(f:GetText()) + 0.5) |
elseif name == "MorgDKP_RaidsPage5WaitStart" then self.db.account.defaults.waitstart = math.floor(tonumber(f:GetText()) + 0.5) |
elseif name == "MorgDKP_RaidsPage5WaitRun" then self.db.account.defaults.waitrun = math.floor(tonumber(f:GetText()) + 0.5) |
elseif name == "MorgDKP_RaidsPage5WaitBoss" then self.db.account.defaults.waitboss = math.floor(tonumber(f:GetText()) + 0.5) |
elseif name == "MorgDKP_RaidsPage5WaitOtime" then self.db.account.defaults.waitotime = math.floor(tonumber(f:GetText()) + 0.5) |
end |
end |
function MorgDKP:EditEvent(frame, name) |
if frame:GetName() == "MorgDKP_RaidsPage1" then self:EditRaidEvent(frame, name) |
elseif frame:GetName() == "MorgDKP_RaidsPage3" then self:EditDKPChange(frame, name) |
elseif frame:GetName() == "MorgDKP_RaidsPage4" then self:EditAlias(frame, name) |
end |
end |
function MorgDKP:EditItem(frame, name) |
if string.find(name, "MorgDKP_RaidsPage2") then self:EditItemDB(name) return end |
local _, _, item = string.find(name, "MorgDKP_RaidsPage1Button(%d+)") |
item = tonumber(item) |
local offset = FauxScrollFrame_GetOffset(MorgDKP_RaidsPage1ScrollBar2) |
item = item - 10 + offset |
self.edititem = item |
MorgDKP_RaidsPage1ItemWinnerLabel:Show() |
MorgDKP_RaidsPage1ItemValueLabel:Show() |
MorgDKP_RaidsPage1ItemWinner:SetText(self.scrolldata2[item].winner) |
MorgDKP_RaidsPage1ItemWinner:Show() |
MorgDKP_RaidsPage1ItemValue:SetText(self.scrolldata2[item].value) |
MorgDKP_RaidsPage1ItemValue:Show() |
MorgDKP_RaidsPage1DeleteItem:Show() |
end |
function MorgDKP:EditRaidEvent(frame, name) |
local _, _, event = string.find(name, "MorgDKP_RaidsPage1Button(%d+)") |
event = tonumber(event) |
local offset = FauxScrollFrame_GetOffset(MorgDKP_RaidsPage1ScrollBar) |
event = event + offset |
self.editevent = event |
MorgDKP_RaidsPage1Name:SetText(self.scrolldata[event].name) |
MorgDKP_RaidsPage1Name:Show() |
MorgDKP_RaidsPage1Note:SetText(self.scrolldata[event].note) |
MorgDKP_RaidsPage1Note:Show() |
MorgDKP_RaidsPage1Value:SetText(self.scrolldata[event].value) |
MorgDKP_RaidsPage1Value:Show() |
local attend = "" |
table.sort(self.scrolldata[event].attendees) |
for _, name in pairs(self.scrolldata[event].attendees) do |
attend = attend .. name .."\n" |
end |
MorgDKP_RaidsPage1Attendees:SetText(attend) |
MorgDKP_RaidsPage1Attendees:Show() |
MorgDKP_RaidsPage1Clear:Show() |
MorgDKP_RaidsPage1Add:Hide() |
MorgDKP_RaidsPage1Delete:Show() |
MorgDKP_RaidsPage1Update:Show() |
MorgDKP_RaidsPage1ExportCurrent:Show() |
MorgDKP_RaidsPage1ItemWinner:Hide() |
MorgDKP_RaidsPage1ItemValue:Hide() |
MorgDKP_RaidsPage1DeleteItem:Hide() |
self:UpdateItemList() |
end |
function MorgDKP:EnterEventData(name, frame) |
local value = self.db.account.defaults.eqDKP[self.editpool].Events[name].value |
local attendees |
if self.editevent then |
local POOL = self:GetPool(self.raidid) |
local oldvalue = self.db.account.raidlog[self.raidid].bosskills[self.editevent].value |
attendees = self.db.account.raidlog[self.raidid].bosskills[self.editevent].attendees |
if value ~= oldvalue then self:AwardDKP(value, oldvalue, POOL, attendees) end |
self.db.account.raidlog[self.raidid].bosskills[self.editevent].value = value |
self.db.account.raidlog[self.raidid].bosskills[self.editevent].name = name |
self.db.account.raidlog[self.raidid].bosskills[self.editevent].note = name |
self.scrolldata[self.editevent] = self.db.account.raidlog[self.raidid].bosskills[self.editevent] |
self:ScrollBar_Update() |
else |
attendees = self:ArraytoString(self.db.account.defaults.raidmembers) |
MorgDKP_RaidsPage1Attendees:SetText(attendees) |
end |
MorgDKP_RaidsPage1Name:SetText(name) |
MorgDKP_RaidsPage1Note:SetText(name) |
MorgDKP_RaidsPage1Value:SetText(value) |
end |
function MorgDKP:UpdateItemList() |
self.scrolldata2 = { } |
if not self.db.account.raidlog[self.raidid].loot then return end |
for index, itemdata in pairs(self.db.account.raidlog[self.raidid].loot) do |
if self.scrolldata[self.editevent].note == itemdata.Boss then |
table.insert(self.scrolldata2, {link = itemdata.ItemLink, name = itemdata.ItemName, winner = itemdata.Player, value = itemdata.Costs, quality = MorgDKP_Quality[itemdata.Quality], index = index}) |
elseif itemdata.Boss == "Trash mob" and self.scrolldata[self.editevent].trash == 2 then |
table.insert(self.scrolldata2, {link = itemdata.ItemLink, name = itemdata.ItemName, winner = itemdata.Player, value = itemdata.Costs, quality = MorgDKP_Quality[itemdata.Quality], index = index}) |
end |
end |
if #self.scrolldata2 == 0 then MorgDKP_RaidsPage1ItemLabel:Hide() |
else MorgDKP_RaidsPage1ItemLabel:Show() end |
MorgDKP_RaidsPage1ItemWinner:Hide() |
MorgDKP_RaidsPage1ItemValue:Hide() |
MorgDKP_RaidsPage1ItemWinnerLabel:Hide() |
MorgDKP_RaidsPage1ItemValueLabel:Hide() |
self.scrollframe2 = MorgDKP_RaidsPage1 |
self.maxitems2 = 4 |
self:ScrollBar_Update2() |
end |
function MorgDKP:AddNewRaid() |
if not self.raidid then return end |
local name = MorgDKP_RaidsPage1Name:GetText() |
local note = MorgDKP_RaidsPage1Note:GetText() |
local value = MorgDKP_RaidsPage1Value:GetText() |
local attendees = self.db.account.defaults.raidmembers |
if name == "" or value == "" or not attendees[1] then |
DEFAULT_CHAT_FRAME:AddMessage(L["badformat"]) |
return |
end |
local POOL = self:GetPool(self.raidid) |
local killtime = date("%m/%d/%y %H:%M:%S") |
table.insert(self.db.account.raidlog[self.raidid].bosskills, { |
["name"] = name, |
["note"] = note, |
["time"] = killtime, |
["attendees"] = attendees, |
["value"] = value, |
["trash"] = 0}) |
DEFAULT_CHAT_FRAME:AddMessage(name..L["bosskill"]..killtime.." and "..tostring(#attendees)..L["attadded"]) |
if value ~= 0 then self:AwardDKP(nil, value, POOL, attendees) end |
self:ClearRaidFrame() |
self:ChangeRaidsFrame(self.raidid) |
end |
function MorgDKP:ClearCurrentData() |
self:ClearRaidFrame() |
MorgDKP_RaidsPage1Raid:SetText("Raid"..self.raidid) |
self:ChangeRaidsFrame(self.raidid) |
end |
function MorgDKP:DeleteCurrentRaid() |
if self.editevent then |
local eventname = self.db.account.raidlog[self.raidid].bosskills[self.editevent].name |
local eventnote = self.db.account.raidlog[self.raidid].bosskills[self.editevent].note |
local eventvalue = self.db.account.raidlog[self.raidid].bosskills[self.editevent].value |
local trash = self.db.account.raidlog[self.raidid].bosskills[self.editevent].trash |
local lootitems = #self.db.account.raidlog[self.raidid].loot |
if lootitems > 0 then |
for i = lootitems, 1, -1 do |
local data = self.db.account.raidlog[self.raidid].loot[i] |
local POOL = self:CheckPool(data.ID) |
if string.find(eventname, data.Boss) or string.find(eventnote, data.Boss) then |
if self.db.account.defaults.zerosum then |
local addpoints = math.floor((data.Costs/#self.db.account.raidlog[self.raidid].bosskills[self.editevent].attendees) + 0.5) |
self:AwardDKP(0, addpoints, POOL, self.db.account.raidlog[self.raidid].bosskills[self.editevent].attendees) |
end |
self:AdjustDKPPoints(data.Player, data.Player, POOL, nil, data.Costs) |
table.remove(self.db.account.raidlog[self.raidid].loot, i) |
end |
end |
end |
local POOL = self:GetPool(self.raidid) |
if not self.db.account.defaults.zerosum then |
for _, name in pairs(self.db.account.raidlog[self.raidid].bosskills[self.editevent].attendees) do |
self.db.account.info[name][POOL].points = self.db.account.info[name][POOL].points - eventvalue |
self.db.account.info[name][POOL].earned = self.db.account.info[name][POOL].earned - eventvalue |
end |
DEFAULT_CHAT_FRAME:AddMessage(L["removed"]..tostring(eventvalue)..L["dkpword"] ..L["from"]..tostring(#self.db.account.raidlog[self.raidid].bosskills[self.editevent].attendees)..L["attend"]) |
end |
if trash == 2 then DEFAULT_CHAT_FRAME:AddMessage(L["runevent"]) |
else table.remove(self.db.account.raidlog[self.raidid].bosskills, self.editevent) |
end |
self:ClearRaidFrame() |
self:ChangeRaidsFrame(self.raidid) |
end |
end |
function MorgDKP:DeleteCurrentRaidItem() |
if self.edititem then |
local winner = self.scrolldata2[self.edititem].winner |
local cost = self.scrolldata2[self.edititem].value |
local POOL = self:CheckPool(self.db.account.raidlog[self.raidid].loot[self.scrolldata2[self.edititem].index].ID) |
if self.db.account.defaults.zerosum then |
local addpoints = math.floor((cost/#self.db.account.raidlog[self.raidid].bosskills[self.editevent].attendees) + 0.5) |
self:AwardDKP(0, addpoints, POOL, self.db.account.raidlog[self.raidid].bosskills[self.editevent].attendees) |
end |
self:AdjustDKPPoints(winner, winner, POOL, nil, cost) |
table.remove(self.db.account.raidlog[self.raidid].loot, self.scrolldata2[self.edititem].index) |
MorgDKP_RaidsPage1ItemWinner:Hide() |
MorgDKP_RaidsPage1ItemValue:Hide() |
self:ScrollBar2_Clear() |
self:UpdateItemList() |
end |
end |
function MorgDKP:UpdateCurrentAttend() |
local oldattend = { } |
local update = self:GetServerTime() |
for _, name in pairs(self.db.account.raidlog[self.raidid].bosskills[self.editevent].attendees) do |
oldattend[name] = true |
end |
local newattend = { } |
local temp = self:AttendtoArray(MorgDKP_RaidsPage1Attendees) |
for _, name in pairs(temp) do |
newattend[name] = true |
end |
local POOL = self:GetPool(self.raidid) |
local eventvalue = self.db.account.raidlog[self.raidid].bosskills[self.editevent].value |
if eventvalue ~= 0 then |
for name, _ in pairs(newattend) do |
if not oldattend[name] then |
self:PlayerinDB(name) |
self.db.account.info[name][POOL].points = self.db.account.info[name][POOL].points + eventvalue |
self.db.account.info[name][POOL].earned = self.db.account.info[name][POOL].earned + eventvalue |
self.db.account.info[name].lastupdate = update |
DEFAULT_CHAT_FRAME:AddMessage(L["add"]..tostring(eventvalue)..L["dkpword"] .."to "..name) |
end |
end |
for name, _ in pairs(oldattend) do |
if not newattend[name] then |
self:PlayerinDB(name) |
self.db.account.info[name][POOL].points = self.db.account.info[name][POOL].points - eventvalue |
self.db.account.info[name][POOL].earned = self.db.account.info[name][POOL].earned - eventvalue |
self.db.account.info[name].lastupdate = update |
DEFAULT_CHAT_FRAME:AddMessage(L["removed"]..tostring(eventvalue)..L["dkpword"] ..L["from"]..name) |
end |
end |
end |
self.db.account.raidlog[self.raidid].bosskills[self.editevent].attendees = temp |
self:ChangeRaidsFrame(self.raidid) |
end |
function MorgDKP:AddTarget(framename) |
local target = UnitName("target") |
if not target then return end |
if UnitIsFriend("player","target") ~= 1 then return end |
if not self.editevent and framename ~= "MorgDKP_RaidsPage3Target" then return end |
if framename == "MorgDKP_RaidsPage1Target" then |
table.insert(self.db.account.raidlog[self.raidid].bosskills[self.editevent].attendees, target) |
local text = MorgDKP_RaidsPage1Attendees:GetText() |
text = text .. target .. "\n" |
MorgDKP_RaidsPage1Attendees:SetText(text) |
elseif framename == "MorgDKP_RaidsPage3Target" then |
local olddata = MorgDKP_RaidsPage3Members:GetText() |
if string.len(olddata) > 1 then |
olddata = olddata .. target .."\n" |
else olddata = target .."\n" end |
MorgDKP_RaidsPage3Members:SetText(olddata) |
end |
end |
function MorgDKP:ShowItemsFrame() |
self:ClearItemsFrame() |
for index, name in pairs(MorgDKP_classes) do |
local classframe = getglobal("MorgDKP_RaidsPage2Class"..index.."Text") |
local altframe = getglobal("MorgDKP_RaidsPage2AltClass"..index.."Text") |
classframe:SetText(name) |
altframe:SetText(name) |
end |
self:UpdateItemsFrame() |
end |
function MorgDKP:ClearItemsFrame() |
MorgDKP_RaidsPage2ItemName:Hide() |
MorgDKP_RaidsPage2ValueLabel:Hide() |
MorgDKP_RaidsPage2Value:Hide() |
MorgDKP_RaidsPage2ClassLabel:Hide() |
MorgDKP_RaidsPage2AltClassLabel:Hide() |
MorgDKP_RaidsPage2DeleteItem:Hide() |
MorgDKP_RaidsPage2IgnoreItem:Hide() |
for index = 1,10 do |
local classframe = getglobal("MorgDKP_RaidsPage2Class"..index) |
local altframe = getglobal("MorgDKP_RaidsPage2AltClass"..index) |
classframe:Hide() |
altframe:Hide() |
end |
self:UpdateItemsFrame() |
end |
function MorgDKP:ToggleClass(frame) |
local name = frame:GetName() |
local _, _, id = string.find(name, "MorgDKP_RaidsPage2Class(%d+)") |
id = tonumber(id) |
if id and self.edititemid then |
local value = self.db.account.items[self.edititemid].classes[MorgDKP_classes[id]] |
self.db.account.items[self.edititemid].classes[MorgDKP_classes[id]] = not value |
if id == 10 then |
for num = 1 , 9 do |
self.db.account.items[self.edititemid].classes[MorgDKP_classes[num]] = not value |
end |
self:UpdateItemClasses() |
end |
end |
end |
function MorgDKP:ToggleAltClass(frame) |
local name = frame:GetName() |
local _, _, id = string.find(name, "MorgDKP_RaidsPage2AltClass(%d+)") |
id = tonumber(id) |
if id and self.edititemid then |
local value = self.db.account.items[self.edititemid].altclasses[MorgDKP_classes[id]] |
self.db.account.items[self.edititemid].altclasses[MorgDKP_classes[id]] = not value |
if id == 10 then |
for num = 1 , 9 do |
self.db.account.items[self.edititemid].altclasses[MorgDKP_classes[num]] = not value |
end |
self:UpdateItemClasses() |
end |
end |
end |
function MorgDKP:UpdateItemClasses() |
for index = 1,10 do |
local classframe = getglobal("MorgDKP_RaidsPage2Class"..index) |
local altframe = getglobal("MorgDKP_RaidsPage2AltClass"..index) |
classframe:SetChecked(self.db.account.items[self.edititemid].classes[MorgDKP_classes[index]]) |
altframe:SetChecked(self.db.account.items[self.edititemid].altclasses[MorgDKP_classes[index]]) |
end |
end |
function MorgDKP:UpdateItemsFrame() |
self.scrolldata2 = { } |
if not self.db.account.items then return end |
for itemid, itemdata in pairs(self.db.account.items) do |
local sName, iLink, iQuality, _, _, _, _, _, _, _ = GetItemInfo(itemid) |
if iLink then table.insert(self.scrolldata2, {name = sName, link = iLink, quality = MorgDKP_Quality[iQuality], id = itemid}) end |
end |
table.sort(self.scrolldata2, function(a,b) return a.name<b.name end) |
self.scrollframe2 = MorgDKP_RaidsPage2 |
self.maxitems2 = 15 |
self:ScrollBar_Update2() |
end |
function MorgDKP:DeleteCurrentItem() |
if not self.edititemid then return end |
self.db.account.items[self.edititemid] = nil |
self:ClearItemsFrame() |
end |
function MorgDKP:IgnoreCurrentItem() |
if not self.edititem then return end |
table.insert(self.db.account.defaults.ignore, self.scrolldata2[self.edititem].link) |
end |
function MorgDKP:EditItemDB(name) |
local _, _, event = string.find(name, "MorgDKP_RaidsPage2Button(%d+)") |
event = tonumber(event) |
local offset = FauxScrollFrame_GetOffset(MorgDKP_RaidsPage2ScrollBar2) |
event = event + offset |
self.edititem = event |
self.edititemid = self.scrolldata2[event].id |
MorgDKP_RaidsPage2ValueLabel:Show() |
MorgDKP_RaidsPage2ClassLabel:Show() |
MorgDKP_RaidsPage2AltClassLabel:Show() |
MorgDKP_RaidsPage2ItemName:SetText(self.scrolldata2[event].quality .. self.scrolldata2[event].name .. "|r") |
MorgDKP_RaidsPage2ItemName:Show() |
MorgDKP_RaidsPage2Value:Show() |
MorgDKP_RaidsPage2DeleteItem:Show() |
MorgDKP_RaidsPage2IgnoreItem:Show() |
for index = 1,10 do |
local classframe = getglobal("MorgDKP_RaidsPage2Class"..index) |
local altframe = getglobal("MorgDKP_RaidsPage2AltClass"..index) |
classframe:Show() |
altframe:Show() |
end |
self:UpdateItemValues() |
end |
function MorgDKP:UpdateItemValues() |
for index = 1,10 do |
local classframe = getglobal("MorgDKP_RaidsPage2Class"..index) |
local altframe = getglobal("MorgDKP_RaidsPage2AltClass"..index) |
classframe:SetChecked(self.db.account.items[self.edititemid].classes[MorgDKP_classes[index]]) |
altframe:SetChecked(self.db.account.items[self.edititemid].altclasses[MorgDKP_classes[index]]) |
end |
MorgDKP_RaidsPage2Value:SetText(self.db.account.items[self.edititemid].points) |
end |
function MorgDKP:ScrollBar_Update() |
local f = MorgDKP.scrollframe:GetName() |
local line |
local lineplusoffset |
local numevents = #MorgDKP.scrolldata |
local maxevents = MorgDKP.maxitems |
FauxScrollFrame_Update(getglobal(f.."ScrollBar"), numevents, maxevents, 35) |
for line=1,maxevents do |
lineplusoffset = line + FauxScrollFrame_GetOffset(getglobal(f.."ScrollBar")) |
if lineplusoffset <= numevents then |
getglobal(f.."Button"..line):SetText(MorgDKP.scrolldata[lineplusoffset].name) |
getglobal(f.."Button"..line):Show() |
else |
getglobal(f.."Button"..line):Hide() |
end |
end |
end |
function MorgDKP:ScrollBar_Update2() |
local f = MorgDKP.scrollframe2:GetName() |
local buttonoffset = 0 |
if f == "MorgDKP_RaidsPage1" then buttonoffset = 10 end |
local line |
local lineplusoffset |
local numevents = #MorgDKP.scrolldata2 |
local maxevents = MorgDKP.maxitems2 |
FauxScrollFrame_Update(getglobal(f.."ScrollBar2"), numevents, maxevents, 35) |
for line=1,maxevents do |
lineplusoffset = line + FauxScrollFrame_GetOffset(getglobal(f.."ScrollBar2")) |
if lineplusoffset <= numevents then |
getglobal(f.."Button"..line + buttonoffset .."Name"):SetText(MorgDKP.scrolldata2[lineplusoffset].quality .. MorgDKP.scrolldata2[lineplusoffset].name .. "|r") |
getglobal(f.."Button"..line + buttonoffset .."ID"):SetText(MorgDKP.scrolldata2[lineplusoffset].link) |
getglobal(f.."Button"..line + buttonoffset):Show() |
else |
getglobal(f.."Button"..line + buttonoffset):Hide() |
end |
end |
end |
function MorgDKP:ScrollBar2_Clear() |
local f = MorgDKP_RaidsPage1:GetName() |
for line=1,6 do |
getglobal(f.."Button"..line + 10):Hide() |
end |
local f = MorgDKP_RaidsPage2:GetName() |
for line=1,15 do |
getglobal(f.."Button"..line):Hide() |
end |
MorgDKP_RaidsPage1ScrollBar2:Hide() |
end |
function MorgDKP:ScrollBar_Clear(frame) |
local f = frame:GetName() |
for line=1,9 do |
getglobal(f.."Button"..line):Hide() |
end |
MorgDKP_RaidsPage1ScrollBar:Hide() |
end |
function MorgDKP:ShowDKPFrame(frame) |
local DKPmenu = { } |
local index = 1 |
for poolname, data in pairs(self.db.account.defaults.eqDKP) do |
DKPmenu[index] = poolname |
index = index + 1 |
end |
DKPmenu[#DKPmenu + 1] = "Close" |
self:CreateDropdownmenu(DKPmenu, 2) |
self:ChangeDKPFrame(self.db.account.defaults.raid) |
end |
function MorgDKP:ChangeDKPFrame(pool) |
self.editpool = pool |
self.editevent = nil |
MorgDKP_RaidsPage3Pool:SetText(pool) |
local numevents |
if not self.db.account.raidlog.dkpevents then self.db.account.raidlog.dkpevents = { } end |
if not self.db.account.raidlog.dkpevents[pool] then |
self.db.account.raidlog.dkpevents[pool] = { } |
numevents = 0 |
else numevents = #self.db.account.raidlog.dkpevents[pool] end |
self.scrolldata = { } |
self.maxitems = 15 |
if numevents > 0 then |
for event = 1, numevents do |
self.scrolldata[event] = self.db.account.raidlog.dkpevents[pool][event] |
end |
end |
self.scrollframe = MorgDKP_RaidsPage3 |
self:ScrollBar_Update() |
end |
function MorgDKP:EditDKPChange(frame, name) |
local _, _, event = string.find(name, "MorgDKP_RaidsPage3Button(%d+)") |
event = tonumber(event) |
local offset = FauxScrollFrame_GetOffset(MorgDKP_RaidsPage3ScrollBar) |
event = event + offset |
self.editevent = event |
MorgDKP_RaidsPage3Value:SetText(self.scrolldata[event].value) |
local attend = "" |
if #self.scrolldata[event].members > 1 then |
table.sort(self.scrolldata[event].members) |
for _, name in pairs(self.scrolldata[event].members) do |
attend = attend .. name .."\n" |
end |
else attend = self.scrolldata[event].members[1] end |
MorgDKP_RaidsPage3Members:SetText(attend) |
MorgDKP_RaidsPage3Members:Show() |
end |
function MorgDKP:CustomDrop(frame, menu) |
MorgDKP.Dropdown = { |
type = "text", |
name = L["ad"], |
desc = L["ad"], |
get = function(v) return v end, |
set = function(v) self:HandleCustomDrop(v, frame) end, |
validate = menu |
} |
dewdrop:Open(frame, |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.Dropdown) |
end, |
'cursorX', true, |
'cursorY', true |
) |
end |
function MorgDKP:HandleCustomDrop(value, frame) |
dewdrop:Close() |
if value == "Close" then return end |
local name = frame:GetName() |
if string.find(name, "MorgDKP_RaidsPage1") then self:EnterEventData(value, frame) |
elseif string.find(name, "MorgDKP_RaidsPage3") then self:AddMember(value, frame) |
elseif string.find(name, "MorgDKP_RaidsPage4") then self:ShowAliasUpdate(value, frame) |
end |
end |
function MorgDKP:IndividualDKPRaid(frame) |
local playermenu = { } |
local index = 1 |
for _, name in pairs(self.db.account.defaults.raidmembers) do |
playermenu[index] = name |
index = index + 1 |
end |
playermenu[index] = "Close" |
self.addtype = "individual" |
self:CustomDrop(frame, playermenu) |
end |
function MorgDKP:AddMember(name, frame) |
if name == "Clear" then MorgDKP_RaidsPage3Members:SetText("") return end |
if name == "Current Raid" then |
local olddata = MorgDKP_RaidsPage3Members:GetText() |
local adds = self:ArraytoString(self.db.account.defaults.raidmembers) |
if string.len(olddata) > 1 then |
olddata = olddata .. adds .."\n" |
else olddata = adds .."\n" end |
MorgDKP_RaidsPage3Members:SetText(olddata) |
else |
local olddata = MorgDKP_RaidsPage3Members:GetText() |
name = string.upper(string.sub(name,1,1))..string.lower(string.sub(name,2,-1)) |
if string.len(olddata) > 1 then |
olddata = olddata .. name .."\n" |
else olddata = name .."\n" end |
MorgDKP_RaidsPage3Members:SetText(olddata) |
MorgDKP_RaidsPage3Members:Show() |
if frame:GetName() == "MorgDKP_RaidsPage3Individual" then self:AddMemberData(name, {[1] = name}) end |
end |
MorgDKP_RaidsPage3Members:Show() |
end |
function MorgDKP:AddMemberData(name, members) |
if not self.db.account.defaults.InRaid then DEFAULT_CHAT_FRAME:AddMessage(L["needraid"]) return end |
local event = self:GetRunEvent() |
table.insert(self.db.account.raidlog.dkpevents[self.editpool], { name = name, |
value = MorgDKP_RaidsPage3Value:GetText(), |
members = members, |
eqdkp = self.db.account.defaults.eqDKP[self.editpool].eqDKPsite, |
prefix = self.db.account.defaults.eqDKP[self.editpool].prefix, |
addtype = self.addtype, |
event = self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[event].note}) |
self:ChangeDKPFrame(self.editpool) |
end |
function MorgDKP:GroupDKPRaid(frame) |
local playermenu = { } |
local index = 2 |
playermenu[1] = "Current Raid" |
for _, name in pairs(self.db.account.defaults.raidmembers) do |
playermenu[index] = name |
index = index + 1 |
end |
playermenu[index] = "Clear" |
playermenu[index + 1] = "Close" |
self.addtype = "Group" |
if frame:GetName() == "MorgDKP_RaidsPage3Decay" then self.addtype = "Decay" end |
self:CustomDrop(frame, playermenu) |
self:ChangeDKPFrame(self.editpool) |
end |
function MorgDKP:DeleteCurrentDKPChange() |
self:AwardDKP(0, self.db.account.raidlog.dkpevents[self.editpool][self.editevent].value, self.editpool, self.db.account.raidlog.dkpevents[self.editpool][self.editevent].members) |
table.remove(self.db.account.raidlog.dkpevents[self.editpool], self.editevent) |
MorgDKP_RaidsPage3Members:Hide() |
MorgDKP_RaidsPage3Value:SetText("0") |
MorgDKP_RaidsPage3Members:SetText("") |
self:ChangeDKPFrame(self.editpool) |
end |
function MorgDKP:AddDKPChange() |
if self.addtype == "individual" then return end |
local attendees = self:AttendtoArray(MorgDKP_RaidsPage3Members) |
local value = MorgDKP_RaidsPage3Value:GetText() |
self:AddMemberData(self.addtype, attendees) |
MorgDKP_RaidsPage3Members:SetText("") |
self:AwardDKP(nil, value, self.editpool, attendees) |
self:ChangeDKPFrame(self.editpool) |
end |
function MorgDKP:AttendtoArray(frame) |
local attends = {self:Explode(frame:GetText(), "\n")} |
local attendees = { } |
local count = 1 |
for i = 1, #attends do |
if string.len(attends[i]) > 1 and attends[i] and attends[i] ~= "" then |
attends[i] = string.upper(string.sub(attends[i],1,1))..string.lower(string.sub(attends[i],2,-1)) |
attendees[count] = attends[i] |
count = count + 1 |
end |
end |
table.sort(attendees) |
return attendees |
end |
function MorgDKP:ArraytoString(array) |
local attend = "" |
if #array > 1 then |
table.sort(array) |
for _, name in pairs(array) do |
attend = attend .. name .."\n" |
end |
else attend = array[1] end |
return attend |
end |
function MorgDKP:ShowAliasFrame(frame) |
local DKPmenu = { } |
local index = 1 |
for poolname, data in pairs(self.db.account.defaults.eqDKP) do |
DKPmenu[index] = poolname |
index = index + 1 |
end |
DKPmenu[#DKPmenu + 1] = "Close" |
self:CreateDropdownmenu(DKPmenu, 3) |
self:ChangeAliasFrame(self.db.account.defaults.raid) |
end |
function MorgDKP:ChangeAliasFrame(pool) |
self.editpool = pool |
if not self.db.account.raidlog.aliases then self.db.account.raidlog.aliases = { } end |
if not self.db.account.raidlog.aliases[pool] then self.db.account.raidlog.aliases[pool] = { } end |
self.editevent = nil |
MorgDKP_RaidsPage4Pool:SetText(pool) |
MorgDKP_RaidsPage4Alias:SetText("") |
MorgDKP_RaidsPage4Member:SetText("") |
local numevents |
numevents = #self.db.account.defaults.eqDKP[pool].Aliases |
self.scrolldata = { } |
self.maxitems = 15 |
if numevents > 0 then |
for event = 1, numevents do |
self.scrolldata[event] = {alt = self.db.account.defaults.eqDKP[pool].Aliases[event].alt, main = self.db.account.defaults.eqDKP[pool].Aliases[event].main, name = self.db.account.defaults.eqDKP[pool].Aliases[event].alt} |
end |
end |
self.scrollframe = MorgDKP_RaidsPage4 |
self:ScrollBar_Update() |
end |
function MorgDKP:EditAlias(frame, name) |
local _, _, event = string.find(name, "MorgDKP_RaidsPage4Button(%d+)") |
event = tonumber(event) |
local offset = FauxScrollFrame_GetOffset(MorgDKP_RaidsPage4ScrollBar) |
event = event + offset |
self.editevent = event |
MorgDKP_RaidsPage4Alias:SetText(self.scrolldata[event].alt) |
MorgDKP_RaidsPage4Member:SetText(self.scrolldata[event].main) |
end |
function MorgDKP:ChooseAlias(frame) |
local playermenu = { } |
for _, name in pairs(self.db.account.defaults.raidmembers) do |
table.insert(playermenu, name) |
end |
table.sort(playermenu) |
table.insert(playermenu, "Close") |
self:CustomDrop(frame, playermenu) |
end |
function MorgDKP:ChooseMember(frame) |
local playermenu = { } |
for name, dkp in pairs(self.db.account.info) do |
if dkp[self.editpool] then table.insert(playermenu, name) end |
end |
table.sort(playermenu) |
table.insert(playermenu, "Close") |
self:CustomDrop(frame, playermenu) |
end |
function MorgDKP:ChooseEvent(frame) |
if not self.raidid then return end |
local POOL = MorgDKP:GetPool(self.raidid) |
self.editpool = POOL |
local playermenu = {} |
for event,data in pairs(self.db.account.defaults.eqDKP[POOL].Events) do |
table.insert(playermenu, event) |
end |
table.sort(playermenu) |
table.insert(playermenu, "Close") |
self:CustomDrop(frame, playermenu) |
end |
function MorgDKP:DeleteCurrentAlias() |
local main = MorgDKP_RaidsPage4Member:GetText() |
local alt = MorgDKP_RaidsPage4Alias:GetText() |
if not self.db.account.raidlog.aliases then self.db.account.raidlog.aliases = { } end |
if not self.db.account.raidlog.aliases[self.editpool] then self.db.account.raidlog.aliases[self.editpool] = { } end |
table.remove(self.db.account.defaults.eqDKP[self.editpool].Aliases, self.editevent) |
table.insert(self.db.account.raidlog.aliases[self.editpool], { alt = alt, |
main = main, |
eqdkp = self.db.account.defaults.eqDKP[self.editpool].eqDKPsite, |
action = "DELETE"}) |
for aliasnum, data in pairs(self.db.account.info[main].aliases) do |
if data.alt == alt and data.raid == self.editpool then |
table.remove(self.db.account.info[main].aliases, aliasnum) |
break |
end |
end |
self.db.account.info[alt] = nil |
self:ChangeAliasFrame(self.editpool) |
end |
function MorgDKP:AddAlias() |
local alt = MorgDKP_RaidsPage4Alias:GetText() |
local main = MorgDKP_RaidsPage4Member:GetText() |
alt = string.upper(string.sub(alt,1,1))..string.lower(string.sub(alt,2,-1)) |
main = string.upper(string.sub(main,1,1))..string.lower(string.sub(main,2,-1)) |
if not self.db.account.info[main] then DEFAULT_CHAT_FRAME:AddMessage(L["nomain"]) return end |
if not self.db.account.raidlog.aliases then self.db.account.raidlog.aliases = { } end |
if not self.db.account.raidlog.aliases[self.editpool] then self.db.account.raidlog.aliases[self.editpool] = { } end |
for _, data in pairs(self.db.account.defaults.eqDKP[self.editpool].Aliases) do |
if data.alt == alt then |
DEFAULT_CHAT_FRAME:AddMessage(L["aliasexists"]) |
return |
end |
end |
self:PlayerinDB(alt) |
self:PlayerinDB(main) |
self.db.account.info[alt][self.editpool] = {points = self.db.account.info[main][self.editpool].points, |
earned = self.db.account.info[main][self.editpool].earned, |
spent = self.db.account.info[main][self.editpool].spent} |
local update = self:GetServerTime() |
self.db.account.info[alt].lastupdate = update |
DEFAULT_CHAT_FRAME:AddMessage(L["transfer"]..tostring(self.db.account.info[main][self.editpool].points)..L["dkpp"]..main..L["to"]..alt) |
if not self:DoesAliasExist(main, alt, self.editpool) then table.insert(self.db.account.info[main].aliases, {raid = self.editpool, alt = alt}) end |
table.insert(self.db.account.defaults.eqDKP[self.editpool].Aliases, {alt = alt, main = main}) |
table.insert(self.db.account.raidlog.aliases[self.editpool], { alt = alt, |
main = main, |
eqdkp = self.db.account.defaults.eqDKP[self.editpool].eqDKPsite, |
action = "ADD"}) |
self.db.account.info[main].lastupdate = update |
self:ChangeAliasFrame(self.editpool) |
end |
function MorgDKP:DoesAliasExist(main, alt, pool) |
local match = nil |
for _, aliasdata in pairs(self.db.account.info[main]["aliases"]) do |
if aliasdata.alt == alt and aliasdata.raid == pool then |
match = true |
break |
end |
end |
return match |
end |
function MorgDKP:ShowAliasUpdate(name, frame) |
if frame:GetName() == "MorgDKP_RaidsPage4AliasChoose" then MorgDKP_RaidsPage4Alias:SetText(name) |
else MorgDKP_RaidsPage4Member:SetText(name) end |
end |
function MorgDKP:ShowOptionFrame(frame) |
MorgDKP_RaidsPage5AutozoneText:SetText(L["autozone"]) |
self:SetTTScript(MorgDKP_RaidsPage5Autozone, L["autozonedesc"]) |
MorgDKP_RaidsPage5StartrunText:SetText(L["startruntrack"]) |
self:SetTTScript(MorgDKP_RaidsPage5Startrun, L["startruntrackdesc"]) |
MorgDKP_RaidsPage5WhisperText:SetText(L["enablewhisper"]) |
self:SetTTScript(MorgDKP_RaidsPage5Whisper, L["enablewhisperdesc"]) |
MorgDKP_RaidsPage5MultipoolText:SetText(L["multi"]) |
self:SetTTScript(MorgDKP_RaidsPage5Multipool, L["multidesc"]) |
MorgDKP_RaidsPage5DkpawardText:SetText(L["dkpaward"]) |
self:SetTTScript(MorgDKP_RaidsPage5Dkpaward, L["dkpawarddesc"]) |
MorgDKP_RaidsPage5DKP:SetText(self.db.account.defaults.dkpamount) |
MorgDKP_RaidsPage5Time:SetText(self.db.account.defaults.dkpsched/60) |
MorgDKP_RaidsPage5SyncPW:SetText(self.db.account.defaults.dbpassword) |
self:SetTTScript(MorgDKP_RaidsPage5SyncPW, L["syncdbdesc"]) |
MorgDKP_RaidsPage5RandomText:SetText(L["enablerandom"]) |
self:SetTTScript(MorgDKP_RaidsPage5Random, L["enablerandomdesc"]) |
MorgDKP_RaidsPage5ZsumText:SetText(L["enablezerosum"]) |
self:SetTTScript(MorgDKP_RaidsPage5Zsum, L["enablezerosumdesc"]) |
MorgDKP_RaidsPage5RelationalText:SetText(L["enablerelationaldkp"]) |
self:SetTTScript(MorgDKP_RaidsPage5Relational, L["enablerelationaldkpdesc"]) |
MorgDKP_RaidsPage5BidwarText:SetText(L["enablebidwar"]) |
self:SetTTScript(MorgDKP_RaidsPage5Bidwar, L["enablebidwardesc"]) |
MorgDKP_RaidsPage5SilentText:SetText(L["enablesilentauction"]) |
self:SetTTScript(MorgDKP_RaidsPage5Silent, L["enablesilentauctiondesc"]) |
MorgDKP_RaidsPage5OneRunText:SetText(L["onerun"]) |
self:SetTTScript(MorgDKP_RaidsPage5OneRun, L["onerundesc"]) |
MorgDKP_RaidsPage5BossAttemptText:SetText(L["bossattemptmode"]) |
self:SetTTScript(MorgDKP_RaidsPage5BossAttempt, L["bossattemptmodedesc"]) |
MorgDKP_RaidsPage5EventFormat:SetText(self.db.account.defaults.eventformat) |
self:SetTTScript(MorgDKP_RaidsPage5EventFormat, L["eventformatdesc"]) |
MorgDKP_RaidsPage5StartFormat:SetText(self.db.account.defaults.startformat) |
self:SetTTScript(MorgDKP_RaidsPage5StartFormat, L["startformatdesc"]) |
MorgDKP_RaidsPage5TrashFormat:SetText(self.db.account.defaults.trashformat) |
self:SetTTScript(MorgDKP_RaidsPage5TrashFormat, L["trashformatdesc"]) |
MorgDKP_RaidsPage5RunTime:SetText(self.db.account.defaults.runrewardtime/60) |
self:SetTTScript(MorgDKP_RaidsPage5RunTime, L["runrewardtimedesc"]) |
MorgDKP_RaidsPage5PTakeNum:SetText(self.db.account.defaults.percent) |
self:SetTTScript(MorgDKP_RaidsPage5PTakeNum, L["enablepercentdesc"]) |
MorgDKP_RaidsPage5PTakeText:SetText(L["percenttake"]) |
self:SetTTScript(MorgDKP_RaidsPage5PTake, L["percenttakedesc"]) |
MorgDKP_RaidsPage5JustEnoughText:SetText(L["enablejustenough"]) |
self:SetTTScript(MorgDKP_RaidsPage5JustEnough, L["enablejustenoughdesc"]) |
MorgDKP_RaidsPage5OverBID:SetText(self.db.account.defaults.overbid) |
self:SetTTScript(MorgDKP_RaidsPage5OverBID, L["overbidmaxdesc"]) |
MorgDKP_RaidsPage5WaitlistText:SetText(L["enablewait"]) |
self:SetTTScript(MorgDKP_RaidsPage5Waitlist, L["enablewaitdesc"]) |
MorgDKP_RaidsPage5WaitStart:SetText(self.db.account.defaults.waitstart) |
self:SetTTScript(MorgDKP_RaidsPage5WaitStart, L["waitstartamtdesc"]) |
MorgDKP_RaidsPage5WaitRun:SetText(self.db.account.defaults.waitrun) |
self:SetTTScript(MorgDKP_RaidsPage5WaitRun, L["waitrunamtdesc"]) |
MorgDKP_RaidsPage5WaitBoss:SetText(self.db.account.defaults.waitboss) |
self:SetTTScript(MorgDKP_RaidsPage5WaitBoss, L["waitbossamtdesc"]) |
MorgDKP_RaidsPage5WaitOtime:SetText(self.db.account.defaults.waitotime) |
self:SetTTScript(MorgDKP_RaidsPage5WaitOtime, L["waitotimeamtdesc"]) |
MorgDKP_RaidsPage5DKPListenText:SetText(L["dkplisten"]) |
self:SetTTScript(MorgDKP_RaidsPage5DKPListen, L["dkplistendesc"]) |
MorgDKP_RaidsPage5BroadcastLeadText:SetText(L["broadlead"]) |
self:SetTTScript(MorgDKP_RaidsPage5BroadcastLead, L["broadleaddesc"]) |
MorgDKP:UpdateOptionFrame() |
end |
function MorgDKP:UpdateOptionFrame() |
MorgDKP_RaidsPage5Autozone:SetChecked(self.db.account.defaults.autozone) |
MorgDKP_RaidsPage5Startrun:SetChecked(self.db.account.defaults.startrun) |
MorgDKP_RaidsPage5Whisper:SetChecked(self.db.account.defaults.whisper) |
MorgDKP_RaidsPage5Multipool:SetChecked(self.db.account.defaults.multiPool) |
MorgDKP_RaidsPage5Dkpaward:SetChecked(self.db.account.defaults.dkpaward) |
MorgDKP_RaidsPage5Random:SetChecked(self.db.account.defaults.random) |
MorgDKP_RaidsPage5Zsum:SetChecked(self.db.account.defaults.zerosum) |
MorgDKP_RaidsPage5Relational:SetChecked(self.db.account.defaults.relational) |
MorgDKP_RaidsPage5Bidwar:SetChecked(self.db.account.defaults.bidwar) |
MorgDKP_RaidsPage5Silent:SetChecked(self.db.account.defaults.silent) |
MorgDKP_RaidsPage5OneRun:SetChecked(self.db.account.defaults.OneEvent) |
MorgDKP_RaidsPage5BossAttempt:SetChecked(self.db.account.defaults.attemptmode) |
MorgDKP_RaidsPage5PTake:SetChecked(self.db.account.defaults.percenttake) |
MorgDKP_RaidsPage5JustEnough:SetChecked(self.db.account.defaults.justenough) |
MorgDKP_RaidsPage5Waitlist:SetChecked(self.db.account.defaults.waitaward) |
MorgDKP_RaidsPage5DKPListen:SetChecked(self.db.account.defaults.dkplistener) |
MorgDKP_RaidsPage5BroadcastLead:SetChecked(self.db.account.defaults.leadbroadcast) |
if self.db.account.defaults.random then |
MorgDKP_RaidsPage5Multipool:Disable() |
MorgDKP_RaidsPage5Zsum:Disable() |
MorgDKP_RaidsPage5Relational:Disable() |
MorgDKP_RaidsPage5Bidwar:Disable() |
MorgDKP_RaidsPage5PTake:Disable() |
else |
MorgDKP_RaidsPage5Multipool:Enable() |
MorgDKP_RaidsPage5Zsum:Enable() |
MorgDKP_RaidsPage5Relational:Enable() |
MorgDKP_RaidsPage5Bidwar:Enable() |
MorgDKP_RaidsPage5PTake:Enable() |
end |
if MorgDKP:IsValid() then MorgDKP_RaidsPage5Random:Disable() |
else MorgDKP_RaidsPage5Random:Enable() end |
if self.db.account.defaults.bidwar then |
MorgDKP_RaidsPage5Silent:Enable() |
MorgDKP_RaidsPage5JustEnough:Enable() |
MorgDKP_RaidsPage5PTake:Disable() |
MorgDKP_RaidsPage5Relational:Disable() |
else |
MorgDKP_RaidsPage5Silent:Disable() |
MorgDKP_RaidsPage5JustEnough:Disable() |
MorgDKP_RaidsPage5PTake:Enable() |
MorgDKP_RaidsPage5Relational:Enable() |
end |
if self.db.account.defaults.relational then MorgDKP_RaidsPage5Bidwar:Disable() |
else MorgDKP_RaidsPage5Bidwar:Enable() end |
if self.db.account.defaults.percent > 0 then MorgDKP_RaidsPage5Bidwar:Disable() |
elseif not self.db.account.defaults.random then MorgDKP_RaidsPage5Bidwar:Enable() end |
end |
function MorgDKP:SetTTScript(frame, text) |
frame:SetScript("OnEnter", function() |
GameTooltip:SetOwner(frame, "ANCHOR_RIGHT") |
GameTooltip:SetText(text, 1, 1, 1, 1, 1) |
GameTooltip:Show() |
end) |
end |
function MorgDKP:ShowEndRaidFrame() |
local id = self:GetRunEvent() |
local runname = self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[id].note |
attendees = {} |
for name, jointime in pairs(self.db.account.raidlog[self.db.account.defaults.raidnum].join) do |
if not self.db.account.raidlog.attendancedone or not self.db.account.raidlog.attendancedone[name] then |
table.insert(attendees, name) |
end |
end |
local num = #attendees |
MorgDKP_EndRaidRaidname:SetText(string.format(L["endraidadd"], runname)) |
MorgDKP_EndRaidQmark:Show() |
MorgDKP_EndRaidAttendees:Hide() |
MorgDKP_EndRaidEndstring:Hide() |
MorgDKP_EndRaidYESADD:Hide() |
MorgDKP_EndRaid:SetHeight(100) |
MorgDKP_EndRaid:SetWidth(350) |
if num > 0 then |
attendees = self:ArraytoString(attendees) |
MorgDKP_EndRaidAttendees:SetText(attendees) |
MorgDKP_EndRaidAttendees:Show() |
MorgDKP_EndRaidEndstring:SetText(string.format(L["endandadd"], self.db.account.defaults.runrewardtime/60)) |
MorgDKP_EndRaidEndstring:Show() |
MorgDKP_EndRaidYESADD:Show() |
MorgDKP_EndRaid:SetHeight(150 + (num * 10)) |
MorgDKP_EndRaidQmark:Hide() |
end |
MorgDKP_EndRaid:Show() |
end |
function MorgDKP:AddandEnd() |
local attendees = self:AttendtoArray(MorgDKP_EndRaidAttendees) |
if attendees then |
local id = self:GetRunEvent() |
local value = 0 |
local POOL = self.db.account.defaults.raid |
if self.db.account.defaults.eqDKP[self.db.account.defaults.raid]['Events'][self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[id].name] then |
value = self.db.account.defaults.eqDKP[self.db.account.defaults.raid]['Events'][self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[id].name].value |
end |
for num, name in pairs(attendees) do |
if not self.db.account.raidlog.attendancedone or not self.db.account.raidlog.attendancedone[name] then |
table.insert(self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[id].attendees, name) |
end |
end |
if value then self:AwardDKP(nil, value, POOL, attendees, nil, 1) end |
end |
self:EndRaid() |
MorgDKP_EndRaid:Hide() |
end |
--[[ |
Name: Tablet-2.0 |
Revision: $Rev$ |
Author(s): ckknight (ckknight@gmail.com) |
Website: http://ckknight.wowinterface.com/ |
Documentation: http://www.wowace.com/index.php/Tablet-2.0 |
SVN: http://svn.wowace.com/wowace/trunk/TabletLib/Tablet-2.0 |
Description: A library to provide an efficient, featureful tooltip-style display. |
Dependencies: AceLibrary, (optional) Dewdrop-2.0 |
License: LGPL v2.1 |
]] |
local MAJOR_VERSION = "Tablet-2.0" |
local MINOR_VERSION = tonumber(("$Revision$"):sub(12, -3)) |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
local DEBUG = false |
local SCROLL_UP = "Scroll up" |
local SCROLL_DOWN = "Scroll down" |
local HINT = "Hint" |
local DETACH = "Detach" |
local DETACH_DESC = "Detach the tablet from its source." |
local SIZE = "Size" |
local SIZE_DESC = "Scale the tablet." |
local CLOSE_MENU = "Close menu" |
local CLOSE_MENU_DESC = "Close the menu." |
local COLOR = "Background color" |
local COLOR_DESC = "Set the background color." |
local LOCK = "Lock" |
local LOCK_DESC = "Lock the tablet in its current position. Alt+Right-click for menu or Alt+drag to drag it when locked." |
if GetLocale() == "deDE" then |
SCROLL_UP = "Hochscrollen" |
SCROLL_DOWN = "Runterscrollen" |
HINT = "Hinweis" |
DETACH = "L\195\182sen" |
DETACH_DESC = "L\195\182st den Tooltip aus seiner Verankerung." |
SIZE = "Gr\195\182\195\159e" |
SIZE_DESC = "Gr\195\182\195\159e des Tooltips \195\164ndern." |
CLOSE_MENU = "Menu schlie\195\159en" |
CLOSE_MENU_DESC = "Schlie\195\159t das Menu." |
COLOR = "Hintergrundfarbe" |
COLOR_DESC = "Hintergrundfarbe setzen." |
LOCK = "Sperren" |
LOCK_DESC = "Sperrt die aktuelle Position vom Tooltip. Alt+Rechts-klick f\195\188rs Men\195\188 oder Alt+Verschieben f\195\188rs verschieben wenn es gesperrt ist." |
elseif GetLocale() == "koKR" then |
SCROLL_UP = "ìë¡ ì¤í¬ë¡¤" |
SCROLL_DOWN = "ìëë¡ ì¤í¬ë¡¤" |
HINT = "íí¸" |
DETACH = "ë¶ë¦¬" |
DETACH_DESC = "í ì´ë¸ì ë¶ë¦¬í©ëë¤." |
SIZE = "í¬ê¸°" |
SIZE_DESC = "í ì´ë¸ì í¬ê¸°ì ëë¤." |
CLOSE_MENU = "ë©ë´ ë«ê¸°" |
CLOSE_MENU_DESC = "ë©ë´ë¥¼ ë«ìµëë¤." |
COLOR = "ë°°ê²½ ìì" |
COLOR_DESC = "ë°°ê²½ ììì ì¤ì í©ëë¤." |
LOCK = "ê³ ì " |
LOCK_DESC = "íì¬ ìì¹ì í ì´ë¸ì ê³ ì í©ëë¤. ìí¸+ì°í´ë¦ : ë©ë´ì´ê¸°, ìí¸+ëëê·¸ : ê³ ì ëê²ì ëëê·¸í©ëë¤." |
elseif GetLocale() == "zhCN" then |
SCROLL_UP = "åä¸ç¿»è½¬" |
SCROLL_DOWN = "åä¸ç¿»è½¬" |
HINT = "æ示" |
DETACH = "å离" |
DETACH_DESC = "å离èå为ç¬ç«æ示." |
SIZE = "尺寸" |
SIZE_DESC = "缩æ¾èåæ¾ç¤ºå°ºå¯¸." |
CLOSE_MENU = "å ³éèå" |
CLOSE_MENU_DESC = "å ³éèå" |
COLOR = "èæ¯é¢è²" |
COLOR_DESC = "设置èåèæ¯é¢è²." |
LOCK = "éå®" |
LOCK_DESC = "éå®èåå½åä½ç½®. alt+å³é® å°æ¾ç¤ºé项, alt+æå¨ å¯ä»¥ç§»å¨å·²éå®çèå." |
elseif GetLocale() == "zhTW" then |
SCROLL_UP = "åä¸ç¿»æ²" |
SCROLL_DOWN = "åä¸ç¿»æ²" |
HINT = "æ示" |
DETACH = "åé¢" |
DETACH_DESC = "åé¢é¸å®çºç¨ç«æ示ã" |
SIZE = "尺寸" |
SIZE_DESC = "縮æ¾é¸å®é¡¯ç¤ºå°ºå¯¸ã" |
CLOSE_MENU = "ééé¸å®" |
CLOSE_MENU_DESC = "ééé¸å®ã" |
COLOR = "èæ¯é¡è²" |
COLOR_DESC = "è¨å®é¸å®èæ¯é¡è²ã" |
LOCK = "éå®" |
LOCK_DESC = "éå®é¸å®ç®åä½ç½®è¨å®ãAlt-å³éµå°é¡¯ç¤ºé¸é ï¼Alt-æåå¯ä»¥ç§»åå·²éå®çé¸å®ã" |
elseif GetLocale() == "frFR" then |
SCROLL_UP = "Parcourir vers le haut" |
SCROLL_DOWN = "Parcourir vers le bas" |
HINT = "Astuce" |
DETACH = "D\195\169tacher" |
DETACH_DESC = "Permet de d\195\169tacher le tableau de sa source." |
SIZE = "Taille" |
SIZE_DESC = "Permet de changer l'\195\169chelle du tableau." |
CLOSE_MENU = "Fermer le menu" |
CLOSE_MENU_DESC = "Ferme ce menu." |
COLOR = "Couleur du fond" |
COLOR_DESC = "Permet de d\195\169finir la couleur du fond." |
LOCK = "Bloquer" |
LOCK_DESC = "Bloque le tableau \195\160 sa position actuelle. Alt+clic-droit pour le menu ou Alt+glisser pour le d\195\169placer quand il est bloqu\195\169." |
elseif GetLocale() == "esES" then |
SCROLL_UP = "Desplazar hacia arriba" |
SCROLL_DOWN = "Desplazar hacia abajo" |
HINT = "Consejo" |
DETACH = "Separar" |
DETACH_DESC = "Separa el tooltip de su fuente." |
SIZE = "Tama\195\177o" |
SIZE_DESC = "Escala el tooltip" |
CLOSE_MENU = "Cerrar men\195\186" |
CLOSE_MENU_DESC = "Cierra el men\195\186" |
COLOR = "Color de fondo" |
COLOR_DESC = "Establece el color de fondo" |
LOCK = "Bloquear" |
LOCK_DESC = "Bloquea el tooltip en su posici\195\179n actual. Clic+Alt para el men\195\186 y arrastra+Alt para arrastrarlo cuando est\195\161 bloqueado" |
end |
local start = GetTime() |
local wrap |
local GetProfileInfo |
if DEBUG then |
local tree = {} |
local treeMemories = {} |
local treeTimes = {} |
local memories = {} |
local times = {} |
function wrap(value, name) |
if type(value) == "function" then |
local oldFunction = value |
memories[name] = 0 |
times[name] = 0 |
return function(self, ...) |
local pos = #tree |
tree[#tree+1] = name |
treeMemories[#treeMemories+1] = 0 |
treeTimes[#treeTimes+1] = 0 |
local t, mem = GetTime(), gcinfo() |
local r1, r2, r3, r4, r5, r6, r7, r8 = oldFunction(self, ...) |
mem, t = gcinfo() - mem, GetTime() - t |
if pos > 0 then |
treeMemories[pos] = treeMemories[pos] + mem |
treeTimes[pos] = treeTimes[pos] + t |
end |
local otherMem = table.remove(treeMemories) |
if mem - otherMem > 0 then |
memories[name] = memories[name] + mem - otherMem |
end |
times[name] = times[name] + t - table.remove(treeTimes) |
table.remove(tree) |
return r1, r2, r3, r4, r5, r6, r7, r8 |
end |
end |
end |
function GetProfileInfo() |
return GetTime() - start, times, memories |
end |
else |
function wrap(value) |
return value |
end |
end |
local function GetMainFrame() |
if UIParent:IsShown() then |
return UIParent |
end |
local f = GetUIPanel("fullscreen") |
if f and f:IsShown() then |
return f |
end |
return nil |
end |
GetMainFrame = wrap(GetMainFrame, "GetMainFrame") |
local MIN_TOOLTIP_SIZE = 200 |
local TESTSTRING_EXTRA_WIDTH = 8 |
local Tablet = {} |
local Dewdrop = nil |
local CleanCategoryPool |
local pool = {} |
local function del(t) |
setmetatable(t, nil) |
for k in pairs(t) do |
t[k] = nil |
end |
t[''] = true |
t[''] = nil |
pool[t] = true |
return nil |
end |
local function copy(parent) |
local t = next(pool) |
if not t then |
t = {} |
else |
pool[t] = nil |
end |
if parent then |
for k,v in pairs(parent) do |
t[k] = v |
end |
setmetatable(t, getmetatable(parent)) |
end |
return t |
end |
local function new(...) |
local t = next(pool) |
if not t then |
t = {} |
else |
pool[t] = nil |
end |
for i = 1, select('#', ...), 2 do |
local k = select(i, ...) |
if k then |
t[k] = select(i+1, ...) |
else |
break |
end |
end |
return t |
end |
local tmp |
tmp = setmetatable({}, {__index = function(self, key) |
local t = {} |
tmp[key] = function(...) |
for k in pairs(t) do |
t[k] = nil |
end |
for i = 1, select('#', ...), 2 do |
local k = select(i, ...) |
if k then |
t[k] = select(i+1, ...) |
else |
break |
end |
end |
return t |
end |
return tmp[key] |
end}) |
local headerSize, normalSize |
if GameTooltipHeaderText then |
headerSize = select(2,GameTooltipHeaderText:GetFont()) |
else |
headerSize = 14 |
end |
if GameTooltipText then |
normalSize = select(2,GameTooltipText:GetFont()) |
else |
normalSize = 12 |
end |
local tooltip |
local testString |
local TabletData = {} |
local Category = {} |
local Line = {} |
local function getTestWidth(font, size, text) |
if not testString then |
return MIN_TOOLTIP_SIZE + 40 |
end |
testString:SetWidth(0) |
testString:SetFontObject(font) |
local a,_,b = font:GetFont() |
testString:SetFont(a, size, b) |
testString:SetText(text) |
return testString:GetStringWidth()-- + TESTSTRING_EXTRA_WIDTH |
end |
getTestWidth = wrap(getTestWidth, "getTestWidth") |
do |
local TabletData_mt = { __index = TabletData } |
function TabletData:new(tablet) |
local self = new() |
self.categories = new() |
self.id = 0 |
self.width = 0 -- (MIN_TOOLTIP_SIZE - 20)*tablet.fontSizePercent |
self.tablet = tablet |
self.title = nil |
self.titleR, self.titleG, self.titleB = nil, nil, nil |
self.num_lines = 0 |
setmetatable(self, TabletData_mt) |
return self |
end |
TabletData.new = wrap(TabletData.new, "TabletData:new") |
function TabletData:checkMinWidth() |
local min = self.minWidth or MIN_TOOLTIP_SIZE |
local width = (min - 20)*self.tablet.fontSizePercent |
if self.width < width then |
self.width = width |
end |
end |
TabletData.checkMinWidth = wrap(TabletData.checkMinWidth, "TabletData:checkMinWidth") |
function TabletData:del() |
for k, v in ipairs(self.categories) do |
v:del() |
end |
del(self.categories) |
del(self) |
end |
TabletData.del = wrap(TabletData.del, "TabletData:del") |
function TabletData:Display() |
if self.title and (self.tablet == tooltip or self.tablet.registration.showTitleWhenDetached) then |
local info = new( |
'hideBlankLine', true, |
'text', self.title, |
'justify', "CENTER", |
'font', GameTooltipHeaderText, |
'isTitle', true |
) |
if self.titleR then |
info.textR = self.titleR |
info.textG = self.titleG |
info.textB = self.titleB |
end |
self:AddCategory(info, 1) |
del(info) |
end |
if self.tablet == tooltip or self.tablet.registration.showHintWhenDetached then |
if self.hint then |
self:AddCategory(nil):AddLine( |
'text', HINT .. ": " .. self.hint, |
'textR', 0, |
'textG', 1, |
'textB', 0, |
'wrap', true |
) |
end |
end |
local tabletData = self.tabletData |
for k, v in ipairs(self.categories) do |
local width |
if v.columns <= 2 then |
width = v.x1 |
else |
width = (v.columns - 1)*20 |
for i = 1, v.columns do |
width = width + v['x' .. i] |
end |
end |
if self.width < width then |
self.width = width |
end |
end |
local good = false |
local lastTitle = true |
for k, v in ipairs(self.categories) do |
if lastTitle then |
v.hideBlankLine = true |
lastTitle = false |
end |
if v:Display(self.tablet) and (not v.isTitle or not self.tablet.registration.hideWhenEmpty or next(self.categories, k)) then |
good = true |
end |
if v.isTitle then |
lastTitle = true |
end |
end |
if not good then |
if self.tablet == tooltip or not self.tablet.registration.hideWhenEmpty then |
local width |
local info = new( |
'hideBlankLine', true, |
'text', self.title, |
'justify', "CENTER", |
'font', GameTooltipHeaderText, |
'isTitle', true |
) |
local cat = self:AddCategory(info) |
del(info) |
self.width = self.categories[#self.categories].x1 |
cat:Display(self.tablet) |
else |
self.tablet:__Hide() |
self.tablet.tmpHidden = true |
end |
else |
self.tablet:__Show() |
self.tablet.tmpHidden = nil |
end |
end |
TabletData.Display = wrap(TabletData.Display, "TabletData:Display") |
function TabletData:AddCategory(info, index) |
local made = false |
if not info then |
made = true |
info = new() |
end |
local cat = Category:new(self, info) |
if index then |
table.insert(self.categories, index, cat) |
else |
self.categories[#self.categories+1] = cat |
end |
if made then |
del(info) |
end |
return cat |
end |
TabletData.AddCategory = wrap(TabletData.AddCategory, "TabletData:AddCategory") |
function TabletData:SetHint(hint) |
self.hint = hint |
end |
TabletData.SetHint = wrap(TabletData.SetHint, "TabletData:SetHint") |
function TabletData:SetTitle(title) |
self.title = title or "Title" |
end |
TabletData.SetTitle = wrap(TabletData.SetTitle, "TabletData:SetTitle") |
function TabletData:SetTitleColor(r, g, b) |
self.titleR = r |
self.titleG = g |
self.titleB = b |
end |
TabletData.SetTitleColor = wrap(TabletData.SetTitleColor, "TabletData:SetTitleColor") |
end |
do |
local Category_mt = { __index = Category } |
function Category:new(tabletData, info, superCategory) |
local self = copy(info) |
if superCategory and not self.noInherit then |
self.superCategory = superCategory.superCategory |
for k, v in pairs(superCategory) do |
if k:find("^child_") then |
local k = strsub(k, 7) |
if self[k] == nil then |
self[k] = v |
end |
end |
end |
self.columns = superCategory.columns |
else |
self.superCategory = self |
end |
self.tabletData = tabletData |
self.lines = new() |
if not self.columns then |
self.columns = 1 |
end |
for i = 1, self.columns do |
self['x' .. i] = 0 |
end |
setmetatable(self, Category_mt) |
self.lastWasTitle = nil |
local good = self.text |
if not good then |
for i = 2, self.columns do |
if self['text' .. i] then |
good = true |
break |
end |
end |
end |
if good then |
local x = new( |
'category', category, |
'text', self.text, |
'fakeChild', true, |
'func', self.func, |
'onEnterFunc', self.onEnterFunc, |
'onLeaveFunc', self.onLeaveFunc, |
'hasCheck', self.hasCheck, |
'checked', self.checked, |
'checkIcon', self.checkIcon, |
'isRadio', self.isRadio, |
'font', self.font, |
'size', self.size, |
'wrap', self.wrap, |
'catStart', true, |
'indentation', self.indentation, |
'noInherit', true, |
'justify', self.justify, |
'isTitle', self.isTitle |
) |
local i = 1 |
while true do |
local k = 'arg' .. i |
local v = self[k] |
if v == nil then |
break |
end |
x[k] = v |
i = i + 1 |
end |
i = 1 |
while true do |
local k = 'onEnterArg' .. i |
local v = self[k] |
if v == nil then |
break |
end |
x[k] = v |
i = i + 1 |
end |
i = 1 |
while true do |
local k = 'onLeaveArg' .. i |
local v = self[k] |
if v == nil then |
break |
end |
x[k] = v |
i = i + 1 |
end |
if self.isTitle then |
x.textR = self.textR or 1 |
x.textG = self.textG or 0.823529 |
x.textB = self.textB or 0 |
else |
x.textR = self.textR or 1 |
x.textG = self.textG or 1 |
x.textB = self.textB or 1 |
end |
for i = 2, self.columns do |
x['text' .. i] = self['text' .. i] |
x['text' .. i .. 'R'] = self['text' .. i .. 'R'] or self['textR' .. i] or 1 |
x['text' .. i .. 'G'] = self['text' .. i .. 'G'] or self['textG' .. i] or 1 |
x['text' .. i .. 'B'] = self['text' .. i .. 'B'] or self['textB' .. i] or 1 |
x['font' .. i] = self['font' .. i] |
x['size' .. i] = self['size' .. i] |
x['justify' .. i] = self['justify' .. i] |
end |
if self.checkIcon and self.checkIcon:find("^Interface\\Icons\\") then |
x.checkCoordLeft = self.checkCoordLeft or 0.05 |
x.checkCoordRight = self.checkCoordRight or 0.95 |
x.checkCoordTop = self.checkCoordTop or 0.05 |
x.checkCoordBottom = self.checkCoordBottom or 0.95 |
else |
x.checkCoordLeft = self.checkCoordLeft or 0 |
x.checkCoordRight = self.checkCoordRight or 1 |
x.checkCoordTop = self.checkCoordTop or 0 |
x.checkCoordBottom = self.checkCoordBottom or 1 |
end |
x.checkColorR = self.checkColorR or 1 |
x.checkColorG = self.checkColorG or 1 |
x.checkColorB = self.checkColorB or 1 |
self:AddLine(x) |
del(x) |
self.lastWasTitle = true |
end |
return self |
end |
Category.new = wrap(Category.new, "Category:new") |
function Category:del() |
local prev = garbageLine |
for k, v in pairs(self.lines) do |
v:del() |
end |
del(self.lines) |
del(self) |
end |
Category.del = wrap(Category.del, "Category:del") |
function Category:AddLine(...) |
self.lastWasTitle = nil |
local line |
local k1 = ... |
if type(k1) == "table" then |
local k2 = select(2, ...) |
Line:new(self, k1, k2) |
else |
local info = new(...) |
Line:new(self, info) |
info = del(info) |
end |
end |
Category.AddLine = wrap(Category.AddLine, "Category:AddLine") |
function Category:AddCategory(...) |
local lastWasTitle = self.lastWasTitle |
self.lastWasTitle = nil |
local info |
local k1 = ... |
if type(k1) == "table" then |
info = k1 |
else |
info = new(...) |
end |
if lastWasTitle or #self.lines == 0 then |
info.hideBlankLine = true |
end |
local cat = Category:new(self.tabletData, info, self) |
self.lines[#self.lines+1] = cat |
if info ~= k1 then |
info = del(info) |
end |
return cat |
end |
Category.AddCategory = wrap(Category.AddCategory, "Category:AddCategory") |
function Category:HasChildren() |
local hasChildren = false |
for k, v in ipairs(self.lines) do |
if v.HasChildren then |
if v:HasChildren() then |
return true |
end |
end |
if not v.fakeChild then |
return true |
end |
end |
return false |
end |
Category.HasChildren = wrap(Category.HasChildren, "Category:HasChildren") |
local lastWasTitle = false |
function Category:Display(tablet) |
if not self.isTitle and not self.showWithoutChildren and not self:HasChildren() then |
return false |
end |
if not self.hideBlankLine and not lastWasTitle then |
local info = new( |
'blank', true, |
'fakeChild', true, |
'noInherit', true |
) |
self:AddLine(info, 1) |
del(info) |
end |
local good = false |
if #self.lines > 0 then |
self.tabletData.id = self.tabletData.id + 1 |
self.id = self.tabletData.id |
for k, v in ipairs(self.lines) do |
if v:Display(tablet) then |
good = true |
end |
end |
end |
lastWasTitle = self.isTitle |
return good |
end |
Category.Display = wrap(Category.Display, "Category:Display") |
end |
do |
local Line_mt = { __index = Line } |
function Line:new(category, info, position) |
local self = copy(info) |
if not info.noInherit then |
for k, v in pairs(category) do |
if k:find("^child_") then |
local k = strsub(k, 7) |
if self[k] == nil then |
self[k] = v |
end |
end |
end |
end |
self.category = category |
if position then |
table.insert(category.lines, position, self) |
else |
category.lines[#category.lines+1] = self |
end |
setmetatable(self, Line_mt) |
local n = category.tabletData.num_lines + 1 |
category.tabletData.num_lines = n |
if n == 10 then |
category.tabletData:checkMinWidth() |
end |
local columns = category.columns |
if columns == 1 then |
if not self.justify then |
self.justify = "LEFT" |
end |
elseif columns == 2 then |
self.justify = "LEFT" |
self.justify2 = "RIGHT" |
if self.wrap then |
self.wrap2 = false |
end |
else |
for i = 2, columns-1 do |
if not self['justify' .. i] then |
self['justify' .. i] = "CENTER" |
end |
end |
if not self.justify then |
self.justify = "LEFT" |
end |
if not self['justify' .. columns] then |
self['justify' .. columns] = "RIGHT" |
end |
if self.wrap then |
for i = 2, columns do |
self['wrap' .. i] = false |
end |
else |
for i = 2, columns do |
if self['wrap' .. i] then |
for j = i+1, columns do |
self['wrap' .. i] = false |
end |
break |
end |
end |
end |
end |
if not self.indentation or self.indentation < 0 then |
self.indentation = 0 |
end |
if not self.font then |
self.font = GameTooltipText |
end |
for i = 2, columns do |
if not self['font' .. i] then |
self['font' .. i] = self.font |
end |
end |
if not self.size then |
self.size = select(2,self.font:GetFont()) |
end |
for i = 2, columns do |
if not self['size' .. i] then |
self['size' .. i] = select(2,self['font' .. i]:GetFont()) |
end |
end |
if self.checkIcon and self.checkIcon:find("^Interface\\Icons\\") then |
if not self.checkCoordLeft then |
self.checkCoordLeft = 0.05 |
end |
if not self.checkCoordRight then |
self.checkCoordRight = 0.95 |
end |
if not self.checkCoordTop then |
self.checkCoordTop = 0.05 |
end |
if not self.checkCoordBottom then |
self.checkCoordBottom = 0.95 |
end |
else |
if not self.checkCoordLeft then |
self.checkCoordLeft = 0 |
end |
if not self.checkCoordRight then |
self.checkCoordRight = 1 |
end |
if not self.checkCoordTop then |
self.checkCoordTop = 0 |
end |
if not self.checkCoordBottom then |
self.checkCoordBottom = 1 |
end |
end |
if not self.checkColorR then |
self.checkColorR = 1 |
end |
if not self.checkColorG then |
self.checkColorG = 1 |
end |
if not self.checkColorB then |
self.checkColorB = 1 |
end |
local fontSizePercent = category.tabletData.tablet.fontSizePercent |
local w = 0 |
self.checkWidth = 0 |
testString = category.tabletData.tablet.buttons[1].col1 |
if self.text then |
if not self.wrap then |
local testWidth = getTestWidth(self.font, self.size * fontSizePercent, self.text) |
local checkWidth = self.hasCheck and self.size * fontSizePercent or 0 |
self.checkWidth = checkWidth |
w = testWidth + self.indentation * fontSizePercent + checkWidth |
if category.superCategory.x1 < w then |
category.superCategory.x1 = w |
end |
else |
if columns == 1 then |
local testWidth = getTestWidth(self.font, self.size * fontSizePercent, self.text) |
local checkWidth = self.hasCheck and self.size * fontSizePercent or 0 |
self.checkWidth = checkWidth |
w = testWidth + self.indentation * fontSizePercent + checkWidth |
if w > (MIN_TOOLTIP_SIZE - 20) * fontSizePercent then |
w = (MIN_TOOLTIP_SIZE - 20) * fontSizePercent |
end |
else |
w = MIN_TOOLTIP_SIZE * fontSizePercent / 2 |
end |
if category.superCategory.x1 < w then |
category.superCategory.x1 = w |
end |
end |
end |
if columns == 2 and self.text2 then |
if not self.wrap2 then |
local testWidth = getTestWidth(self.font2, self.size2 * fontSizePercent, self.text2) |
w = w + 40 * fontSizePercent + testWidth |
if category.superCategory.x1 < w then |
category.superCategory.x1 = w |
end |
else |
w = w + 40 * fontSizePercent + MIN_TOOLTIP_SIZE * fontSizePercent / 2 |
if category.superCategory.x1 < w then |
category.superCategory.x1 = w |
end |
end |
elseif columns >= 3 then |
if self.text2 then |
if not self.wrap2 then |
local testWidth = getTestWidth(self.font2, self.size2 * fontSizePercent, self.text2) |
local w = testWidth |
if category.superCategory.x2 < w then |
category.superCategory.x2 = w |
end |
else |
local w = MIN_TOOLTIP_SIZE / 2 |
if category.superCategory.x2 < w then |
category.superCategory.x2 = w |
end |
end |
end |
for i = 3, columns do |
local text = self['text' .. i] |
if text then |
local x_i = 'x' .. i |
if not self['wrap' .. i] then |
local testWidth = getTestWidth(self['font' .. i], self['size' .. i] * fontSizePercent, text) |
local w = testWidth |
if category.superCategory[x_i] < w then |
category.superCategory[x_i] = w |
end |
else |
local w = MIN_TOOLTIP_SIZE / 2 |
if category.superCategory[x_i] < w then |
category.superCategory[x_i] = w |
end |
end |
end |
end |
end |
return self |
end |
Line.new = wrap(Line.new, "Line:new") |
function Line:del() |
del(self) |
end |
Line.del = wrap(Line.del, "Line:del") |
function Line:Display(tablet) |
tablet:AddLine(self) |
return true |
end |
Line.Display = wrap(Line.Display, "Line:Display") |
end |
local fake_ipairs |
do |
local function iter(tmp, i) |
i = i + 1 |
local x = tmp[i] |
tmp[i] = nil |
if x then |
return i, x |
end |
end |
local tmp = {} |
function fake_ipairs(...) |
for i = 1, select('#', ...) do |
tmp[i] = select(i, ...) |
end |
return iter, tmp, 0 |
end |
fake_ipairs = wrap(fake_ipairs, "fake_ipairs") |
end |
local function argunpack(t, key, i) |
if not i then |
i = 1 |
end |
local k = key .. i |
local v = t[k] |
if v then |
return v, argunpack(t, key, i+1) |
end |
end |
argunpack = wrap(argunpack, "argunpack") |
local delstring, newstring |
do |
local cache = {} |
function delstring(t) |
cache[#cache+1] = t |
t:SetText(nil) |
t:ClearAllPoints() |
t:Hide() |
t:SetParent(UIParent) |
return nil |
end |
delstring = wrap(delstring, "delstring") |
function newstring(parent) |
if #cache ~= 0 then |
local t = cache[#cache] |
cache[#cache] = nil |
t:Show() |
t:SetParent(parent) |
return t |
end |
local t = parent:CreateFontString(nil, "ARTWORK") |
return t |
end |
newstring = wrap(newstring, "newstring") |
end |
local function button_OnEnter(this, ...) |
if type(this.self:GetScript("OnEnter")) == "function" then |
this.self:GetScript("OnEnter")(this.self, ...) |
end |
this.highlight:Show() |
if this.onEnterFunc then |
local success, ret = pcall(this.onEnterFunc, argunpack(this, 'onEnterArg')) |
if not success then |
geterrorhandler()(ret) |
end |
end |
end |
button_OnEnter = wrap(button_OnEnter, "button_OnEnter") |
local function button_OnLeave(this, ...) |
if type(this.self:GetScript("OnLeave")) == "function" then |
this.self:GetScript("OnLeave")(this.self, ...) |
end |
this.highlight:Hide() |
if this.onLeaveFunc then |
local success, ret = pcall(this.onLeaveFunc, argunpack(this, 'onLeaveArg')) |
if not success then |
geterrorhandler()(ret) |
end |
end |
end |
button_OnLeave = wrap(button_OnLeave, "button_OnLeave") |
local lastMouseDown |
local function button_OnClick(this, arg1, ...) |
if this.self:HasScript("OnClick") and type(this.self:GetScript("OnClick")) == "function" then |
this.self:GetScript("OnClick")(this.self, arg1, ...) |
end |
if arg1 == "RightButton" then |
if this.self:HasScript("OnClick") and type(this.self:GetScript("OnClick")) == "function" then |
this.self:GetScript("OnClick")(this.self, arg1, ...) |
end |
elseif arg1 == "LeftButton" then |
if this.self.preventClick == nil or GetTime() > this.self.preventClick and GetTime() < lastMouseDown + 0.5 then |
this.self.preventClick = nil |
this.self.updating = true |
this.self.preventRefresh = true |
local success, ret = pcall(this.func, argunpack(this, 'arg')) |
if not success then |
geterrorhandler()(ret) |
end |
if this.self and this.self.registration then |
this.self.preventRefresh = false |
this.self:children() |
this.self.updating = false |
end |
end |
end |
end |
button_OnClick = wrap(button_OnClick, "button_OnClick") |
local function button_OnMouseUp(this, arg1, ...) |
if this.self:HasScript("OnMouseUp") and type(this.self:GetScript("OnMouseUp")) == "function" then |
this.self:GetScript("OnMouseUp")(this.self, arg1, ...) |
end |
if arg1 ~= "RightButton" then |
if this.clicked then |
local a,b,c,d,e = this.check:GetPoint(1) |
this.check:SetPoint(a,b,c,d-1,e+1) |
this.clicked = false |
end |
end |
end |
button_OnMouseUp = wrap(button_OnMouseUp, "button_OnMouseUp") |
local function button_OnMouseDown(this, arg1, ...) |
if this.self:HasScript("OnMouseDown") and type(this.self:GetScript("OnMouseDown")) == "function" then |
this.self:GetScript("OnMouseDown")(this.self, arg1, ...) |
end |
lastMouseDown = GetTime() |
if arg1 ~= "RightButton" then |
local a,b,c,d,e = this.check:GetPoint(1) |
this.check:SetPoint(a,b,c,d+1,e-1) |
this.clicked = true |
end |
end |
button_OnMouseDown = wrap(button_OnMouseDown, "button_OnMouseDown") |
local function button_OnDragStart(this, ...) |
local parent = this:GetParent() and this:GetParent().tablet |
if parent:GetScript("OnDragStart") then |
return parent:GetScript("OnDragStart")(parent, ...) |
end |
end |
button_OnDragStart = wrap(button_OnDragStart, "button_OnDragStart") |
local function button_OnDragStop(this, ...) |
local parent = this:GetParent() and this:GetParent().tablet |
if parent:GetScript("OnDragStop") then |
return parent:GetScript("OnDragStop")(parent, ...) |
end |
end |
button_OnDragStop = wrap(button_OnDragStop, "button_OnDragStop") |
local num_buttons = 0 |
local function NewLine(self) |
if self.maxLines <= self.numLines then |
self.maxLines = self.maxLines + 1 |
num_buttons = num_buttons + 1 |
local button = CreateFrame("Button", "Tablet20Button" .. num_buttons, self.scrollChild) |
button:SetFrameLevel(12) |
button.indentation = 0 |
local check = button:CreateTexture(nil, "ARTWORK") |
local col1 = newstring(button) |
testString = col1 |
local highlight = button:CreateTexture(nil, "BACKGROUND") |
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") |
button.highlight = highlight |
highlight:SetBlendMode("ADD") |
highlight:SetAllPoints(button) |
highlight:Hide() |
self.buttons[#self.buttons+1] = button |
button.check = check |
button.col1 = col1 |
col1:SetWidth(0) |
if self.maxLines == 1 then |
col1:SetFontObject(GameTooltipHeaderText) |
col1:SetJustifyH("CENTER") |
button:SetPoint("TOPLEFT", self.scrollFrame, "TOPLEFT", 3, -5) |
else |
col1:SetFontObject(GameTooltipText) |
button:SetPoint("TOPLEFT", self.buttons[self.maxLines - 1], "BOTTOMLEFT", 0, -2) |
end |
button:SetScript("OnEnter", button_OnEnter) |
button:SetScript("OnLeave", button_OnLeave) |
button.check = check |
button.self = self |
button:SetPoint("RIGHT", self.scrollFrame, "RIGHT", -7, 0) |
check.shown = false |
check:SetPoint("TOPLEFT", button, "TOPLEFT") |
col1:SetPoint("TOPLEFT", check, "TOPLEFT") |
local size = select(2,GameTooltipText:GetFont()) |
check:SetHeight(size * 1.5) |
check:SetWidth(size * 1.5) |
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") |
check:SetAlpha(0) |
if not button.clicked then |
button:SetScript("OnMouseWheel", self:GetScript("OnMouseWheel")) |
button:EnableMouseWheel(true) |
button:Hide() |
end |
check:Show() |
col1:Hide() |
end |
end |
NewLine = wrap(NewLine, "NewLine") |
local function RecalculateTabletHeight(detached) |
detached.height_ = nil |
if detached.registration and detached.registration.positionFunc then |
local height = detached:GetHeight() |
if height > 0 then |
detached.height_ = height |
else |
local top, bottom |
for i = 1, detached:GetNumPoints() do |
local a,b,c,d,e = detached:GetPoint(i) |
if a:find("^TOP") then |
if c:find("^TOP") then |
top = b:GetTop() |
elseif c:find("^BOTTOM") then |
top = b:GetBottom() |
else |
top = select(2,b:GetCenter()) |
end |
if top then |
top = top + e |
end |
elseif a:find("^BOTTOM") then |
if c:find("^TOP") then |
bottom = b:GetTop() |
elseif c:find("^BOTTOM") then |
bottom = b:GetBottom() |
else |
bottom = select(2,b:GetCenter()) |
end |
if bottom then |
bottom = bottom + e |
end |
end |
end |
if top and bottom then |
detached.height_ = top - bottom |
end |
end |
end |
end |
RecalculateTabletHeight = wrap(RecalculateTabletHeight, "RecalculateTabletHeight") |
local function GetTooltipHeight(self) |
RecalculateTabletHeight(self) |
if self.height_ then |
local height = self:GetTop() and self:GetBottom() and self:GetTop() - self:GetBottom() or self:GetHeight() |
if height == 0 then |
height = self.height_ |
end |
return height |
end |
if self.registration.maxHeight then |
return self.registration.maxHeight |
end |
if self == tooltip then |
return GetScreenHeight()*3/4 |
else |
return GetScreenHeight()*2/3 |
end |
end |
GetTooltipHeight = wrap(GetTooltipHeight, "GetTooltipHeight") |
local overFrame = nil |
local detachedTooltips = {} |
local AcquireDetachedFrame, ReleaseDetachedFrame |
local function AcquireFrame(self, registration, data, detachedData) |
if not detachedData then |
detachedData = data |
end |
if tooltip then |
tooltip.data = data |
tooltip.detachedData = detachedData |
local fontSizePercent = tooltip.data and tooltip.data.fontSizePercent or 1 |
local transparency = tooltip.data and tooltip.data.transparency or 0.75 |
local r = tooltip.data and tooltip.data.r or 0 |
local g = tooltip.data and tooltip.data.g or 0 |
local b = tooltip.data and tooltip.data.b or 0 |
tooltip:SetFontSizePercent(fontSizePercent) |
tooltip:SetTransparency(transparency) |
tooltip:SetColor(r, g, b) |
tooltip:SetParent(GetMainFrame()) |
tooltip:SetFrameStrata(registration.strata or "TOOLTIP") |
tooltip:SetFrameLevel(10) |
for _,frame in fake_ipairs(tooltip:GetChildren()) do |
frame:SetFrameLevel(12) |
end |
else |
tooltip = CreateFrame("Frame", "Tablet20Frame", UIParent) |
tooltip:SetParent(GetMainFrame()) |
self.tooltip = tooltip |
tooltip.data = data |
tooltip.detachedData = detachedData |
tooltip:EnableMouse(true) |
tooltip:EnableMouseWheel(true) |
tooltip:SetFrameStrata(registration.strata or "TOOLTIP") |
tooltip:SetFrameLevel(10) |
local backdrop = new( |
'bgFile', "Interface\\Buttons\\WHITE8X8", |
'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", |
'tile', true, |
'tileSize', 16, |
'edgeSize', 16, |
'insets', new( |
'left', 5, |
'right', 5, |
'top', 5, |
'bottom', 5 |
) |
) |
tooltip:SetBackdrop(backdrop) |
del(backdrop.insets) |
del(backdrop) |
tooltip:SetBackdropColor(0, 0, 0, 1) |
tooltip.numLines = 0 |
tooltip.owner = nil |
tooltip.fontSizePercent = tooltip.data and tooltip.data.fontSizePercent or 1 |
tooltip.maxLines = 0 |
tooltip.buttons = {} |
tooltip.transparency = tooltip.data and tooltip.data.transparency or 0.75 |
tooltip:SetBackdropColor(0, 0, 0, tooltip.transparency) |
tooltip:SetBackdropBorderColor(1, 1, 1, tooltip.transparency) |
tooltip:SetScript("OnUpdate", function(this, elapsed) |
if not tooltip.updating and (not tooltip.enteredFrame or (overFrame and not MouseIsOver(overFrame))) then |
tooltip.scrollFrame:SetVerticalScroll(0) |
tooltip.slider:SetValue(0) |
tooltip:Hide() |
tooltip.registration.tooltip = nil |
tooltip.registration = nil |
overFrame = nil |
end |
end) |
tooltip:SetScript("OnEnter", function(this) |
if tooltip.clickable then |
tooltip.enteredFrame = true |
overFrame = nil |
end |
end) |
tooltip:SetScript("OnLeave", function(this) |
if not tooltip.updating then |
tooltip.enteredFrame = false |
end |
end) |
tooltip:SetScript("OnMouseWheel", function(this, arg1) |
tooltip.updating = true |
tooltip:Scroll(arg1 < 0) |
tooltip.updating = false |
end) |
local scrollFrame = CreateFrame("ScrollFrame", "Tablet20FrameScrollFrame", tooltip) |
scrollFrame:SetFrameLevel(11) |
local scrollChild = CreateFrame("Frame", "Tablet20FrameScrollChild", scrollFrame) |
scrollChild.tablet = tooltip |
scrollFrame:SetScrollChild(scrollChild) |
tooltip.scrollFrame = scrollFrame |
tooltip.scrollChild = scrollChild |
scrollFrame:SetPoint("TOPLEFT", 5, -5) |
scrollFrame:SetPoint("TOPRIGHT", -5, -5) |
scrollFrame:SetPoint("BOTTOMLEFT", 5, 5) |
scrollFrame:SetPoint("BOTTOMRIGHT", -5, 5) |
scrollChild:SetWidth(1) |
scrollChild:SetHeight(1) |
local slider = CreateFrame("Slider", "Tablet20FrameSlider", scrollFrame) |
tooltip.slider = slider |
slider:SetOrientation("VERTICAL") |
slider:SetMinMaxValues(0, 1) |
slider:SetValueStep(0.001) |
slider:SetValue(0) |
slider:SetWidth(8) |
slider:SetPoint("TOPRIGHT", 0, 0) |
slider:SetPoint("BOTTOMRIGHT", 0, 0) |
slider:SetBackdrop(new( |
'bgFile', "Interface\\Buttons\\UI-SliderBar-Background", |
'edgeFile', "Interface\\Buttons\\UI-SliderBar-Border", |
'tile', true, |
'edgeSize', 8, |
'tileSize', 8, |
'insets', new( |
'left', 3, |
'right', 3, |
'top', 3, |
'bottom', 3 |
) |
)) |
slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical") |
slider:SetScript("OnEnter", tooltip:GetScript("OnEnter")) |
slider:SetScript("OnLeave", tooltip:GetScript("OnLeave")) |
slider.tablet = tooltip |
slider:SetScript("OnValueChanged", function(this) |
local max = this.tablet.scrollChild:GetHeight() - this.tablet:GetHeight() |
local val = this:GetValue() * max |
if math.abs(this.tablet.scrollFrame:GetVerticalScroll() - val) < 1 then |
return |
end |
this.tablet.scrollFrame:SetVerticalScroll(val) |
end) |
NewLine(tooltip) |
function tooltip:SetOwner(o) |
self:Hide(o) |
self.owner = o |
end |
tooltip.SetOwner = wrap(tooltip.SetOwner, "tooltip:SetOwner") |
function tooltip:IsOwned(o) |
return self.owner == o |
end |
tooltip.IsOwned = wrap(tooltip.IsOwned, "tooltip:IsOwned") |
function tooltip:ClearLines(hide) |
CleanCategoryPool(self) |
for i = 1, self.numLines do |
local button = self.buttons[i] |
local check = button.check |
if not button.clicked or hide then |
button:Hide() |
end |
check.shown = false |
check:SetAlpha(0) |
end |
self.numLines = 0 |
end |
tooltip.ClearLines = wrap(tooltip.ClearLines, "tooltip:ClearLines") |
function tooltip:NumLines() |
return self.numLines |
end |
local lastWidth |
local old_tooltip_Hide = tooltip.Hide |
tooltip.__Hide = old_tooltip_Hide |
function tooltip:Hide(newOwner) |
if self == tooltip or newOwner == nil then |
old_tooltip_Hide(self) |
end |
self:ClearLines(true) |
self.owner = nil |
self.lastWidth = nil |
self.tmpHidden = nil |
end |
tooltip.Hide = wrap(tooltip.Hide, "tooltip:Hide") |
local old_tooltip_Show = tooltip.Show |
tooltip.__Show = old_tooltip_Show |
function tooltip:Show(tabletData) |
if self.owner == nil or self.notInUse then |
return |
end |
if not self.tmpHidden then |
old_tooltip_Show(self) |
end |
testString = self.buttons[1].col1 |
local maxWidth = tabletData and tabletData.width or self:GetWidth() - 20 |
local hasWrap = false |
local numColumns |
local height = 20 |
self:SetWidth(maxWidth + 20) |
for i = 1, self.numLines do |
local button = self.buttons[i] |
local col1 = button.col1 |
local col2 = button.col2 |
local check = button.check |
button:SetWidth(maxWidth) |
button:SetHeight(col2 and math.max(col1:GetHeight(), col2:GetHeight()) or col1:GetHeight()) |
height = height + button:GetHeight() + 2 |
if i == 1 then |
button:SetPoint("TOPLEFT", self.scrollChild, "TOPLEFT", 5, -5) |
else |
button:SetPoint("TOPLEFT", self.buttons[i - 1], "BOTTOMLEFT", 0, -2) |
end |
if button.clicked then |
check:SetPoint("TOPLEFT", button, "TOPLEFT", button.indentation * self.fontSizePercent + (check.width - check:GetWidth()) / 2 + 1, -1) |
else |
check:SetPoint("TOPLEFT", button, "TOPLEFT", button.indentation * self.fontSizePercent + (check.width - check:GetWidth()) / 2, 0) |
end |
button:Show() |
end |
self.scrollFrame:SetFrameLevel(11) |
self.scrollChild:SetWidth(maxWidth) |
self.scrollChild:SetHeight(height) |
local maxHeight = GetTooltipHeight(self) |
if height > maxHeight then |
height = maxHeight |
self.slider:Show() |
else |
self.slider:Hide() |
end |
self:SetHeight(height) |
self.scrollFrame:SetScrollChild(self.scrollChild) |
local val = self.scrollFrame:GetVerticalScroll() |
local max = self.scrollChild:GetHeight() - self:GetHeight() |
if val > max then |
val = max |
end |
if val < 0 then |
val = 0 |
end |
self.scrollFrame:SetVerticalScroll(val) |
self.slider:SetValue(val/max) |
end |
tooltip.Show = wrap(tooltip.Show, "tooltip:Show") |
function tooltip:AddLine(info) |
local category = info.category.superCategory |
local maxWidth = category.tabletData.width |
local text = info.blank and "\n" or info.text |
local id = info.id |
local func = info.func |
local checked = info.checked |
local isRadio = info.isRadio |
local checkTexture = info.checkTexture |
local fontSizePercent = self.fontSizePercent |
if not info.font then |
info.font = GameTooltipText |
end |
if not info.size then |
info.size = select(2,info.font:GetFont()) |
end |
local catStart = false |
local columns = category and category.columns or 1 |
local x_total = 0 |
local x1, x2 |
if category then |
for i = 1, category.columns do |
x_total = x_total + category['x' .. i] |
end |
x1, x2 = category.x1, category.x2 |
else |
x1, x2 = 0, 0 |
end |
self.numLines = self.numLines + 1 |
NewLine(self) |
local num = self.numLines |
local button = self.buttons[num] |
button:Show() |
button.col1:Show() |
button.indentation = info.indentation |
local col1 = button.col1 |
local check = button.check |
do -- if columns >= 1 then |
col1:SetWidth(0) |
col1:SetFontObject(info.font) |
local font,_,flags = info.font:GetFont() |
col1:SetFont(font, info.size * fontSizePercent, flags) |
col1:SetText(text) |
col1:SetJustifyH(info.justify) |
col1:Show() |
if info.textR and info.textG and info.textB then |
col1:SetTextColor(info.textR, info.textG, info.textB) |
else |
col1:SetTextColor(1, 0.823529, 0) |
end |
if columns < 2 then |
local i = 2 |
while true do |
local col = button['col' .. i] |
if col then |
button['col' .. i] = delstring(col) |
else |
break |
end |
i = i + 1 |
end |
else |
local i = 2 |
while true do |
local col = button['col' .. i] |
if not col then |
button['col' .. i] = newstring(button) |
col = button['col' .. i] |
end |
col:SetFontObject(info['font' .. i]) |
col:SetText(info['text' .. i]) |
col:Show() |
local r,g,b = info['text' .. i .. 'R'] |
if r then |
g = info['text' .. i .. 'G'] |
if g then |
b = info['text' .. i .. 'B'] |
end |
end |
if b then |
col:SetTextColor(r, g, b) |
else |
col:SetTextColor(1, 0.823529, 0) |
end |
local a,_,b = info.font2:GetFont() |
col:SetFont(a, info['size' .. i] * fontSizePercent, b) |
col:SetJustifyH(info['justify' .. i]) |
if columns == i then |
if i == 2 then |
col:SetPoint("TOPLEFT", col1, "TOPRIGHT", 40 * fontSizePercent, 0) |
col:SetPoint("TOPRIGHT", button, "TOPRIGHT", -5, 0) |
else |
local col2 = button.col2 |
col2:ClearAllPoints() |
col2:SetPoint("TOPLEFT", col1, "TOPRIGHT", (20 - info.indentation) * fontSizePercent, 0) |
end |
i = i + 1 |
while true do |
local col = button['col' .. i] |
if col then |
button['col' .. i] = delstring(col) |
else |
break |
end |
i = i + 1 |
end |
break |
end |
i = i + 1 |
end |
end |
end |
check:SetWidth(info.size * fontSizePercent) |
check:SetHeight(info.size * fontSizePercent) |
check.width = info.size * fontSizePercent |
if info.hasCheck then |
check.shown = true |
check:Show() |
if isRadio then |
check:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") |
if info.checked then |
check:SetAlpha(1) |
check:SetTexCoord(0.25, 0.5, 0, 1) |
else |
check:SetAlpha(self.transparency) |
check:SetTexCoord(0, 0.25, 0, 1) |
end |
check:SetVertexColor(1, 1, 1) |
else |
if info.checkIcon then |
check:SetTexture(info.checkIcon) |
check:SetTexCoord(info.checkCoordLeft, info.checkCoordRight, info.checkCoordTop, info.checkCoordBottom) |
check:SetVertexColor(info.checkColorR, info.checkColorG, info.checkColorB) |
else |
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") |
check:SetWidth(info.size * fontSizePercent * 1.5) |
check:SetHeight(info.size * fontSizePercent * 1.5) |
check.width = info.size * fontSizePercent * 1.2 |
check:SetTexCoord(0, 1, 0, 1) |
check:SetVertexColor(1, 1, 1) |
end |
check:SetAlpha(info.checked and 1 or 0) |
end |
col1:SetPoint("TOPLEFT", check, "TOPLEFT", check.width, 0) |
else |
col1:SetPoint("TOPLEFT", check, "TOPLEFT") |
end |
local col2 = button.col2 |
if columns == 1 then |
col1:SetWidth(maxWidth) |
elseif columns == 2 then |
if info.wrap then |
col1:SetWidth(maxWidth - col2:GetWidth() - 40 * fontSizePercent) |
col2:SetWidth(0) |
elseif info.wrap2 then |
col1:SetWidth(0) |
col2:SetWidth(maxWidth - col1:GetWidth() - 40 * fontSizePercent) |
else |
col1:SetWidth(0) |
col2:SetWidth(0) |
end |
col2:ClearAllPoints() |
col2:SetPoint("TOPRIGHT", button, "TOPRIGHT", 0, 0) |
if not info.text2 then |
col1:SetJustifyH(info.justify or "LEFT") |
end |
else |
col1:SetWidth(x1 - info.checkWidth) |
col2:SetWidth(x2) |
local num = (category.tabletData.width - x_total) / (columns - 1) |
col2:SetPoint("TOPLEFT", col1, "TOPRIGHT", num - info.indentation * fontSizePercent, 0) |
local last = col2 |
for i = 3, category.columns do |
local col = button['col' .. i] |
col:SetWidth(category['x' .. i]) |
col:SetPoint("TOPLEFT", last, "TOPRIGHT", num, 0) |
last = col |
end |
end |
button.func = nil |
button.onEnterFunc = nil |
button.onLeaveFunc = nil |
button:SetFrameLevel(12) -- hack suggested on forum. Added 06/17/2007. (hC) |
if not self.locked or IsAltKeyDown() then |
local func = info.func |
if func then |
if type(func) == "string" then |
if type(info.arg1) ~= "table" then |
Tablet:error("Cannot call method " .. info.func .. " on a non-table") |
end |
func = info.arg1[func] |
if type(func) ~= "function" then |
Tablet:error("Method " .. info.func .. " nonexistant") |
end |
else |
if type(func) ~= "function" then |
Tablet:error("func must be a function or method") |
end |
end |
button.func = func |
local i = 1 |
while true do |
local k = 'arg' .. i |
if button[k] ~= nil then |
button[k] = nil |
else |
break |
end |
i = i + 1 |
end |
i = 1 |
while true do |
local k = 'arg' .. i |
local v = info[k] |
if v == nil then |
break |
end |
button[k] = v |
i = i + 1 |
end |
local onEnterFunc = info.onEnterFunc |
if onEnterFunc then |
if type(onEnterFunc) == "string" then |
if type(info.onEnterArg1) ~= "table" then |
Tablet:error("Cannot call method " .. info.onEnterFunc .. " on a non-table") |
end |
onEventFunc = info.onEnterArg1[onEnterFunc] |
if type(onEnterFunc) ~= "function" then |
Tablet:error("Method " .. info.onEnterFunc .. " nonexistant") |
end |
else |
if type(onEnterFunc) ~= "function" then |
Tablet:error("func must be a function or method") |
end |
end |
button.onEnterFunc = onEnterFunc |
local i = 1 |
while true do |
local k = 'onEnterArg' .. i |
if button[k] ~= nil then |
button[k] = nil |
else |
break |
end |
i = i + 1 |
end |
i = 1 |
while true do |
local k = 'onEnterArg' .. i |
local v = info[k] |
if v == nil then |
break |
end |
button[k] = v |
i = i + 1 |
end |
end |
local onLeaveFunc = info.onLeaveFunc |
if onLeaveFunc then |
if type(onLeaveFunc) == "string" then |
if type(info.onLeaveArg1) ~= "table" then |
Tablet:error("Cannot call method " .. info.onLeaveFunc .. " on a non-table") |
end |
onLeaveFunc = info.onLeaveArg1[onLeaveFunc] |
if type(onLeaveFunc) ~= "function" then |
Tablet:error("Method " .. info.onLeaveFunc .. " nonexistant") |
end |
else |
if type(onLeaveFunc) ~= "function" then |
Tablet:error("func must be a function or method") |
end |
end |
button.onLeaveFunc = onLeaveFunc |
local i = 1 |
while true do |
local k = 'onLeaveArg' .. i |
if button[k] ~= nil then |
button[k] = nil |
else |
break |
end |
i = i + 1 |
end |
i = 1 |
while true do |
local k = 'onLeaveArg' .. i |
local v = info[k] |
if v == nil then |
break |
end |
button[k] = v |
i = i + 1 |
end |
end |
button.self = self |
button:SetScript("OnMouseUp", button_OnMouseUp) |
button:SetScript("OnMouseDown", button_OnMouseDown) |
button:RegisterForDrag("LeftButton") |
button:SetScript("OnDragStart", button_OnDragStart) |
button:SetScript("OnDragStop", button_OnDragStop) |
button:SetScript("OnClick", button_OnClick) |
if button.clicked then |
button:SetButtonState("PUSHED") |
end |
button:EnableMouse(true) |
else |
button:SetScript("OnMouseDown", nil) |
button:SetScript("OnMouseUp", nil) |
button:RegisterForDrag() |
button:SetScript("OnDragStart", nil) |
button:SetScript("OnDragStop", nil) |
button:SetScript("OnClick", nil) |
button:EnableMouse(false) |
end |
else |
button:SetScript("OnMouseDown", nil) |
button:SetScript("OnMouseUp", nil) |
button:RegisterForDrag() |
button:SetScript("OnDragStart", nil) |
button:SetScript("OnDragStop", nil) |
button:SetScript("OnClick", nil) |
button:EnableMouse(false) |
end |
end |
tooltip.AddLine = wrap(tooltip.AddLine, "tooltip:AddLine") |
function tooltip:SetFontSizePercent(percent) |
local data, detachedData = self.data, self.detachedData |
if detachedData and detachedData.detached then |
data = detachedData |
end |
local lastSize = self.fontSizePercent |
percent = tonumber(percent) or 1 |
if percent < 0.25 then |
percent = 0.25 |
elseif percent > 4 then |
percent = 4 |
end |
self.fontSizePercent = percent |
if data then |
data.fontSizePercent = percent |
end |
local ratio = self.fontSizePercent / lastSize |
for i = 1, self.numLines do |
local button = self.buttons[i] |
local j = 1 |
while true do |
local col = button['col' .. j] |
if not col then |
break |
end |
local font, size, flags = col:GetFont() |
col:SetFont(font, size * ratio, flags) |
j = j + 1 |
end |
local check = button.check |
check.width = check.width * ratio |
check:SetWidth(check:GetWidth() * ratio) |
check:SetHeight(check:GetHeight() * ratio) |
end |
self:SetWidth((self:GetWidth() - 51) * ratio + 51) |
self:SetHeight((self:GetHeight() - 51) * ratio + 51) |
if self:IsShown() and self.children then |
self:children() |
self:Show() |
end |
end |
tooltip.SetFontSizePercent = wrap(tooltip.SetFontSizePercent, "tooltip:SetFontSizePercent") |
function tooltip:GetFontSizePercent() |
return self.fontSizePercent |
end |
function tooltip:SetTransparency(alpha) |
local data, detachedData = self.data, self.detachedData |
if detachedData and detachedData.detached then |
data = detachedData |
end |
self.transparency = alpha |
if data then |
data.transparency = alpha ~= 0.75 and alpha or nil |
end |
self:SetBackdropColor(self.r or 0, self.g or 0, self.b or 0, alpha) |
self:SetBackdropBorderColor(1, 1, 1, alpha) |
self.slider:SetBackdropColor(self.r or 0, self.g or 0, self.b or 0, alpha) |
self.slider:SetBackdropBorderColor(1, 1, 1, alpha) |
end |
tooltip.SetTransparency = wrap(tooltip.SetTransparency, "tooltip:SetTransparency") |
function tooltip:GetTransparency() |
return self.transparency |
end |
function tooltip:SetColor(r, g, b) |
local data, detachedData = self.data, self.detachedData |
if detachedData and detachedData.detached then |
data = detachedData |
end |
self.r = r |
self.g = g |
self.b = b |
if data then |
data.r = r ~= 0 and r or nil |
data.g = g ~= 0 and g or nil |
data.b = b ~= 0 and b or nil |
end |
self:SetBackdropColor(r or 0, g or 0, b or 0, self.transparency) |
self:SetBackdropBorderColor(1, 1, 1, self.transparency) |
end |
tooltip.SetColor = wrap(tooltip.SetColor, "tooltip:SetColor") |
function tooltip:GetColor() |
return self.r, self.g, self.b |
end |
function tooltip:Scroll(down) |
local val |
local max = self.scrollChild:GetHeight() - self:GetHeight() |
if down then |
if IsShiftKeyDown() then |
val = max |
else |
val = self.scrollFrame:GetVerticalScroll() + 36 |
if val > max then |
val = max |
end |
end |
else |
if IsShiftKeyDown() then |
val = 0 |
else |
val = self.scrollFrame:GetVerticalScroll() - 36 |
if val < 0 then |
val = 0 |
end |
end |
end |
self.scrollFrame:SetVerticalScroll(val) |
self.slider:SetValue(val/max) |
end |
tooltip.Scroll = wrap(tooltip.Scroll, "tooltip:Scroll") |
function tooltip.Detach(tooltip) |
local owner = tooltip.owner |
tooltip:Hide() |
if not tooltip.detachedData then |
self:error("You cannot detach if detachedData is not present") |
end |
tooltip.detachedData.detached = true |
local detached = AcquireDetachedFrame(self, tooltip.registration, tooltip.data, tooltip.detachedData) |
detached.menu, tooltip.menu = tooltip.menu, nil |
detached.runChildren = tooltip.runChildren |
detached.children = tooltip.children |
detached.minWidth = tooltip.minWidth |
tooltip.runChildren = nil |
tooltip.children = nil |
tooltip.minWidth = nil |
detached:SetOwner(owner) |
detached:children() |
detached:Show() |
end |
tooltip.Detach = wrap(tooltip.Detach, "tooltip:Detach") |
end |
tooltip.registration = registration |
registration.tooltip = tooltip |
return tooltip |
end |
AcquireFrame = wrap(AcquireFrame, "AcquireFrame") |
function ReleaseDetachedFrame(self, data, detachedData) |
if not detachedData then |
detachedData = data |
end |
for _, detached in ipairs(detachedTooltips) do |
if detached.detachedData == detachedData then |
detached.notInUse = true |
detached:Hide() |
detached.registration.tooltip = nil |
detached.registration = nil |
detached.detachedData = nil |
end |
end |
end |
ReleaseDetachedFrame = wrap(ReleaseDetachedFrame, "ReleaseDetachedFrame") |
local StartCheckingAlt, StopCheckingAlt |
do |
local frame |
function StartCheckingAlt(func) |
if not frame then |
frame = CreateFrame("Frame") |
frame:SetScript("OnEvent", function(this, _, modifier) |
if modifier == "LALT" or modifier == "RALT" then |
this.func() |
end |
end) |
end |
frame:RegisterEvent("MODIFIER_STATE_CHANGED") |
frame.func = func |
end |
StartCheckingAlt = wrap(StartCheckingAlt, "StartCheckingAlt") |
function StopCheckingAlt() |
if frame then |
frame:UnregisterEvent("MODIFIER_STATE_CHANGED") |
end |
end |
StopCheckingAlt = wrap(StopCheckingAlt, "StopCheckingAlt") |
end |
function AcquireDetachedFrame(self, registration, data, detachedData) |
if not detachedData then |
detachedData = data |
end |
for _, detached in ipairs(detachedTooltips) do |
if detached.notInUse then |
detached.data = data |
detached.detachedData = detachedData |
detached.notInUse = nil |
local fontSizePercent = detachedData.fontSizePercent or 1 |
local transparency = detachedData.transparency or 0.75 |
local r = detachedData.r or 0 |
local g = detachedData.g or 0 |
local b = detachedData.b or 0 |
detached:SetFontSizePercent(fontSizePercent) |
detached:SetTransparency(transparency) |
detached:SetColor(r, g, b) |
detached:ClearAllPoints() |
detached:SetWidth(0) |
detached:SetHeight(0) |
if not registration.strata then |
detached:SetFrameStrata("BACKGROUND") |
end |
if not registration.frameLevel then |
detached:SetFrameLevel(10) |
for _,frame in fake_ipairs(detached:GetChildren()) do |
frame:SetFrameLevel(12) |
end |
end |
detached:SetParent(registration.parent or GetMainFrame()) |
if registration.strata then |
detached:SetFrameStrata(registration.strata) |
end |
if registration.frameLevel then |
detached:SetFrameLevel(registration.frameLevel) |
for _,frame in fake_ipairs(detached:GetChildren()) do |
frame:SetFrameLevel(registration.frameLevel+2) |
end |
end |
detached.height_ = nil |
if registration.positionFunc then |
registration.positionFunc(detached) |
RecalculateTabletHeight(detached) |
else |
detached:SetPoint(detachedData.anchor or "CENTER", GetMainFrame(), detachedData.anchor or "CENTER", detachedData.offsetx or 0, detachedData.offsety or 0) |
end |
detached.registration = registration |
registration.tooltip = detached |
if registration.movable == false then |
detached:RegisterForDrag() |
else |
detached:RegisterForDrag("LeftButton") |
end |
return detached |
end |
end |
if not Dewdrop and AceLibrary:HasInstance("Dewdrop-2.0") then |
Dewdrop = AceLibrary("Dewdrop-2.0") |
end |
StartCheckingAlt(function() |
for _, detached in ipairs(detachedTooltips) do |
if detached:IsShown() and detached.locked then |
detached:EnableMouse(IsAltKeyDown()) |
detached:children() |
if detached.moving then |
local a1 = arg1 |
arg1 = "LeftButton" |
if type(detached:GetScript("OnMouseUp")) == "function" then |
detached:GetScript("OnMouseUp")(detached, arg1) |
end |
arg1 = a1 |
end |
end |
end |
end) |
if not tooltip then |
AcquireFrame(self, {}) |
end |
local detached = CreateFrame("Frame", "Tablet20DetachedFrame" .. (#detachedTooltips + 1), GetMainFrame()) |
detachedTooltips[#detachedTooltips+1] = detached |
detached.notInUse = true |
detached:EnableMouse(not data.locked) |
detached:EnableMouseWheel(true) |
detached:SetMovable(true) |
detached:SetPoint(data.anchor or "CENTER", GetMainFrame(), data.anchor or "CENTER", data.offsetx or 0, data.offsety or 0) |
detached.numLines = 0 |
detached.owner = nil |
detached.fontSizePercent = 1 |
detached.maxLines = 0 |
detached.buttons = {} |
detached.transparency = 0.75 |
detached.r = 0 |
detached.g = 0 |
detached.b = 0 |
detached:SetFrameStrata(registration and registration.strata or "BACKGROUND") |
detached:SetBackdrop(tmp.a( |
'bgFile', "Interface\\Buttons\\WHITE8X8", |
'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", |
'tile', true, |
'tileSize', 16, |
'edgeSize', 16, |
'insets', tmp.b( |
'left', 5, |
'right', 5, |
'top', 5, |
'bottom', 5 |
) |
)) |
detached.locked = detachedData.locked |
detached:EnableMouse(not detached.locked) |
local width = GetScreenWidth() |
local height = GetScreenHeight() |
if registration and registration.movable == false then |
detached:RegisterForDrag() |
else |
detached:RegisterForDrag("LeftButton") |
end |
detached:SetScript("OnDragStart", function(this) |
detached:StartMoving() |
detached.moving = true |
end) |
detached:SetScript("OnDragStop", function(this) |
detached:StopMovingOrSizing() |
detached.moving = nil |
detached:SetClampedToScreen(1) |
detached:SetClampedToScreen(nil) |
local anchor |
local offsetx |
local offsety |
if detached:GetTop() + detached:GetBottom() < height then |
anchor = "BOTTOM" |
offsety = detached:GetBottom() |
if offsety < 0 then |
offsety = 0 |
end |
if offsety < MainMenuBar:GetTop() and MainMenuBar:IsVisible() then |
offsety = MainMenuBar:GetTop() |
end |
local top = 0 |
if FuBar then |
for i = 1, FuBar:GetNumPanels() do |
local panel = FuBar:GetPanel(i) |
if panel:GetAttachPoint() == "BOTTOM" then |
if panel.frame:GetTop() > top then |
top = panel.frame:GetTop() |
break |
end |
end |
end |
end |
if offsety < top then |
offsety = top |
end |
else |
anchor = "TOP" |
offsety = detached:GetTop() - height |
if offsety > 0 then |
offsety = 0 |
end |
local bottom = GetScreenHeight() |
if FuBar then |
for i = 1, FuBar:GetNumPanels() do |
local panel = FuBar:GetPanel(i) |
if panel:GetAttachPoint() == "TOP" then |
if panel.frame:GetBottom() < bottom then |
bottom = panel.frame:GetBottom() |
break |
end |
end |
end |
end |
bottom = bottom - GetScreenHeight() |
if offsety > bottom then |
offsety = bottom |
end |
end |
if detached:GetLeft() + detached:GetRight() < width * 2 / 3 then |
anchor = anchor .. "LEFT" |
offsetx = detached:GetLeft() |
if offsetx < 0 then |
offsetx = 0 |
end |
elseif detached:GetLeft() + detached:GetRight() < width * 4 / 3 then |
if anchor == "" then |
anchor = "CENTER" |
end |
offsetx = (detached:GetLeft() + detached:GetRight() - GetScreenWidth()) / 2 |
else |
anchor = anchor .. "RIGHT" |
offsetx = detached:GetRight() - width |
if offsetx > 0 then |
offsetx = 0 |
end |
end |
detached:ClearAllPoints() |
detached:SetPoint(anchor, GetMainFrame(), anchor, offsetx, offsety) |
local t = detached.detachedData |
if t.anchor ~= anchor or math.abs(t.offsetx - offsetx) > 8 or math.abs(t.offsety - offsety) > 8 then |
detached.preventClick = GetTime() + 0.05 |
end |
t.anchor = anchor |
t.offsetx = offsetx |
t.offsety = offsety |
detached:Show() |
end) |
if Dewdrop then |
Dewdrop:Register(detached, |
'children', function(level, value) |
if not detached.registration then |
return |
end |
if detached.menu then |
if type(detached.menu) == "function" then |
detached.menu(level, value) |
else |
Dewdrop:FeedAceOptionsTable(detached.menu) |
end |
if level == 1 then |
Dewdrop:AddLine() |
end |
end |
if level == 1 then |
if not detached.registration.cantAttach then |
Dewdrop:AddLine( |
'text', DETACH, |
'tooltipTitle', DETACH, |
'tooltipText', DETACH_DESC, |
'checked', true, |
'arg1', detached, |
'func', "Attach", |
'closeWhenClicked', true |
) |
end |
if not detached.registration.positionFunc then |
Dewdrop:AddLine( |
'text', LOCK, |
'tooltipTitle', LOCK, |
'tooltipText', LOCK_DESC, |
'checked', detached:IsLocked(), |
'arg1', detached, |
'func', "Lock", |
'closeWhenClicked', not detached:IsLocked() |
) |
end |
Dewdrop:AddLine( |
'text', COLOR, |
'tooltipTitle', COLOR, |
'tooltipText', COLOR_DESC, |
'hasColorSwatch', true, |
'r', detached.r, |
'g', detached.g, |
'b', detached.b, |
'hasOpacity', true, |
'opacity', detached.transparency, |
'colorFunc', function(r, g, b, a) |
detached:SetColor(r, g, b) |
detached:SetTransparency(a) |
end |
) |
Dewdrop:AddLine( |
'text', SIZE, |
'tooltipTitle', SIZE, |
'tooltipText', SIZE_DESC, |
'hasArrow', true, |
'hasSlider', true, |
'sliderFunc', function(value) |
detached:SetFontSizePercent(value) |
end, |
'sliderMax', 2, |
'sliderMin', 0.5, |
'sliderStep', 0.05, |
'sliderIsPercent', true, |
'sliderValue', detached:GetFontSizePercent() |
) |
Dewdrop:AddLine( |
'text', CLOSE_MENU, |
'tooltipTitle', CLOSE_MENU, |
'tooltipText', CLOSE_MENU_DESC, |
'func', function() |
Dewdrop:Close() |
end |
) |
end |
end, |
'point', function() |
local x, y = detached:GetCenter() |
if x < GetScreenWidth() / 2 then |
if y < GetScreenHeight() / 2 then |
return "BOTTOMLEFT", "BOTTOMRIGHT" |
else |
return "TOPLEFT", "TOPRIGHT" |
end |
else |
if y < GetScreenHeight() / 2 then |
return "BOTTOMRIGHT", "BOTTOMLEFT" |
else |
return "TOPRIGHT", "TOPLEFT" |
end |
end |
end |
) |
end |
local scrollFrame = CreateFrame("ScrollFrame", detached:GetName() .. "ScrollFrame", detached) |
local scrollChild = CreateFrame("Frame", detached:GetName() .. "ScrollChild", scrollFrame) |
scrollFrame:SetFrameLevel(11) |
scrollFrame:SetScrollChild(scrollChild) |
scrollChild.tablet = detached |
detached.scrollFrame = scrollFrame |
detached.scrollChild = scrollChild |
scrollFrame:SetPoint("TOPLEFT", 5, -5) |
scrollFrame:SetPoint("BOTTOMRIGHT", -5, 5) |
scrollChild:SetWidth(1) |
scrollChild:SetHeight(1) |
local slider = CreateFrame("Slider", detached:GetName() .. "Slider", scrollFrame) |
detached.slider = slider |
slider:SetOrientation("VERTICAL") |
slider:SetMinMaxValues(0, 1) |
slider:SetValueStep(0.001) |
slider:SetValue(0) |
slider:SetWidth(8) |
slider:SetPoint("TOPRIGHT", 0, 0) |
slider:SetPoint("BOTTOMRIGHT", 0, 0) |
slider:SetBackdrop(new( |
'bgFile', "Interface\\Buttons\\UI-SliderBar-Background", |
'edgeFile', "Interface\\Buttons\\UI-SliderBar-Border", |
'tile', true, |
'edgeSize', 8, |
'tileSize', 8, |
'insets', new( |
'left', 3, |
'right', 3, |
'top', 3, |
'bottom', 3 |
) |
)) |
slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical") |
slider:SetScript("OnEnter", detached:GetScript("OnEnter")) |
slider:SetScript("OnLeave", detached:GetScript("OnLeave")) |
slider.tablet = detached |
slider:SetScript("OnValueChanged", Tablet20FrameSlider:GetScript("OnValueChanged")) |
NewLine(detached) |
detached:SetScript("OnMouseWheel", function(this, arg1) |
detached:Scroll(arg1 < 0) |
end) |
detached.SetTransparency = tooltip.SetTransparency |
detached.GetTransparency = tooltip.GetTransparency |
detached.SetColor = tooltip.SetColor |
detached.GetColor = tooltip.GetColor |
detached.SetFontSizePercent = tooltip.SetFontSizePercent |
detached.GetFontSizePercent = tooltip.GetFontSizePercent |
detached.SetOwner = tooltip.SetOwner |
detached.IsOwned = tooltip.IsOwned |
detached.ClearLines = tooltip.ClearLines |
detached.NumLines = tooltip.NumLines |
detached.__Hide = detached.Hide |
detached.__Show = detached.Show |
detached.Hide = tooltip.Hide |
detached.Show = tooltip.Show |
local old_IsShown = detached.IsShown |
function detached:IsShown() |
if self.tmpHidden then |
return true |
else |
return old_IsShown(self) |
end |
end |
detached.AddLine = tooltip.AddLine |
detached.Scroll = tooltip.Scroll |
function detached:IsLocked() |
return self.locked |
end |
function detached:Lock() |
self:EnableMouse(self.locked) |
self.locked = not self.locked |
if self.detachedData then |
self.detachedData.locked = self.locked or nil |
end |
self:children() |
end |
function detached.Attach(detached) |
if not detached then |
self:error("Detached tooltip not given.") |
end |
if not detached.AddLine then |
self:error("detached argument not a Tooltip.") |
end |
if not detached.owner then |
self:error("Detached tooltip has no owner.") |
end |
if detached.notInUse then |
self:error("Detached tooltip not in use.") |
end |
detached.menu = nil |
detached.detachedData.detached = nil |
detached:SetOwner(nil) |
detached.notInUse = true |
end |
return AcquireDetachedFrame(self, registration, data, detachedData) |
end |
AcquireDetachedFrame = wrap(AcquireDetachedFrame, "AcquireDetachedFrame") |
function Tablet:Close(parent) |
if not parent then |
if tooltip and tooltip:IsShown() then |
tooltip:Hide() |
tooltip.registration.tooltip = nil |
tooltip.registration = nil |
tooltip.enteredFrame = false |
end |
return |
else |
self:argCheck(parent, 2, "table", "string") |
end |
local info = self.registry[parent] |
if not info then |
self:error("You cannot close a tablet with an unregistered parent frame.") |
end |
local data = info.data |
local detachedData = info.detachedData |
if detachedData and detachedData.detached then |
ReleaseDetachedFrame(self, data, detachedData) |
elseif tooltip and tooltip.data == data then |
tooltip:Hide() |
if tooltip.registration then |
tooltip.registration.tooltip = nil |
tooltip.registration = nil |
end |
end |
if tooltip then tooltip.enteredFrame = false end |
end |
Tablet.Close = wrap(Tablet.Close, "Tablet:Close") |
local function frame_children(self) |
if not self.preventRefresh and self:GetParent() and self:GetParent():IsShown() then |
Tablet.currentFrame = self |
Tablet.currentTabletData = TabletData:new(self) |
Tablet.currentTabletData.minWidth = self.minWidth |
self:ClearLines() |
if self.runChildren then |
self.runChildren() |
end |
Tablet.currentTabletData:Display(Tablet.currentFrame) |
self:Show(Tablet.currentTabletData) |
Tablet.currentTabletData:del() |
Tablet.currentTabletData = nil |
Tablet.currentFrame = nil |
end |
end |
frame_children = wrap(frame_children, "frame_children") |
function Tablet:Open(fakeParent, parent) |
self:argCheck(fakeParent, 2, "table", "string") |
self:argCheck(parent, 3, "nil", "table", "string") |
if not parent then |
parent = fakeParent |
end |
local info = self.registry[parent] |
if not info then |
self:error("You cannot open a tablet with an unregistered parent frame.") |
end |
local detachedData = info.detachedData |
if detachedData then |
for _, detached in ipairs(detachedTooltips) do |
if not detached.notInUse and detached.detachedData == detachedData then |
return |
end |
end |
end |
local data = info.data |
local children = info.children |
if not children then |
return |
end |
local frame = AcquireFrame(self, info, data, detachedData) |
frame.clickable = info.clickable |
frame.menu = info.menu |
frame.runChildren = info.children |
frame.minWidth = info.minWidth |
if not frame.children or not frame.childrenVer or frame.childrenVer < MINOR_VERSION then |
frame.childrenVer = MINOR_VERSION |
frame.children = frame_children |
end |
frame:SetOwner(fakeParent) |
frame:children() |
local point = info.point |
local relativePoint = info.relativePoint |
if type(point) == "function" then |
local b |
point, b = point(fakeParent) |
if b then |
relativePoint = b |
end |
end |
if type(relativePoint) == "function" then |
relativePoint = relativePoint(fakeParent) |
end |
if not point then |
point = "CENTER" |
end |
if not relativePoint then |
relativePoint = point |
end |
frame:ClearAllPoints() |
if type(parent) ~= "string" then |
frame:SetPoint(point, fakeParent, relativePoint) |
end |
local offsetx = 0 |
local offsety = 0 |
frame:SetClampedToScreen(1) |
frame:SetClampedToScreen(nil) |
if frame:GetBottom() and frame:GetLeft() then |
if frame:GetRight() > GetScreenWidth() then |
offsetx = frame:GetRight() - GetScreenWidth() |
elseif frame:GetLeft() < 0 then |
offsetx = -frame:GetLeft() |
end |
local ratio = GetScreenWidth() / GetScreenHeight() |
if ratio >= 2.4 and frame:GetRight() > GetScreenWidth() / 2 and frame:GetLeft() < GetScreenWidth() / 2 then |
if frame:GetCenter() < GetScreenWidth() / 2 then |
offsetx = frame:GetRight() - GetScreenWidth() / 2 |
else |
offsetx = frame:GetLeft() - GetScreenWidth() / 2 |
end |
end |
if frame:GetBottom() < 0 then |
offsety = frame:GetBottom() |
elseif frame:GetTop() and frame:GetTop() > GetScreenHeight() then |
offsety = frame:GetTop() - GetScreenHeight() |
end |
if MainMenuBar:IsVisible() and frame:GetBottom() < MainMenuBar:GetTop() and offsety < frame:GetBottom() - MainMenuBar:GetTop() then |
offsety = frame:GetBottom() - MainMenuBar:GetTop() |
end |
if FuBar then |
local top = 0 |
if FuBar then |
for i = 1, FuBar:GetNumPanels() do |
local panel = FuBar:GetPanel(i) |
if panel:GetAttachPoint() == "BOTTOM" then |
if panel.frame:GetTop() and panel.frame:GetTop() > top then |
top = panel.frame:GetTop() |
break |
end |
end |
end |
end |
if frame:GetBottom() < top and offsety < frame:GetBottom() - top then |
offsety = frame:GetBottom() - top |
end |
local bottom = GetScreenHeight() |
if FuBar then |
for i = 1, FuBar:GetNumPanels() do |
local panel = FuBar:GetPanel(i) |
if panel:GetAttachPoint() == "TOP" then |
if panel.frame:GetBottom() and panel.frame:GetBottom() < bottom then |
bottom = panel.frame:GetBottom() |
break |
end |
end |
end |
end |
if frame:GetTop() > bottom and offsety < frame:GetTop() - bottom then |
offsety = frame:GetTop() - bottom |
end |
end |
end |
if type(fakeParent) ~= "string" then |
frame:SetPoint(point, fakeParent, relativePoint, -offsetx, -offsety) |
end |
if detachedData and (info.cantAttach or detachedData.detached) and frame == tooltip then |
detachedData.detached = false |
frame:Detach() |
end |
if (not detachedData or not detachedData.detached) and GetMouseFocus() == fakeParent then |
self.tooltip.enteredFrame = true |
end |
overFrame = type(fakeParent) == "table" and MouseIsOver(fakeParent) and fakeParent |
end |
Tablet.Open = wrap(Tablet.Open, "Tablet:Open") |
function Tablet:Register(parent, ...) |
self:argCheck(parent, 2, "table", "string") |
if self.registry[parent] then |
self:Unregister(parent) |
end |
local info |
local k1 = ... |
if type(k1) == "table" and k1[0] then |
if type(self.registry[k1]) ~= "table" then |
self:error("Other parent not registered") |
end |
info = copy(self.registry[k1]) |
local v1 = select(2, ...) |
if type(v1) == "function" then |
info.point = v1 |
info.relativePoint = nil |
end |
else |
info = new(...) |
end |
self.registry[parent] = info |
info.data = info.data or info.detachedData or new() |
info.detachedData = info.detachedData or info.data |
local data = info.data |
local detachedData = info.detachedData |
if not self.onceRegistered[parent] and type(parent) == "table" and type(parent.SetScript) == "function" and not info.dontHook then |
if not Dewdrop and AceLibrary:HasInstance("Dewdrop-2.0") then |
Dewdrop = AceLibrary("Dewdrop-2.0") |
end |
local script = parent:GetScript("OnEnter") |
parent:SetScript("OnEnter", function(...) |
if script then |
script(...) |
end |
if self.registry[parent] then |
if (not data or not detachedData.detached) and (Dewdrop and not Dewdrop:IsOpen(parent)) then |
self:Open(parent) |
end |
end |
end) |
if parent:HasScript("OnMouseDown") then |
local script = parent:GetScript("OnMouseDown") |
parent:SetScript("OnMouseDown", function(...) |
if script then |
script(...) |
end |
if self.registry[parent] and self.registry[parent].tooltip and self.registry[parent].tooltip == self.tooltip then |
self.tooltip:Hide() |
end |
end) |
end |
if parent:HasScript("OnMouseWheel") then |
local script = parent:GetScript("OnMouseWheel") |
parent:SetScript("OnMouseWheel", function(...) |
if script then |
script(...) |
end |
if self.registry[parent] and self.registry[parent].tooltip then |
self.registry[parent].tooltip:Scroll(arg1 < 0) |
end |
end) |
end |
end |
self.onceRegistered[parent] = true |
if GetMouseFocus() == parent then |
self:Open(parent) |
end |
end |
Tablet.Register = wrap(Tablet.Register, "Tablet:Register") |
function Tablet:Unregister(parent) |
self:argCheck(parent, 2, "table", "string") |
if not self.registry[parent] then |
self:error("You cannot unregister a parent frame if it has not been registered already.") |
end |
self.registry[parent] = nil |
end |
Tablet.Unregister = wrap(Tablet.Unregister, "Tablet:Unregister") |
function Tablet:IsRegistered(parent) |
self:argCheck(parent, 2, "table", "string") |
return self.registry[parent] and true |
end |
Tablet.IsRegistered = wrap(Tablet.IsRegistered, "Tablet:IsRegistered") |
local _id = 0 |
local addedCategory |
local depth = 0 |
local categoryPool = {} |
function CleanCategoryPool(self) |
for k,v in pairs(categoryPool) do |
del(v) |
categoryPool[k] = nil |
end |
_id = 0 |
end |
CleanCategoryPool = wrap(CleanCategoryPool, "CleanCategoryPool") |
function Tablet:AddCategory(...) |
if not self.currentFrame then |
self:error("You must add categories in within a registration.") |
end |
local info = new(...) |
local cat = self.currentTabletData:AddCategory(info) |
info = del(info) |
return cat |
end |
Tablet.AddCategory = wrap(Tablet.AddCategory, "Tablet:AddCategory") |
function Tablet:SetHint(text) |
if not self.currentFrame then |
self:error("You must set hint within a registration.") |
end |
self.currentTabletData:SetHint(text) |
end |
Tablet.SetHint = wrap(Tablet.SetHint, "Tablet:SetHint") |
function Tablet:SetTitle(text) |
if not self.currentFrame then |
self:error("You must set title within a registration.") |
end |
self.currentTabletData:SetTitle(text) |
end |
Tablet.SetTitle = wrap(Tablet.SetTitle, "Tablet:SetTitle") |
function Tablet:SetTitleColor(r, g, b) |
if not self.currentFrame then |
self:error("You must set title color within a registration.") |
end |
self:argCheck(r, 2, "number") |
self:argCheck(g, 3, "number") |
self:argCheck(b, 4, "number") |
self.currentTabletData:SetTitleColor(r, g, b) |
end |
Tablet.SetTitleColor = wrap(Tablet.SetTitleColor, "Tablet:SetTitleColor") |
function Tablet:GetNormalFontSize() |
return normalSize |
end |
Tablet.GetNormalFontSize = wrap(Tablet.GetNormalFontSize, "Tablet:GetNormalFontSize") |
function Tablet:GetHeaderFontSize() |
return headerSize |
end |
Tablet.GetHeaderFontSize = wrap(Tablet.GetHeaderFontSize, "Tablet:GetHeaderFontSize") |
function Tablet:GetNormalFontObject() |
return GameTooltipText |
end |
Tablet.GetNormalFontObject = wrap(Tablet.GetNormalFontObject, "Tablet:GetNormalFontObject") |
function Tablet:GetHeaderFontObject() |
return GameTooltipHeaderText |
end |
Tablet.GetHeaderFontObject = wrap(Tablet.GetHeaderFontObject, "Tablet:GetHeaderFontObject") |
function Tablet:SetFontSizePercent(parent, percent) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if info then |
if info.tooltip then |
info.tooltip:SetFontSizePercent(percent) |
else |
local data = info.data |
local detachedData = info.detachedData |
if detachedData.detached then |
detachedData.fontSizePercent = percent |
else |
data.fontSizePercent = percent |
end |
end |
elseif type(parent) == "table" then |
parent.fontSizePercent = percent |
else |
self:error("You cannot change font size with an unregistered parent frame.") |
end |
end |
Tablet.SetFontSizePercent = wrap(Tablet.SetFontSizePercent, "Tablet:SetFontSizePercent") |
function Tablet:GetFontSizePercent(parent) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if info then |
local data = info.data |
local detachedData = info.detachedData |
if detachedData.detached then |
return detachedData.fontSizePercent or 1 |
else |
return data.fontSizePercent or 1 |
end |
elseif type(parent) == "table" then |
return parent.fontSizePercent or 1 |
else |
self:error("You cannot check font size with an unregistered parent frame.") |
end |
end |
Tablet.GetFontSizePercent = wrap(Tablet.GetFontSizePercent, "Tablet:GetFontSizePercent") |
function Tablet:SetTransparency(parent, percent) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if info then |
if info.tooltip then |
info.tooltip:SetTransparency(percent) |
else |
local data = info.data |
local detachedData = info.detachedData |
if detachedData.detached then |
detachedData.transparency = percent |
elseif data then |
data.transparency = percent |
end |
end |
elseif type(parent) == "table" then |
parent.transparency = percent |
else |
self:error("You cannot change transparency with an unregistered parent frame.") |
end |
end |
Tablet.SetTransparency = wrap(Tablet.SetTransparency, "Tablet:SetTransparency") |
function Tablet:GetTransparency(parent) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if info then |
local data = info.data |
local detachedData = info.detachedData |
if detachedData.detached then |
return detachedData.transparency or 0.75 |
else |
return data.transparency or 0.75 |
end |
elseif type(parent) == "table" then |
return parent.transparency or 0.75 |
else |
self:error("You cannot get transparency with an unregistered parent frame.") |
end |
end |
Tablet.GetTransparency = wrap(Tablet.GetTransparency, "Tablet:GetTransparency") |
function Tablet:SetColor(parent, r, g, b) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if info then |
if info.tooltip then |
info.tooltip:SetColor(r, g, b) |
else |
local data = info.data |
local detachedData = info.detachedData |
if detachedData.detached then |
detachedData.r = r |
detachedData.g = g |
detachedData.b = b |
else |
data.r = r |
data.g = g |
data.b = b |
end |
end |
elseif type(parent) == "table" then |
parent.r = r |
parent.g = g |
parent.b = b |
else |
self:error("You cannot change color with an unregistered parent frame.") |
end |
end |
Tablet.SetColor = wrap(Tablet.SetColor, "Tablet:SetColor") |
function Tablet:GetColor(parent) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if info then |
local data = info.data |
local detachedData = info.detachedData |
if detachedData.detached then |
return detachedData.r or 0, detachedData.g or 0, detachedData.b or 0 |
else |
return data.r or 0, data.g or 0, data.b or 0 |
end |
elseif type(parent) == "table" then |
return parent.r or 0, parent.g or 0, parent.b or 0 |
else |
self:error("You must provide a registered parent frame to check color") |
end |
end |
Tablet.GetColor = wrap(Tablet.GetColor, "Tablet:GetColor") |
function Tablet:Detach(parent) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if not info then |
self:error("You cannot detach tablet with an unregistered parent frame.") |
end |
if not info.detachedData then |
self:error("You cannot detach tablet without a data field.") |
end |
if info.tooltip and info.tooltip == tooltip and tooltip.registration then |
tooltip:Detach() |
else |
info.detachedData.detached = true |
local detached = AcquireDetachedFrame(self, info, info.data, info.detachedData) |
detached.menu = info.menu |
detached.runChildren = info.children |
detached.minWidth = info.minWidth |
if not detached.children or not detached.childrenVer or detached.childrenVer < MINOR_VERSION then |
detached.childrenVer = MINOR_VERSION |
detached.children = frame_children |
end |
detached:SetOwner(parent) |
detached:children() |
end |
end |
Tablet.Detach = wrap(Tablet.Detach, "Tablet:Detach") |
function Tablet:Attach(parent) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if not info then |
self:error("You cannot detach tablet with an unregistered parent frame.") |
end |
if not info.detachedData then |
self:error("You cannot attach tablet without a data field.") |
end |
if info.tooltip and info.tooltip ~= tooltip then |
info.tooltip:Attach() |
else |
info.detachedData.detached = false |
end |
end |
Tablet.Attach = wrap(Tablet.Attach, "Tablet:Attach") |
function Tablet:IsAttached(parent) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if not info then |
self:error("You cannot check tablet with an unregistered parent frame.") |
end |
return not info.detachedData or not info.detachedData.detached |
end |
Tablet.IsAttached = wrap(Tablet.IsAttached, "Tablet:IsAttached") |
function Tablet:Refresh(parent) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if not info then |
self:error("You cannot refresh tablet with an unregistered parent frame.") |
end |
local tt = info.tooltip |
if tt and not tt.preventRefresh and tt:IsShown() then |
tt.updating = true |
tt:children() |
tt.updating = false |
end |
end |
Tablet.Refresh = wrap(Tablet.Refresh, "Tablet:Refresh") |
function Tablet:IsLocked(parent) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if not info then |
self:error("You cannot check tablet with an unregistered parent frame.") |
end |
return info.detachedData and info.detachedData.locked |
end |
Tablet.IsLocked = wrap(Tablet.IsLocked, "Tablet:IsLocked") |
function Tablet:ToggleLocked(parent) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if not info then |
self:error("You cannot lock tablet with an unregistered parent frame.") |
end |
if info.tooltip and info.tooltip ~= tooltip then |
info.tooltip:Lock() |
elseif info.detachedData then |
info.detachedData.locked = info.detachedData.locked |
end |
end |
Tablet.ToggleLocked = wrap(Tablet.ToggleLocked, "Tablet:ToggleLocked") |
function Tablet:UpdateDetachedData(parent, detachedData) |
self:argCheck(parent, 2, "table", "string") |
local info = self.registry[parent] |
if not info then |
self:error("You cannot update tablet with an unregistered parent frame.") |
end |
self:argCheck(detachedData, 3, "table") |
if info.data == info.detachedData then |
info.data = detachedData |
end |
info.detachedData = detachedData |
if info.detachedData.detached then |
self:Detach(parent) |
elseif info.tooltip and info.tooltip.owner then |
self:Attach(parent) |
end |
end |
Tablet.UpdateDetachedData = wrap(Tablet.UpdateDetachedData, "Tablet:UpdateDetachedData") |
if DEBUG then |
function Tablet:ListProfileInfo() |
local duration, times, memories = GetProfileInfo() |
if not duration or not time or not memories then |
self:error("Problems") |
end |
local t = new() |
for method in pairs(memories) do |
t[#t+1] = method |
end |
table.sort(t, function(alpha, bravo) |
if memories[alpha] ~= memories[bravo] then |
return memories[alpha] < memories[bravo] |
elseif times[alpha] ~= times[bravo] then |
return times[alpha] < times[bravo] |
else |
return alpha < bravo |
end |
end) |
local memory = 0 |
local time = 0 |
for _,method in ipairs(t) do |
DEFAULT_CHAT_FRAME:AddMessage(format("%s || %.3f s || %.3f%% || %d KiB", method, times[method], times[method] / duration * 100, memories[method])) |
memory = memory + memories[method] |
time = time + times[method] |
end |
DEFAULT_CHAT_FRAME:AddMessage(format("%s || %.3f s || %.3f%% || %d KiB", "Total", time, time / duration * 100, memory)) |
del(t) |
end |
SLASH_TABLET1 = "/tablet" |
SLASH_TABLET2 = "/tabletlib" |
SlashCmdList["TABLET"] = function(msg) |
AceLibrary(MAJOR_VERSION):ListProfileInfo() |
end |
end |
local function activate(self, oldLib, oldDeactivate) |
Tablet = self |
if oldLib then |
self.registry = oldLib.registry |
self.onceRegistered = oldLib.onceRegistered |
self.tooltip = oldLib.tooltip |
self.currentFrame = oldLib.currentFrame |
self.currentTabletData = oldLib.currentTabletData |
else |
self.registry = {} |
self.onceRegistered = {} |
end |
tooltip = self.tooltip |
if oldDeactivate then |
oldDeactivate(oldLib) |
end |
end |
local function deactivate(self) |
StopCheckingAlt() |
end |
AceLibrary:Register(Tablet, MAJOR_VERSION, MINOR_VERSION, activate, deactivate) |
--[[ |
Name: AceConsole-2.0 |
Revision: $Rev$ |
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) |
Inspired By: Ace 1.x by Turan (turan@gryphon.com) |
Website: http://www.wowace.com/ |
Documentation: http://www.wowace.com/index.php/AceConsole-2.0 |
SVN: http://svn.wowace.com/wowace/trunk/Ace2/AceConsole-2.0 |
Description: Mixin to allow for input/output capabilities. This uses the |
AceOptions data table format to determine input. |
http://www.wowace.com/index.php/AceOptions_data_table |
Dependencies: AceLibrary, AceOO-2.0 |
License: LGPL v2.1 |
]] |
local MAJOR_VERSION = "AceConsole-2.0" |
local MINOR_VERSION = "$Revision$" |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0.") end |
-- #AUTODOC_NAMESPACE AceConsole |
local MAP_ONOFF, USAGE, IS_CURRENTLY_SET_TO, IS_NOW_SET_TO, IS_NOT_A_VALID_OPTION_FOR, IS_NOT_A_VALID_VALUE_FOR, NO_OPTIONS_AVAILABLE, OPTION_HANDLER_NOT_FOUND, OPTION_HANDLER_NOT_VALID, OPTION_IS_DISABLED, KEYBINDING_USAGE, DEFAULT_CONFIRM_MESSAGE |
if GetLocale() == "deDE" then |
MAP_ONOFF = { [false] = "|cffff0000Aus|r", [true] = "|cff00ff00An|r" } |
USAGE = "Benutzung" |
IS_CURRENTLY_SET_TO = "|cffffff7f%s|r steht momentan auf |cffffff7f[|r%s|cffffff7f]|r" |
IS_NOW_SET_TO = "|cffffff7f%s|r ist nun auf |cffffff7f[|r%s|cffffff7f]|r gesetzt" |
IS_NOT_A_VALID_OPTION_FOR = "[|cffffff7f%s|r] ist keine g\195\188ltige Option f\195\188r |cffffff7f%s|r" |
IS_NOT_A_VALID_VALUE_FOR = "[|cffffff7f%s|r] ist kein g\195\188ltiger Wert f\195\188r |cffffff7f%s|r" |
NO_OPTIONS_AVAILABLE = "Keine Optionen verfügbar" |
OPTION_HANDLER_NOT_FOUND = "Optionen handler |cffffff7f%q|r nicht gefunden." |
OPTION_HANDLER_NOT_VALID = "Optionen handler nicht g\195\188ltig." |
OPTION_IS_DISABLED = "Option |cffffff7f%s|r deaktiviert." |
KEYBINDING_USAGE = "<ALT-CTRL-SHIFT-KEY>" -- fix |
DEFAULT_CONFIRM_MESSAGE = "Are you sure you want to perform `%s'?" -- fix |
elseif GetLocale() == "frFR" then |
MAP_ONOFF = { [false] = "|cffff0000Inactif|r", [true] = "|cff00ff00Actif|r" } |
USAGE = "Utilisation" |
IS_CURRENTLY_SET_TO = "|cffffff7f%s|r est actuellement positionn\195\169 sur |cffffff7f[|r%s|cffffff7f]|r" |
IS_NOW_SET_TO = "|cffffff7f%s|r est maintenant positionn\195\169 sur |cffffff7f[|r%s|cffffff7f]|r" |
IS_NOT_A_VALID_OPTION_FOR = "[|cffffff7f%s|r] n'est pas une option valide pour |cffffff7f%s|r" |
IS_NOT_A_VALID_VALUE_FOR = "[|cffffff7f%s|r] n'est pas une valeur valide pour |cffffff7f%s|r" |
NO_OPTIONS_AVAILABLE = "Pas d'options disponibles" |
OPTION_HANDLER_NOT_FOUND = "Le gestionnaire d'option |cffffff7f%q|r n'a pas \195\169t\195\169 trouv\195\169." |
OPTION_HANDLER_NOT_VALID = "Le gestionnaire d'option n'est pas valide." |
OPTION_IS_DISABLED = "L'option |cffffff7f%s|r est d\195\169sactiv\195\169e." |
KEYBINDING_USAGE = "<ALT-CTRL-SHIFT-KEY>" -- fix |
DEFAULT_CONFIRM_MESSAGE = "Are you sure you want to perform `%s'?" -- fix |
elseif GetLocale() == "koKR" then |
MAP_ONOFF = { [false] = "|cffff0000ë|r", [true] = "|cff00ff00켬|r" } |
USAGE = "ì¬ì©ë²" |
IS_CURRENTLY_SET_TO = "|cffffff7f%s|r|1ì;ë; íì¬ ìíë |cffffff7f[|r%s|cffffff7f]|r|1ì¼ë¡;ë¡; ì¤ì ëì´ ììµëë¤." |
IS_NOW_SET_TO = "|cffffff7f%s|r|1ì;를; |cffffff7f[|r%s|cffffff7f]|r ìíë¡ ë³ê²½í©ëë¤." |
IS_NOT_A_VALID_OPTION_FOR = "[|cffffff7f%s|r]|1ì;ë; |cffffff7f%s|rìì ì¬ì© ë¶ê°ë¥í ì¤ì ì ëë¤." |
IS_NOT_A_VALID_VALUE_FOR = "[|cffffff7f%s|r]|1ì;ë; |cffffff7f%s|rìì ì¬ì© ë¶ê°ë¥í ì¤ì ê°ì ëë¤." |
NO_OPTIONS_AVAILABLE = "ê°ë¥í ì¤ì ì´ ììµëë¤." |
OPTION_HANDLER_NOT_FOUND = "ì¤ì ì¡°ì ê°ì¸ |cffffff7f%q|r|1ì;를; ì°¾ì§ ëª»íìµëë¤." |
OPTION_HANDLER_NOT_VALID = "ì¤ì ì¡°ì ê°ì´ ì¬ë°ë¥´ì§ ììµëë¤." |
OPTION_IS_DISABLED = "|cffffff7f%s|r ì¤ì ì ì¬ì©í ì ììµëë¤." |
KEYBINDING_USAGE = "<ALT-CTRL-SHIFT-KEY>" |
DEFAULT_CONFIRM_MESSAGE = "ì ë§ ë¹ì ì `%s'|1ì;를; íìê² ìµëê¹?" |
elseif GetLocale() == "zhCN" then |
MAP_ONOFF = { [false] = "|cffff0000\229\133\179\233\151\173|r", [true] = "|cff00ff00\229\188\128\229\144\175|r" } |
USAGE = "\231\148\168\230\179\149" |
IS_CURRENTLY_SET_TO = "|cffffff7f%s|r \229\189\147\229\137\141\232\162\171\232\174\190\231\189\174 |cffffff7f[|r%s|cffffff7f]|r" |
IS_NOW_SET_TO = "|cffffff7f%s|r \231\142\176\229\156\168\232\162\171\232\174\190\231\189\174\228\184\186 |cffffff7f[|r%s|cffffff7f]|r" |
IS_NOT_A_VALID_OPTION_FOR = "[|cffffff7f%s|r] \228\184\141\230\152\175\228\184\128\228\184\170\230\156\137\230\149\136\231\154\132\233\128\137\233\161\185 \228\184\186 |cffffff7f%s|r" |
IS_NOT_A_VALID_VALUE_FOR = "[|cffffff7f%s|r] \228\184\141\230\152\175\228\184\128\228\184\170\230\156\137\230\149\136\229\128\188 \228\184\186 |cffffff7f%s|r" |
NO_OPTIONS_AVAILABLE = "\230\178\161\230\156\137\233\128\137\233\161\185\229\143\175\231\148\168" |
OPTION_HANDLER_NOT_FOUND = "\233\128\137\233\161\185\229\164\132\231\144\134\231\168\139\229\186\143 |cffffff7f%q|r \230\178\161\230\159\165\230\137\190." |
OPTION_HANDLER_NOT_VALID = "\233\128\137\233\161\185\229\164\132\231\144\134\231\168\139\229\186\143 \230\151\160\230\149\136." |
OPTION_IS_DISABLED = "\233\128\137\233\161\185 |cffffff7f%s|r \228\184\141\229\174\140\230\149\180." |
KEYBINDING_USAGE = "<ALT-CTRL-SHIFT-KEY>" -- fix |
DEFAULT_CONFIRM_MESSAGE = "Are you sure you want to perform `%s'?" -- fix |
elseif GetLocale() == "zhTW" then |
MAP_ONOFF = { [false] = "|cffff0000éé|r", [true] = "|cff00ff00éå|r" } |
USAGE = "ç¨æ³" |
IS_CURRENTLY_SET_TO = "|cffffff7f%s|rç®åçè¨å®çº|cffffff7f[|r%s|cffffff7f]|r" |
IS_NOW_SET_TO = "|cffffff7f%s|rç¾å¨è¢«è¨å®çº|cffffff7f[|r%s|cffffff7f]|r" |
IS_NOT_A_VALID_OPTION_FOR = "å°æ¼|cffffff7f%2$s|rï¼[|cffffff7f%1$s|r]æ¯ä¸åä¸ç¬¦åè¦å®çé¸é " |
IS_NOT_A_VALID_VALUE_FOR = "å°æ¼|cffffff7f%2$s|rï¼[|cffffff7f%1$s|r]æ¯ä¸åä¸ç¬¦åè¦å®çæ¸å¼" |
NO_OPTIONS_AVAILABLE = "æ²æå¯ç¨çé¸é " |
OPTION_HANDLER_NOT_FOUND = "æ¾ä¸å°|cffffff7f%q|ré¸é èçå¨ã" |
OPTION_HANDLER_NOT_VALID = "é¸é èçå¨ä¸ç¬¦åè¦å®ã" |
OPTION_IS_DISABLED = "|cffffff7f%s|r已被åç¨ã" |
KEYBINDING_USAGE = "<Alt-Ctrl-Shift-éµ>" |
DEFAULT_CONFIRM_MESSAGE = "æ¯å¦å·è¡ã%sã?" |
elseif GetLocale() == "esES" then |
MAP_ONOFF = { [false] = "|cffff0000Desactivado|r", [true] = "|cff00ff00Activado|r" } |
USAGE = "Uso" |
IS_CURRENTLY_SET_TO = "|cffffff7f%s|r est\195\161 establecido actualmente a |cffffff7f[|r%s|cffffff7f]|r" |
IS_NOW_SET_TO = "|cffffff7f%s|r se ha establecido a |cffffff7f[|r%s|cffffff7f]|r" |
IS_NOT_A_VALID_OPTION_FOR = "[|cffffff7f%s|r] no es una opci\195\179n valida para |cffffff7f%s|r" |
IS_NOT_A_VALID_VALUE_FOR = "[|cffffff7f%s|r] no es un valor v\195\161lido para |cffffff7f%s|r" |
NO_OPTIONS_AVAILABLE = "No hay opciones disponibles" |
OPTION_HANDLER_NOT_FOUND = "Gestor de opciones |cffffff7f%q|r no encontrado." |
OPTION_HANDLER_NOT_VALID = "Gestor de opciones no v\195\161lido." |
OPTION_IS_DISABLED = "La opci\195\179n |cffffff7f%s|r est\195\161 desactivada." |
KEYBINDING_USAGE = "<ALT-CTRL-SHIFT-KEY>" |
DEFAULT_CONFIRM_MESSAGE = "Are you sure you want to perform `%s'?" -- fix |
else -- enUS |
MAP_ONOFF = { [false] = "|cffff0000Off|r", [true] = "|cff00ff00On|r" } |
USAGE = "Usage" |
IS_CURRENTLY_SET_TO = "|cffffff7f%s|r is currently set to |cffffff7f[|r%s|cffffff7f]|r" |
IS_NOW_SET_TO = "|cffffff7f%s|r is now set to |cffffff7f[|r%s|cffffff7f]|r" |
IS_NOT_A_VALID_OPTION_FOR = "[|cffffff7f%s|r] is not a valid option for |cffffff7f%s|r" |
IS_NOT_A_VALID_VALUE_FOR = "[|cffffff7f%s|r] is not a valid value for |cffffff7f%s|r" |
NO_OPTIONS_AVAILABLE = "No options available" |
OPTION_HANDLER_NOT_FOUND = "Option handler |cffffff7f%q|r not found." |
OPTION_HANDLER_NOT_VALID = "Option handler not valid." |
OPTION_IS_DISABLED = "Option |cffffff7f%s|r is disabled." |
KEYBINDING_USAGE = "<ALT-CTRL-SHIFT-KEY>" |
DEFAULT_CONFIRM_MESSAGE = "Are you sure you want to perform `%s'?" |
end |
local NONE = NONE or "None" |
local AceOO = AceLibrary("AceOO-2.0") |
local AceEvent |
local AceConsole = AceOO.Mixin { "Print", "PrintComma", "PrintLiteral", "CustomPrint", "RegisterChatCommand" } |
local Dewdrop |
local _G = getfenv(0) |
local function print(text, name, r, g, b, frame, delay) |
if not text or text:len() == 0 then |
text = " " |
end |
if not name or name == AceConsole then |
else |
text = "|cffffff78" .. tostring(name) .. ":|r " .. text |
end |
local last_color |
for t in text:gmatch("[^\n]+") do |
(frame or DEFAULT_CHAT_FRAME):AddMessage(last_color and "|cff" .. last_color .. t or t, r, g, b, nil, delay or 5) |
if not last_color or t:find("|r") or t:find("|c") then |
last_color = t:match(".*|c[fF][fF](%x%x%x%x%x%x)[^|]-$") |
end |
end |
return text |
end |
local real_tostring = tostring |
local function tostring(t) |
if type(t) == "table" then |
if type(rawget(t, 0)) == "userdata" and type(t.GetObjectType) == "function" then |
return ("<%s:%s>"):format(t:GetObjectType(), t:GetName() or "(anon)") |
end |
end |
return real_tostring(t) |
end |
local getkeystring |
local function isList(t) |
local n = #t |
for k,v in pairs(t) do |
if type(k) ~= "number" then |
return false |
elseif k < 1 or k > n then |
return false |
end |
end |
return true |
end |
local findGlobal = setmetatable({}, {__index=function(self, t) |
for k,v in pairs(_G) do |
if v == t then |
k = tostring(k) |
self[v] = k |
return k |
end |
end |
self[t] = false |
return false |
end}) |
local recurse = {} |
local timeToEnd |
local GetTime = GetTime |
local type = type |
local new, del |
do |
local cache = setmetatable({},{__mode='k'}) |
function new() |
local t = next(cache) |
if t then |
cache[t] = nil |
return t |
else |
return {} |
end |
end |
function del(t) |
for k in pairs(t) do |
t[k] = nil |
end |
cache[t] = true |
return nil |
end |
end |
local function ignoreCaseSort(alpha, bravo) |
if not alpha or not bravo then |
return false |
end |
return tostring(alpha):lower() < tostring(bravo):lower() |
end |
local function specialSort(alpha, bravo) |
if alpha == nil or bravo == nil then |
return false |
end |
local type_alpha, type_bravo = type(alpha), type(bravo) |
if type_alpha ~= type_bravo then |
return type_alpha < type_bravo |
end |
if type_alpha == "string" then |
return alpha:lower() < bravo:lower() |
elseif type_alpha == "number" then |
return alpha < bravo |
elseif type_alpha == "table" then |
return #alpha < #bravo |
elseif type_alpha == "boolean" then |
return not alpha |
else |
return false |
end |
end |
local function escapeChar(c) |
return ("\\%03d"):format(c:byte()) |
end |
local function literal_tostring_prime(t, depth) |
if type(t) == "string" then |
return ("|cff00ff00%q|r"):format((t:gsub("|", "||"))):gsub("[\001-\012\014-\031\128-\255]", escapeChar) |
elseif type(t) == "table" then |
if t == _G then |
return "|cffffea00_G|r" |
end |
if type(rawget(t, 0)) == "userdata" and type(t.GetObjectType) == "function" then |
return ("|cffffea00<%s:%s>|r"):format(t:GetObjectType(), t:GetName() or "(anon)") |
end |
if next(t) == nil then |
local mt = getmetatable(t) |
if type(mt) == "table" and type(mt.__raw) == "table" then |
t = mt.__raw |
end |
end |
if recurse[t] then |
local g = findGlobal[t] |
if g then |
return ("|cff9f9f9f<Recursion _G[%q]>|r"):format(g) |
else |
return ("|cff9f9f9f<Recursion %s>|r"):format(real_tostring(t):gsub("|", "||")) |
end |
elseif GetTime() > timeToEnd then |
local g = findGlobal[t] |
if g then |
return ("|cff9f9f9f<Timeout _G[%q]>|r"):format(g) |
else |
return ("|cff9f9f9f<Timeout %s>|r"):format(real_tostring(t):gsub("|", "||")) |
end |
elseif depth >= 2 then |
local g = findGlobal[t] |
if g then |
return ("|cff9f9f9f<_G[%q]>|r"):format(g) |
else |
return ("|cff9f9f9f<%s>|r"):format(real_tostring(t):gsub("|", "||")) |
end |
end |
recurse[t] = true |
if next(t) == nil then |
return "{}" |
elseif next(t, (next(t))) == nil then |
local k, v = next(t) |
if k == 1 then |
return "{ " .. literal_tostring_prime(v, depth+1) .. " }" |
else |
return "{ " .. getkeystring(k, depth+1) .. " = " .. literal_tostring_prime(v, depth+1) .. " }" |
end |
end |
local s |
local g = findGlobal[t] |
if g then |
s = ("{ |cff9f9f9f-- _G[%q]|r\n"):format(g) |
else |
s = "{ |cff9f9f9f-- " .. real_tostring(t):gsub("|", "||") .. "|r\n" |
end |
if isList(t) then |
for i = 1, #t do |
s = s .. (" "):rep(depth+1) .. literal_tostring_prime(t[i], depth+1) .. (i == #t and "\n" or ",\n") |
end |
else |
local tmp = new() |
for k in pairs(t) do |
tmp[#tmp+1] = k |
end |
table.sort(tmp, specialSort) |
for i,k in ipairs(tmp) do |
tmp[i] = nil |
local v = t[k] |
s = s .. (" "):rep(depth+1) .. getkeystring(k, depth+1) .. " = " .. literal_tostring_prime(v, depth+1) .. (tmp[i+1] == nil and "\n" or ",\n") |
end |
tmp = del(tmp) |
end |
if g then |
s = s .. (" "):rep(depth) .. string.format("} |cff9f9f9f-- _G[%q]|r", g) |
else |
s = s .. (" "):rep(depth) .. "} |cff9f9f9f-- " .. real_tostring(t):gsub("|", "||") |
end |
return s |
end |
if type(t) == "number" then |
return "|cffff7fff" .. real_tostring(t) .. "|r" |
elseif type(t) == "boolean" then |
return "|cffff9100" .. real_tostring(t) .. "|r" |
elseif t == nil then |
return "|cffff7f7f" .. real_tostring(t) .. "|r" |
else |
return "|cffffea00" .. real_tostring(t) .. "|r" |
end |
end |
function getkeystring(t, depth) |
if type(t) == "string" then |
if t:find("^[%a_][%a%d_]*$") then |
return "|cff7fd5ff" .. t .. "|r" |
end |
end |
return "[" .. literal_tostring_prime(t, depth) .. "]" |
end |
local get_stringed_args |
do |
local function g(value, ...) |
if select('#', ...) == 0 then |
return literal_tostring_prime(value, 1) |
end |
return literal_tostring_prime(value, 1) .. ", " .. g(...) |
end |
local function f(success, ...) |
if not success then |
return |
end |
return g(...) |
end |
function get_stringed_args(func, ...) |
return f(pcall(func, ...)) |
end |
end |
local function literal_tostring_frame(t) |
local s = ("|cffffea00<%s:%s|r\n"):format(t:GetObjectType(), t:GetName() or "(anon)") |
local __index = getmetatable(t).__index |
local tmp, tmp2, tmp3 = new(), new(), new() |
for k in pairs(t) do |
if k ~= 0 then |
tmp3[k] = true |
tmp2[k] = true |
end |
end |
for k in pairs(__index) do |
tmp2[k] = true |
end |
for k in pairs(tmp2) do |
tmp[#tmp+1] = k |
tmp2[k] = nil |
end |
table.sort(tmp, ignoreCaseSort) |
local first = true |
for i,k in ipairs(tmp) do |
local v = t[k] |
local good = true |
if k == "GetPoint" then |
for i = 1, t:GetNumPoints() do |
if not first then |
s = s .. ",\n" |
else |
first = false |
end |
s = s .. " " .. getkeystring(k, 1) .. "(" .. literal_tostring_prime(i, 1) .. ") => " .. get_stringed_args(v, t, i) |
end |
elseif type(v) == "function" and type(k) == "string" and (k:find("^Is") or k:find("^Get") or k:find("^Can")) then |
local q = get_stringed_args(v, t) |
if q then |
if not first then |
s = s .. ",\n" |
else |
first = false |
end |
s = s .. " " .. getkeystring(k, 1) .. "() => " .. q |
end |
elseif type(v) ~= "function" or (type(v) == "function" and type(k) == "string" and tmp3[k]) then |
if not first then |
s = s .. ",\n" |
else |
first = false |
end |
s = s .. " " .. getkeystring(k, 1) .. " = " .. literal_tostring_prime(v, 1) |
else |
good = false |
end |
end |
tmp, tmp2, tmp3 = del(tmp), del(tmp2), del(tmp3) |
s = s .. "\n|cffffea00>|r" |
return s |
end |
local function literal_tostring(t, only) |
timeToEnd = GetTime() + 0.2 |
local s |
if only and type(t) == "table" and type(rawget(t, 0)) == "userdata" and type(t.GetObjectType) == "function" then |
s = literal_tostring_frame(t) |
else |
s = literal_tostring_prime(t, 0) |
end |
for k,v in pairs(recurse) do |
recurse[k] = nil |
end |
for k,v in pairs(findGlobal) do |
findGlobal[k] = nil |
end |
return s |
end |
local function tostring_args(a1, ...) |
if select('#', ...) < 1 then |
return tostring(a1) |
end |
return tostring(a1), tostring_args(...) |
end |
local function literal_tostring_args(a1, ...) |
if select('#', ...) < 1 then |
return literal_tostring(a1) |
end |
return literal_tostring(a1), literal_tostring_args(...) |
end |
function AceConsole:CustomPrint(r, g, b, frame, delay, connector, a1, ...) |
if connector == true then |
local s |
if select('#', ...) == 0 then |
s = literal_tostring(a1, true) |
else |
s = (", "):join(literal_tostring_args(a1, ...)) |
end |
return print(s, self, r, g, b, frame or self.printFrame, delay) |
elseif tostring(a1):find("%%") and select('#', ...) >= 1 then |
local success, text = pcall(string.format, tostring_args(a1, ...)) |
if success then |
return print(text, self, r, g, b, frame or self.printFrame, delay) |
end |
end |
return print((connector or " "):join(tostring_args(a1, ...)), self, r, g, b, frame or self.printFrame, delay) |
end |
function AceConsole:Print(...) |
return AceConsole.CustomPrint(self, nil, nil, nil, nil, nil, " ", ...) |
end |
function AceConsole:PrintComma(...) |
return AceConsole.CustomPrint(self, nil, nil, nil, nil, nil, ", ", ...) |
end |
function AceConsole:PrintLiteral(...) |
return AceConsole.CustomPrint(self, nil, nil, nil, nil, nil, true, ...) |
end |
local work |
local argwork |
local function findTableLevel(self, options, chat, text, index, passTable) |
if not index then |
index = 1 |
if work then |
for k,v in pairs(work) do |
work[k] = nil |
end |
for k,v in pairs(argwork) do |
argwork[k] = nil |
end |
else |
work = {} |
argwork = {} |
end |
local len = text:len() |
local count |
repeat |
text, count = text:gsub("(|cff%x%x%x%x%x%x|Hitem:%d-:%d-:%d-:%d-|h%[[^%]]-) (.-%]|h|r)", "%1\001%2") |
until count == 0 |
text = text:gsub("(%]|h|r)(|cff%x%x%x%x%x%x|Hitem:%d-:%d-:%d-:%d-|h%[)", "%1 %2") |
for token in text:gmatch("([^%s]+)") do |
local token = token |
local num = tonumber(token) |
if num then |
token = num |
else |
token = token:gsub("\001", " ") |
end |
table.insert(work, token) |
end |
end |
local path = chat |
for i = 1, index - 1 do |
path = path .. " " .. tostring(work[i]) |
end |
local passValue = options.passValue or (passTable and work[index-1]) |
passTable = passTable or options |
if type(options.args) == "table" then |
local disabled, hidden = options.disabled, options.cmdHidden or options.hidden |
if hidden then |
if type(hidden) == "function" then |
hidden = hidden(passValue) |
elseif type(hidden) == "string" then |
local handler = options.handler or self |
local f = hidden |
local neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
if type(handler[f]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(f))) |
end |
hidden = handler[f](handler, passValue) |
if neg then |
hidden = not hidden |
end |
end |
end |
if hidden then |
disabled = true |
elseif disabled then |
if type(disabled) == "function" then |
disabled = disabled(passValue) |
elseif type(disabled) == "string" then |
local handler = options.handler or self |
local f = disabled |
local neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
if type(handler[f]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(f))) |
end |
disabled = handler[f](handler, passValue) |
if neg then |
disabled = not disabled |
end |
end |
end |
if not disabled then |
local next = work[index] and tostring(work[index]):lower() |
local next_num = tonumber(next) |
if next then |
for k,v in pairs(options.args) do |
local good = false |
if tostring(k):gsub("%s", "-"):lower() == next then |
good = true |
elseif k == next_num then |
good = true |
elseif type(v.aliases) == "table" then |
for _,alias in ipairs(v.aliases) do |
if alias:gsub("%s", "-"):lower() == next then |
good = true |
break |
end |
end |
elseif type(v.aliases) == "string" and v.aliases:gsub("%s", "-"):lower() == next then |
good = true |
end |
if good then |
work[index] = k -- revert it back to its original form as supplied in args |
if options.pass then |
passTable = passTable or options |
if options.get and options.set then |
passTable = options |
end |
else |
passTable = nil |
end |
return findTableLevel(options.handler or self, v, chat, text, index + 1, passTable) |
end |
end |
end |
end |
end |
for i = index, #work do |
table.insert(argwork, work[i]) |
end |
return options, path, argwork, options.handler or self, passTable, passValue |
end |
local function validateOptionsMethods(self, options, position) |
if type(options) ~= "table" then |
return "Options must be a table.", position |
end |
self = options.handler or self |
if options.type == "execute" then |
if options.func and type(options.func) ~= "string" and type(options.func) ~= "function" then |
return "func must be a string or function", position |
end |
if options.func and type(options.func) == "string" and type(self[options.func]) ~= "function" then |
return ("%q is not a proper function"):format(tostring(options.func)), position |
end |
else |
if options.get then |
if type(options.get) ~= "string" and type(options.get) ~= "function" then |
return "get must be a string or function", position |
end |
if type(options.get) == "string" then |
local f = options.get |
if options.type == "toggle" then |
f = f:match("^~(.-)$") or f |
end |
if type(self[f]) ~= "function" then |
return ("%q is not a proper function"):format(tostring(f)), position |
end |
end |
end |
if options.set then |
if type(options.set) ~= "string" and type(options.set) ~= "function" then |
return "set must be a string or function", position |
end |
if type(options.set) == "string" and type(self[options.set]) ~= "function" then |
return ("%q is not a proper function"):format(tostring(options.set)), position |
end |
end |
if options.validate and type(options.validate) ~= "table" and options.validate ~= "keybinding" then |
if type(options.validate) ~= "string" and type(options.validate) ~= "function" then |
return "validate must be a string or function", position |
end |
if type(options.validate) == "string" and type(self[options.validate]) ~= "function" then |
return ("%q is not a proper function"):format(tostring(options.validate)), position |
end |
end |
end |
if options.disabled and type(options.disabled) == "string" then |
local f = options.disabled |
f = f:match("^~(.-)$") or f |
if type(self[f]) ~= "function" then |
return ("%q is not a proper function"):format(tostring(f)), position |
end |
end |
if options.cmdHidden and type(options.cmdHidden) == "string" then |
local f = options.cmdHidden |
f = f:match("^~(.-)$") or f |
if type(self[f]) ~= "function" then |
return ("%q is not a proper function"):format(tostring(f)), position |
end |
end |
if options.guiHidden and type(options.guiHidden) == "string" then |
local f = options.guiHidden |
f = f:match("^~(.-)$") or f |
if type(self[f]) ~= "function" then |
return ("%q is not a proper function"):format(tostring(f)), position |
end |
end |
if options.hidden and type(options.hidden) == "string" then |
local f = options.hidden |
f = f:match("^~(.-)$") or f |
if type(self[f]) ~= "function" then |
return ("%q is not a proper function"):format(tostring(f)), position |
end |
end |
if options.type == "group" and type(options.args) == "table" then |
for k,v in pairs(options.args) do |
if type(v) == "table" then |
local newposition |
if position then |
newposition = position .. ".args." .. k |
else |
newposition = "args." .. k |
end |
local err, pos = validateOptionsMethods(self, v, newposition) |
if err then |
return err, pos |
end |
end |
end |
end |
end |
local function validateOptions(options, position, baseOptions, fromPass) |
if not baseOptions then |
baseOptions = options |
end |
if type(options) ~= "table" then |
return "Options must be a table.", position |
end |
local kind = options.type |
if type(kind) ~= "string" then |
return '"type" must be a string.', position |
elseif kind ~= "group" and kind ~= "range" and kind ~= "text" and kind ~= "execute" and kind ~= "toggle" and kind ~= "color" and kind ~= "header" then |
return '"type" must either be "range", "text", "group", "toggle", "execute", "color", or "header".', position |
end |
if options.aliases then |
if type(options.aliases) ~= "table" and type(options.aliases) ~= "string" then |
return '"alias" must be a table or string', position |
end |
end |
if not fromPass then |
if kind == "execute" then |
if type(options.func) ~= "string" and type(options.func) ~= "function" then |
return '"func" must be a string or function', position |
end |
elseif kind == "range" or kind == "text" or kind == "toggle" then |
if type(options.set) ~= "string" and type(options.set) ~= "function" then |
return '"set" must be a string or function', position |
end |
if kind == "text" and options.get == false then |
elseif type(options.get) ~= "string" and type(options.get) ~= "function" then |
return '"get" must be a string or function', position |
end |
elseif kind == "group" and options.pass then |
if options.pass ~= true then |
return '"pass" must be either nil, true, or false', position |
end |
if not options.func then |
if type(options.set) ~= "string" and type(options.set) ~= "function" then |
return '"set" must be a string or function', position |
end |
if type(options.get) ~= "string" and type(options.get) ~= "function" then |
return '"get" must be a string or function', position |
end |
elseif type(options.func) ~= "string" and type(options.func) ~= "function" then |
return '"func" must be a string or function', position |
end |
end |
end |
if options ~= baseOptions then |
if kind == "header" then |
elseif type(options.desc) ~= "string" then |
return '"desc" must be a string', position |
elseif options.desc:len() == 0 then |
return '"desc" cannot be a 0-length string', position |
end |
end |
if options ~= baseOptions or kind == "range" or kind == "text" or kind == "toggle" or kind == "color" then |
if options.type == "header" and not options.cmdName and not options.name then |
elseif options.cmdName then |
if type(options.cmdName) ~= "string" then |
return '"cmdName" must be a string or nil', position |
elseif options.cmdName:len() == 0 then |
return '"cmdName" cannot be a 0-length string', position |
end |
if type(options.guiName) ~= "string" then |
if not options.guiNameIsMap then |
return '"guiName" must be a string or nil', position |
end |
elseif options.guiName:len() == 0 then |
return '"guiName" cannot be a 0-length string', position |
end |
else |
if type(options.name) ~= "string" then |
return '"name" must be a string', position |
elseif options.name:len() == 0 then |
return '"name" cannot be a 0-length string', position |
end |
end |
end |
if options.guiNameIsMap then |
if type(options.guiNameIsMap) ~= "boolean" then |
return '"guiNameIsMap" must be a boolean or nil', position |
elseif options.type ~= "toggle" then |
return 'if "guiNameIsMap" is true, then "type" must be set to \'toggle\'', position |
elseif type(options.map) ~= "table" then |
return '"map" must be a table', position |
end |
end |
if options.message and type(options.message) ~= "string" then |
return '"message" must be a string or nil', position |
end |
if options.error and type(options.error) ~= "string" then |
return '"error" must be a string or nil', position |
end |
if options.current and type(options.current) ~= "string" then |
return '"current" must be a string or nil', position |
end |
if options.order then |
if type(options.order) ~= "number" or (-1 < options.order and options.order < 0.999) then |
return '"order" must be a non-zero number or nil', position |
end |
end |
if options.disabled then |
if type(options.disabled) ~= "function" and type(options.disabled) ~= "string" and options.disabled ~= true then |
return '"disabled" must be a function, string, or boolean', position |
end |
end |
if options.cmdHidden then |
if type(options.cmdHidden) ~= "function" and type(options.cmdHidden) ~= "string" and options.cmdHidden ~= true then |
return '"cmdHidden" must be a function, string, or boolean', position |
end |
end |
if options.guiHidden then |
if type(options.guiHidden) ~= "function" and type(options.guiHidden) ~= "string" and options.guiHidden ~= true then |
return '"guiHidden" must be a function, string, or boolean', position |
end |
end |
if options.hidden then |
if type(options.hidden) ~= "function" and type(options.hidden) ~= "string" and options.hidden ~= true then |
return '"hidden" must be a function, string, or boolean', position |
end |
end |
if kind == "text" then |
if type(options.validate) == "table" then |
local t = options.validate |
local iTable = nil |
for k,v in pairs(t) do |
if type(k) == "number" then |
if iTable == nil then |
iTable = true |
elseif not iTable then |
return '"validate" must either have all keys be indexed numbers or strings', position |
elseif k < 1 or k > #t then |
return '"validate" numeric keys must be indexed properly. >= 1 and <= #validate', position |
end |
else |
if iTable == nil then |
iTable = false |
elseif iTable then |
return '"validate" must either have all keys be indexed numbers or strings', position |
end |
end |
if type(v) ~= "string" then |
return '"validate" values must all be strings', position |
end |
end |
if options.multiToggle and options.multiToggle ~= true then |
return '"multiToggle" must be a boolean or nil if "validate" is a table', position |
end |
elseif options.validate == "keybinding" then |
else |
if type(options.usage) ~= "string" then |
return '"usage" must be a string', position |
elseif options.validate and type(options.validate) ~= "string" and type(options.validate) ~= "function" then |
return '"validate" must be a string, function, or table', position |
end |
end |
if options.multiToggle and type(options.validate) ~= "table" then |
return '"validate" must be a table if "multiToggle" is true', position |
end |
elseif kind == "range" then |
if options.min or options.max then |
if type(options.min) ~= "number" then |
return '"min" must be a number', position |
elseif type(options.max) ~= "number" then |
return '"max" must be a number', position |
elseif options.min >= options.max then |
return '"min" must be less than "max"', position |
end |
end |
if options.step then |
if type(options.step) ~= "number" then |
return '"step" must be a number', position |
elseif options.step < 0 then |
return '"step" must be nonnegative', position |
end |
end |
if options.isPercent and options.isPercent ~= true then |
return '"isPercent" must either be nil, true, or false', position |
end |
elseif kind == "toggle" then |
if options.map then |
if type(options.map) ~= "table" then |
return '"map" must be a table', position |
elseif type(options.map[true]) ~= "string" then |
return '"map[true]" must be a string', position |
elseif type(options.map[false]) ~= "string" then |
return '"map[false]" must be a string', position |
end |
end |
elseif kind == "color" then |
if options.hasAlpha and options.hasAlpha ~= true then |
return '"hasAlpha" must be nil, true, or false', position |
end |
elseif kind == "group" then |
if options.pass and options.pass ~= true then |
return '"pass" must be nil, true, or false', position |
end |
if type(options.args) ~= "table" then |
return '"args" must be a table', position |
end |
for k,v in pairs(options.args) do |
if type(k) ~= "number" then |
if type(k) ~= "string" then |
return '"args" keys must be strings or numbers', position |
elseif k:len() == 0 then |
return '"args" keys must not be 0-length strings.', position |
end |
end |
if type(v) ~= "table" then |
if type(k) == "number" then |
return '"args" values must be tables', position and position .. "[" .. k .. "]" or "[" .. k .. "]" |
else |
return '"args" values must be tables', position and position .. "." .. k or k |
end |
end |
local newposition |
if type(k) == "number" then |
newposition = position and position .. ".args[" .. k .. "]" or "args[" .. k .. "]" |
else |
newposition = position and position .. ".args." .. k or "args." .. k |
end |
local err, pos = validateOptions(v, newposition, baseOptions, options.pass) |
if err then |
return err, pos |
end |
end |
elseif kind == "execute" then |
if type(options.confirm) ~= "string" and type(options.confirm) ~= "boolean" and type(options.confirm) ~= "nil" then |
return '"confirm" must be a string, boolean, or nil', position |
end |
end |
end |
local colorTable |
local colorFunc |
local colorCancelFunc |
local function keybindingValidateFunc(text) |
if text == nil or text == "NONE" then |
return nil |
end |
text = text:upper() |
local shift, ctrl, alt |
local modifier |
while true do |
if text == "-" then |
break |
end |
modifier, text = strsplit('-', text, 2) |
if text then |
if modifier ~= "SHIFT" and modifier ~= "CTRL" and modifier ~= "ALT" then |
return false |
end |
if modifier == "SHIFT" then |
if shift then |
return false |
end |
shift = true |
end |
if modifier == "CTRL" then |
if ctrl then |
return false |
end |
ctrl = true |
end |
if modifier == "ALT" then |
if alt then |
return false |
end |
alt = true |
end |
else |
text = modifier |
break |
end |
end |
if not text:find("^F%d+$") and text ~= "CAPSLOCK" and text:len() ~= 1 and (text:byte() < 128 or text:len() > 4) and not _G["KEY_" .. text] then |
return false |
end |
local s = text |
if shift then |
s = "SHIFT-" .. s |
end |
if ctrl then |
s = "CTRL-" .. s |
end |
if alt then |
s = "ALT-" .. s |
end |
return s |
end |
AceConsole.keybindingValidateFunc = keybindingValidateFunc |
local order |
local mysort_args |
local mysort |
local function icaseSort(alpha, bravo) |
if type(alpha) == "number" and type(bravo) == "number" then |
return alpha < bravo |
end |
return tostring(alpha):lower() < tostring(bravo):lower() |
end |
local tmp = {} |
local function printUsage(self, handler, realOptions, options, path, args, passValue, quiet, filter) |
if filter then |
filter = "^" .. filter:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") |
end |
local hidden, disabled = options.cmdHidden or options.hidden, options.disabled |
if hidden then |
if type(hidden) == "function" then |
hidden = hidden(options.passValue) |
elseif type(hidden) == "string" then |
local f = hidden |
local neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
if type(handler[f]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(f))) |
end |
hidden = handler[f](handler, options.passValue) |
if neg then |
hidden = not hidden |
end |
end |
end |
if hidden then |
disabled = true |
elseif disabled then |
if type(disabled) == "function" then |
disabled = disabled(options.passValue) |
elseif type(disabled) == "string" then |
local f = disabled |
local neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
if type(handler[f]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(f))) |
end |
disabled = handler[f](handler, options.passValue) |
if neg then |
disabled = not disabled |
end |
end |
end |
local kind = (options.type or "group"):lower() |
if disabled then |
print(OPTION_IS_DISABLED:format(path), realOptions.cmdName or realOptions.name or self) |
elseif kind == "text" then |
local var |
local multiToggle |
for k in pairs(tmp) do |
tmp[k] = nil |
end |
if passTable then |
multiToggle = passTable.multiToggle |
if not passTable.get then |
elseif type(passTable.get) == "function" then |
if not multiToggle then |
var = passTable.get(passValue) |
else |
var = tmp |
for k,v in pairs(options.validate) do |
local val = type(k) ~= "number" and k or v |
if passValue == nil then |
var[val] = passTable.get(val) or nil |
else |
var[val] = passTable.get(passValue, val) or nil |
end |
end |
end |
else |
local handler = passTable.handler or handler |
if type(handler[passTable.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(passTable.get))) |
end |
var = handler[passTable.get](handler, passValue) |
if not multiToggle then |
var = handler[passTable.get](handler, passValue) |
else |
var = tmp |
for k,v in pairs(options.validate) do |
local val = type(k) ~= "number" and k or v |
if passValue == nil then |
var[val] = handler[passTable.get](handler, val) or nil |
else |
var[val] = handler[passTable.get](handler, passValue, val) or nil |
end |
end |
end |
end |
else |
multiToggle = options.multiToggle |
if not options.get then |
elseif type(options.get) == "function" then |
if not multiToggle then |
var = options.get(passValue) |
else |
var = tmp |
for k,v in pairs(options.validate) do |
local val = type(k) ~= "number" and k or v |
if passValue == nil then |
var[val] = options.get(val) or nil |
else |
var[val] = options.get(passValue, val) or nil |
end |
end |
end |
else |
local handler = options.handler or handler |
if type(handler[options.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options.get))) |
end |
if not multiToggle then |
var = handler[options.get](handler, passValue) |
else |
var = tmp |
for k,v in pairs(options.validate) do |
local val = type(k) ~= "number" and k or v |
if passValue == nil then |
var[val] = handler[options.get](handler, val) or nil |
else |
var[val] = handler[options.get](handler, passValue, val) or nil |
end |
end |
end |
end |
end |
local usage |
if type(options.validate) == "table" then |
if filter then |
if not order then |
order = {} |
end |
for k,v in pairs(options.validate) do |
if v:find(filter) then |
table.insert(order, v) |
end |
end |
table.sort(order, icaseSort) |
usage = "{" .. table.concat(order, " || ") .. "}" |
for k in pairs(order) do |
order[k] = nil |
end |
else |
if not order then |
order = {} |
end |
for k,v in pairs(options.validate) do |
table.insert(order, v) |
end |
table.sort(order, icaseSort) |
usage = "{" .. table.concat(order, " || ") .. "}" |
for k in pairs(order) do |
order[k] = nil |
end |
end |
if multiToggle then |
if not next(var) then |
var = NONE |
else |
if not order then |
order = {} |
end |
for k in pairs(var) do |
if options.validate[k] then |
order[#order+1] = options.validate[k] |
else |
for _,v in pairs(options.validate) do |
if v == k or (type(v) == "string" and type(k) == "string" and v:lower() == k:lower()) then |
order[#order+1] = v |
break |
end |
end |
end |
end |
table.sort(order, icaseSort) |
var = table.concat(order, ", ") |
for k in pairs(order) do |
order[k] = nil |
end |
end |
else |
var = options.validate[var] or var |
end |
elseif options.validate == "keybinding" then |
usage = KEYBINDING_USAGE |
else |
usage = options.usage or "<value>" |
end |
if not quiet then |
print(("|cffffff7f%s:|r %s %s"):format(USAGE, path, usage), realOptions.cmdName or realOptions.name or self) |
end |
if (passTable and passTable.get) or options.get then |
print((options.current or IS_CURRENTLY_SET_TO):format(tostring(options.cmdName or options.name), tostring(var or NONE))) |
end |
elseif kind == "range" then |
local var |
if passTable then |
if type(passTable.get) == "function" then |
var = passTable.get(passValue) |
else |
local handler = passTable.handler or handler |
if type(handler[passTable.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(passTable.get))) |
end |
var = handler[passTable.get](handler, passValue) |
end |
else |
if type(options.get) == "function" then |
var = options.get(passValue) |
else |
local handler = options.handler or handler |
if type(handler[options.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options.get))) |
end |
var = handler[options.get](handler, passValue) |
end |
end |
local usage |
local min = options.min or 0 |
local max = options.max or 1 |
if options.isPercent then |
min, max = min * 100, max * 100 |
var = tostring(var * 100) .. "%" |
end |
local bit = "-" |
if min < 0 or max < 0 then |
bit = " - " |
end |
usage = ("(%s%s%s)"):format(min, bit, max) |
if not quiet then |
print(("|cffffff7f%s:|r %s %s"):format(USAGE, path, usage), realOptions.cmdName or realOptions.name or self) |
end |
print((options.current or IS_CURRENTLY_SET_TO):format(tostring(options.cmdName or options.name), tostring(var or NONE))) |
elseif kind == "group" then |
local usage |
if next(options.args) then |
if not order then |
order = {} |
end |
for k,v in pairs(options.args) do |
if v.type ~= "header" then |
local hidden = v.cmdHidden or v.hidden |
if hidden then |
if type(hidden) == "function" then |
hidden = hidden() |
elseif type(hidden) == "string" then |
local f = hidden |
local neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
if type(handler[f]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(f))) |
end |
hidden = handler[f](handler) |
if neg then |
hidden = not hidden |
end |
end |
end |
if not hidden then |
if filter then |
if k:find(filter) then |
table.insert(order, k) |
elseif type(v.aliases) == "table" then |
for _,bit in ipairs(v.aliases) do |
if bit:find(filter) then |
table.insert(order, k) |
break |
end |
end |
elseif type(v.aliases) == "string" then |
if v.aliases:find(filter) then |
table.insert(order, k) |
end |
end |
else |
table.insert(order, k) |
end |
end |
end |
end |
if not mysort then |
mysort = function(a, b) |
local alpha, bravo = mysort_args[a], mysort_args[b] |
local alpha_order = alpha and alpha.order or 100 |
local bravo_order = bravo and bravo.order or 100 |
if alpha_order == bravo_order then |
return tostring(a):lower() < tostring(b):lower() |
else |
if alpha_order < 0 then |
if bravo_order > 0 then |
return false |
end |
else |
if bravo_order < 0 then |
return true |
end |
end |
if alpha_order > 0 and bravo_order > 0 then |
return tostring(a):lower() < tostring(b):lower() |
end |
return alpha_order < bravo_order |
end |
end |
end |
mysort_args = options.args |
table.sort(order, mysort) |
mysort_args = nil |
if not quiet then |
if options == realOptions then |
if options.desc then |
print(tostring(options.desc), realOptions.cmdName or realOptions.name or self) |
print(("|cffffff7f%s:|r %s %s"):format(USAGE, path, "{" .. table.concat(order, " || ") .. "}")) |
elseif self.description or self.notes then |
print(tostring(self.description or self.notes), realOptions.cmdName or realOptions.name or self) |
print(("|cffffff7f%s:|r %s %s"):format(USAGE, path, "{" .. table.concat(order, " || ") .. "}")) |
else |
print(("|cffffff7f%s:|r %s %s"):format(USAGE, path, "{" .. table.concat(order, " || ") .. "}"), realOptions.cmdName or realOptions.name or self) |
end |
else |
if options.desc then |
print(("|cffffff7f%s:|r %s %s"):format(USAGE, path, "{" .. table.concat(order, " || ") .. "}"), realOptions.cmdName or realOptions.name or self) |
print(tostring(options.desc)) |
else |
print(("|cffffff7f%s:|r %s %s"):format(USAGE, path, "{" .. table.concat(order, " || ") .. "}"), realOptions.cmdName or realOptions.name or self) |
end |
end |
end |
local passTable = options.pass and options or nil |
for _,k in ipairs(order) do |
local passValue = passTable and k or nil |
local real_k = k |
local v = options.args[k] |
if v then |
local v_p = passTable or v |
if v.get and v.set then |
v_p = v |
passValue = nil |
end |
if v.passValue then |
passValue = v.passValue |
end |
local k = tostring(k):gsub("%s", "-") |
local disabled = v.disabled |
if disabled then |
if type(disabled) == "function" then |
disabled = disabled(passValue) |
elseif type(disabled) == "string" then |
local f = disabled |
local neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
if type(handler[f]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(f))) |
end |
disabled = handler[f](handler, passValue) |
if neg then |
disabled = not disabled |
end |
end |
end |
if type(v.aliases) == "table" then |
for _,s in ipairs(v.aliases) do |
k = k .. " || " .. s:gsub("%s", "-") |
end |
elseif type(v.aliases) == "string" then |
k = k .. " || " .. v.aliases:gsub("%s", "-") |
end |
if v_p.get then |
local a1,a2,a3,a4 |
local multiToggle = v_p.type == "text" and v_p.multiToggle |
for k in pairs(tmp) do |
tmp[k] = nil |
end |
if type(v_p.get) == "function" then |
if multiToggle then |
a1 = tmp |
for k,v in pairs(v.validate) do |
local val = type(k) ~= "number" and k or v |
if passValue == nil then |
a1[val] = v_p.get(val) or nil |
else |
a1[val] = v_p.get(passValue, val) or nil |
end |
end |
else |
a1,a2,a3,a4 = v_p.get(passValue) |
end |
else |
local handler = v_p.handler or handler |
local f = v_p.get |
local neg |
if v.type == "toggle" then |
neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
end |
if type(handler[f]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(f))) |
end |
if multiToggle then |
a1 = tmp |
for k,v in pairs(v.validate) do |
local val = type(k) ~= "number" and k or v |
if passValue == nil then |
a1[val] = handler[f](handler, val) or nil |
else |
a1[val] = handler[f](handler, passValue, val) or nil |
end |
end |
else |
a1,a2,a3,a4 = handler[f](handler, passValue) |
end |
if neg then |
a1 = not a1 |
end |
end |
local s |
if v.type == "color" then |
if v.hasAlpha then |
if not a1 or not a2 or not a3 or not a4 then |
s = NONE |
else |
s = ("|c%02x%02x%02x%02x%02x%02x%02x%02x|r"):format(a4*255, a1*255, a2*255, a3*255, a4*255, a1*255, a2*255, a3*255) |
end |
else |
if not a1 or not a2 or not a3 then |
s = NONE |
else |
s = ("|cff%02x%02x%02x%02x%02x%02x|r"):format(a1*255, a2*255, a3*255, a1*255, a2*255, a3*255) |
end |
end |
elseif v.type == "toggle" then |
if v.map then |
s = tostring(v.map[a1 and true or false] or NONE) |
else |
s = tostring(MAP_ONOFF[a1 and true or false] or NONE) |
end |
elseif v.type == "range" then |
if v.isPercent then |
s = tostring(a1 * 100) .. "%" |
else |
s = tostring(a1) |
end |
elseif v.type == "text" and type(v.validate) == "table" then |
if multiToggle then |
if not next(a1) then |
s = NONE |
else |
s = '' |
for k in pairs(a1) do |
if v.validate[k] then |
if s == '' then |
s = v.validate[k] |
else |
s = s .. ', ' .. v.validate[k] |
end |
else |
for _,u in pairs(v.validate) do |
if u == k or (type(v) == "string" and type(k) == "string" and v:lower() == k:lower()) then |
if s == '' then |
s = u |
else |
s = s .. ', ' .. u |
end |
break |
end |
end |
end |
end |
end |
else |
s = tostring(v.validate[a1] or a1 or NONE) |
end |
else |
s = tostring(a1 or NONE) |
end |
if disabled then |
local s = s:gsub("|cff%x%x%x%x%x%x(.-)|r", "%1") |
local desc = (v.desc or NONE):gsub("|cff%x%x%x%x%x%x(.-)|r", "%1") |
print(("|cffcfcfcf - %s: [%s] %s|r"):format(k, s, desc)) |
else |
print((" - |cffffff7f%s: [|r%s|cffffff7f]|r %s"):format(k, s, v.desc or NONE)) |
end |
else |
if disabled then |
local desc = (v.desc or NONE):gsub("|cff%x%x%x%x%x%x(.-)|r", "%1") |
print(("|cffcfcfcf - %s: %s"):format(k, desc)) |
else |
print((" - |cffffff7f%s:|r %s"):format(k, v.desc or NONE)) |
end |
end |
end |
end |
for k in pairs(order) do |
order[k] = nil |
end |
else |
if options.desc then |
print(("|cffffff7f%s:|r %s"):format(USAGE, path), realOptions.cmdName or realOptions.name or self) |
print(tostring(options.desc)) |
elseif options == realOptions and (self.description or self.notes) then |
print(tostring(self.description or self.notes), realOptions.cmdName or realOptions.name or self) |
print(("|cffffff7f%s:|r %s"):format(USAGE, path)) |
else |
print(("|cffffff7f%s:|r %s"):format(USAGE, path), realOptions.cmdName or realOptions.name or self) |
end |
print(NO_OPTIONS_AVAILABLE) |
end |
end |
end |
local function confirmPopup(message, func, ...) |
if not StaticPopupDialogs["ACECONSOLE20_CONFIRM_DIALOG"] then |
StaticPopupDialogs["ACECONSOLE20_CONFIRM_DIALOG"] = {} |
end |
local t = StaticPopupDialogs["ACECONSOLE20_CONFIRM_DIALOG"] |
for k in pairs(t) do |
t[k] = nil |
end |
t.text = message |
t.button1 = ACCEPT or "Accept" |
t.button2 = CANCEL or "Cancel" |
t.OnAccept = function() |
func(unpack(t)) |
end |
for i = 1, select('#', ...) do |
t[i] = select(i, ...) |
end |
t.timeout = 0 |
t.whileDead = 1 |
t.hideOnEscape = 1 |
StaticPopup_Show("ACECONSOLE20_CONFIRM_DIALOG") |
end |
local function handlerFunc(self, chat, msg, options) |
if not msg then |
msg = "" |
else |
msg = msg:gsub("^%s*(.-)%s*$", "%1") |
msg = msg:gsub("%s+", " ") |
end |
local realOptions = options |
local options, path, args, handler, passTable, passValue = findTableLevel(self, options, chat, msg) |
if options.type == "execute" then |
if options.func then |
passTable = nil |
end |
else |
if options.get and options.set then |
passTable = nil |
end |
end |
passValue = options.passValue or passTable and passValue |
local hidden, disabled = options.cmdHidden or options.hidden, options.disabled |
if hidden then |
if type(hidden) == "function" then |
hidden = hidden(passValue) |
elseif type(hidden) == "string" then |
local f = hidden |
local neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
if type(handler[f]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(f))) |
end |
hidden = handler[f](handler, passValue) |
if neg then |
hidden = not hidden |
end |
end |
end |
if hidden then |
disabled = true |
elseif disabled then |
if type(disabled) == "function" then |
disabled = disabled(passValue) |
elseif type(disabled) == "string" then |
local f = disabled |
local neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
if type(handler[f]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(f))) |
end |
disabled = handler[f](handler, passValue) |
if neg then |
disabled = not disabled |
end |
end |
end |
local _G_this = this |
local kind = (options.type or "group"):lower() |
local options_p = passTable or options |
if disabled then |
print(OPTION_IS_DISABLED:format(path), realOptions.cmdName or realOptions.name or self) |
elseif kind == "text" then |
if #args > 0 then |
if (type(options.validate) == "table" and #args > 1) or (type(options.validate) ~= "table" and not options.input) then |
local arg = table.concat(args, " ") |
for k,v in pairs(args) do |
args[k] = nil |
end |
args[1] = arg |
end |
if options.validate then |
local good |
if type(options.validate) == "function" then |
good = options.validate(unpack(args)) |
elseif type(options.validate) == "table" then |
local arg = args[1] |
arg = tostring(arg):lower() |
for k,v in pairs(options.validate) do |
if v:lower() == arg then |
args[1] = type(k) == "string" and k or v |
good = true |
break |
end |
end |
if not good and type((next(options.validate))) == "string" then |
for k,v in pairs(options.validate) do |
if type(k) == "string" and k:lower() == arg then |
args[1] = k |
good = true |
break |
end |
end |
end |
elseif options.validate == "keybinding" then |
good = keybindingValidateFunc(unpack(args)) |
if good ~= false then |
args[1] = good |
end |
else |
if type(handler[options.validate]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options.validate))) |
end |
good = handler[options.validate](handler, unpack(args)) |
end |
if not good then |
local usage |
if type(options.validate) == "table" then |
if not order then |
order = {} |
end |
for k,v in pairs(options.validate) do |
table.insert(order, v) |
end |
usage = "{" .. table.concat(order, " || ") .. "}" |
for k in pairs(order) do |
order[k] = nil |
end |
elseif options.validate == "keybinding" then |
usage = KEYBINDING_USAGE |
else |
usage = options.usage or "<value>" |
end |
print((options.error or IS_NOT_A_VALID_OPTION_FOR):format(tostring(table.concat(args, " ")), path), realOptions.cmdName or realOptions.name or self) |
print(("|cffffff7f%s:|r %s %s"):format(USAGE, path, usage)) |
return |
end |
end |
local var |
local multiToggle |
for k in pairs(tmp) do |
tmp[k] = nil |
end |
multiToggle = options_p.multiToggle |
if not options_p.get then |
elseif type(options_p.get) == "function" then |
if multiToggle then |
var = tmp |
for k,v in pairs(options.validate) do |
local val = type(k) ~= "number" and k or v |
if passValue then |
var[val] = options_p.get(passValue, val) or nil |
else |
var[val] = options_p.get(val) or nil |
end |
end |
else |
var = options_p.get(passValue) |
end |
else |
if type(handler[options_p.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options_p.get))) |
end |
if multiToggle then |
var = tmp |
for k,v in pairs(options.validate) do |
local val = type(k) ~= "number" and k or v |
if passValue then |
var[val] = handler[options_p.get](handler, passValue, val) or nil |
else |
var[val] = handler[options_p.get](handler, val) or nil |
end |
end |
else |
var = handler[options_p.get](handler, passValue) |
end |
end |
if multiToggle or var ~= args[1] then |
if multiToggle then |
local current = var[args[1]] |
if current == nil and type(args[1]) == "string" then |
for k in pairs(var) do |
if type(k) == "string" and k:lower() == args[1]:lower() then |
current = true |
break |
end |
end |
end |
args[2] = not current |
end |
if type(options_p.set) == "function" then |
if passValue then |
options_p.set(passValue, unpack(args)) |
else |
options_p.set(unpack(args)) |
end |
else |
if type(handler[options_p.set]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options_p.set))) |
end |
if passValue then |
handler[options_p.set](handler, passValue, unpack(args)) |
else |
handler[options_p.set](handler, unpack(args)) |
end |
end |
end |
end |
if #args > 0 then |
local var |
local multiToggle |
for k in pairs(tmp) do |
tmp[k] = nil |
end |
multiToggle = options_p.multiToggle |
if not options_p.get then |
elseif type(options_p.get) == "function" then |
if multiToggle then |
var = tmp |
for k,v in pairs(options_p.validate) do |
local val = type(k) ~= "number" and k or v |
if passValue then |
var[val] = options_p.get(passValue, val) or nil |
else |
var[val] = options_p.get(val) or nil |
end |
end |
else |
var = options_p.get(passValue) |
end |
else |
if type(handler[options_p.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options_p.get))) |
end |
if multiToggle then |
var = tmp |
for k,v in pairs(options.validate) do |
local val = type(k) ~= "number" and k or v |
if passValue then |
var[val] = handler[options_p.get](handler, passValue, val) or nil |
else |
var[val] = handler[options_p.get](handler, val) or nil |
end |
end |
else |
var = handler[options_p.get](handler, passValue) |
end |
end |
if multiToggle then |
if not next(var) then |
var = NONE |
else |
if not order then |
order = {} |
end |
for k in pairs(var) do |
if options.validate[k] then |
order[#order+1] = options.validate[k] |
else |
for _,v in pairs(options.validate) do |
if v == k or (type(v) == "string" and type(k) == "string" and v:lower() == k:lower()) then |
order[#order+1] = v |
break |
end |
end |
end |
end |
table.sort(order, icaseSort) |
var = table.concat(order, ", ") |
for k in pairs(order) do |
order[k] = nil |
end |
end |
elseif type(options.validate) == "table" then |
var = options.validate[var] or var |
end |
if options_p.get then |
print((options.message or IS_NOW_SET_TO):format(tostring(options.cmdName or options.name), tostring(var or NONE)), realOptions.cmdName or realOptions.name or self) |
end |
if var == args[1] then |
return |
end |
else |
printUsage(self, handler, realOptions, options, path, args, passValue) |
return |
end |
elseif kind == "execute" then |
local confirm = options.confirm |
if confirm == true then |
confirm = DEFAULT_CONFIRM_MESSAGE:format(options.desc or options.name or UNKNOWN or "Unknown") |
end |
if type(options_p.func) == "function" then |
if confirm then |
confirmPopup(confirm, options_p.func, passValue) |
else |
options_p.func(passValue) |
end |
else |
if type(handler[options_p.func]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options_p.func))) |
end |
if confirm then |
confirmPopup(confirm, handler[options_p.func], handler, passValue) |
else |
handler[options_p.func](handler, passValue) |
end |
end |
elseif kind == "toggle" then |
local var |
if type(options_p.get) == "function" then |
var = options_p.get(passValue) |
else |
local f = options_p.get |
local neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
if type(handler[f]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(f))) |
end |
var = handler[f](handler, passValue) |
if neg then |
var = not var |
end |
end |
if type(options_p.set) == "function" then |
if passValue then |
options_p.set(passValue, not var) |
else |
options_p.set(not var) |
end |
else |
if type(handler[options_p.set]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options_p.set))) |
end |
if passValue then |
handler[options_p.set](handler, passValue, not var) |
else |
handler[options_p.set](handler, not var) |
end |
end |
if type(options_p.get) == "function" then |
var = options_p.get(passValue) |
else |
local f = options_p.get |
local neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
var = handler[f](handler, passValue) |
if neg then |
var = not var |
end |
end |
print((options.message or IS_NOW_SET_TO):format(tostring(options.cmdName or options.name), (options.map or MAP_ONOFF)[var and true or false] or NONE), realOptions.cmdName or realOptions.name or self) |
elseif kind == "range" then |
local arg |
if #args <= 1 then |
arg = args[1] |
else |
arg = table.concat(args, " ") |
end |
if arg then |
local min = options.min or 0 |
local max = options.max or 1 |
local good = false |
if type(arg) == "number" then |
if options.isPercent then |
arg = arg / 100 |
end |
if arg >= min and arg <= max then |
good = true |
end |
if good and type(options.step) == "number" and options.step > 0 then |
local step = options.step |
arg = math.floor((arg - min) / step + 0.5) * step + min |
if arg > max then |
arg = max |
elseif arg < min then |
arg = min |
end |
end |
end |
if not good then |
local usage |
local min = options.min or 0 |
local max = options.max or 1 |
if options.isPercent then |
min, max = min * 100, max * 100 |
end |
local bit = "-" |
if min < 0 or max < 0 then |
bit = " - " |
end |
usage = ("(%s%s%s)"):format(min, bit, max) |
print((options.error or IS_NOT_A_VALID_VALUE_FOR):format(tostring(arg), path), realOptions.cmdName or realOptions.name or self) |
print(("|cffffff7f%s:|r %s %s"):format(USAGE, path, usage)) |
return |
end |
local var |
if type(options_p.get) == "function" then |
var = options_p.get(passValue) |
else |
if type(handler[options_p.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options_p.get))) |
end |
var = handler[options_p.get](handler, passValue) |
end |
if var ~= arg then |
if type(options_p.set) == "function" then |
if passValue then |
options_p.set(passValue, arg) |
else |
options_p.set(arg) |
end |
else |
if type(handler[options_p.set]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options_p.set))) |
end |
if passValue then |
handler[options_p.set](handler, passValue, arg) |
else |
handler[options_p.set](handler, arg) |
end |
end |
end |
end |
if arg then |
local var |
if type(options_p.get) == "function" then |
var = options_p.get(passValue) |
else |
if type(handler[options_p.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options_p.get))) |
end |
var = handler[options_p.get](handler, passValue) |
end |
if var and options.isPercent then |
var = tostring(var * 100) .. "%" |
end |
print((options.message or IS_NOW_SET_TO):format(tostring(options.cmdName or options.name), tostring(var or NONE)), realOptions.cmdName or realOptions.name or self) |
if var == arg then |
return |
end |
else |
printUsage(self, handler, realOptions, options, path, args, passValue) |
return |
end |
elseif kind == "color" then |
if #args > 0 then |
local r,g,b,a |
if #args == 1 then |
local arg = tostring(args[1]) |
if options.hasAlpha then |
if arg:len() == 8 and arg:find("^%x*$") then |
r,g,b,a = tonumber(arg:sub(1, 2), 16) / 255, tonumber(arg:sub(3, 4), 16) / 255, tonumber(arg:sub(5, 6), 16) / 255, tonumber(arg:sub(7, 8), 16) / 255 |
end |
else |
if arg:len() == 6 and arg:find("^%x*$") then |
r,g,b = tonumber(arg:sub(1, 2), 16) / 255, tonumber(arg:sub(3, 4), 16) / 255, tonumber(arg:sub(5, 6), 16) / 255 |
end |
end |
elseif #args == 4 and options.hasAlpha then |
local a1,a2,a3,a4 = args[1], args[2], args[3], args[4] |
if type(a1) == "number" and type(a2) == "number" and type(a3) == "number" and type(a4) == "number" and a1 <= 1 and a2 <= 1 and a3 <= 1 and a4 <= 1 then |
r,g,b,a = a1,a2,a3,a4 |
elseif (type(a1) == "number" or a1:len() == 2) and a1:find("^%x*$") and (type(a2) == "number" or a2:len() == 2) and a2:find("^%x*$") and (type(a3) == "number" or a3:len() == 2) and a3:find("^%x*$") and (type(a4) == "number" or a4:len() == 2) and a4:find("^%x*$") then |
r,g,b,a = tonumber(a1, 16) / 255, tonumber(a2, 16) / 255, tonumber(a3, 16) / 255, tonumber(a4, 16) / 255 |
end |
elseif #args == 3 and not options.hasAlpha then |
local a1,a2,a3 = args[1], args[2], args[3] |
if type(a1) == "number" and type(a2) == "number" and type(a3) == "number" and a1 <= 1 and a2 <= 1 and a3 <= 1 then |
r,g,b = a1,a2,a3 |
elseif (type(a1) == "number" or a1:len() == 2) and a1:find("^%x*$") and (type(a2) == "number" or a2:len() == 2) and a2:find("^%x*$") and (type(a3) == "number" or a3:len() == 2) and a3:find("^%x*$") then |
r,g,b = tonumber(a1, 16) / 255, tonumber(a2, 16) / 255, tonumber(a3, 16) / 255 |
end |
end |
if not r then |
print((options.error or IS_NOT_A_VALID_OPTION_FOR):format(table.concat(args, ' '), path), realOptions.cmdName or realOptions.name or self) |
print(("|cffffff7f%s:|r %s {0-1} {0-1} {0-1}%s"):format(USAGE, path, options.hasAlpha and " {0-1}" or "")) |
return |
end |
if type(options_p.set) == "function" then |
if passValue then |
options_p.set(passValue, r,g,b,a) |
else |
options_p.set(r,g,b,a) |
end |
else |
if type(handler[options_p.set]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options_p.set))) |
end |
if passValue then |
handler[options_p.set](handler, passValue, r,g,b,a) |
else |
handler[options_p.set](handler, r,g,b,a) |
end |
end |
local r,g,b,a |
if type(options_p.get) == "function" then |
r,g,b,a = options_p.get(passValue) |
else |
if type(handler[options_p.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options_p.get))) |
end |
r,g,b,a = handler[options_p.get](handler, passValue) |
end |
local s |
if type(r) == "number" and type(g) == "number" and type(b) == "number" then |
if options.hasAlpha and type(a) == "number" then |
s = ("|c%02x%02x%02x%02x%02x%02x%02x%02x|r"):format(a*255, r*255, g*255, b*255, r*255, g*255, b*255, a*255) |
else |
s = ("|cff%02x%02x%02x%02x%02x%02x|r"):format(r*255, g*255, b*255, r*255, g*255, b*255) |
end |
else |
s = NONE |
end |
print((options.message or IS_NOW_SET_TO):format(tostring(options.cmdName or options.name), s), realOptions.cmdName or realOptions.name or self) |
else |
local r,g,b,a |
if type(options_p.get) == "function" then |
r,g,b,a = options_p.get(passValue) |
else |
if type(handler[options_p.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(options_p.get))) |
end |
r,g,b,a = handler[options_p.get](handler, passValue) |
end |
if not colorTable then |
colorTable = {} |
local t = colorTable |
if ColorPickerOkayButton then |
local ColorPickerOkayButton_OnClick = ColorPickerOkayButton:GetScript("OnClick") |
ColorPickerOkayButton:SetScript("OnClick", function() |
if ColorPickerOkayButton_OnClick then |
ColorPickerOkayButton_OnClick() |
end |
if t.active then |
ColorPickerFrame.cancelFunc = nil |
ColorPickerFrame.func = nil |
ColorPickerFrame.opacityFunc = nil |
local r,g,b,a |
if t.passValue then |
if type(t.get) == "function" then |
r,g,b,a = t.get(t.passValue) |
else |
if type(t.handler[t.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(t.get))) |
end |
r,g,b,a = t.handler[t.get](t.handler, t.passValue) |
end |
else |
if type(t.get) == "function" then |
r,g,b,a = t.get() |
else |
if type(t.handler[t.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(t.get))) |
end |
r,g,b,a = t.handler[t.get](t.handler) |
end |
end |
if r ~= t.r or g ~= t.g or b ~= t.b or (t.hasAlpha and a ~= t.a) then |
local s |
if type(r) == "number" and type(g) == "number" and type(b) == "number" then |
if t.hasAlpha and type(a) == "number" then |
s = ("|c%02x%02x%02x%02x%02x%02x%02x%02x|r"):format(a*255, r*255, g*255, b*255, r*255, g*255, b*255, a*255) |
else |
s = ("|cff%02x%02x%02x%02x%02x%02x|r"):format(r*255, g*255, b*255, r*255, g*255, b*255) |
end |
else |
s = NONE |
end |
print(t.message:format(tostring(t.name), s), t.realOptions.cmdName or t.realOptions.name or self) |
end |
for k,v in pairs(t) do |
t[k] = nil |
end |
end |
end) |
end |
else |
for k,v in pairs(colorTable) do |
colorTable[k] = nil |
end |
end |
if type(r) ~= "number" or type(g) ~= "number" or type(b) ~= "number" then |
r,g,b = 1, 1, 1 |
end |
if type(a) ~= "number" then |
a = 1 |
end |
local t = colorTable |
t.r = r |
t.g = g |
t.b = b |
if hasAlpha then |
t.a = a |
end |
t.realOptions = realOptions |
t.hasAlpha = options.hasAlpha |
t.handler = handler |
t.set = options_p.set |
t.get = options_p.get |
t.name = options.cmdName or options.name |
t.message = options.message or IS_NOW_SET_TO |
t.passValue = passValue |
t.active = true |
if not colorFunc then |
colorFunc = function() |
local r,g,b = ColorPickerFrame:GetColorRGB() |
if t.hasAlpha then |
local a = 1 - OpacitySliderFrame:GetValue() |
if type(t.set) == "function" then |
if t.passValue then |
t.set(t.passValue, r,g,b,a) |
else |
t.set(r,g,b,a) |
end |
else |
if type(t.handler[t.set]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(t.set))) |
end |
if t.passValue then |
t.handler[t.set](t.handler, t.passValue, r,g,b,a) |
else |
t.handler[t.set](t.handler, r,g,b,a) |
end |
end |
else |
if type(t.set) == "function" then |
if t.passValue then |
t.set(t.passValue, r,g,b) |
else |
t.set(r,g,b) |
end |
else |
if type(t.handler[t.set]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(t.set))) |
end |
if t.passValue then |
t.handler[t.set](t.handler, t.passValue, r,g,b) |
else |
t.handler[t.set](t.handler, r,g,b) |
end |
end |
end |
end |
end |
ColorPickerFrame.func = colorFunc |
ColorPickerFrame.hasOpacity = options.hasAlpha |
if options.hasAlpha then |
ColorPickerFrame.opacityFunc = ColorPickerFrame.func |
ColorPickerFrame.opacity = 1 - a |
end |
ColorPickerFrame:SetColorRGB(r,g,b) |
if not colorCancelFunc then |
colorCancelFunc = function() |
if t.hasAlpha then |
if type(t.set) == "function" then |
if t.passValue then |
t.set(t.passValue, t.r,t.g,t.b,t.a) |
else |
t.set(t.r,t.g,t.b,t.a) |
end |
else |
if type(t.handler[t.get]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(t.get))) |
end |
if t.passValue then |
t.handler[t.set](t.handler, t.passValue, t.r,t.g,t.b,t.a) |
else |
t.handler[t.set](t.handler, t.r,t.g,t.b,t.a) |
end |
end |
else |
if type(t.set) == "function" then |
if t.passValue then |
t.set(t.passValue, t.r,t.g,t.b) |
else |
t.set(t.r,t.g,t.b) |
end |
else |
if type(t.handler[t.set]) ~= "function" then |
AceConsole:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(t.set))) |
end |
if t.passValue then |
t.handler[t.set](t.handler, t.passValue, t.r,t.g,t.b) |
else |
t.handler[t.set](t.handler, t.r,t.g,t.b) |
end |
end |
end |
for k,v in pairs(t) do |
t[k] = nil |
end |
ColorPickerFrame.cancelFunc = nil |
ColorPickerFrame.func = nil |
ColorPickerFrame.opacityFunc = nil |
end |
end |
ColorPickerFrame.cancelFunc = colorCancelFunc |
ShowUIPanel(ColorPickerFrame) |
end |
return |
elseif kind == "group" then |
if #args == 0 then |
printUsage(self, handler, realOptions, options, path, args, passValue) |
else |
-- invalid argument |
print((options.error or IS_NOT_A_VALID_OPTION_FOR):format(args[1], path), realOptions.cmdName or realOptions.name or self) |
end |
return |
end |
this = _G_this |
if Dewdrop then |
Dewdrop:Refresh() |
end |
end |
local external |
local tmp |
function AceConsole:RegisterChatCommand(...) -- slashCommands, options, name |
local slashCommands, options, name |
if type((...)) == "string" then |
if not tmp then |
tmp = {} |
else |
for i in ipairs(tmp) do |
tmp[i] = nil |
end |
end |
for i = 1, select('#', ...)+1 do |
local v = select(i, ...) |
if type(v) == "string" then |
tmp[#tmp+1] = v |
else |
slashCommands = tmp |
options = v |
name = select(i+1, ...) |
break |
end |
end |
else |
slashCommands, options, name = ... |
end |
if type(slashCommands) ~= "table" and slashCommands ~= false then |
AceConsole:error("Bad argument #2 to `RegisterChatCommand' (expected table, got %s)", type(slashCommands)) |
end |
if not slashCommands and type(name) ~= "string" then |
AceConsole:error("Bad argument #4 to `RegisterChatCommand' (expected string, got %s)", type(name)) |
end |
if type(options) ~= "table" and type(options) ~= "function" and options ~= nil then |
AceConsole:error("Bad argument #3 to `RegisterChatCommand' (expected table, function, or nil, got %s)", type(options)) |
end |
if name then |
if type(name) ~= "string" then |
AceConsole:error("Bad argument #4 to `RegisterChatCommand' (expected string or nil, got %s)", type(name)) |
elseif not name:find("^%w+$") or name:upper() ~= name or name:len() == 0 then |
AceConsole:error("Argument #4 must be an uppercase, letters-only string with at least 1 character") |
end |
end |
if slashCommands then |
if #slashCommands == 0 then |
AceConsole:error("Argument #2 to `RegisterChatCommand' must include at least one string") |
end |
for k,v in pairs(slashCommands) do |
if type(k) ~= "number" then |
AceConsole:error("All keys in argument #2 to `RegisterChatCommand' must be numbers") |
end |
if type(v) ~= "string" then |
AceConsole:error("All values in argument #2 to `RegisterChatCommand' must be strings") |
elseif not v:find("^/[A-Za-z][A-Za-z0-9_]*$") then |
AceConsole:error("All values in argument #2 to `RegisterChatCommand' must be in the form of \"/word\"") |
end |
end |
end |
if not options then |
options = { |
type = 'group', |
args = {}, |
handler = self |
} |
end |
if type(options) == "table" then |
local err, position = validateOptions(options) |
if err then |
if position then |
AceConsole:error(position .. ": " .. err) |
else |
AceConsole:error(err) |
end |
end |
if not options.handler then |
options.handler = self |
end |
if options.handler == self and options.type:lower() == "group" and self.class then |
AceConsole:InjectAceOptionsTable(self, options) |
end |
end |
local chat |
if slashCommands then |
chat = slashCommands[1] |
else |
chat = _G["SLASH_"..name..1] |
end |
local handler |
if type(options) == "function" then |
handler = options |
for k,v in pairs(_G) do |
if handler == v then |
local k = k |
handler = function(msg) |
return _G[k](msg) |
end |
end |
end |
else |
function handler(msg) |
handlerFunc(self, chat, msg, options) |
end |
end |
if not _G.SlashCmdList then |
_G.SlashCmdList = {} |
end |
if not name and type(slashCommands) == "table" and type(slashCommands[1]) == "string" then |
name = slashCommands[1]:gsub("%A", ""):upper() |
end |
if not name then |
local A = ('A'):byte() |
repeat |
name = string.char(math.random(26) + A - 1) .. string.char(math.random(26) + A - 1) .. string.char(math.random(26) + A - 1) .. string.char(math.random(26) + A - 1) .. string.char(math.random(26) + A - 1) .. string.char(math.random(26) + A - 1) .. string.char(math.random(26) + A - 1) .. string.char(math.random(26) + A - 1) |
until not _G.SlashCmdList[name] |
end |
if slashCommands then |
if _G.SlashCmdList[name] then |
local i = 0 |
while true do |
i = i + 1 |
if _G["SLASH_"..name..i] then |
_G["SLASH_"..name..i] = nil |
else |
break |
end |
end |
end |
local i = 0 |
for _,command in ipairs(slashCommands) do |
i = i + 1 |
_G["SLASH_"..name..i] = command |
if command:lower() ~= command then |
i = i + 1 |
_G["SLASH_"..name..i] = command:lower() |
end |
end |
end |
_G.SlashCmdList[name] = handler |
if self ~= AceConsole and self.slashCommand == nil then |
self.slashCommand = chat |
end |
if not AceEvent and AceLibrary:HasInstance("AceEvent-2.0") then |
external(AceConsole, "AceEvent-2.0", AceLibrary("AceEvent-2.0")) |
end |
if AceEvent then |
if not AceConsole.nextAddon then |
AceConsole.nextAddon = {} |
end |
if type(options) == "table" then |
AceConsole.nextAddon[self] = options |
if not self.playerLogin then |
AceConsole:RegisterEvent("PLAYER_LOGIN", "PLAYER_LOGIN", true) |
end |
end |
end |
AceConsole.registry[name] = options |
if slashCommands == tmp then |
for i in ipairs(tmp) do |
tmp[i] = nil |
end |
end |
end |
function AceConsole:InjectAceOptionsTable(handler, options) |
self:argCheck(handler, 2, "table") |
self:argCheck(options, 3, "table") |
if options.type:lower() ~= "group" then |
self:error('Cannot inject into options table argument #3 if its type is not "group"') |
end |
if options.handler ~= nil and options.handler ~= handler then |
self:error("Cannot inject into options table argument #3 if it has a different handler than argument #2") |
end |
options.handler = handler |
local class = handler.class |
if not AceLibrary:HasInstance("AceOO-2.0") or not class then |
if Rock then |
-- possible Rock object |
for mixin in Rock:IterateObjectMixins(handler) do |
if type(mixin.GetAceOptionsDataTable) == "function" then |
local t = mixin:GetAceOptionsDataTable(handler) |
for k,v in pairs(t) do |
if type(options.args) ~= "table" then |
options.args = {} |
end |
if options.args[k] == nil then |
options.args[k] = v |
end |
end |
end |
end |
end |
else |
-- Ace2 object |
while class and class ~= AceLibrary("AceOO-2.0").Class do |
if type(class.GetAceOptionsDataTable) == "function" then |
local t = class:GetAceOptionsDataTable(handler) |
for k,v in pairs(t) do |
if type(options.args) ~= "table" then |
options.args = {} |
end |
if options.args[k] == nil then |
options.args[k] = v |
end |
end |
end |
local mixins = class.mixins |
if mixins then |
for mixin in pairs(mixins) do |
if type(mixin.GetAceOptionsDataTable) == "function" then |
local t = mixin:GetAceOptionsDataTable(handler) |
for k,v in pairs(t) do |
if type(options.args) ~= "table" then |
options.args = {} |
end |
if options.args[k] == nil then |
options.args[k] = v |
end |
end |
end |
end |
end |
class = class.super |
end |
end |
return options |
end |
function AceConsole:PLAYER_LOGIN() |
self.playerLogin = true |
for addon, options in pairs(self.nextAddon) do |
local err, position = validateOptionsMethods(addon, options) |
if err then |
if position then |
geterrorhandler()(tostring(addon) .. ": AceConsole: " .. position .. ": " .. err) |
else |
geterrorhandler()(tostring(addon) .. ": AceConsole: " .. err) |
end |
end |
self.nextAddon[addon] = nil |
end |
end |
function AceConsole:TabCompleteInfo(cmdpath) |
local cmd = cmdpath:match("(/%S+)") |
if not cmd then |
return |
end |
local path = cmdpath:sub(cmd:len() + 2) |
for name in pairs(SlashCmdList) do --global |
if AceConsole.registry[name] then |
local i = 0 |
while true do |
i = i + 1 |
local scmd = _G["SLASH_"..name..i] |
if not scmd then break end |
if cmd == scmd then |
return name, cmd, path |
end |
end |
end |
end |
end |
function external(self, major, instance) |
if major == "AceEvent-2.0" then |
if not AceEvent then |
AceEvent = instance |
AceEvent:embed(self) |
end |
elseif major == "AceTab-2.0" then |
instance:RegisterTabCompletion("AceConsole", "%/.*", function(t, cmdpath, pos) |
local name, cmd, path = self:TabCompleteInfo(cmdpath:sub(1, pos)) |
if not self.registry[name] then |
return false |
else |
local validArgs, _, _, handler = findTableLevel(self, self.registry[name], cmd, path or "") |
if validArgs.args then |
for arg, v in pairs(validArgs.args) do |
local hidden = v.hidden |
local handler = v.handler or handler |
if hidden then |
if type(hidden) == "function" then |
hidden = hidden(v.passValue) |
elseif type(hidden) == "string" then |
local f = hidden |
local neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
if type(handler[f]) ~= "function" then |
self:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(f))) |
end |
hidden = handler[f](handler, v.passValue) |
if neg then |
hidden = not hidden |
end |
end |
end |
local disabled = hidden or v.disabled |
if disabled then |
if type(disabled) == "function" then |
disabled = disabled(v.passValue) |
elseif type(disabled) == "string" then |
local f = disabled |
local neg = f:match("^~(.-)$") |
if neg then |
f = neg |
end |
if type(handler[f]) ~= "function" then |
self:error("%s: %s", handler, OPTION_HANDLER_NOT_FOUND:format(tostring(f))) |
end |
disabled = handler[f](handler, v.passValue) |
if neg then |
disabled = not disabled |
end |
end |
end |
if not hidden and not disabled and v.type ~= "header" then |
table.insert(t, (tostring(arg):gsub("%s", "-"))) |
end |
end |
end |
end |
end, function(u, matches, gcs, cmdpath) |
local name, cmd, path = self:TabCompleteInfo(cmdpath) |
if self.registry[name] then |
local validArgs, path2, argwork, handler = findTableLevel(self, self.registry[name], cmd, path) |
printUsage(self, validArgs.handler or handler, self.registry[name], validArgs, path2, argwork, argwork[#argwork], not gcs or gcs ~= "", gcs) |
end |
end) |
elseif major == "Dewdrop-2.0" then |
Dewdrop = instance |
end |
end |
local function activate(self, oldLib, oldDeactivate) |
AceConsole = self |
if oldLib then |
self.registry = oldLib.registry |
self.nextAddon = oldLib.nextAddon |
end |
if not self.registry then |
self.registry = {} |
else |
for name,options in pairs(self.registry) do |
self:RegisterChatCommand(false, options, name) |
end |
end |
self:RegisterChatCommand("/reload", "/rl", "/reloadui", ReloadUI, "RELOAD") |
self:RegisterChatCommand("/gm", ToggleHelpFrame, "GM") |
local t = { "/print", "/echo" } |
local _,_,_,enabled,loadable = GetAddOnInfo("DevTools") |
if not enabled and not loadable then |
table.insert(t, "/dump") |
end |
self:RegisterChatCommand(t, function(text) |
text = text:trim():match("^(.-);*$") |
local f, err = loadstring("AceLibrary('AceConsole-2.0'):PrintLiteral(" .. text .. ")") |
if not f then |
self:Print("|cffff0000Error:|r", err) |
else |
f() |
end |
end, "PRINT") |
self:activate(oldLib, oldDeactivate) |
if oldDeactivate then |
oldDeactivate(oldLib) |
end |
end |
AceLibrary:Register(AceConsole, MAJOR_VERSION, MINOR_VERSION, activate, nil, external) |
## Interface: 20400 |
## Title: Lib: AceConsole-2.0 |
## Notes: AddOn development framework |
## Author: Ace Development Team |
## LoadOnDemand: 1 |
## X-Website: http://www.wowace.com |
## X-Category: Library |
## X-License: LGPL v2.1 + MIT for AceOO-2.0 |
## Dependencies: AceLibrary, AceEvent-2.0, AceOO-2.0 |
AceConsole-2.0.lua |
--[[ |
Name: Babble-Class-2.2 |
Revision: $Rev$ |
Author(s): ckknight (ckknight@gmail.com) |
Website: http://ckknight.wowinterface.com/ |
Documentation: http://wiki.wowace.com/index.php/Babble-Class-2.2 |
SVN: http://svn.wowace.com/root/trunk/Babble-2.2/Babble-Class-2.2 |
Description: A library to provide localizations for classes. |
Dependencies: AceLibrary, AceLocale-2.2 |
License: MIT |
]] |
local MAJOR_VERSION = "Babble-Class-2.2" |
local MINOR_VERSION = tonumber(string.sub("$Revision$", 12, -3)) |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end |
if not AceLibrary:HasInstance("AceLocale-2.2") then error(MAJOR_VERSION .. " requires AceLocale-2.2") end |
local _, x = AceLibrary("AceLocale-2.2"):GetLibraryVersion() |
MINOR_VERSION = MINOR_VERSION * 100000 + x |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
local BabbleClass = AceLibrary("AceLocale-2.2"):new(MAJOR_VERSION) |
-- uncomment below for debug information |
-- BabbleClass:EnableDebugging() |
BabbleClass:RegisterTranslations("enUS", function() |
return { |
["Warlock"] = true, |
["Warrior"] = true, |
["Hunter"] = true, |
["Mage"] = true, |
["Priest"] = true, |
["Druid"] = true, |
["Paladin"] = true, |
["Shaman"] = true, |
["Rogue"] = true, |
["WARLOCK"] = true, |
["WARRIOR"] = true, |
["HUNTER"] = true, |
["MAGE"] = true, |
["PRIEST"] = true, |
["DRUID"] = true, |
["PALADIN"] = true, |
["SHAMAN"] = true, |
["ROGUE"] = true, |
} |
end) |
BabbleClass:RegisterTranslations("deDE", function() |
return { |
["Warlock"] = "Hexenmeister", |
["Warrior"] = "Krieger", |
["Hunter"] = "J\195\164ger", |
["Mage"] = "Magier", |
["Priest"] = "Priester", |
["Druid"] = "Druide", |
["Paladin"] = "Paladin", |
["Shaman"] = "Schamane", |
["Rogue"] = "Schurke", |
["WARLOCK"] = "Hexenmeisterin", |
["WARRIOR"] = "Kriegerin", |
["HUNTER"] = "J\195\164gerin", |
["MAGE"] = "Magierin", |
["PRIEST"] = "Priesterin", |
["DRUID"] = "Druidin", |
["PALADIN"] = "Paladin", |
["SHAMAN"] = "Schamanin", |
["ROGUE"] = "Schurkin", |
} |
end) |
BabbleClass:RegisterTranslations("frFR", function() |
return { |
["Warlock"] = "Démoniste", |
["Warrior"] = "Guerrier", |
["Hunter"] = "Chasseur", |
["Mage"] = "Mage", |
["Priest"] = "Prêtre", |
["Druid"] = "Druide", |
["Paladin"] = "Paladin", |
["Shaman"] = "Chaman", |
["Rogue"] = "Voleur", |
["WARRIOR"] = "Guerrière", |
["HUNTER"] = "Chasseresse", |
["PRIEST"] = "Prêtresse", |
["DRUID"] = "Druidesse", |
["SHAMAN"] = "Chamane", |
["ROGUE"] = "Voleuse", |
} |
end) |
BabbleClass:RegisterTranslations("zhCN", function() |
return { |
["Warlock"] = "æ¯å£«", |
["Warrior"] = "æ士", |
["Hunter"] = "ç人", |
["Mage"] = "æ³å¸", |
["Priest"] = "ç§å¸", |
["Druid"] = "å¾·é²ä¼", |
["Paladin"] = "å£éªå£«", |
["Shaman"] = "è¨æ»¡ç¥å¸", |
["Rogue"] = "æ½è¡è ", |
} |
end) |
BabbleClass:RegisterTranslations("zhTW", function() |
return { |
["Warlock"] = "è¡å£«", |
["Warrior"] = "æ°å£«", |
["Hunter"] = "çµäºº", |
["Mage"] = "æ³å¸«", |
["Priest"] = "ç§å¸«", |
["Druid"] = "å¾·é¯ä¼", |
["Paladin"] = "èé¨å£«", |
["Shaman"] = "è©æ»¿", |
["Rogue"] = "çè³", |
["WARLOCK"] = "è¡å£«", |
["WARRIOR"] = "æ°å£«", |
["HUNTER"] = "çµäºº", |
["MAGE"] = "æ³å¸«", |
["PRIEST"] = "ç§å¸«", |
["DRUID"] = "å¾·é¯ä¼", |
["PALADIN"] = "èé¨å£«", |
["SHAMAN"] = "è©æ»¿", |
["ROGUE"] = "çè³", |
} |
end) |
BabbleClass:RegisterTranslations("koKR", function() |
return { |
["Warlock"] = "íë§ë²ì¬", |
["Warrior"] = "ì ì¬", |
["Hunter"] = "ì¬ë¥ê¾¼", |
["Mage"] = "ë§ë²ì¬", |
["Priest"] = "ì¬ì ", |
["Druid"] = "ë루ì´ë", |
["Paladin"] = "ì±ê¸°ì¬", |
["Shaman"] = "주ì ì¬", |
["Rogue"] = "ëì ", |
["WARLOCK"] = "íë§ë²ì¬", |
["WARRIOR"] = "ì ì¬", |
["HUNTER"] = "ì¬ë¥ê¾¼", |
["MAGE"] = "ë§ë²ì¬", |
["PRIEST"] = "ì¬ì ", |
["DRUID"] = "ë루ì´ë", |
["PALADIN"] = "ì±ê¸°ì¬", |
["SHAMAN"] = "주ì ì¬", |
["ROGUE"] = "ëì ", |
} |
end) |
BabbleClass:RegisterTranslations("esES", function() |
return { |
["Warlock"] = "Brujo", |
["Warrior"] = "Guerrero", |
["Hunter"] = "Cazador", |
["Mage"] = "Mago", |
["Priest"] = "Sacerdote", |
["Druid"] = "Druida", |
["Paladin"] = "Palad\195\173n", |
["Shaman"] = "Cham\195\161n", |
["Rogue"] = "P\195\173caro", |
["WARLOCK"] = "Bruja", |
["WARRIOR"] = "Guerrera", |
["HUNTER"] = "Cazadora", |
["MAGE"] = "Maga", |
["PRIEST"] = "Sacerdotisa", |
["DRUID"] = "Druida", |
["PALADIN"] = "Palad\195\173n", |
["SHAMAN"] = "Cham\195\161n", |
["ROGUE"] = "P\195\173cara", |
} |
end) |
BabbleClass:Debug() |
BabbleClass:SetStrictness(true) |
function BabbleClass:GetColor(class) |
self:argCheck(class, 2, "string") |
if self:HasReverseTranslation(class) then |
class = string.upper(self:GetReverseTranslation(class)) |
else |
class = string.upper(class) |
end |
if RAID_CLASS_COLORS and RAID_CLASS_COLORS[class] then |
return RAID_CLASS_COLORS[class].r, RAID_CLASS_COLORS[class].g, RAID_CLASS_COLORS[class].b |
end |
return 0.63, 0.63, 0.63 |
end |
function BabbleClass:GetHexColor(class) |
self:argCheck(class, 2, "string") |
local r, g, b = self:GetColor(class) |
return string.format("%02x%02x%02x", r * 255, g * 255, b * 255) |
end |
function BabbleClass:GetGenderNeutralClass(class) |
self:argCheck(class, 2, "string") |
if self:HasReverseTranslation(class) then |
class = string.upper(self:GetReverseTranslation(class)) |
else |
class = string.upper(class) |
end |
return class |
end |
AceLibrary:Register(BabbleClass, MAJOR_VERSION, MINOR_VERSION) |
BabbleClass = nil |
## Interface: 20300 |
## LoadOnDemand: 1 |
## Title: Lib: Babble [|cffeda55fClass|r] |
## Notes: A library to help with localization. |
## Notes-deDE: BabbleLib ist eine Bibliothek, die bei der Lokalisierung helfen soll. |
## Notes-frFR: Une bibliothèque d'aide à la localisation. |
## Notes-esES: Una biblioteca para ayudar con las localizaciones. |
## Author: ckknight |
## X-eMail: ckknight@gmail.com |
## Version: 2.2.$Revision$ |
## X-Category: Library |
## OptionalDeps: Ace2 |
## X-AceLibrary-Babble-Class-2.2: true |
## X-License: MIT |
Babble-Class-2.2.lua |
--[[ |
Name: FuBarPlugin-2.0 |
Revision: $Rev$ |
Author: Cameron Kenneth Knight (ckknight@gmail.com) |
Website: http://wiki.wowace.com/index.php/FuBarPlugin-2.0 |
Documentation: http://wiki.wowace.com/index.php/FuBarPlugin-2.0 |
SVN: svn://svn.wowace.com/wowace/trunk/FuBarPlugin-2.0/FuBarPlugin-2.0/ |
Description: Plugin for FuBar. |
Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0, (optional) Tablet-2.0, Dewdrop-2.0 |
License: LGPL v2.1 |
Notes: When embeding this library, FuBar should be set as an optional dependency. |
]] |
local MAJOR_VERSION = "FuBarPlugin-2.0" |
local MINIMAPCONTAINER_MAJOR_VERSION = "FuBarPlugin-MinimapContainer-2.0" |
local MINOR_VERSION = "$Revision$" |
-- This ensures the code is only executed if the libary doesn't already exist, or is a newer version |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0.") end |
local AceEvent = AceLibrary:HasInstance("AceEvent-2.0") and AceLibrary("AceEvent-2.0") |
local Tablet = AceLibrary:HasInstance("Tablet-2.0") and AceLibrary("Tablet-2.0") |
local Dewdrop = AceLibrary:HasInstance("Dewdrop-2.0") and AceLibrary("Dewdrop-2.0") |
local AceAddon |
local epsilon = 1e-5 |
local _G = getfenv(0) |
local SHOW_ICON = "Show icon" |
local SHOW_ICON_DESC = "Show the plugins icon on the panel." |
local SHOW_TEXT = "Show text" |
local SHOW_TEXT_DESC = "Show the plugins text on the panel." |
local SHOW_COLORED_TEXT = "Show colored text" |
local SHOW_COLORED_TEXT_DESC = "Allow the plugin to color its text." |
local DETACH_TOOLTIP = "Detach tooltip" |
local DETACH_TOOLTIP_DESC = "Detach the tooltip from the panel." |
local LOCK_TOOLTIP = "Lock tooltip" |
local LOCK_TOOLTIP_DESC = "Lock the tooltips position. When the tooltip is locked, you must use Alt to access it with your mouse." |
local POSITION = "Position" |
local POSITION_DESC = "Position the plugin on the panel." |
local POSITION_LEFT = "Left" |
local POSITION_RIGHT = "Right" |
local POSITION_CENTER = "Center" |
local ATTACH_TO_MINIMAP = "Attach to minimap" |
local ATTACH_TO_MINIMAP_DESC = "Attach the plugin to the minimap instead of the panel." |
local HIDE_FUBAR_PLUGIN = "Hide plugin" |
local HIDE_FUBAR_PLUGIN_CMD = "Hidden" |
local HIDE_FUBAR_PLUGIN_DESC = "Hide the plugin from the panel or minimap, leaving the addon running." |
local OTHER = "Other" |
local CLOSE = "Close" |
local CLOSE_DESC = "Close the menu." |
if GetLocale() == "koKR" then |
SHOW_ICON = "ìì´ì½ íì" |
SHOW_ICON_DESC = "í¨ëì íë¬ê·¸ì¸ ìì´ì½ì íìí©ëë¤." |
SHOW_TEXT = "í ì¤í¸ íì" |
SHOW_TEXT_DESC = "íëì íë¬ê·¸ì¸ í ì¤í¸ë¥¼ íìí©ëë¤." |
SHOW_COLORED_TEXT = "ììíë í ì¤í¸ íì" |
SHOW_COLORED_TEXT_DESC = "íë¬ê·¸ì¸ì í ì¤í¸ ììì íì©í©ëë¤." |
DETACH_TOOLTIP = "í´í ë¶ë¦¬" |
DETACH_TOOLTIP_DESC = "í¨ëìì í´íì ë¶ë¦¬ í©ëë¤." |
LOCK_TOOLTIP = "í´í ê³ ì " |
LOCK_TOOLTIP_DESC = "í´í ìì¹ë¥¼ ê³ ì í©ëë¤." |
POSITION = "ìì¹" |
POSITION_DESC = "í¨ëìì íë¬ê·¸ì¸ì ìì¹ë¥¼ ì¤ì í©ëë¤." |
POSITION_LEFT = "ì¼ìª½" |
POSITION_RIGHT = "ì¤ë¥¸ìª½" |
POSITION_CENTER = "ê°ì´ë°" |
ATTACH_TO_MINIMAP = "미ë맵ì íì" |
ATTACH_TO_MINIMAP_DESC = "íë¬ê·¸ì¸ì í¨ë ëì 미ë맵ì íìí©ëë¤." |
HIDE_FUBAR_PLUGIN = "FuBar íë¬ê·¸ì¸ ì¨ê¸°ê¸°" |
HIDE_FUBAR_PLUGIN_CMD = "ì¨ê²¨ì§" |
HIDE_FUBAR_PLUGIN_DESC = "í¨ëìì íë¬ê·¸ì¸ì ì¨ê¹ëë¤." |
OTHER = "기í" |
CLOSE = "ë«ê¸°" |
CLOSE_DESC = "ë©ë´ ë«ê¸°." |
elseif GetLocale() == "deDE" then |
SHOW_ICON = "Zeige Icon" |
SHOW_ICON_DESC = "Zeige das Plugin-Icon auf der Leiste." |
SHOW_TEXT = "Zeige Text" |
SHOW_TEXT_DESC = "Zeige den Plugin-Text auf der Leiste." |
SHOW_COLORED_TEXT = "Zeige gef\195\164rbten Text" |
SHOW_COLORED_TEXT_DESC = "Dem Plugin erlauben sein Text zu f\195\164rben." |
DETACH_TOOLTIP = "Tooltip l\195\182sen" |
DETACH_TOOLTIP_DESC = "Tooltip von der Leiste l\195\182sen." |
LOCK_TOOLTIP = "Tooltip sperren" |
LOCK_TOOLTIP_DESC = "Tooltip an der Position sperren." |
POSITION = "Position" |
POSITION_DESC = "Positioniert das Plugin auf der Leiste." |
POSITION_LEFT = "Links" |
POSITION_RIGHT = "Rechts" |
POSITION_CENTER = "Mitte" |
ATTACH_TO_MINIMAP = "An der Minimap anbringen" |
ATTACH_TO_MINIMAP_DESC = "Bringt das Plugin an der Minimap anstelle der Leiste an." |
HIDE_FUBAR_PLUGIN = "Versteckt das FuBar Plugin" |
HIDE_FUBAR_PLUGIN_CMD = "Verstecken" |
HIDE_FUBAR_PLUGIN_DESC = "Versteckt das Plugin von der Leiste." |
CLOSE = "Schlie\195\159en" |
CLOSE_DESC = "Men\195\188 schlie\195\159en." |
elseif GetLocale() == "frFR" then |
SHOW_ICON = "Afficher l'ic\195\180ne" |
SHOW_ICON_DESC = "Afficher l'ic\195\180ne du plugin sur le panneau." |
SHOW_TEXT = "Afficher le texte" |
SHOW_TEXT_DESC = "Afficher le texte du plugin sur le panneau." |
SHOW_COLORED_TEXT = "Afficher la couleur du texte" |
SHOW_COLORED_TEXT_DESC = "Permet au plugin de colorer le texte." |
DETACH_TOOLTIP = "D\195\169tacher le tooltip" |
DETACH_TOOLTIP_DESC = "Permet de d\195\169tacher le tooltip du panneau." |
LOCK_TOOLTIP = "Bloquer le tooltip" |
LOCK_TOOLTIP_DESC = "Permet de bloquer le tooltip \195\160 sa position actuelle. Une fois le tooltip bloqu\195\169, vous devez utiliser la touche Alt pour le d\195\169placer avec votre souris." |
POSITION = "Position" |
POSITION_DESC = "Permet de changer la position du plugin dans le panneau." |
POSITION_LEFT = "Gauche" |
POSITION_RIGHT = "Droite" |
POSITION_CENTER = "Centre" |
ATTACH_TO_MINIMAP = "Attacher \195\160 la minicarte" |
ATTACH_TO_MINIMAP_DESC = "Attache l'ic\195\180ne du plugin \195\160 la minicarte." |
HIDE_FUBAR_PLUGIN = "Masquer le plugin" |
HIDE_FUBAR_PLUGIN_CMD = "Masqu\195\169" |
HIDE_FUBAR_PLUGIN_DESC = "Permet de masquer compl\195\168tement le plugin du panneau, mais laisse l'addon fonctionner." |
OTHER = "Autre" |
CLOSE = "Fermer" |
CLOSE_DESC = "Ferme le menu." |
elseif GetLocale() == "zhCN" then |
SHOW_ICON = "æ¾ç¤ºå¾æ " |
SHOW_ICON_DESC = "å¨é¢æ¿ä¸æ¾ç¤ºæ件å¾æ ã" |
SHOW_TEXT = "æ¾ç¤ºæå" |
SHOW_TEXT_DESC = "å¨é¢æ¿ä¸æ¾ç¤ºæåæ é¢ã" |
SHOW_COLORED_TEXT = "æ¾ç¤ºå½©è²æå" |
SHOW_COLORED_TEXT_DESC = "å 许æ件æ¾ç¤ºå½©è²æåã" |
DETACH_TOOLTIP = "ç¬ç«æ示信æ¯" |
DETACH_TOOLTIP_DESC = "ä»é¢æ¿ä¸ç¬ç«æ示信æ¯ã" |
LOCK_TOOLTIP = "éå®æ示信æ¯" |
LOCK_TOOLTIP_DESC = "éå®æ示信æ¯ä½ç½®ã" |
POSITION = "ä½ç½®" |
POSITION_DESC = "æ件å¨é¢æ¿ä¸çä½ç½®ã" |
POSITION_LEFT = "å± å·¦" |
POSITION_RIGHT = "å± å³" |
POSITION_CENTER = "å± ä¸" |
ATTACH_TO_MINIMAP = "ä¾éå¨å°å°å¾" |
ATTACH_TO_MINIMAP_DESC = "æ件å¾æ ä¾éå¨å°å°å¾èä¸æ¾ç¤ºå¨é¢æ¿ä¸ã" |
HIDE_FUBAR_PLUGIN = "éè FuBar æ件" |
HIDE_FUBAR_PLUGIN_CMD = "éè" |
HIDE_FUBAR_PLUGIN_DESC = "å¨é¢æ¿ä¸éè该æ件ã" |
OTHER = "å ¶ä»" |
CLOSE = "å ³é" |
CLOSE_DESC = "å ³éèå" |
elseif GetLocale() == "zhTW" then |
SHOW_ICON = "顯示å示" |
SHOW_ICON_DESC = "å¨é¢æ¿ä¸é¡¯ç¤ºæ件å示ã" |
SHOW_TEXT = "顯示æå" |
SHOW_TEXT_DESC = "å¨é¢æ¿ä¸é¡¯ç¤ºæ件æåã" |
SHOW_COLORED_TEXT = "å 許彩è²æå" |
SHOW_COLORED_TEXT_DESC = "å 許æ件å¨é¢æ¿ä¸ä½¿ç¨å½©è²æåã" |
DETACH_TOOLTIP = "ç¨ç«æ示è¨æ¯" |
DETACH_TOOLTIP_DESC = "å¾é¢æ¿ä¸ç¨ç«æ示è¨æ¯ã" |
LOCK_TOOLTIP = "éå®æ示è¨æ¯" |
LOCK_TOOLTIP_DESC = "éå®æ示è¨æ¯ä½ç½®ãç¶æ示è¨æ¯éå®æï¼éè¦ç¨Altéµä½¿ç¨æ示è¨æ¯çåè½ã" |
POSITION = "ä½ç½®" |
POSITION_DESC = "æ件å¨é¢æ¿ä¸çä½ç½®ã" |
POSITION_LEFT = "é å·¦" |
POSITION_RIGHT = "é å³" |
POSITION_CENTER = "ç½®ä¸" |
ATTACH_TO_MINIMAP = "ä¾éå¨å°å°å" |
ATTACH_TO_MINIMAP_DESC = "æ件åæ¨ä¾éå¨å°å°åèä¸é¡¯ç¤ºå¨é¢æ¿ä¸ã" |
HIDE_FUBAR_PLUGIN = "é±èæ件" |
HIDE_FUBAR_PLUGIN_CMD = "é±è" |
HIDE_FUBAR_PLUGIN_DESC = "å¨é¢æ¿æå°å°åä¸é±è該æ件ï¼ä½ä¿æå·è¡çæ ã" |
OTHER = "å ¶ä»" |
CLOSE = "éé" |
CLOSE_DESC = "ééé¸å®ã" |
elseif GetLocale() == "esES" then |
SHOW_ICON = "Mostrar icono" |
SHOW_ICON_DESC = "Muestra el icono del plugin en el panel" |
SHOW_TEXT = "Mostrar texto" |
SHOW_TEXT_DESC = "Muestra el texto del plugin en el panel" |
SHOW_COLORED_TEXT = "Mostrar el texto en color" |
SHOW_COLORED_TEXT_DESC = "Permite al plugin colorear su texto" |
DETACH_TOOLTIP = "Separar tooltip" |
DETACH_TOOLTIP_DESC = "Separa el tooltip del panel" |
LOCK_TOOLTIP = "Bloquear tooltip" |
LOCK_TOOLTIP_DESC = "Bloquea la posici\195\179n de los tooltips. Cuando el tooltip est\195\161 bloqueado debes usar Alt para acceder a \195\169l con el rat\195\179n" |
POSITION = "Posici\195\179n" |
POSITION_DESC = "Posici\195\179n del plugin en el panel" |
POSITION_LEFT = "Izquierda" |
POSITION_RIGHT = "Derecha" |
POSITION_CENTER = "Centro" |
ATTACH_TO_MINIMAP = "Adjuntar al minimapa" |
ATTACH_TO_MINIMAP_DESC = "Adjunta el plugin al minimapa en vez de al panel." |
HIDE_FUBAR_PLUGIN = "Ocultar plugin" |
HIDE_FUBAR_PLUGIN_CMD = "Oculto" |
HIDE_FUBAR_PLUGIN_DESC = "Oculta el plugin del panel o minimapa, dejando el accesorio funcionando." |
OTHER = "Otros" |
CLOSE = "Cerrar" |
CLOSE_DESC = "Cierra el men\195\186." |
end |
local AceOO = AceLibrary("AceOO-2.0") |
local FuBarPlugin = AceOO.Mixin { |
"GetTitle", |
"GetName", |
"GetCategory", |
"SetFontSize", |
"GetFrame", |
"Show", |
"Hide", |
"GetPanel", |
"IsTextColored", |
"ToggleTextColored", |
"IsMinimapAttached", |
"ToggleMinimapAttached", |
"Update", |
"UpdateDisplay", |
"UpdateData", |
"UpdateText", |
"UpdateTooltip", |
"SetIcon", |
"GetIcon", |
"CheckWidth", |
"SetText", |
"GetText", |
"IsIconShown", |
"ToggleIconShown", |
"ShowIcon", |
"HideIcon", |
"IsTextShown", |
"ToggleTextShown", |
"ShowText", |
"HideText", |
"IsTooltipDetached", |
"ToggleTooltipDetached", |
"DetachTooltip", |
"ReattachTooltip", |
"GetDefaultPosition", |
"SetPanel", |
"IsLoadOnDemand", |
"IsDisabled", |
"CreateBasicPluginFrame", |
"CreatePluginChildFrame", |
"OpenMenu", |
"AddImpliedMenuOptions", |
} |
local MinimapContainer |
local good = nil |
local function CheckFuBar() |
if not good then |
good = FuBar and tonumber(FuBar.version:sub(1, 3)) and tonumber(FuBar.version:sub(1, 3)) >= 2 and true |
end |
return good |
end |
function FuBarPlugin:GetTitle() |
local name = self.title or self.name |
if not name then |
FuBarPlugin:error("You must provide self.title or self.name") |
end |
local title = select(3, name:find("FuBar %- (.-)%s*$")) |
if not title then |
title = name |
end |
return title:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "") |
end |
function FuBarPlugin:GetName() |
return self.name |
end |
function FuBarPlugin:GetCategory() |
return self.category or OTHER |
end |
function FuBarPlugin:GetFrame() |
return self.frame |
end |
function FuBarPlugin:GetPanel() |
return self.panel |
end |
function FuBarPlugin:IsTextColored() |
return not self.db or not self.db.profile or not self.db.profile.uncolored |
end |
function FuBarPlugin:ToggleTextColored() |
if not self.db then |
FuBarPlugin:error("Cannot change text color if self.db is not available. (" .. self:GetTitle() .. ")") |
end |
self.db.profile.uncolored = not self.db.profile.uncolored or nil |
self:UpdateText() |
end |
function FuBarPlugin:ToggleMinimapAttached() |
if CheckFuBar() and not self.cannotAttachToMinimap then |
local value = self:IsMinimapAttached() |
if value then |
if self.panel then |
self.panel:RemovePlugin(self) |
end |
if self.defaultPosition == "MINIMAP" then |
FuBar:GetPanel(1):AddPlugin(self, nil, "LEFT") |
else |
FuBar:GetPanel(1):AddPlugin(self, nil, self.defaultPosition) |
end |
else |
if self.panel then |
self.panel:RemovePlugin(self) |
end |
MinimapContainer:AddPlugin(self) |
end |
end |
Dewdrop:Close() |
end |
function FuBarPlugin:IsMinimapAttached() |
if not CheckFuBar() then |
return true |
end |
return self.panel == MinimapContainer |
end |
function FuBarPlugin:Update() |
self:UpdateData() |
self:UpdateText() |
self:UpdateTooltip() |
end |
function FuBarPlugin:UpdateDisplay() |
self:UpdateText() |
self:UpdateTooltip() |
end |
function FuBarPlugin:UpdateData() |
if type(self.OnDataUpdate) == "function" then |
if not self:IsDisabled() then |
self:OnDataUpdate() |
end |
end |
end |
function FuBarPlugin:UpdateText() |
if type(self.OnTextUpdate) == "function" then |
if not self:IsDisabled() then |
self:OnTextUpdate() |
end |
elseif self:IsTextShown() then |
self:SetText(self:GetTitle()) |
end |
end |
function FuBarPlugin:RegisterTablet() |
if self.blizzardTooltip or self.overrideTooltip or not Tablet then |
return |
end |
if not Tablet:IsRegistered(self.frame) then |
if self.db and self.db.profile and not self.db.profile.detachedTooltip then |
self.db.profile.detachedTooltip = {} |
end |
Tablet:Register(self.frame, |
'children', function() |
Tablet:SetTitle(self:GetTitle()) |
if type(self.OnTooltipUpdate) == "function" then |
if not self:IsDisabled() then |
self:OnTooltipUpdate() |
end |
end |
end, |
'clickable', self.clickableTooltip, |
'data', CheckFuBar() and FuBar.db.profile.tooltip or self.db and self.db.profile.detachedTooltip or {}, |
'detachedData', self.db and self.db.profile.detachedTooltip or {}, |
'point', function(frame) |
if frame:GetTop() > GetScreenHeight() / 2 then |
local x = frame:GetCenter() |
if x < GetScreenWidth() / 3 then |
return "TOPLEFT", "BOTTOMLEFT" |
elseif x < GetScreenWidth() * 2 / 3 then |
return "TOP", "BOTTOM" |
else |
return "TOPRIGHT", "BOTTOMRIGHT" |
end |
else |
local x = frame:GetCenter() |
if x < GetScreenWidth() / 3 then |
return "BOTTOMLEFT", "TOPLEFT" |
elseif x < GetScreenWidth() * 2 / 3 then |
return "BOTTOM", "TOP" |
else |
return "BOTTOMRIGHT", "TOPRIGHT" |
end |
end |
end, |
'menu', self.OnMenuRequest and function(level, value, valueN_1, valueN_2, valueN_3, valueN_4) |
if level == 1 then |
local name = tostring(self) |
if not name:find('^table:') then |
name = name:gsub("|c%x%x%x%x%x%x%x%x(.-)|r", "%1") |
Dewdrop:AddLine( |
'text', name, |
'isTitle', true |
) |
end |
end |
if type(self.OnMenuRequest) == "function" then |
self:OnMenuRequest(level, value, true, valueN_1, valueN_2, valueN_3, valueN_4) |
elseif type(self.OnMenuRequest) == "table" then |
Dewdrop:FeedAceOptionsTable(self.OnMenuRequest) |
end |
end, |
'hideWhenEmpty', self.tooltipHiddenWhenEmpty |
) |
local func = self.frame:GetScript("OnEnter") |
local function newFunc(...) |
func(...) |
if FuBar and FuBar.IsHidingTooltipsInCombat and FuBar:IsHidingTooltipsInCombat() and InCombatLockdown() then |
local frame = this.self.frame |
if self.blizzardTooltip then |
if GameTooltip:IsOwned(self:IsMinimapAttached() and self.minimapFrame or self.frame) then |
GameTooltip:Hide() |
end |
elseif self.overrideTooltip and type(self.CloseTooltip) == "function" then |
self:CloseTooltip() |
elseif not self.overrideTooltip and Tablet and Tablet:IsAttached(frame) then |
Tablet:Close(frame) |
end |
end |
end |
self.frame:SetScript("OnEnter", newFunc) |
end |
end |
function FuBarPlugin:UpdateTooltip() |
if self.blizzardTooltip then |
if GameTooltip:IsOwned(self:IsMinimapAttached() and self.minimapFrame or self.frame) then |
GameTooltip:Hide() |
local frame = self:IsMinimapAttached() and self.minimapFrame or self.frame |
local anchor |
if frame:GetTop() > GetScreenHeight() / 2 then |
local x = frame:GetCenter() |
if x < GetScreenWidth() / 2 then |
anchor = "ANCHOR_BOTTOMRIGHT" |
else |
anchor = "ANCHOR_BOTTOMLEFT" |
end |
else |
local x = frame:GetCenter() |
if x < GetScreenWidth() / 2 then |
anchor = "ANCHOR_TOPLEFT" |
else |
anchor = "ANCHOR_TOPRIGHT" |
end |
end |
GameTooltip:SetOwner(frame, anchor) |
if type(self.OnTooltipUpdate) == "function" and not self:IsDisabled() then |
self:OnTooltipUpdate() |
end |
GameTooltip:Show() |
end |
return |
elseif self.overrideTooltip then |
if type(self.OnTooltipUpdate) == "function" and not self:IsDisabled() then |
self:OnTooltipUpdate() |
end |
return |
end |
if not Tablet then return end |
FuBarPlugin.RegisterTablet(self) |
if self:IsMinimapAttached() and not self:IsTooltipDetached() and self.minimapFrame then |
Tablet:Refresh(self.minimapFrame) |
else |
Tablet:Refresh(self.frame) |
end |
end |
function FuBarPlugin:OnProfileEnable() |
self:Update() |
end |
function FuBarPlugin:Show(panelId) |
if self.frame:IsShown() or (self.minimapFrame and self.minimapFrame:IsShown()) then |
return |
end |
if panelId ~= false then |
if self.db then |
self.db.profile.hidden = nil |
end |
end |
if self.IsActive and not self:IsActive() then |
self.panelIdTmp = panelId |
self:ToggleActive() |
self.panelIdTmp = nil |
if self.db then |
self.db.profile.disabled = nil |
end |
elseif not self.db or not self.db.profile.hidden then |
if panelId == 0 or not CheckFuBar() then |
MinimapContainer:AddPlugin(self) |
else |
FuBar:ShowPlugin(self, panelId or self.panelIdTmp) |
end |
if not self.userDefinedFrame then |
if not self:IsTextShown() then |
self.textFrame:SetText("") |
self.textFrame:SetWidth(epsilon) |
self.textFrame:Hide() |
end |
if not self:IsIconShown() then |
self.iconFrame:SetWidth(epsilon) |
self.iconFrame:Hide() |
end |
end |
if AceOO.inherits(self, "AceAddon-2.0") then |
if not AceAddon then |
AceAddon = AceLibrary("AceAddon-2.0") |
end |
if AceAddon.addonsEnabled and not AceAddon.addonsEnabled[self] then |
return |
end |
end |
self:Update() |
end |
end |
function FuBarPlugin:Hide(check) |
if not self.frame:IsShown() and (not self.minimapFrame or not self.minimapFrame:IsShown()) then |
return |
end |
if self.hideWithoutStandby and self.db and check ~= false then |
self.db.profile.hidden = true |
end |
if not self.hideWithoutStandby then |
if self.db and not self.overrideTooltip and not self.blizzardTooltip and not self.cannotDetachTooltip and self:IsTooltipDetached() and self.db.profile.detachedTooltip and self.db.profile.detachedTooltip.detached then |
self:ReattachTooltip() |
self.db.profile.detachedTooltip.detached = true |
end |
if self.IsActive and self:IsActive() and self.ToggleActive and (not CheckFuBar() or not FuBar:IsChangingProfile()) then |
self:ToggleActive() |
end |
end |
if self.panel then |
self.panel:RemovePlugin(self) |
end |
self.frame:Hide() |
if self.minimapFrame then |
self.minimapFrame:Hide() |
end |
if Dewdrop:IsOpen(self.frame) or (self.minimapFrame and Dewdrop:IsOpen(self.minimapFrame)) then |
Dewdrop:Close() |
end |
end |
function FuBarPlugin:SetIcon(path) |
if not path then |
return |
end |
FuBarPlugin:argCheck(path, 2, "string", "boolean") |
if not self.hasIcon then |
FuBarPlugin:error("Cannot set icon unless self.hasIcon is set. (" .. self:GetTitle() .. ")") |
end |
if not self.iconFrame then |
return |
end |
if type(path) ~= "string" then |
path = format("Interface\\AddOns\\%s\\icon", FuBarPlugin.folderNames[self] or self.folderName) |
elseif not path:find('^Interface[\\/]') then |
path = format("Interface\\AddOns\\%s\\%s", FuBarPlugin.folderNames[self] or self.folderName, path) |
end |
if path:sub(1, 16) == "Interface\\Icons\\" then |
self.iconFrame:SetTexCoord(0.05, 0.95, 0.05, 0.95) |
else |
self.iconFrame:SetTexCoord(0, 1, 0, 1) |
end |
self.iconFrame:SetTexture(path) |
if self.minimapIcon then |
if path:sub(1, 16) == "Interface\\Icons\\" then |
self.minimapIcon:SetTexCoord(0.05, 0.95, 0.05, 0.95) |
else |
self.minimapIcon:SetTexCoord(0, 1, 0, 1) |
end |
self.minimapIcon:SetTexture(path) |
end |
end |
function FuBarPlugin:GetIcon() |
if self.hasIcon then |
return self.iconFrame:GetTexture() |
end |
end |
function FuBarPlugin:CheckWidth(force) |
FuBarPlugin:argCheck(force, 2, "boolean", "nil") |
if (self.iconFrame and self.iconFrame:IsShown()) or (self.textFrame and self.textFrame:IsShown()) then |
if (self.db and self.db.profile and not self:IsIconShown()) or not self.hasIcon then |
self.iconFrame:SetWidth(epsilon) |
end |
local width |
if not self.hasNoText then |
self.textFrame:SetHeight(0) |
self.textFrame:SetWidth(500) |
width = self.textFrame:GetStringWidth() + 1 |
self.textFrame:SetWidth(width) |
self.textFrame:SetHeight(self.textFrame:GetHeight()) |
end |
if self.hasNoText or not self.textFrame:IsShown() then |
self.frame:SetWidth(self.iconFrame:GetWidth()) |
if self.panel and self.panel:GetPluginSide(self) == "CENTER" then |
self.panel:UpdateCenteredPosition() |
end |
elseif force or not self.textWidth or self.textWidth < width or self.textWidth - 8 > width then |
self.textWidth = width |
self.textFrame:SetWidth(width) |
if self.iconFrame and self.iconFrame:IsShown() then |
self.frame:SetWidth(width + self.iconFrame:GetWidth()) |
else |
self.frame:SetWidth(width) |
end |
if self.panel and self.panel:GetPluginSide(self) == "CENTER" then |
self.panel:UpdateCenteredPosition() |
end |
end |
end |
end |
function FuBarPlugin:SetText(text) |
if not self.textFrame then |
return |
end |
if self.hasNoText then |
FuBarPlugin:error("Cannot set text if self.hasNoText has been set. (" .. self:GetTitle() .. ")") |
end |
FuBarPlugin:argCheck(text, 2, "string", "number") |
if text == "" then |
if self.hasIcon then |
self:ShowIcon() |
else |
text = self:GetTitle() |
end |
end |
if not self:IsTextColored() then |
text = text:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "") |
end |
self.textFrame:SetText(text) |
self:CheckWidth() |
end |
function FuBarPlugin:GetText() |
if not self.textFrame then |
FuBarPlugin:error("Cannot get text without a self.textFrame (" .. self:GetTitle() .. ")") |
end |
if not self.hasNoText then |
return self.textFrame:GetText() or "" |
end |
end |
function FuBarPlugin:IsIconShown() |
if not self.hasIcon then |
return false |
elseif self.hasNoText then |
return true |
elseif not self.db then |
return true |
elseif self.db and self.db.profile.showIcon == nil then |
return true |
else |
return (self.db and (self.db.profile.showIcon == 1 or self.db.profile.showIcon == true)) and true or false |
end |
end |
function FuBarPlugin:ToggleIconShown() |
if not self.iconFrame then |
FuBarPlugin:error("Cannot toggle icon without a self.iconFrame (" .. self:GetTitle() .. ")") |
end |
if not self.hasIcon then |
FuBarPlugin:error("Cannot show icon unless self.hasIcon is set. (" .. self:GetTitle() .. ")") |
end |
if self.hasNoText then |
FuBarPlugin:error("Cannot hide icon if self.hasNoText is set. (" .. self:GetTitle() .. ")") |
end |
if not self.textFrame then |
FuBarPlugin:error("Cannot hide icon if self.textFrame is not set. (" .. self:GetTitle() .. ")") |
end |
if not self.iconFrame then |
FuBarPlugin:error("Cannot hide icon if self.iconFrame is not set. (" .. self:GetTitle() .. ")") |
end |
if not self.db then |
FuBarPlugin:error("Cannot hide icon if self.db is not available. (" .. self:GetTitle() .. ")") |
end |
local value = not self:IsIconShown() |
self.db.profile.showIcon = value |
if value then |
if not self:IsTextShown() and self.textFrame:IsShown() and self.textFrame:GetText() == self:GetTitle() then |
self.textFrame:Hide() |
self.textFrame:SetText("") |
end |
self.iconFrame:Show() |
self.iconFrame:SetWidth(self.iconFrame:GetHeight()) |
else |
if not self.textFrame:IsShown() or not self.textFrame:GetText() then |
self.textFrame:Show() |
self.textFrame:SetText(self:GetTitle()) |
end |
self.iconFrame:Hide() |
self.iconFrame:SetWidth(epsilon) |
end |
self:CheckWidth(true) |
return value |
end |
function FuBarPlugin:ShowIcon() |
if not self:IsIconShown() then |
self:ToggleIconShown() |
end |
end |
function FuBarPlugin:HideIcon() |
if self:IsIconShown() then |
self:ToggleIconShown() |
end |
end |
function FuBarPlugin:IsTextShown() |
if self.hasNoText then |
return false |
elseif not self.hasIcon then |
return true |
elseif not self.db then |
return true |
elseif self.db and self.db.profile.showText == nil then |
return true |
else |
return (self.db and (self.db.profile.showText == 1 or self.db.profile.showText == true)) and true or false |
end |
end |
function FuBarPlugin:ToggleTextShown() |
if self.cannotHideText then |
FuBarPlugin:error("Cannot hide text unless self.cannotHideText is unset. (" .. self:GetTitle() .. ")") |
end |
if not self.hasIcon then |
FuBarPlugin:error("Cannot show text unless self.hasIcon is set. (" .. self:GetTitle() .. ")") |
end |
if self.hasNoText then |
FuBarPlugin:error("Cannot hide text if self.hasNoText is set. (" .. self:GetTitle() .. ")") |
end |
if not self.textFrame then |
FuBarPlugin:error("Cannot hide text if self.textFrame is not set. (" .. self:GetTitle() .. ")") |
end |
if not self.iconFrame then |
FuBarPlugin:error("Cannot hide text if self.iconFrame is not set. (" .. self:GetTitle() .. ")") |
end |
if not self.db then |
FuBarPlugin:error("Cannot hide text if self.db is not available. (" .. self:GetTitle() .. ")") |
end |
local value = not self:IsTextShown() |
self.db.profile.showText = value |
if value then |
self.textFrame:Show() |
self:UpdateText() |
else |
self.textFrame:SetText("") |
self.textFrame:SetWidth(epsilon) |
self.textFrame:Hide() |
if not self:IsIconShown() then |
DropDownList1:Hide() |
end |
self:ShowIcon() |
end |
self:CheckWidth(true) |
return value |
end |
function FuBarPlugin:ShowText() |
if not self:IsTextShown() then |
self:ToggleTextShown() |
end |
end |
function FuBarPlugin:HideText() |
if self:IsTextShown() then |
self:ToggleTextShown() |
end |
end |
function FuBarPlugin:IsTooltipDetached() |
if self.blizzardTooltip or self.overrideTooltip or not Tablet then return end |
FuBarPlugin.RegisterTablet(self) |
return not Tablet:IsAttached(self.frame) |
end |
function FuBarPlugin:ToggleTooltipDetached() |
if self.blizzardTooltip or self.overrideTooltip or not Tablet then return end |
FuBarPlugin.RegisterTablet(self) |
if self:IsTooltipDetached() then |
Tablet:Attach(self.frame) |
else |
Tablet:Detach(self.frame) |
end |
if Dewdrop then Dewdrop:Close() end |
end |
function FuBarPlugin:DetachTooltip() |
if self.blizzardTooltip or self.overrideTooltip or not Tablet then return end |
FuBarPlugin.RegisterTablet(self) |
Tablet:Detach(self.frame) |
end |
function FuBarPlugin:ReattachTooltip() |
if self.blizzardTooltip or self.overrideTooltip or not Tablet then return end |
FuBarPlugin.RegisterTablet(self) |
Tablet:Attach(self.frame) |
end |
function FuBarPlugin:GetDefaultPosition() |
return self.defaultPosition or "LEFT" |
end |
local function IsCorrectPanel(panel) |
if type(panel) ~= "table" then |
return false |
elseif type(panel.AddPlugin) ~= "function" then |
return false |
elseif type(panel.RemovePlugin) ~= "function" then |
return false |
elseif type(panel.GetNumPlugins) ~= "function" then |
return false |
elseif type(panel:GetNumPlugins()) ~= "number" then |
return false |
elseif type(panel.GetPlugin) ~= "function" then |
return false |
elseif type(panel.HasPlugin) ~= "function" then |
return false |
elseif type(panel.GetPluginSide) ~= "function" then |
return false |
end |
return true |
end |
function FuBarPlugin:SetPanel(panel) |
if panel and not IsCorrectPanel(panel) then |
FuBarPlugin:error("Bad argument #2 to `SetPanel'. Panel does not have the correct API.") |
end |
self.panel = panel |
end |
function FuBarPlugin:SetFontSize(size) |
if self.userDefinedFrame then |
FuBarPlugin:error((self.name and self.name .. ": " or "") .. "You must provide a SetFontSize(size) method if you provide your own frame.") |
end |
if self.hasIcon then |
if not self.iconFrame then |
FuBarPlugin:error((self.name and self.name .. ": " or "") .. "No iconFrame found") |
end |
self.iconFrame:SetWidth(size + 3) |
self.iconFrame:SetHeight(size + 3) |
end |
if not self.hasNoText then |
if not self.textFrame then |
FuBarPlugin:error((self.name and self.name .. ": " or "") .. "No textFrame found") |
end |
local font, _, flags = self.textFrame:GetFont() |
self.textFrame:SetFont(font, size, flags) |
end |
self:CheckWidth() |
end |
function FuBarPlugin:IsLoadOnDemand() |
return IsAddOnLoadOnDemand(FuBarPlugin.folderNames[self] or self.folderName) |
end |
function FuBarPlugin:IsDisabled() |
return self.IsActive and not self:IsActive() or false |
end |
function FuBarPlugin:OnInstanceInit(target) |
if not AceEvent then |
self:error(MAJOR_VERSION .. " requires AceEvent-2.0.") |
elseif not Dewdrop then |
self:error(MAJOR_VERSION .. " requires Dewdrop-2.0.") |
end |
self.registry[target] = true |
local folderName |
for i = 6, 3, -1 do |
folderName = debugstack(i, 1, 0):match("\\AddOns\\(.*)\\") |
if folderName then |
break |
end |
end |
target.folderName = folderName |
self.folderNames[target] = folderName |
end |
FuBarPlugin.OnManualEmbed = FuBarPlugin.OnInstanceInit |
local frame_OnClick, frame_OnDoubleClick, frame_OnMouseDown, frame_OnMouseUp, frame_OnReceiveDrag, frame_OnEnter, frame_OnLeave |
function FuBarPlugin:CreateBasicPluginFrame(name) |
local frame = CreateFrame("Button", name, UIParent) |
frame:SetFrameStrata("HIGH") |
frame:SetFrameLevel(7) |
frame:EnableMouse(true) |
frame:EnableMouseWheel(true) |
frame:SetMovable(true) |
frame:SetWidth(150) |
frame:SetHeight(24) |
frame:SetPoint("CENTER", UIParent, "CENTER") |
frame.self = self |
if not frame_OnEnter then |
function frame_OnEnter() |
local self = this.self |
if self.blizzardTooltip then |
GameTooltip:SetOwner(self:IsMinimapAttached() and self.minimapFrame or self.frame, "ANCHOR_CURSOR") |
self:UpdateTooltip() |
end |
if type(self.OnEnter) == "function" then |
self:OnEnter() |
end |
end |
end |
frame:SetScript("OnEnter", frame_OnEnter) |
if not frame_OnLeave then |
function frame_OnLeave() |
local self = this.self |
if type(self.OnLeave) == "function" then |
self:OnLeave() |
end |
if self.blizzardTooltip and GameTooltip:IsOwned(self:IsMinimapAttached() and self.minimapFrame or self.frame) then |
GameTooltip:Hide() |
end |
end |
end |
frame:SetScript("OnLeave", frame_OnLeave) |
if not frame_OnClick then |
function frame_OnClick() |
if this.self:IsMinimapAttached() and this.dragged then return end |
if type(this.self.OnClick) == "function" then |
this.self:OnClick(arg1) |
end |
end |
end |
frame:SetScript("OnClick", frame_OnClick) |
if not frame_OnDoubleClick then |
function frame_OnDoubleClick() |
if type(this.self.OnDoubleClick) == "function" then |
this.self:OnDoubleClick(arg1) |
end |
end |
end |
frame:SetScript("OnDoubleClick", frame_OnDoubleClick) |
if not frame_OnMouseDown then |
function frame_OnMouseDown() |
if arg1 == "RightButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then |
this.self:OpenMenu() |
return |
else |
HideDropDownMenu(1) |
if type(this.self.OnMouseDown) == "function" then |
this.self:OnMouseDown(arg1) |
end |
end |
end |
end |
frame:SetScript("OnMouseDown", frame_OnMouseDown) |
if not frame_OnMouseUp then |
function frame_OnMouseUp() |
if type(this.self.OnMouseUp) == "function" then |
this.self:OnMouseUp(arg1) |
end |
end |
end |
frame:SetScript("OnMouseUp", frame_OnMouseUp) |
if not frame_OnReceiveDrag then |
function frame_OnReceiveDrag() |
if (this.self:IsMinimapAttached() and not this.dragged) and type(this.self.OnReceiveDrag) == "function" then |
this.self:OnReceiveDrag() |
end |
end |
end |
frame:SetScript("OnReceiveDrag", frame_OnReceiveDrag) |
return frame |
end |
local child_OnEnter, child_OnLeave, child_OnClick, child_OnDoubleClick, child_OnMouseDown, child_OnMouseUp, child_OnReceiveDrag |
function FuBarPlugin:CreatePluginChildFrame(frameType, name, parent) |
if not self.frame then |
FuBarPlugin:error((self.name and self.name .. ": " or "") .. "You must have self.frame declared in order to add child frames") |
end |
FuBarPlugin:argCheck(frameType, 1, "string") |
local child = CreateFrame(frameType, name, parent) |
if parent then |
child:SetFrameLevel(parent:GetFrameLevel() + 2) |
end |
child.self = self |
if not child_OnEnter then |
function child_OnEnter(...) |
if this.self.frame:GetScript("OnEnter") then |
this.self.frame:GetScript("OnEnter")(...) |
end |
end |
end |
child:SetScript("OnEnter", child_OnEnter) |
if not child_OnLeave then |
function child_OnLeave(...) |
if this.self.frame:GetScript("OnLeave") then |
this.self.frame:GetScript("OnLeave")(...) |
end |
end |
end |
child:SetScript("OnLeave", child_OnLeave) |
if child:HasScript("OnClick") then |
if not child_OnClick then |
function child_OnClick(...) |
if this.self.frame:HasScript("OnClick") and this.self.frame:GetScript("OnClick") then |
this.self.frame:GetScript("OnClick")(...) |
end |
end |
end |
child:SetScript("OnClick", child_OnClick) |
end |
if child:HasScript("OnDoubleClick") then |
if not child_OnDoubleClick then |
function child_OnDoubleClick(...) |
if this.self.frame:HasScript("OnDoubleClick") and this.self.frame:GetScript("OnDoubleClick") then |
this.self.frame:GetScript("OnDoubleClick")(...) |
end |
end |
end |
child:SetScript("OnDoubleClick", child_OnDoubleClick) |
end |
if not child_OnMouseDown then |
function child_OnMouseDown(...) |
if this.self.frame:HasScript("OnMouseDown") and this.self.frame:GetScript("OnMouseDown") then |
this.self.frame:GetScript("OnMouseDown")(...) |
end |
end |
end |
child:SetScript("OnMouseDown", child_OnMouseDown) |
if not child_OnMouseUp then |
function child_OnMouseUp(...) |
if this.self.frame:HasScript("OnMouseUp") and this.self.frame:GetScript("OnMouseUp") then |
this.self.frame:GetScript("OnMouseUp")(...) |
end |
end |
end |
child:SetScript("OnMouseUp", child_OnMouseUp) |
if not child_OnReceiveDrag then |
function child_OnReceiveDrag(this) |
if this.self.frame:HasScript("OnReceiveDrag") and this.self.frame:GetScript("OnReceiveDrag") then |
this.self.frame:GetScript("OnReceiveDrag")() |
end |
end |
end |
child:SetScript("OnReceiveDrag", child_OnReceiveDrag) |
return child |
end |
function FuBarPlugin:OpenMenu(frame) |
if not frame then |
frame = self:IsMinimapAttached() and self.minimapFrame or self.frame |
end |
if not frame:IsVisible() then |
frame = UIParent |
end |
if not frame or not self:GetFrame() or Dewdrop:IsOpen(frame) then |
Dewdrop:Close() |
return |
end |
if self.blizzardTooltip then |
if GameTooltip:IsOwned(frame) then |
GameTooltip:Hide() |
end |
elseif self.overrideTooltip and type(self.CloseTooltip) == "function" then |
self:CloseTooltip() |
elseif not self.overrideTooltip and Tablet then |
Tablet:Close() |
end |
if not Dewdrop:IsRegistered(self:GetFrame()) then |
if type(self.OnMenuRequest) == "table" and (not self.OnMenuRequest.handler or self.OnMenuRequest.handler == self) and self.OnMenuRequest.type == "group" then |
Dewdrop:InjectAceOptionsTable(self, self.OnMenuRequest) |
if self.OnMenuRequest.args and CheckFuBar() and not self.independentProfile then |
self.OnMenuRequest.args.profile = nil |
end |
end |
Dewdrop:Register(self:GetFrame(), |
'children', type(self.OnMenuRequest) == "table" and self.OnMenuRequest or function(level, value, valueN_1, valueN_2, valueN_3, valueN_4) |
if level == 1 then |
if not self.hideMenuTitle then |
Dewdrop:AddLine( |
'text', self:GetTitle(), |
'isTitle', true |
) |
end |
if self.OnMenuRequest then |
self:OnMenuRequest(level, value, false, valueN_1, valueN_2, valueN_3, valueN_4) |
end |
if not self.overrideMenu then |
if self.MenuSettings and not self.hideMenuTitle then |
Dewdrop:AddLine() |
end |
self:AddImpliedMenuOptions() |
end |
else |
if not self.overrideMenu and self:AddImpliedMenuOptions() then |
else |
if self.OnMenuRequest then |
self:OnMenuRequest(level, value, false, valueN_1, valueN_2, valueN_3, valueN_4) |
end |
end |
end |
if level == 1 then |
Dewdrop:AddLine( |
'text', CLOSE, |
'tooltipTitle', CLOSE, |
'tooltipText', CLOSE_DESC, |
'func', Dewdrop.Close, |
'arg1', Dewdrop |
) |
end |
end, |
'point', function(frame) |
local x, y = frame:GetCenter() |
local leftRight |
if x < GetScreenWidth() / 2 then |
leftRight = "LEFT" |
else |
leftRight = "RIGHT" |
end |
if y < GetScreenHeight() / 2 then |
return "BOTTOM" .. leftRight, "TOP" .. leftRight |
else |
return "TOP" .. leftRight, "BOTTOM" .. leftRight |
end |
end, |
'dontHook', true |
) |
end |
if frame == self:GetFrame() then |
Dewdrop:Open(self:GetFrame()) |
elseif frame ~= UIParent then |
Dewdrop:Open(frame, self:GetFrame()) |
else |
Dewdrop:Open(frame, self:GetFrame(), 'cursorX', true, 'cursorY', true) |
end |
end |
local impliedMenuOptions |
function FuBarPlugin:AddImpliedMenuOptions(level) |
FuBarPlugin:argCheck(level, 2, "number", "nil") |
if not impliedMenuOptions then |
impliedMenuOptions = {} |
end |
if not impliedMenuOptions[self] then |
impliedMenuOptions[self] = { type = 'group', args = {} } |
Dewdrop:InjectAceOptionsTable(self, impliedMenuOptions[self]) |
if impliedMenuOptions[self].args and CheckFuBar() and not self.independentProfile then |
impliedMenuOptions[self].args.profile = nil |
end |
end |
return Dewdrop:FeedAceOptionsTable(impliedMenuOptions[self], level and level - 1) |
end |
function FuBarPlugin.OnEmbedInitialize(FuBarPlugin, self) |
if not self.frame then |
local name = "FuBarPlugin" .. self:GetTitle() .. "Frame" |
local frame = _G[name] |
if not frame or not _G[name .. "Text"] or not _G[name .. "Icon"] then |
frame = self:CreateBasicPluginFrame(name) |
local icon = frame:CreateTexture(name .. "Icon", "ARTWORK") |
icon:SetWidth(16) |
icon:SetHeight(16) |
icon:SetPoint("LEFT", frame, "LEFT") |
local text = frame:CreateFontString(name .. "Text", "ARTWORK") |
text:SetWidth(134) |
text:SetHeight(24) |
text:SetPoint("LEFT", icon, "RIGHT", 0, 1) |
text:SetFontObject(GameFontNormal) |
end |
self.frame = frame |
self.textFrame = _G[name .. "Text"] |
self.iconFrame = _G[name .. "Icon"] |
else |
self.userDefinedFrame = true |
end |
self.frame.plugin = self |
self.frame:SetParent(UIParent) |
self.frame:SetPoint("RIGHT", UIParent, "LEFT", -5, 0) |
self.frame:Hide() |
if self.hasIcon then |
self:SetIcon(self.hasIcon) |
end |
if CheckFuBar() then |
FuBar:RegisterPlugin(self) |
end |
end |
local CheckShow = function(self, panelId) |
if not self.frame:IsShown() and (not self.minimapFrame or not self.minimapFrame:IsShown()) then |
self:Show(panelId) |
Dewdrop:Refresh(2) |
end |
end |
local recheckPlugins |
local AceConsole |
function FuBarPlugin.OnEmbedEnable(FuBarPlugin, self) |
if not self.userDefinedFrame then |
if self:IsIconShown() then |
self.iconFrame:Show() |
else |
self.iconFrame:Hide() |
end |
end |
self:CheckWidth(true) |
if not self.hideWithoutStandby or (self.db and not self.db.profile.hidden) then |
if FuBarPlugin.enabledPlugins[self] then |
CheckShow(self, self.panelIdTmp) |
else |
FuBarPlugin:ScheduleEvent("FuBarPlugin-CheckShow-" .. tostring(self), CheckShow, 0, self, self.panelIdTmp) |
end |
end |
FuBarPlugin.enabledPlugins[self] = true |
if not self.blizzardTooltip and not self.overrideTooltip and not self.cannotDetachTooltip and self.db and self.db.profile.detachedTooltip and self.db.profile.detachedTooltip.detached then |
FuBarPlugin:ScheduleEvent("FuBarPlugin-DetachTooltip-" .. tostring(self), self.DetachTooltip, 0, self) |
end |
if self:IsLoadOnDemand() and CheckFuBar() then |
if not FuBar.db.profile.loadOnDemand then |
FuBar.db.profile.loadOnDemand = {} |
end |
if not FuBar.db.profile.loadOnDemand[FuBarPlugin.folderNames[self] or self.folderName] then |
FuBar.db.profile.loadOnDemand[FuBarPlugin.folderNames[self] or self.folderName] = {} |
end |
FuBar.db.profile.loadOnDemand[FuBarPlugin.folderNames[self] or self.folderName].disabled = nil |
end |
if CheckFuBar() and AceLibrary:HasInstance("AceConsole-2.0") then |
if not recheckPlugins then |
if not AceConsole then |
AceConsole = AceLibrary("AceConsole-2.0") |
end |
recheckPlugins = function() |
for k,v in pairs(AceConsole.registry) do |
if type(v) == "table" and v.args and AceOO.inherits(v.handler, FuBarPlugin) and not v.handler.independentProfile then |
v.args.profile = nil |
end |
end |
end |
end |
FuBarPlugin:ScheduleEvent("FuBarPlugin-recheckPlugins", recheckPlugins, 0) |
end |
end |
function FuBarPlugin.OnEmbedDisable(FuBarPlugin, self) |
self:Hide(false) |
if self:IsLoadOnDemand() and CheckFuBar() then |
if not FuBar.db.profile.loadOnDemand then |
FuBar.db.profile.loadOnDemand = {} |
end |
if not FuBar.db.profile.loadOnDemand[FuBarPlugin.folderNames[self] or self.folderName] then |
FuBar.db.profile.loadOnDemand[FuBarPlugin.folderNames[self] or self.folderName] = {} |
end |
FuBar.db.profile.loadOnDemand[FuBarPlugin.folderNames[self] or self.folderName].disabled = true |
end |
end |
function FuBarPlugin.OnEmbedProfileEnable(FuBarPlugin, self) |
self:Update() |
if self.db and self.db.profile then |
if not self.db.profile.detachedTooltip then |
self.db.profile.detachedTooltip = {} |
end |
if not self.blizzardTooltip and not self.overrideTooltip and Tablet then |
if Tablet.registry[self.frame] then |
Tablet:UpdateDetachedData(self.frame, self.db.profile.detachedTooltip) |
else |
FuBarPlugin.RegisterTablet(self) |
end |
end |
if MinimapContainer:HasPlugin(self) then |
MinimapContainer:ReadjustLocation(self) |
end |
end |
end |
function FuBarPlugin.GetAceOptionsDataTable(FuBarPlugin, self) |
return { |
icon = { |
type = "toggle", |
name = SHOW_ICON, |
desc = SHOW_ICON_DESC, |
set = "ToggleIconShown", |
get = "IsIconShown", |
hidden = function() |
return not self.hasIcon or self.hasNoText or self:IsDisabled() or self:IsMinimapAttached() or not self.db |
end, |
order = -13.7, |
handler = self, |
}, |
text = { |
type = "toggle", |
name = SHOW_TEXT, |
desc = SHOW_TEXT_DESC, |
set = "ToggleTextShown", |
get = "IsTextShown", |
hidden = function() |
return self.cannotHideText or not self.hasIcon or self.hasNoText or self:IsDisabled() or self:IsMinimapAttached() or not self.db |
end, |
order = -13.6, |
handler = self, |
}, |
colorText = { |
type = "toggle", |
name = SHOW_COLORED_TEXT, |
desc = SHOW_COLORED_TEXT_DESC, |
set = "ToggleTextColored", |
get = "IsTextColored", |
hidden = function() |
return self.userDefinedFrame or self.hasNoText or self.hasNoColor or self:IsDisabled() or self:IsMinimapAttached() or not self.db |
end, |
order = -13.5, |
handler = self, |
}, |
detachTooltip = { |
type = "toggle", |
name = DETACH_TOOLTIP, |
desc = DETACH_TOOLTIP_DESC, |
get = "IsTooltipDetached", |
set = "ToggleTooltipDetached", |
hidden = function() |
return not Tablet or self.blizzardTooltip or self.overrideTooltip or self.cannotDetachTooltip or self:IsDisabled() |
end, |
order = -13.4, |
handler = self, |
}, |
lockTooltip = { |
type = "toggle", |
name = LOCK_TOOLTIP, |
desc = LOCK_TOOLTIP_DESC, |
get = function() |
return Tablet:IsLocked(self.frame) |
end, |
set = function() |
return Tablet:ToggleLocked(self.frame) |
end, |
disabled = function() |
return not self:IsTooltipDetached() |
end, |
hidden = function() |
return not Tablet or self.blizzardTooltip or self.overrideTooltip or self.cannotDetachTooltip or self:IsDisabled() |
end, |
order = -13.3, |
handler = self, |
}, |
position = { |
type = "text", |
name = POSITION, |
desc = POSITION_DESC, |
validate = { |
LEFT = POSITION_LEFT, |
CENTER = POSITION_CENTER, |
RIGHT = POSITION_RIGHT |
}, |
get = function() |
return self.panel and self.panel:GetPluginSide(self) |
end, |
set = function(value) |
if self.panel then |
self.panel:SetPluginSide(self, value) |
end |
end, |
hidden = function() |
return self:IsMinimapAttached() or self:IsDisabled() or not self.panel |
end, |
order = -13.2, |
handler = self, |
}, |
minimapAttach = { |
type = "toggle", |
name = ATTACH_TO_MINIMAP, |
desc = ATTACH_TO_MINIMAP_DESC, |
get = "IsMinimapAttached", |
set = "ToggleMinimapAttached", |
hidden = function() |
return (self.cannotAttachToMinimap and not self:IsMinimapAttached()) or not CheckFuBar() or self:IsDisabled() |
end, |
order = -13.1, |
handler = self, |
}, |
hide = { |
type = "toggle", |
cmdName = HIDE_FUBAR_PLUGIN_CMD, |
guiName = HIDE_FUBAR_PLUGIN, |
desc = HIDE_FUBAR_PLUGIN_DESC, |
get = function() |
return not self.frame:IsShown() and (not self.minimapFrame or not self.minimapFrame:IsShown()) |
end, |
set = function() |
if not self.frame:IsShown() and (not self.minimapFrame or not self.minimapFrame:IsShown()) then |
self:Show() |
else |
self:Hide() |
end |
end, |
hidden = function() |
return not self.hideWithoutStandby or self:IsDisabled() |
end, |
order = -13, |
handler = self, |
}, |
} |
end |
local function activate(self, oldLib, oldDeactivate) |
FuBarPlugin = self |
if oldLib then |
self.registry = oldLib.registry |
self.folderNames = oldLib.folderNames |
self.enabledPlugins = oldLib.enabledPlugins |
end |
if not self.registry then |
self.registry = {} |
end |
if not self.folderNames then |
self.folderNames = {} |
end |
if not self.enabledPlugins then |
self.enabledPlugins = {} |
end |
FuBarPlugin.activate(self, oldLib, oldDeactivate) |
if oldDeactivate then |
oldDeactivate(oldLib) |
end |
end |
local function external(self, major, instance) |
if major == "AceEvent-2.0" then |
AceEvent = instance |
AceEvent:embed(self) |
elseif major == "Tablet-2.0" then |
Tablet = instance |
elseif major == "Dewdrop-2.0" then |
Dewdrop = instance |
end |
end |
AceLibrary:Register(FuBarPlugin, MAJOR_VERSION, MINOR_VERSION, activate, nil, external) |
MinimapContainer = {} |
local minimap_OnMouseDown, minimap_OnMouseUp |
function MinimapContainer:AddPlugin(plugin) |
if CheckFuBar() and FuBar:IsChangingProfile() then |
return |
end |
if plugin.panel ~= nil then |
plugin.panel:RemovePlugin(plugin) |
end |
plugin.panel = self |
if not plugin.minimapFrame then |
local frame = CreateFrame("Button", plugin.frame:GetName() .. "MinimapButton", Minimap) |
plugin.minimapFrame = frame |
frame.plugin = plugin |
frame:SetWidth(31) |
frame:SetHeight(31) |
frame:SetFrameStrata("BACKGROUND") |
frame:SetFrameLevel(4) |
frame:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight") |
local icon = frame:CreateTexture(frame:GetName() .. "Icon", "BACKGROUND") |
plugin.minimapIcon = icon |
local path = plugin:GetIcon() or (plugin.iconFrame and plugin.iconFrame:GetTexture()) or "Interface\\Icons\\INV_Misc_QuestionMark" |
icon:SetTexture(path) |
if path:sub(1, 16) == "Interface\\Icons\\" then |
icon:SetTexCoord(0.05, 0.95, 0.05, 0.95) |
else |
icon:SetTexCoord(0, 1, 0, 1) |
end |
icon:SetWidth(20) |
icon:SetHeight(20) |
icon:SetPoint("TOPLEFT", frame, "TOPLEFT", 7, -5) |
local overlay = frame:CreateTexture(frame:GetName() .. "Overlay","OVERLAY") |
overlay:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder") |
overlay:SetWidth(53) |
overlay:SetHeight(53) |
overlay:SetPoint("TOPLEFT",frame,"TOPLEFT") |
frame:EnableMouse(true) |
frame:RegisterForClicks("LeftButtonUp") |
frame.self = plugin |
if not frame_OnEnter then |
function frame_OnEnter() |
if type(this.self.OnEnter) == "function" then |
this.self:OnEnter() |
end |
end |
end |
frame:SetScript("OnEnter", frame_OnEnter) |
if not frame_OnLeave then |
function frame_OnLeave() |
if type(this.self.OnLeave) == "function" then |
this.self:OnLeave() |
end |
end |
end |
frame:SetScript("OnLeave", frame_OnLeave) |
if not frame_OnClick then |
function frame_OnClick() |
if this.self:IsMinimapAttached() and this.dragged then return end |
if type(this.self.OnClick) == "function" then |
this.self:OnClick(arg1) |
end |
end |
end |
frame:SetScript("OnClick", frame_OnClick) |
if not frame_OnDoubleClick then |
function frame_OnDoubleClick() |
if type(this.self.OnDoubleClick) == "function" then |
this.self:OnDoubleClick(arg1) |
end |
end |
end |
frame:SetScript("OnDoubleClick", frame_OnDoubleClick) |
if not frame_OnReceiveDrag then |
function frame_OnReceiveDrag() |
if (this.self:IsMinimapAttached() and not this.dragged) and type(this.self.OnReceiveDrag) == "function" then |
this.self:OnReceiveDrag() |
end |
end |
end |
frame:SetScript("OnReceiveDrag", frame_OnReceiveDrag) |
if not minimap_OnMouseDown then |
function minimap_OnMouseDown() |
this.dragged = false |
if arg1 == "LeftButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then |
HideDropDownMenu(1) |
if type(this.self.OnMouseDown) == "function" then |
this.self:OnMouseDown(arg1) |
end |
elseif arg1 == "RightButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then |
this.self:OpenMenu(this) |
else |
HideDropDownMenu(1) |
if type(this.self.OnMouseDown) == "function" then |
this.self:OnMouseDown(arg1) |
end |
end |
if this.self.OnClick or this.self.OnMouseDown or this.self.OnMouseUp or this.self.OnDoubleClick then |
if this.self.minimapIcon:GetTexture():sub(1, 16) == "Interface\\Icons\\" then |
this.self.minimapIcon:SetTexCoord(0.14, 0.86, 0.14, 0.86) |
else |
this.self.minimapIcon:SetTexCoord(0.1, 0.9, 0.1, 0.9) |
end |
end |
end |
end |
frame:SetScript("OnMouseDown", minimap_OnMouseDown) |
if not minimap_OnMouseUp then |
function minimap_OnMouseUp() |
if not this.dragged and type(this.self.OnMouseUp) == "function" then |
this.self:OnMouseUp(arg1) |
end |
if this.self.minimapIcon:GetTexture():sub(1, 16) == "Interface\\Icons\\" then |
this.self.minimapIcon:SetTexCoord(0.05, 0.95, 0.05, 0.95) |
else |
this.self.minimapIcon:SetTexCoord(0, 1, 0, 1) |
end |
end |
end |
frame:SetScript("OnMouseUp", minimap_OnMouseUp) |
frame:RegisterForDrag("LeftButton") |
frame:SetScript("OnDragStart", self.OnDragStart) |
frame:SetScript("OnDragStop", self.OnDragStop) |
if not plugin.blizzardTooltip and not plugin.overrideTooltip and Tablet then |
-- Note that we have to do this after :SetScript("OnEnter"), etc, |
-- so that Tablet-2.0 can override it properly. |
FuBarPlugin.RegisterTablet(plugin) |
Tablet:Register(frame, plugin.frame) |
end |
end |
plugin.frame:Hide() |
plugin.minimapFrame:Show() |
self:ReadjustLocation(plugin) |
table.insert(self.plugins, plugin) |
local exists = false |
return true |
end |
function MinimapContainer:RemovePlugin(index) |
if CheckFuBar() and FuBar:IsChangingProfile() then |
return |
end |
if type(index) == "table" then |
index = self:IndexOfPlugin(index) |
if not index then |
return |
end |
end |
local t = self.plugins |
local plugin = t[index] |
assert(plugin.panel == self, "Plugin has improper panel field") |
plugin:SetPanel(nil) |
table.remove(t, index) |
return true |
end |
function MinimapContainer:ReadjustLocation(plugin) |
local frame = plugin.minimapFrame |
if plugin.db and plugin.db.profile.minimapPositionWild then |
frame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", plugin.db.profile.minimapPositionX, plugin.db.profile.minimapPositionY) |
elseif not plugin.db and plugin.minimapPositionWild then |
frame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", plugin.minimapPositionX, plugin.minimapPositionY) |
else |
local position |
if plugin.db then |
position = plugin.db.profile.minimapPosition or plugin.defaultMinimapPosition or math.random(1, 360) |
else |
position = plugin.minimapPosition or plugin.defaultMinimapPosition or math.random(1, 360) |
end |
local angle = math.rad(position or 0) |
local x,y |
local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND" |
local cos = math.cos(angle) |
local sin = math.sin(angle) |
local round = true |
if minimapShape == "ROUND" then |
-- do nothing |
elseif minimapShape == "SQUARE" then |
round = false |
elseif minimapShape == "CORNER-TOPRIGHT" then |
if cos < 0 or sin < 0 then |
round = false |
end |
elseif minimapShape == "CORNER-TOPLEFT" then |
if cos > 0 or sin < 0 then |
round = false |
end |
elseif minimapShape == "CORNER-BOTTOMRIGHT" then |
if cos < 0 or sin > 0 then |
round = false |
end |
elseif minimapShape == "CORNER-BOTTOMLEFT" then |
if cos > 0 or sin > 0 then |
round = false |
end |
elseif minimapShape == "SIDE-LEFT" then |
if cos > 0 then |
round = false |
end |
elseif minimapShape == "SIDE-RIGHT" then |
if cos < 0 then |
round = false |
end |
elseif minimapShape == "SIDE-TOP" then |
if sin < 0 then |
round = false |
end |
elseif minimapShape == "SIDE-BOTTOM" then |
if sin > 0 then |
round = false |
end |
elseif minimapShape == "TRICORNER-TOPRIGHT" then |
if cos < 0 and sin < 0 then |
round = false |
end |
elseif minimapShape == "TRICORNER-TOPLEFT" then |
if cos > 0 and sin < 0 then |
round = false |
end |
elseif minimapShape == "TRICORNER-BOTTOMRIGHT" then |
if cos < 0 and sin > 0 then |
round = false |
end |
elseif minimapShape == "TRICORNER-BOTTOMLEFT" then |
if cos > 0 and sin > 0 then |
round = false |
end |
end |
if round then |
x = cos * 80 |
y = sin * 80 |
else |
x = 80 * 2^0.5 * cos |
y = 80 * 2^0.5 * sin |
if x < -80 then |
x = -80 |
elseif x > 80 then |
x = 80 |
end |
if y < -80 then |
y = -80 |
elseif y > 80 then |
y = 80 |
end |
end |
frame:SetPoint("CENTER", Minimap, "CENTER", x, y) |
end |
end |
function MinimapContainer:GetPlugin(index) |
return self.plugins[index] |
end |
function MinimapContainer:GetNumPlugins() |
return #self.plugins |
end |
function MinimapContainer:IndexOfPlugin(plugin) |
for i,p in ipairs(self.plugins) do |
if p == plugin then |
return i, "MINIMAP" |
end |
end |
end |
function MinimapContainer:HasPlugin(plugin) |
return self:IndexOfPlugin(plugin) ~= nil |
end |
function MinimapContainer:GetPluginSide(plugin) |
local index = self:IndexOfPlugin(plugin) |
assert(index, "Plugin not in panel") |
return "MINIMAP" |
end |
function MinimapContainer.OnDragStart() |
this.dragged = true |
this:LockHighlight() |
this:SetScript("OnUpdate", MinimapContainer.OnUpdate) |
if this.self.minimapIcon:GetTexture():sub(1, 16) == "Interface\\Icons\\" then |
this.self.minimapIcon:SetTexCoord(0.05, 0.95, 0.05, 0.95) |
else |
this.self.minimapIcon:SetTexCoord(0, 1, 0, 1) |
end |
end |
function MinimapContainer.OnDragStop() |
this:SetScript("OnUpdate", nil) |
this:UnlockHighlight() |
end |
function MinimapContainer.OnUpdate() |
if not IsAltKeyDown() then |
local mx, my = Minimap:GetCenter() |
local px, py = GetCursorPosition() |
local scale = UIParent:GetEffectiveScale() |
px, py = px / scale, py / scale |
local position = math.deg(math.atan2(py - my, px - mx)) |
if position <= 0 then |
position = position + 360 |
elseif position > 360 then |
position = position - 360 |
end |
if this.self.db then |
this.self.db.profile.minimapPosition = position |
this.self.db.profile.minimapPositionX = nil |
this.self.db.profile.minimapPositionY = nil |
this.self.db.profile.minimapPositionWild = nil |
else |
this.self.minimapPosition = position |
this.self.minimapPositionX = nil |
this.self.minimapPositionY = nil |
this.self.minimapPositionWild = nil |
end |
else |
local px, py = GetCursorPosition() |
local scale = UIParent:GetEffectiveScale() |
px, py = px / scale, py / scale |
if this.self.db then |
this.self.db.profile.minimapPositionX = px |
this.self.db.profile.minimapPositionY = py |
this.self.db.profile.minimapPosition = nil |
this.self.db.profile.minimapPositionWild = true |
else |
this.self.minimapPositionX = px |
this.self.minimapPositionY = py |
this.self.minimapPosition = nil |
this.self.minimapPositionWild = true |
end |
end |
MinimapContainer:ReadjustLocation(this.self) |
end |
local function activate(self, oldLib, oldDeactivate) |
MinimapContainer = self |
if oldLib then |
self.plugins = oldLib.plugins |
end |
if not self.plugins then |
self.plugins = {} |
end |
if oldDeactivate then |
oldDeactivate(oldLib) |
end |
end |
AceLibrary:Register(MinimapContainer, MINIMAPCONTAINER_MAJOR_VERSION, MINOR_VERSION, activate) |
--[[ |
Name: Roster-2.1 |
Revision: $Revision$ |
X-ReleaseDate: $Date$ |
Author: Maia (maia.proudmoore@gmail.com) |
Website: http://www.wowace.com/ |
Documentation: http://www.wowace.com/wiki/Roster-2.1 |
SVN: http://svn.wowace.com/wowace/trunk/RosterLib/ |
Description: Party/raid roster management |
Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0 |
]] |
local MAJOR_VERSION = "Roster-2.1" |
local MINOR_VERSION = "$Revision$" |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end |
if not AceLibrary:HasInstance("AceEvent-2.0") then error(MAJOR_VERSION .. " requires AceEvent-2.0") end |
local unknownUnits = {} |
local Lib = {} |
local roster |
local new, del |
do |
local cache = setmetatable({}, {__mode='k'}) |
function new() |
local t = next(cache) |
if t then |
cache[t] = nil |
return t |
else |
return {} |
end |
end |
function del(t) |
for k in pairs(t) do |
t[k] = nil |
end |
cache[t] = true |
return nil |
end |
end |
local LegitimateUnits = {player = true, pet = true, playerpet = true, target = true, focus = true, mouseover = true, npc = true, NPC = true} |
for i = 1, 4 do |
LegitimateUnits["party" .. i] = true |
LegitimateUnits["partypet" .. i] = true |
LegitimateUnits["party" .. i .. "pet"] = true |
end |
for i = 1, 40 do |
LegitimateUnits["raid" .. i] = true |
LegitimateUnits["raidpet" .. i] = true |
LegitimateUnits["raid" .. i .. "pet"] = true |
end |
setmetatable(LegitimateUnits, {__index=function(self, key) |
if type(key) ~= "string" then |
return false |
end |
if key:find("target$") and not key:find("^npc") then |
local value = self[key:sub(1, -7)] |
self[key] = value |
return value |
end |
self[key] = false |
return false |
end}) |
------------------------------------------------ |
-- activate, enable, disable |
------------------------------------------------ |
local function activate(self, oldLib, oldDeactivate) |
Lib = self |
if oldLib then |
if oldLib.roster then self.roster = oldLib.roster end |
oldLib:UnregisterAllEvents() |
oldLib:CancelAllScheduledEvents() |
end |
if not self.roster then self.roster = {} end |
if oldDeactivate then oldDeactivate(oldLib) end |
roster = self.roster |
end |
local function external(self, major, instance) |
if major == "AceEvent-2.0" then |
instance:embed(self) |
if instance:IsFullyInitialized() then |
self:AceEvent_FullyInitialized() |
else |
self:RegisterEvent("AceEvent_FullyInitialized") |
end |
end |
end |
------------------------------------------------ |
-- Internal functions |
------------------------------------------------ |
function Lib:AceEvent_FullyInitialized() |
self:TriggerEvent("RosterLib_Enabled") |
self:RegisterBucketEvent({"RAID_ROSTER_UPDATE", "PARTY_MEMBERS_CHANGED"}, 0.2, "ScanFullRoster") |
self:RegisterBucketEvent("UNIT_PET", 0.2, "ScanPet") |
self:ScanFullRoster() |
end |
------------------------------------------------ |
-- Unit iterator |
------------------------------------------------ |
local UnitIterator |
do |
local rmem, pmem, step, count |
local function SelfIterator() |
while step do |
local unit |
if step == 1 then |
-- STEP 1: player |
unit = "player" |
step = 2 |
elseif step == 2 then |
-- STEP 2: pet |
unit = "pet" |
step = nil |
end |
if unit and UnitExists(unit) then return unit end |
end |
end |
local function SelfAndPartyIterator() |
while step do |
local unit |
if step <= 2 then |
unit = SelfIterator() |
if not step then step = 3 end |
elseif step == 3 then |
-- STEP 3: party units |
unit = string.format("party%d", count) |
step = 4 |
elseif step == 4 then |
-- STEP 4: party pets |
unit = string.format("partypet%d", count) |
count = count + 1 |
step = count <= pmem and 3 or nil |
end |
if unit and UnitExists(unit) then return unit end |
end |
end |
local function RaidIterator() |
while step do |
local unit |
if step == 1 then |
-- STEP 1: raid units |
unit = string.format("raid%d", count) |
step = 2 |
elseif step == 2 then |
-- STEP 2: raid pets |
unit = string.format("raidpet%d", count) |
count = count + 1 |
step = count <= rmem and 1 or nil |
end |
if unit and UnitExists(unit) then return unit end |
end |
end |
function UnitIterator() |
rmem = GetNumRaidMembers() |
step = 1 |
if rmem == 0 then |
pmem = GetNumPartyMembers() |
if pmem == 0 then |
return SelfIterator, false |
else |
count = 1 |
return SelfAndPartyIterator, false |
end |
else |
count = 1 |
return RaidIterator, true |
end |
end |
end |
------------------------------------------------ |
-- Roster code |
------------------------------------------------ |
local rosterScanCache = {} |
function Lib:ScanFullRoster() |
local changed |
local it, isInRaid = UnitIterator() |
-- save all units we currently have, this way we can check who to remove from roster later. |
for name in pairs(roster) do |
rosterScanCache[name] = true |
end |
-- update data |
for unitid in it do |
local name, unitchanged = self:CreateOrUpdateUnit(unitid, isInRaid) |
-- we successfully added a unit, so we don't need to remove it next step |
if name then |
rosterScanCache[name] = nil |
if unitchanged then |
changed = true |
end |
end |
end |
-- clear units we had in roster that either left the raid or are unknown for some reason. |
for name in pairs(rosterScanCache) do |
self:RemoveUnit(name) |
rosterScanCache[name] = nil |
changed = true |
end |
self:ProcessRoster() |
if changed then |
self:TriggerEvent("RosterLib_RosterUpdated") |
end |
end |
function Lib:ScanPet(owner_list) |
local changed |
for owner in pairs(owner_list) do |
local unitid = self:GetPetFromOwner(owner) |
if not unitid then return end |
if not UnitExists(unitid) then |
unknownUnits[unitid] = nil |
-- find the pet in the roster we need to delete |
for _,u in pairs(roster) do |
if u.unitid == unitid then |
self:RemoveUnit(u.name) |
changed = true |
end |
end |
else |
changed = select(2, self:CreateOrUpdateUnit(unitid)) |
end |
self:ProcessRoster() |
end |
if changed then |
self:TriggerEvent("RosterLib_RosterUpdated") |
end |
end |
function Lib:GetPetFromOwner(id) |
-- convert party3 crap to raid IDs when in raid. |
local owner = self:GetUnitIDFromUnit(id) |
if not owner then return end |
-- get ID |
if owner:find("raid") then |
return owner:gsub("raid", "raidpet") |
elseif owner:find("party") then |
return owner:gsub("party", "partypet") |
elseif owner == "player" then |
return "pet" |
else |
return nil |
end |
end |
function Lib:ScanUnknownUnits() |
local changed |
for unitid in pairs(unknownUnits) do |
local name, c |
if UnitExists(unitid) then |
name, c = self:CreateOrUpdateUnit(unitid) |
else |
unknownUnits[unitid] = nil |
end |
-- some pets never have a name. too bad for them, farewell! |
if not name and unitid:find("pet") then |
unknownUnits[unitid] = nil |
else |
changed = changed or c |
end |
end |
self:ProcessRoster() |
if changed then |
self:TriggerEvent("RosterLib_RosterUpdated") |
end |
end |
function Lib:ProcessRoster() |
if next(unknownUnits, nil) then |
self:CancelScheduledEvent("ScanUnknownUnits") |
self:ScheduleEvent("ScanUnknownUnits", self.ScanUnknownUnits, 1, self) |
end |
end |
function Lib:CreateOrUpdateUnit(unitid, isInRaid) |
if not LegitimateUnits[unitid] then |
Lib:error("Bad argument #2 to `CreateOrUpdateUnit'. %q is not a legitimate UnitID.", unitid) |
end |
-- check for name |
local name = UnitName(unitid) |
if name and name ~= UNKNOWNOBJECT and name ~= UKNOWNBEING then |
local unit = roster[name] |
local isPet = unitid:find("pet") |
-- clear stuff |
unknownUnits[unitid] = nil |
-- return if a pet attempts to replace a player name |
-- this doesnt fix the problem with 2 pets overwriting each other FIXME |
if isPet and unit and unit.class ~= "PET" then |
return name |
end |
-- save old data if existing |
local old_name, old_unitid, old_class, old_rank, old_subgroup, old_online, old_role, old_ML |
if unit then |
old_name = unit.name |
old_unitid = unit.unitid |
old_class = unit.class |
old_rank = unit.rank |
old_subgroup = unit.subgroup |
old_online = unit.online |
old_role = unit.role |
old_ML = unit.ML |
else |
-- object |
unit = new() |
roster[name] = unit |
end |
local new_name, new_unitid, new_class, new_rank, new_subgroup, new_online, new_role, new_ML |
-- name |
new_name = name |
-- unitid |
new_unitid = unitid |
-- class |
if isPet then |
new_class = "PET" |
else |
new_class = select(2, UnitClass(unitid)) |
end |
if isInRaid == nil and GetNumRaidMembers() > 0 then |
isInRaid = true |
end |
-- subgroup and rank |
new_subgroup = 1 |
new_rank = 0 |
if isInRaid then |
local num = select(3, unitid:find("(%d+)")) |
if num then |
local _ |
new_rank, new_subgroup, _, _, _, _, _, _, new_role, new_ML = select(2, GetRaidRosterInfo(num)) |
end |
else |
new_rank = UnitIsPartyLeader(new_unitid) and 2 or 0 |
end |
-- online/offline status |
new_online = UnitIsConnected(unitid) |
-- compare data |
if not old_name |
or new_name ~= old_name |
or new_unitid ~= old_unitid |
or new_class ~= old_class |
or new_subgroup ~= old_subgroup |
or new_rank ~= old_rank |
or new_online ~= old_online |
or new_role ~= old_role |
or new_ML ~= old_ML |
then |
unit.name = new_name |
unit.unitid = new_unitid |
unit.class = new_class |
unit.subgroup = new_subgroup |
unit.rank = new_rank |
unit.online = new_online |
unit.role = new_role |
unit.ML = new_ML |
self:TriggerEvent("RosterLib_UnitChanged", |
new_unitid, new_name, new_class, new_subgroup, new_rank, |
old_name, old_unitid, old_class, old_subgroup, old_rank, |
new_role, new_ML, |
old_role, old_ML) |
return name, true |
end |
return name |
else |
unknownUnits[unitid] = true |
return false |
end |
end |
function Lib:RemoveUnit(name) |
local r = roster[name] |
roster[name] = nil |
self:TriggerEvent("RosterLib_UnitChanged", |
nil, nil, nil, nil, nil, |
r.name, r.unitid, r.class, r.subgroup, r.rank, |
nil, nil, |
r.role, r.ML) |
r = del(r) |
end |
------------------------------------------------ |
-- API |
------------------------------------------------ |
function Lib:GetUnitIDFromName(name) |
if roster[name] then |
return roster[name].unitid |
else |
return nil |
end |
end |
function Lib:GetUnitIDFromUnit(unit) |
if not LegitimateUnits[unit] then |
Lib:error("Bad argument #2 to `GetUnitIDFromUnit'. %q is not a legitimate UnitID.", unit) |
end |
local name = UnitName(unit) |
if name and roster[name] then |
return roster[name].unitid |
else |
return nil |
end |
end |
function Lib:GetUnitObjectFromName(name) |
return roster[name] |
end |
function Lib:GetUnitObjectFromUnit(unit) |
if not LegitimateUnits[unit] then |
Lib:error("Bad argument #2 to `GetUnitObjectFromUnit'. %q is not a legitimate UnitID.", unit) |
end |
local name = UnitName(unit) |
return roster[name] |
end |
local function iter(t) |
local key = t.key |
local pets = t.pets |
repeat |
key = next(roster, key) |
if not key then |
t = del(t) |
return nil |
end |
until (pets or roster[key].class ~= "PET") |
t.key = key |
return roster[key] |
end |
function Lib:IterateRoster(pets) |
local t = new() |
t.pets = pets |
return iter, t |
end |
AceLibrary:Register(Lib, MAJOR_VERSION, MINOR_VERSION, activate, nil, external) |
--[[ |
Name: AceLibrary |
Revision: $Rev$ |
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) |
Inspired By: Iriel (iriel@vigilance-committee.org) |
Tekkub (tekkub@gmail.com) |
Revision: $Rev$ |
Website: http://www.wowace.com/ |
Documentation: http://www.wowace.com/index.php/AceLibrary |
SVN: http://svn.wowace.com/root/trunk/Ace2/AceLibrary |
Description: Versioning library to handle other library instances, upgrading, |
and proper access. |
It also provides a base for libraries to work off of, providing |
proper error tools. It is handy because all the errors occur in the |
file that called it, not in the library file itself. |
Dependencies: None |
License: LGPL v2.1 |
]] |
local ACELIBRARY_MAJOR = "AceLibrary" |
local ACELIBRARY_MINOR = "$Revision$" |
local _G = getfenv(0) |
local previous = _G[ACELIBRARY_MAJOR] |
if previous and not previous:IsNewVersion(ACELIBRARY_MAJOR, ACELIBRARY_MINOR) then return end |
do |
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info |
-- LibStub is hereby placed in the Public Domain -- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke |
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! |
local LibStub = _G[LIBSTUB_MAJOR] |
if not LibStub or LibStub.minor < LIBSTUB_MINOR then |
LibStub = LibStub or {libs = {}, minors = {} } |
_G[LIBSTUB_MAJOR] = LibStub |
LibStub.minor = LIBSTUB_MINOR |
function LibStub:NewLibrary(major, minor) |
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") |
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") |
local oldminor = self.minors[major] |
if oldminor and oldminor >= minor then return nil end |
self.minors[major], self.libs[major] = minor, self.libs[major] or {} |
return self.libs[major], oldminor |
end |
function LibStub:GetLibrary(major, silent) |
if not self.libs[major] and not silent then |
error(("Cannot find a library instance of %q."):format(tostring(major)), 2) |
end |
return self.libs[major], self.minors[major] |
end |
function LibStub:IterateLibraries() return pairs(self.libs) end |
setmetatable(LibStub, { __call = LibStub.GetLibrary }) |
end |
end |
local LibStub = _G.LibStub |
-- If you don't want AceLibrary to enable libraries that are LoadOnDemand but |
-- disabled in the addon screen, set this to true. |
local DONT_ENABLE_LIBRARIES = nil |
local function safecall(func,...) |
local success, err = pcall(func,...) |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("\n(.-: )in.-\n") or "") .. err) end |
end |
-- @table AceLibrary |
-- @brief System to handle all versioning of libraries. |
local AceLibrary = {} |
local AceLibrary_mt = {} |
setmetatable(AceLibrary, AceLibrary_mt) |
local function error(self, message, ...) |
if type(self) ~= "table" then |
return _G.error(("Bad argument #1 to `error' (table expected, got %s)"):format(type(self)), 2) |
end |
local stack = debugstack() |
if not message then |
local second = stack:match("\n(.-)\n") |
message = "error raised! " .. second |
else |
local arg = { ... } -- not worried about table creation, as errors don't happen often |
for i = 1, #arg do |
arg[i] = tostring(arg[i]) |
end |
for i = 1, 10 do |
table.insert(arg, "nil") |
end |
message = message:format(unpack(arg)) |
end |
if getmetatable(self) and getmetatable(self).__tostring then |
message = ("%s: %s"):format(tostring(self), message) |
elseif type(rawget(self, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self:GetLibraryVersion()) then |
message = ("%s: %s"):format(self:GetLibraryVersion(), message) |
elseif type(rawget(self, 'class')) == "table" and type(rawget(self.class, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self.class:GetLibraryVersion()) then |
message = ("%s: %s"):format(self.class:GetLibraryVersion(), message) |
end |
local first = stack:gsub("\n.*", "") |
local file = first:gsub(".*\\(.*).lua:%d+: .*", "%1") |
file = file:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") |
local i = 0 |
for s in stack:gmatch("\n([^\n]*)") do |
i = i + 1 |
if not s:find(file .. "%.lua:%d+:") and not s:find("%(tail call%)") then |
file = s:gsub("^.*\\(.*).lua:%d+: .*", "%1") |
file = file:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") |
break |
end |
end |
local j = 0 |
for s in stack:gmatch("\n([^\n]*)") do |
j = j + 1 |
if j > i and not s:find(file .. "%.lua:%d+:") and not s:find("%(tail call%)") then |
return _G.error(message, j+1) |
end |
end |
return _G.error(message, 2) |
end |
local type = type |
local function argCheck(self, arg, num, kind, kind2, kind3, kind4, kind5) |
if type(num) ~= "number" then |
return error(self, "Bad argument #3 to `argCheck' (number expected, got %s)", type(num)) |
elseif type(kind) ~= "string" then |
return error(self, "Bad argument #4 to `argCheck' (string expected, got %s)", type(kind)) |
end |
arg = type(arg) |
if arg ~= kind and arg ~= kind2 and arg ~= kind3 and arg ~= kind4 and arg ~= kind5 then |
local stack = debugstack() |
local func = stack:match("`argCheck'.-([`<].-['>])") |
if not func then |
func = stack:match("([`<].-['>])") |
end |
if kind5 then |
return error(self, "Bad argument #%s to %s (%s, %s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, kind5, arg) |
elseif kind4 then |
return error(self, "Bad argument #%s to %s (%s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, arg) |
elseif kind3 then |
return error(self, "Bad argument #%s to %s (%s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, arg) |
elseif kind2 then |
return error(self, "Bad argument #%s to %s (%s or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, arg) |
else |
return error(self, "Bad argument #%s to %s (%s expected, got %s)", tonumber(num) or 0/0, func, kind, arg) |
end |
end |
end |
local pcall |
do |
local function check(self, ret, ...) |
if not ret then |
local s = ... |
return error(self, (s:gsub(".-%.lua:%d-: ", ""))) |
else |
return ... |
end |
end |
function pcall(self, func, ...) |
return check(self, _G.pcall(func, ...)) |
end |
end |
local recurse = {} |
local function addToPositions(t, major) |
if not AceLibrary.positions[t] or AceLibrary.positions[t] == major then |
rawset(t, recurse, true) |
AceLibrary.positions[t] = major |
for k,v in pairs(t) do |
if type(v) == "table" and not rawget(v, recurse) then |
addToPositions(v, major) |
end |
if type(k) == "table" and not rawget(k, recurse) then |
addToPositions(k, major) |
end |
end |
local mt = getmetatable(t) |
if mt and not rawget(mt, recurse) then |
addToPositions(mt, major) |
end |
rawset(t, recurse, nil) |
end |
end |
local function svnRevisionToNumber(text) |
local kind = type(text) |
if kind == "number" or tonumber(text) then |
return tonumber(text) |
elseif kind == "string" then |
if text:find("^%$Revision: (%d+) %$$") then |
return tonumber((text:match("^%$Revision: (%d+) %$$"))) |
elseif text:find("^%$Rev: (%d+) %$$") then |
return tonumber((text:match("^%$Rev: (%d+) %$$"))) |
elseif text:find("^%$LastChangedRevision: (%d+) %$$") then |
return tonumber((text:match("^%$LastChangedRevision: (%d+) %$$"))) |
end |
end |
return nil |
end |
local crawlReplace |
do |
local recurse = {} |
local function func(t, to, from) |
if recurse[t] then |
return |
end |
recurse[t] = true |
local mt = getmetatable(t) |
setmetatable(t, nil) |
rawset(t, to, rawget(t, from)) |
rawset(t, from, nil) |
for k,v in pairs(t) do |
if v == from then |
t[k] = to |
elseif type(v) == "table" then |
if not recurse[v] then |
func(v, to, from) |
end |
end |
if type(k) == "table" then |
if not recurse[k] then |
func(k, to, from) |
end |
end |
end |
setmetatable(t, mt) |
if mt then |
if mt == from then |
setmetatable(t, to) |
elseif not recurse[mt] then |
func(mt, to, from) |
end |
end |
end |
function crawlReplace(t, to, from) |
func(t, to, from) |
for k in pairs(recurse) do |
recurse[k] = nil |
end |
end |
end |
-- @function destroyTable |
-- @brief remove all the contents of a table |
-- @param t table to destroy |
local function destroyTable(t) |
setmetatable(t, nil) |
for k,v in pairs(t) do |
t[k] = nil |
end |
end |
local function isFrame(frame) |
return type(frame) == "table" and type(rawget(frame, 0)) == "userdata" and type(rawget(frame, 'IsFrameType')) == "function" and getmetatable(frame) and type(rawget(getmetatable(frame), '__index')) == "function" |
end |
-- @function copyTable |
-- @brief Create a shallow copy of a table and return it. |
-- @param from The table to copy from |
-- @return A shallow copy of the table |
local function copyTable(from, to) |
if not to then |
to = {} |
end |
for k,v in pairs(from) do |
to[k] = v |
end |
setmetatable(to, getmetatable(from)) |
return to |
end |
-- @function deepTransfer |
-- @brief Fully transfer all data, keeping proper previous table |
-- backreferences stable. |
-- @param to The table with which data is to be injected into |
-- @param from The table whose data will be injected into the first |
-- @param saveFields If available, a shallow copy of the basic data is saved |
-- in here. |
-- @param list The account of table references |
-- @param list2 The current status on which tables have been traversed. |
local deepTransfer |
do |
-- @function examine |
-- @brief Take account of all the table references to be shared |
-- between the to and from tables. |
-- @param to The table with which data is to be injected into |
-- @param from The table whose data will be injected into the first |
-- @param list An account of the table references |
local function examine(to, from, list, major) |
list[from] = to |
for k,v in pairs(from) do |
if rawget(to, k) and type(from[k]) == "table" and type(to[k]) == "table" and not list[from[k]] then |
if from[k] == to[k] then |
list[from[k]] = to[k] |
elseif AceLibrary.positions[from[v]] ~= major and AceLibrary.positions[from[v]] then |
list[from[k]] = from[k] |
elseif not list[from[k]] then |
examine(to[k], from[k], list, major) |
end |
end |
end |
return list |
end |
function deepTransfer(to, from, saveFields, major, list, list2) |
setmetatable(to, nil) |
if not list then |
list = {} |
list2 = {} |
examine(to, from, list, major) |
end |
list2[to] = to |
for k,v in pairs(to) do |
if type(rawget(from, k)) ~= "table" or type(v) ~= "table" or isFrame(v) then |
if saveFields then |
saveFields[k] = v |
end |
to[k] = nil |
elseif v ~= _G then |
if saveFields then |
saveFields[k] = copyTable(v) |
end |
end |
end |
for k in pairs(from) do |
if rawget(to, k) and to[k] ~= from[k] and AceLibrary.positions[to[k]] == major and from[k] ~= _G then |
if not list2[to[k]] then |
deepTransfer(to[k], from[k], nil, major, list, list2) |
end |
to[k] = list[to[k]] or list2[to[k]] |
else |
rawset(to, k, from[k]) |
end |
end |
setmetatable(to, getmetatable(from)) |
local mt = getmetatable(to) |
if mt then |
if list[mt] then |
setmetatable(to, list[mt]) |
elseif mt.__index and list[mt.__index] then |
mt.__index = list[mt.__index] |
end |
end |
destroyTable(from) |
end |
end |
local function TryToEnable(addon) |
if DONT_ENABLE_LIBRARIES then return end |
local isondemand = IsAddOnLoadOnDemand(addon) |
if isondemand then |
local _, _, _, enabled = GetAddOnInfo(addon) |
EnableAddOn(addon) |
local _, _, _, _, loadable = GetAddOnInfo(addon) |
if not loadable and not enabled then |
DisableAddOn(addon) |
end |
return loadable |
end |
end |
-- @method TryToLoadStandalone |
-- @brief Attempt to find and load a standalone version of the requested library |
-- @param major A string representing the major version |
-- @return If library is found and loaded, true is return. If not loadable, false is returned. |
-- If the library has been requested previously, nil is returned. |
local function TryToLoadStandalone(major) |
if not AceLibrary.scannedlibs then AceLibrary.scannedlibs = {} end |
if AceLibrary.scannedlibs[major] then return end |
AceLibrary.scannedlibs[major] = true |
local name, _, _, enabled, loadable = GetAddOnInfo(major) |
loadable = (enabled and loadable) or TryToEnable(name) |
local loaded = false |
if loadable then |
loaded = true |
LoadAddOn(name) |
end |
local field = "X-AceLibrary-" .. major |
for i = 1, GetNumAddOns() do |
if GetAddOnMetadata(i, field) then |
name, _, _, enabled, loadable = GetAddOnInfo(i) |
loadable = (enabled and loadable) or TryToEnable(name) |
if loadable then |
loaded = true |
LoadAddOn(name) |
end |
end |
end |
return loaded |
end |
-- @method IsNewVersion |
-- @brief Obtain whether the supplied version would be an upgrade to the |
-- current version. This allows for bypass code in library |
-- declaration. |
-- @param major A string representing the major version |
-- @param minor An integer or an svn revision string representing the minor version |
-- @return whether the supplied version would be newer than what is |
-- currently available. |
function AceLibrary:IsNewVersion(major, minor) |
argCheck(self, major, 2, "string") |
TryToLoadStandalone(major) |
if type(minor) == "string" then |
local m = svnRevisionToNumber(minor) |
if m then |
minor = m |
else |
_G.error(("Bad argument #3 to `IsNewVersion'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2) |
end |
end |
argCheck(self, minor, 3, "number") |
local lib, oldMinor = LibStub:GetLibrary(major, true) |
if lib then |
return oldMinor < minor |
end |
local data = self.libs[major] |
if not data then |
return true |
end |
return data.minor < minor |
end |
-- @method HasInstance |
-- @brief Returns whether an instance exists. This allows for optional support of a library. |
-- @param major A string representing the major version. |
-- @param minor (optional) An integer or an svn revision string representing the minor version. |
-- @return Whether an instance exists. |
function AceLibrary:HasInstance(major, minor) |
argCheck(self, major, 2, "string") |
if minor ~= false then |
TryToLoadStandalone(major) |
end |
local lib, ver = LibStub:GetLibrary(major, true) |
if not lib and self.libs[major] then |
lib, ver = self.libs[major].instance, self.libs[major].minor |
end |
if minor then |
if type(minor) == "string" then |
local m = svnRevisionToNumber(minor) |
if m then |
minor = m |
else |
_G.error(("Bad argument #3 to `HasInstance'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2) |
end |
end |
argCheck(self, minor, 3, "number") |
if not lib then |
return false |
end |
return ver == minor |
end |
return not not lib |
end |
-- @method GetInstance |
-- @brief Returns the library with the given major/minor version. |
-- @param major A string representing the major version. |
-- @param minor (optional) An integer or an svn revision string representing the minor version. |
-- @return The library with the given major/minor version. |
function AceLibrary:GetInstance(major, minor) |
argCheck(self, major, 2, "string") |
if minor ~= false then |
TryToLoadStandalone(major) |
end |
local data, ver = LibStub:GetLibrary(major, true) |
if not data then |
if self.libs[major] then |
data, ver = self.libs[major].instance, self.libs[major].minor |
else |
_G.error(("Cannot find a library instance of %s."):format(major), 2) |
return |
end |
end |
if minor then |
if type(minor) == "string" then |
local m = svnRevisionToNumber(minor) |
if m then |
minor = m |
else |
_G.error(("Bad argument #3 to `GetInstance'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2) |
end |
end |
argCheck(self, minor, 2, "number") |
if ver ~= minor then |
_G.error(("Cannot find a library instance of %s, minor version %d."):format(major, minor), 2) |
end |
end |
return data |
end |
-- Syntax sugar. AceLibrary("FooBar-1.0") |
AceLibrary_mt.__call = AceLibrary.GetInstance |
local donothing = function() end |
local AceEvent |
local tmp = {} |
-- @method Register |
-- @brief Registers a new version of a given library. |
-- @param newInstance the library to register |
-- @param major the major version of the library |
-- @param minor the minor version of the library |
-- @param activateFunc (optional) A function to be called when the library is |
-- fully activated. Takes the arguments |
-- (newInstance [, oldInstance, oldDeactivateFunc]). If |
-- oldInstance is given, you should probably call |
-- oldDeactivateFunc(oldInstance). |
-- @param deactivateFunc (optional) A function to be called by a newer library's |
-- activateFunc. |
-- @param externalFunc (optional) A function to be called whenever a new |
-- library is registered. |
function AceLibrary:Register(newInstance, major, minor, activateFunc, deactivateFunc, externalFunc) |
argCheck(self, newInstance, 2, "table") |
argCheck(self, major, 3, "string") |
if major ~= ACELIBRARY_MAJOR then |
for k,v in pairs(_G) do |
if v == newInstance then |
geterrorhandler()((debugstack():match("(.-: )in.-\n") or "") .. ("Cannot register library %q. It is part of the global table in _G[%q]."):format(major, k)) |
end |
end |
end |
if major ~= ACELIBRARY_MAJOR and not major:find("^[%a%-][%a%d%-]*%-%d+%.%d+$") then |
_G.error(string.format("Bad argument #3 to `Register'. Must be in the form of \"Name-1.0\". %q is not appropriate", major), 2) |
end |
if type(minor) == "string" then |
local m = svnRevisionToNumber(minor) |
if m then |
minor = m |
else |
_G.error(("Bad argument #4 to `Register'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2) |
end |
end |
argCheck(self, minor, 4, "number") |
if math.floor(minor) ~= minor or minor < 0 then |
error(self, "Bad argument #4 to `Register' (integer >= 0 expected, got %s)", minor) |
end |
argCheck(self, activateFunc, 5, "function", "nil") |
argCheck(self, deactivateFunc, 6, "function", "nil") |
argCheck(self, externalFunc, 7, "function", "nil") |
if not deactivateFunc then |
deactivateFunc = donothing |
end |
local data = self.libs[major] |
if not data then |
-- This is new |
if LibStub:GetLibrary(major, true) then |
error(self, "Cannot register library %q. It is already registered with LibStub.", major) |
end |
local instance = LibStub:NewLibrary(major, minor) |
copyTable(newInstance, instance) |
crawlReplace(instance, instance, newInstance) |
destroyTable(newInstance) |
if AceLibrary == newInstance then |
self = instance |
AceLibrary = instance |
end |
self.libs[major] = { |
instance = instance, |
minor = minor, |
deactivateFunc = deactivateFunc, |
externalFunc = externalFunc, |
} |
rawset(instance, 'GetLibraryVersion', function(self) |
return major, minor |
end) |
if not rawget(instance, 'error') then |
rawset(instance, 'error', error) |
end |
if not rawget(instance, 'argCheck') then |
rawset(instance, 'argCheck', argCheck) |
end |
if not rawget(instance, 'pcall') then |
rawset(instance, 'pcall', pcall) |
end |
addToPositions(instance, major) |
if activateFunc then |
safecall(activateFunc, instance, nil, nil) -- no old version, so explicit nil |
end |
if externalFunc then |
for k, data_instance in LibStub:IterateLibraries() do -- all libraries |
tmp[k] = data_instance |
end |
for k, data in pairs(self.libs) do -- Ace libraries which may not have been registered with LibStub |
tmp[k] = data.instance |
end |
for k, data_instance in pairs(tmp) do |
if k ~= major then |
safecall(externalFunc, instance, k, data_instance) |
end |
tmp[k] = nil |
end |
end |
for k,data in pairs(self.libs) do -- only Ace libraries |
if k ~= major and data.externalFunc then |
safecall(data.externalFunc, data.instance, major, instance) |
end |
end |
if major == "AceEvent-2.0" then |
AceEvent = instance |
end |
if AceEvent then |
AceEvent.TriggerEvent(self, "AceLibrary_Register", major, instance) |
end |
return instance |
end |
if minor <= data.minor then |
-- This one is already obsolete, raise an error. |
_G.error(("Obsolete library registered. %s is already registered at version %d. You are trying to register version %d. Hint: if not AceLibrary:IsNewVersion(%q, %d) then return end"):format(major, data.minor, minor, major, minor), 2) |
return |
end |
local instance = data.instance |
-- This is an update |
local oldInstance = {} |
local libStubInstance = LibStub:GetLibrary(major, true) |
if not libStubInstance then -- non-LibStub AceLibrary registered the library |
-- pass |
elseif libStubInstance ~= instance then |
error(self, "Cannot register library %q. It is already registered with LibStub.", major) |
else |
LibStub:NewLibrary(major, minor) -- upgrade the minor version |
end |
addToPositions(newInstance, major) |
local isAceLibrary = (AceLibrary == newInstance) |
local old_error, old_argCheck, old_pcall |
if isAceLibrary then |
self = instance |
AceLibrary = instance |
old_error = instance.error |
old_argCheck = instance.argCheck |
old_pcall = instance.pcall |
self.error = error |
self.argCheck = argCheck |
self.pcall = pcall |
end |
deepTransfer(instance, newInstance, oldInstance, major) |
crawlReplace(instance, instance, newInstance) |
local oldDeactivateFunc = data.deactivateFunc |
data.minor = minor |
data.deactivateFunc = deactivateFunc |
data.externalFunc = externalFunc |
rawset(instance, 'GetLibraryVersion', function() |
return major, minor |
end) |
if not rawget(instance, 'error') then |
rawset(instance, 'error', error) |
end |
if not rawget(instance, 'argCheck') then |
rawset(instance, 'argCheck', argCheck) |
end |
if not rawget(instance, 'pcall') then |
rawset(instance, 'pcall', pcall) |
end |
if isAceLibrary then |
for _,v in pairs(self.libs) do |
local i = type(v) == "table" and v.instance |
if type(i) == "table" then |
if not rawget(i, 'error') or i.error == old_error then |
rawset(i, 'error', error) |
end |
if not rawget(i, 'argCheck') or i.argCheck == old_argCheck then |
rawset(i, 'argCheck', argCheck) |
end |
if not rawget(i, 'pcall') or i.pcall == old_pcall then |
rawset(i, 'pcall', pcall) |
end |
end |
end |
end |
if activateFunc then |
safecall(activateFunc, instance, oldInstance, oldDeactivateFunc) |
else |
safecall(oldDeactivateFunc, oldInstance) |
end |
oldInstance = nil |
if externalFunc then |
for k, data_instance in LibStub:IterateLibraries() do -- all libraries |
tmp[k] = data_instance |
end |
for k, data in pairs(self.libs) do -- Ace libraries which may not have been registered with LibStub |
tmp[k] = data.instance |
end |
for k, data_instance in pairs(tmp) do |
if k ~= major then |
safecall(externalFunc, instance, k, data_instance) |
end |
tmp[k] = nil |
end |
end |
return instance |
end |
function AceLibrary:IterateLibraries() |
local t = {} |
for major, instance in LibStub:IterateLibraries() do |
t[major] = instance |
end |
for major, data in pairs(self.libs) do |
t[major] = data.instance |
end |
return pairs(t) |
end |
local function manuallyFinalize(major, instance) |
if AceLibrary.libs[major] then |
-- don't work on Ace libraries |
return |
end |
local finalizedExternalLibs = AceLibrary.finalizedExternalLibs |
if finalizedExternalLibs[major] then |
return |
end |
finalizedExternalLibs[major] = true |
for k,data in pairs(AceLibrary.libs) do -- only Ace libraries |
if k ~= major and data.externalFunc then |
safecall(data.externalFunc, data.instance, major, instance) |
end |
end |
end |
-- @function Activate |
-- @brief The activateFunc for AceLibrary itself. Called when |
-- AceLibrary properly registers. |
-- @param self Reference to AceLibrary |
-- @param oldLib (optional) Reference to an old version of AceLibrary |
-- @param oldDeactivate (optional) Function to deactivate the old lib |
local function activate(self, oldLib, oldDeactivate) |
AceLibrary = self |
if not self.libs then |
self.libs = oldLib and oldLib.libs or {} |
self.scannedlibs = oldLib and oldLib.scannedlibs or {} |
end |
if not self.positions then |
self.positions = oldLib and oldLib.positions or setmetatable({}, { __mode = "k" }) |
end |
self.finalizedExternalLibs = oldLib and oldLib.finalizedExternalLibs or {} |
self.frame = oldLib and oldLib.frame or CreateFrame("Frame") |
self.frame:UnregisterAllEvents() |
self.frame:RegisterEvent("ADDON_LOADED") |
self.frame:SetScript("OnEvent", function() |
for major, instance in LibStub:IterateLibraries() do |
manuallyFinalize(major, instance) |
end |
end) |
for major, instance in LibStub:IterateLibraries() do |
manuallyFinalize(major, instance) |
end |
-- Expose the library in the global environment |
_G[ACELIBRARY_MAJOR] = self |
if oldDeactivate then |
oldDeactivate(oldLib) |
end |
end |
if not previous then |
previous = AceLibrary |
end |
if not previous.libs then |
previous.libs = {} |
end |
AceLibrary.libs = previous.libs |
if not previous.positions then |
previous.positions = setmetatable({}, { __mode = "k" }) |
end |
AceLibrary.positions = previous.positions |
AceLibrary:Register(AceLibrary, ACELIBRARY_MAJOR, ACELIBRARY_MINOR, activate, nil) |
## Interface: 20400 |
## Title: Lib: AceLibrary |
## Notes: AddOn development framework |
## Author: Ace Development Team |
## X-Website: http://www.wowace.com |
## X-Category: Library |
## X-License: LGPL v2.1 + MIT for AceOO-2.0 |
AceLibrary.lua |
--[[ |
Name: AceOO-2.0 |
Revision: $Rev$ |
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) |
Inspired By: Ace 1.x by Turan (turan@gryphon.com) |
Website: http://www.wowace.com/ |
Documentation: http://www.wowace.com/index.php/AceOO-2.0 |
SVN: http://svn.wowace.com/root/trunk/Ace2/AceOO-2.0 |
Description: Library to provide an object-orientation framework. |
Dependencies: AceLibrary |
License: MIT |
]] |
local MAJOR_VERSION = "AceOO-2.0" |
local MINOR_VERSION = "$Revision$" |
-- This ensures the code is only executed if the libary doesn't already exist, or is a newer version |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
local AceOO = { |
error = AceLibrary.error, |
argCheck = AceLibrary.argCheck |
} |
-- @function getuid |
-- @brief Obtain a unique string identifier for the object in question. |
-- @param t The object to obtain the uid for. |
-- @return The uid string. |
local function getuid(t) |
local mt = getmetatable(t) |
setmetatable(t, nil) |
local str = tostring(t) |
setmetatable(t, mt) |
local cap = str:match("[^:]*: 0x(.*)$") or str:match("[^:]*: (.*)$") |
if cap then |
return ("0"):rep(8 - #cap) .. cap |
end |
end |
local function getlibrary(o) |
if type(o) == "table" then |
return o |
elseif type(o) == "string" then |
if not AceLibrary:HasInstance(o) then |
AceOO:error("Library %q does not exist.", o) |
end |
return AceLibrary(o) |
end |
end |
local function deeprawget(self, k) |
while true do |
local v = rawget(self, k) |
if v ~= nil then |
return v |
end |
local mt = getmetatable(self) |
if not mt or type(mt.__index) ~= "table" then |
return nil |
end |
self = mt.__index |
end |
end |
-- @function Factory |
-- @brief Construct a factory for the creation of objects. |
-- @param obj The object whose init method will be called on the new factory |
-- object. |
-- @param newobj The object whose init method will be called on the new |
-- objects that the Factory creates, to initialize them. |
-- @param (...) Arguments which will be passed to obj.init() in addition |
-- to the Factory object. |
-- @return The new factory which creates a newobj when its new method is called, |
-- or when it is called directly (__call metamethod). |
local Factory |
do |
local function getlibraries(...) |
if select('#', ...) == 0 then |
return |
end |
return getlibrary((select(1, ...))), getlibraries(select(2, ...)) |
end |
local arg = {} |
local function new(obj, ...) |
local t = {} |
local uid = getuid(t) |
obj:init(t, getlibraries(...)) |
t.uid = uid |
return t |
end |
local function createnew(self, ...) |
local o = self.prototype |
local x = new(o, getlibraries(...)) |
return x |
end |
function Factory(obj, newobj, ...) |
local t = new(obj, ...) |
t.prototype = newobj |
t.new = createnew |
getmetatable(t).__call = t.new |
return t |
end |
end |
local function objtostring(self) |
if self.ToString then |
return self:ToString() |
elseif self.GetLibraryVersion then |
return (self:GetLibraryVersion()) |
elseif self.super then |
local s = "Sub-" .. tostring(self.super) |
local first = true |
if self.interfaces then |
for interface in pairs(self.interfaces) do |
if first then |
s = s .. "(" .. tostring(interface) |
first = false |
else |
s = s .. ", " .. tostring(interface) |
end |
end |
end |
if self.mixins then |
for mixin in pairs(self.mixins) do |
if first then |
s = s .. tostring(mixin) |
first = false |
else |
s = s .. ", " .. tostring(mixin) |
end |
end |
end |
if first then |
if self.uid then |
return s .. ":" .. self.uid |
else |
return s |
end |
else |
return s .. ")" |
end |
else |
return self.uid and 'Subclass:' .. self.uid or 'Subclass' |
end |
end |
-- @table Object |
-- @brief Base of all objects, including Class. |
-- |
-- @method init |
-- @brief Initialize a new object. |
-- @param newobject The object to initialize |
-- @param class The class to make newobject inherit from |
local Object |
do |
Object = {} |
function Object:init(newobject, class) |
local parent = class or self |
if not rawget(newobject, 'uid') then |
newobject.uid = getuid(newobject) |
end |
local mt = { |
__index = parent, |
__tostring = objtostring, |
} |
setmetatable(newobject, mt) |
end |
Object.uid = getuid(Object) |
setmetatable(Object, { __tostring = function() return 'Object' end }) |
end |
local Interface |
local function validateInterface(object, interface) |
if not object.class and object.prototype then |
object = object.prototype |
end |
for k,v in pairs(interface.interface) do |
if tostring(type(object[k])) ~= v then |
return false |
end |
end |
if interface.superinterfaces then |
for superinterface in pairs(interface.superinterfaces) do |
if not validateInterface(object, superinterface) then |
return false |
end |
end |
end |
if type(object.class) == "table" and rawequal(object.class.prototype, object) then |
if not object.class.interfaces then |
rawset(object.class, 'interfaces', {}) |
end |
object.class.interfaces[interface] = true |
elseif type(object.class) == "table" and type(object.class.prototype) == "table" then |
validateInterface(object.class.prototype, interface) |
-- check if class is proper, thus preventing future checks. |
end |
return true |
end |
-- @function inherits |
-- @brief Return whether an Object or Class inherits from a given |
-- parent. |
-- @param object Object or Class to check |
-- @param parent Parent to test inheritance from |
-- @return whether an Object or Class inherits from a given |
-- parent. |
local function inherits(object, parent) |
object = getlibrary(object) |
if type(parent) == "string" then |
if not AceLibrary:HasInstance(parent) then |
return false |
else |
parent = AceLibrary(parent) |
end |
end |
AceOO:argCheck(parent, 2, "table") |
if type(object) ~= "table" then |
return false |
end |
local current |
local class = deeprawget(object, 'class') |
if class then |
current = class |
else |
current = object |
end |
if type(current) ~= "table" then |
return false |
end |
if rawequal(current, parent) then |
return true |
end |
if parent.class then |
while true do |
if rawequal(current, Object) then |
break |
end |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if rawequal(mixin, parent) then |
return true |
end |
end |
end |
if current.interfaces then |
for interface in pairs(current.interfaces) do |
if rawequal(interface, parent) then |
return true |
end |
end |
end |
current = deeprawget(current, 'super') |
if type(current) ~= "table" then |
break |
end |
end |
local isInterface = false |
local curr = parent.class |
while true do |
if rawequal(curr, Object) then |
break |
elseif rawequal(curr, Interface) then |
isInterface = true |
break |
end |
curr = deeprawget(curr, 'super') |
if type(curr) ~= "table" then |
break |
end |
end |
return isInterface and validateInterface(object, parent) |
else |
while true do |
if rawequal(current, parent) then |
return true |
elseif rawequal(current, Object) then |
return false |
end |
current = deeprawget(current, 'super') |
if type(current) ~= "table" then |
return false |
end |
end |
end |
end |
-- @table Class |
-- @brief An object factory which sets up inheritence and supports |
-- 'mixins'. |
-- |
-- @metamethod Class call |
-- @brief Call ClassFactory:new() to create a new class. |
-- |
-- @method Class new |
-- @brief Construct a new object. |
-- @param (...) Arguments to pass to the object init function. |
-- @return The new object. |
-- |
-- @method Class init |
-- @brief Initialize a new class. |
-- @param parent Superclass. |
-- @param (...) Mixins. |
-- |
-- @method Class ToString |
-- @return A string representing the object, in this case 'Class'. |
local initStatus |
local Class |
local Mixin |
local autoEmbed = false |
local function traverseInterfaces(bit, total) |
if bit.superinterfaces then |
for interface in pairs(bit.superinterfaces) do |
if not total[interface] then |
total[interface] = true |
traverseInterfaces(interface, total) |
end |
end |
end |
end |
local class_new |
do |
Class = Factory(Object, setmetatable({}, {__index = Object}), Object) |
Class.super = Object |
local function protostring(t) |
return '<' .. tostring(t.class) .. ' prototype>' |
end |
local function classobjectstring(t) |
if t.ToString then |
return t:ToString() |
elseif t.GetLibraryVersion then |
return (t:GetLibraryVersion()) |
else |
return '<' .. tostring(t.class) .. ' instance>' |
end |
end |
local function classobjectequal(self, other) |
if type(self) == "table" and self.Equals then |
return self:Equals(other) |
elseif type(other) == "table" and other.Equals then |
return other:Equals(self) |
elseif type(self) == "table" and self.CompareTo then |
return self:CompareTo(other) == 0 |
elseif type(other) == "table" and other.CompareTo then |
return other:CompareTo(self) == 0 |
else |
return rawequal(self, other) |
end |
end |
local function classobjectlessthan(self, other) |
if type(self) == "table" and self.IsLessThan then |
return self:IsLessThan(other) |
elseif type(other) == "table" and other.IsLessThanOrEqualTo then |
return not other:IsLessThanOrEqualTo(self) |
elseif type(self) == "table" and self.CompareTo then |
return self:CompareTo(other) < 0 |
elseif type(other) == "table" and other.CompareTo then |
return other:CompareTo(self) > 0 |
elseif type(other) == "table" and other.IsLessThan and other.Equals then |
return other:Equals(self) or other:IsLessThan(self) |
else |
AceOO:error("cannot compare two objects") |
end |
end |
local function classobjectlessthanequal(self, other) |
if type(self) == "table" and self.IsLessThanOrEqualTo then |
return self:IsLessThanOrEqualTo(other) |
elseif type(other) == "table" and other.IsLessThan then |
return not other:IsLessThan(self) |
elseif type(self) == "table" and self.CompareTo then |
return self:CompareTo(other) <= 0 |
elseif type(other) == "table" and other.CompareTo then |
return other:CompareTo(self) >= 0 |
elseif type(self) == "table" and self.IsLessThan and self.Equals then |
return self:Equals(other) or self:IsLessThan(other) |
else |
AceOO:error("cannot compare two incompatible objects") |
end |
end |
local function classobjectadd(self, other) |
if type(self) == "table" and self.Add then |
return self:Add(other) |
else |
AceOO:error("cannot add two incompatible objects") |
end |
end |
local function classobjectsub(self, other) |
if type(self) == "table" and self.Subtract then |
return self:Subtract(other) |
else |
AceOO:error("cannot subtract two incompatible objects") |
end |
end |
local function classobjectunm(self, other) |
if type(self) == "table" and self.UnaryNegation then |
return self:UnaryNegation(other) |
else |
AceOO:error("attempt to negate an incompatible object") |
end |
end |
local function classobjectmul(self, other) |
if type(self) == "table" and self.Multiply then |
return self:Multiply(other) |
else |
AceOO:error("cannot multiply two incompatible objects") |
end |
end |
local function classobjectdiv(self, other) |
if type(self) == "table" and self.Divide then |
return self:Divide(other) |
else |
AceOO:error("cannot divide two incompatible objects") |
end |
end |
local function classobjectpow(self, other) |
if type(self) == "table" and self.Exponent then |
return self:Exponent(other) |
else |
AceOO:error("cannot exponentiate two incompatible objects") |
end |
end |
local function classobjectconcat(self, other) |
if type(self) == "table" and self.Concatenate then |
return self:Concatenate(other) |
else |
AceOO:error("cannot concatenate two incompatible objects") |
end |
end |
function class_new(self, ...) |
if self.virtual then |
AceOO:error("Cannot instantiate a virtual class.") |
end |
local o = self.prototype |
local newobj = {} |
if o.class and o.class.instancemeta then |
setmetatable(newobj, o.class.instancemeta) |
else |
Object:init(newobj, o) |
end |
if self.interfaces and not self.interfacesVerified then |
-- Verify the interfaces |
for interface in pairs(self.interfaces) do |
for field,kind in pairs(interface.interface) do |
if tostring(type(newobj[field])) ~= kind then |
AceOO:error("Class did not satisfy all interfaces. %q is required to be a %s. It is a %s", field, kind, tostring(type(newobj[field]))) |
end |
end |
end |
self.interfacesVerified = true |
end |
local tmp = initStatus |
initStatus = newobj |
newobj:init(...) |
if initStatus then |
initStatus = tmp |
AceOO:error("Initialization not completed, be sure to call the superclass's init method.") |
return |
end |
initStatus = tmp |
return newobj |
end |
local classmeta = { |
__tostring = objtostring, |
__call = function(self, ...) |
return self:new(...) |
end, |
} |
function Class:init(newclass, parent, ...) |
parent = parent or self |
local total |
if parent.class then |
total = { parent, ... } |
parent = self |
else |
total = { ... } |
end |
if not inherits(parent, Class) then |
AceOO:error("Classes must inherit from a proper class") |
end |
if parent.sealed then |
AceOO:error("Cannot inherit from a sealed class") |
end |
for i,v in ipairs(total) do |
if inherits(v, Mixin) and v.class then |
if v.__deprecated then |
AceOO:error(v.__deprecated) |
end |
if not newclass.mixins then |
newclass.mixins = {} |
end |
if newclass.mixins[v] then |
AceOO:error("Cannot explicitly inherit from the same mixin twice") |
end |
newclass.mixins[v] = true |
elseif inherits(v, Interface) and v.class then |
if not newclass.interfaces then |
newclass.interfaces = {} |
end |
if newclass.interfaces[v] then |
AceOO:error("Cannot explicitly inherit from the same interface twice") |
end |
newclass.interfaces[v] = true |
else |
AceOO:error("Classes can only inherit from one or zero classes and any number of mixins or interfaces") |
end |
end |
if parent.interfaces then |
if not newclass.interfaces then |
newclass.interfaces = {} |
end |
for interface in pairs(parent.interfaces) do |
newclass.interfaces[interface] = true |
end |
end |
for k in pairs(total) do |
total[k] = nil |
end |
newclass.super = parent |
newclass.prototype = setmetatable(total, { |
__index = parent.prototype, |
__tostring = protostring, |
}) |
total = nil |
newclass.instancemeta = { |
__index = newclass.prototype, |
__tostring = classobjectstring, |
__eq = classobjectequal, |
__lt = classobjectlessthan, |
__le = classobjectlessthanequal, |
__add = classobjectadd, |
__sub = classobjectsub, |
__unm = classobjectunm, |
__mul = classobjectmul, |
__div = classobjectdiv, |
__pow = classobjectpow, |
__concat = classobjectconcat, |
} |
setmetatable(newclass, classmeta) |
newclass.new = class_new |
if newclass.mixins then |
-- Fold in the mixins |
local err, msg |
for mixin in pairs(newclass.mixins) do |
local ret |
autoEmbed = true |
ret, msg = pcall(mixin.embed, mixin, newclass.prototype) |
autoEmbed = false |
if not ret then |
err = true |
break |
end |
end |
if err then |
local pt = newclass.prototype |
for k,v in pairs(pt) do |
pt[k] = nil |
end |
-- method conflict |
AceOO:error(msg) |
end |
end |
newclass.prototype.class = newclass |
if newclass.interfaces then |
for interface in pairs(newclass.interfaces) do |
traverseInterfaces(interface, newclass.interfaces) |
end |
end |
if newclass.mixins then |
for mixin in pairs(newclass.mixins) do |
if mixin.interfaces then |
if not newclass.interfaces then |
newclass.interfaces = {} |
end |
for interface in pairs(mixin.interfaces) do |
newclass.interfaces[interface] = true |
end |
end |
end |
end |
end |
function Class:ToString() |
if type(self.GetLibraryVersion) == "function" then |
return (self:GetLibraryVersion()) |
else |
return "Class" |
end |
end |
local tmp |
function Class.prototype:init() |
if rawequal(self, initStatus) then |
initStatus = nil |
else |
AceOO:error("Improper self passed to init. You must do MyClass.super.prototype.init(self, ...)", 2) |
end |
self.uid = getuid(self) |
local current = self.class |
while true do |
if current == Class then |
break |
end |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnInstanceInit) == "function" then |
mixin:OnInstanceInit(self) |
end |
end |
end |
current = current.super |
end |
end |
end |
-- @object ClassFactory |
-- @brief A factory for creating classes. Rarely used directly. |
local ClassFactory = Factory(Object, Class, Object) |
function Class:new(...) |
local x = ClassFactory:new(...) |
if AceOO.classes then |
AceOO.classes[x] = true |
end |
return x |
end |
getmetatable(Class).__call = Class.new |
-- @class Mixin |
-- @brief A class to create mixin objects, which contain methods that get |
-- "mixed in" to class prototypes. |
-- |
-- @object Mixin prototype |
-- @brief The prototype that mixin objects inherit their methods from. |
-- |
-- @method Mixin prototype embed |
-- @brief Mix in the methods of our object which are listed in our interface |
-- to the supplied target table. |
-- |
-- @method Mixin prototype init |
-- @brief Initialize the mixin object. |
-- @param newobj The new object we're initializing. |
-- @param interface The interface we implement (the list of methods our |
-- prototype provides which should be mixed into the target |
-- table by embed). |
do |
Mixin = Class() |
function Mixin:ToString() |
if self.GetLibraryVersion then |
return (self:GetLibraryVersion()) |
else |
return 'Mixin' |
end |
end |
local function _Embed(state, field, target) |
field = next(state.export, field) |
if field == nil then |
return |
end |
if rawget(target, field) or (target[field] and target[field] ~= state[field]) then |
AceOO:error("Method conflict in attempt to mixin. Field %q", field) |
end |
target[field] = state[field] |
local ret,msg = pcall(_Embed, state, field, target) |
if not ret then |
-- Mix in the next method according to the defined interface. If that |
-- fails due to a conflict, re-raise to back out the previous mixed |
-- methods. |
target[field] = nil |
AceOO:error(msg) |
end |
end |
function Mixin.prototype:embed(target) |
if self.__deprecated then |
AceOO:error(self.__deprecated) |
end |
local mt = getmetatable(target) |
setmetatable(target, nil) |
local err, msg = pcall(_Embed, self, nil, target) |
if not err then |
setmetatable(target, mt) |
AceOO:error(msg) |
return |
end |
if type(self.embedList) == "table" then |
self.embedList[target] = true |
end |
if type(target.class) ~= "table" then |
target[self] = true |
end |
if not autoEmbed and type(self.OnManualEmbed) == "function" then |
self:OnManualEmbed(target) |
end |
setmetatable(target, mt) |
end |
function Mixin.prototype:activate(oldLib, oldDeactivate) |
if oldLib and oldLib.embedList then |
for target in pairs(oldLib.embedList) do |
local mt = getmetatable(target) |
setmetatable(target, nil) |
for field in pairs(oldLib.export) do |
target[field] = nil |
end |
setmetatable(target, mt) |
end |
self.embedList = oldLib.embedList |
for target in pairs(self.embedList) do |
self:embed(target) |
end |
else |
self.embedList = setmetatable({}, {__mode="k"}) |
end |
end |
function Mixin.prototype:init(export, ...) |
AceOO:argCheck(export, 2, "table") |
for k,v in pairs(export) do |
if type(k) ~= "number" then |
AceOO:error("All keys to argument #2 must be numbers.") |
elseif type(v) ~= "string" then |
AceOO:error("All values to argument #2 must be strings.") |
end |
end |
local num = #export |
for i = 1, num do |
local v = export[i] |
export[i] = nil |
export[v] = true |
end |
local interfaces |
if select('#', ...) >= 1 then |
interfaces = { ... } |
for i,v in ipairs(interfaces) do |
v = getlibrary(v) |
interfaces[i] = v |
if not v.class or not inherits(v, Interface) then |
AceOO:error("Mixins can inherit only from interfaces") |
end |
end |
local num = #interfaces |
for i = 1, num do |
local v = interfaces[i] |
interfaces[i] = nil |
interfaces[v] = true |
end |
for interface in pairs(interfaces) do |
traverseInterfaces(interface, interfaces) |
end |
for interface in pairs(interfaces) do |
for field,kind in pairs(interface.interface) do |
if kind ~= "nil" then |
local good = false |
for bit in pairs(export) do |
if bit == field then |
good = true |
break |
end |
end |
if not good then |
AceOO:error("Mixin does not fully accommodate field %q", field) |
end |
end |
end |
end |
end |
self.super = Mixin.prototype |
Mixin.super.prototype.init(self) |
self.export = export |
self.interfaces = interfaces |
end |
end |
-- @class Interface |
-- @brief A class to create interfaces, which contain contracts that classes |
-- which inherit from this must comply with. |
-- |
-- @object Interface prototype |
-- @brief The prototype that interface objects must adhere to. |
-- |
-- @method Interface prototype init |
-- @brief Initialize the mixin object. |
-- @param interface The interface we contract (the hash of fields forced). |
-- @param (...) Superinterfaces |
do |
Interface = Class() |
function Interface:ToString() |
if self.GetLibraryVersion then |
return (self:GetLibraryVersion()) |
else |
return 'Instance' |
end |
end |
function Interface.prototype:init(interface, ...) |
Interface.super.prototype.init(self) |
AceOO:argCheck(interface, 2, "table") |
for k,v in pairs(interface) do |
if type(k) ~= "string" then |
AceOO:error("All keys to argument #2 must be numbers.") |
elseif type(v) ~= "string" then |
AceOO:error("All values to argument #2 must be strings.") |
elseif v ~= "nil" and v ~= "string" and v ~= "number" and v ~= "table" and v ~= "function" then |
AceOO:error('All values to argument #2 must either be "nil", "string", "number", "table", or "function".') |
end |
end |
if select('#', ...) >= 1 then |
self.superinterfaces = { ... } |
for i,v in ipairs(self.superinterfaces) do |
v = getlibrary(v) |
self.superinterfaces[i] = v |
if not inherits(v, Interface) or not v.class then |
AceOO:error('Cannot provide a non-Interface to inherit from') |
end |
end |
local num = #self.superinterfaces |
for i = 1, num do |
local v = self.superinterfaces[i] |
self.superinterfaces[i] = nil |
self.superinterfaces[v] = true |
end |
end |
self.interface = interface |
end |
end |
-- @function Classpool |
-- @brief Obtain a read only class from our pool of classes, indexed by the |
-- superclass and mixins. |
-- @param sc The superclass of the class we want. |
-- @param (m1..m20) Mixins of the class we want's objects. |
-- @return A read only class from the class pool. |
local Classpool |
do |
local pool = setmetatable({}, {__mode = 'v'}) |
local function newindex(k, v) |
AceOO:error('Attempt to modify a read-only class.') |
end |
local function protonewindex(k, v) |
AceOO:error('Attempt to modify a read-only class prototype.') |
end |
local function ts(bit) |
if type(bit) ~= "table" then |
return tostring(bit) |
elseif getmetatable(bit) and bit.__tostring then |
return tostring(bit) |
elseif type(bit.GetLibraryVersion) == "function" then |
return bit:GetLibraryVersion() |
else |
return tostring(bit) |
end |
end |
local t = {} |
local function getcomplexuid(sc, ...) |
if sc then |
if sc.uid then |
table.insert(t, sc.uid) |
else |
AceOO:error("%s is not an appropriate class/mixin", ts(sc)) |
end |
end |
for i = 1, select('#', ...) do |
local m = select(i, ...) |
if m.uid then |
table.insert(t, m.uid) |
else |
AceOO:error("%s is not an appropriate mixin", ts(m)) |
end |
end |
table.sort(t) |
local uid = table.concat(t, '') |
local num = #t |
for i = 1, num do |
t[i] = nil |
end |
return uid |
end |
local classmeta |
local arg = {} |
function Classpool(superclass, ...) |
local l = getlibrary |
superclass = getlibrary(superclass) |
arg = { ... } |
for i, v in ipairs(arg) do |
arg[i] = getlibrary(v) |
end |
if superclass then |
if superclass.class then -- mixin |
table.insert(arg, 1, superclass) |
superclass = Class |
end |
else |
superclass = Class |
end |
local key = getcomplexuid(superclass, unpack(arg)) |
if not pool[key] then |
local class = Class(superclass, unpack(arg)) |
if not classmeta then |
classmeta = {} |
local mt = getmetatable(class) |
for k,v in pairs(mt) do |
classmeta[k] = v |
end |
classmeta.__newindex = newindex |
end |
-- Prevent the user from adding methods to this class. |
-- NOTE: I'm not preventing modifications of existing class members, |
-- but it's likely that only a truly malicious user will be doing so. |
class.sealed = true |
setmetatable(class, classmeta) |
getmetatable(class.prototype).__newindex = protonewindex |
pool[key] = class |
end |
return pool[key] |
end |
end |
AceOO.Factory = Factory |
AceOO.Object = Object |
AceOO.Class = Class |
AceOO.Mixin = Mixin |
AceOO.Interface = Interface |
AceOO.Classpool = Classpool |
AceOO.inherits = inherits |
-- Library handling bits |
local function activate(self, oldLib, oldDeactivate) |
AceOO = self |
Factory = self.Factory |
Object = self.Object |
Class = self.Class |
ClassFactory.prototype = Class |
Mixin = self.Mixin |
Interface = self.Interface |
Classpool = self.Classpool |
if oldLib then |
self.classes = oldLib.classes |
end |
if not self.classes then |
self.classes = setmetatable({}, {__mode="k"}) |
else |
for class in pairs(self.classes) do |
class.new = class_new |
end |
end |
if oldDeactivate then |
oldDeactivate(oldLib) |
end |
end |
AceLibrary:Register(AceOO, MAJOR_VERSION, MINOR_VERSION, activate) |
AceOO = AceLibrary(MAJOR_VERSION) |
## Interface: 20400 |
## Title: Lib: AceOO-2.0 |
## Notes: AddOn development framework |
## Author: Ace Development Team |
## LoadOnDemand: 1 |
## X-Website: http://www.wowace.com |
## X-Category: Library |
## X-License: LGPL v2.1 + MIT for AceOO-2.0 |
## Dependencies: AceLibrary |
AceOO-2.0.lua |
--[[ |
Name: AceEvent-2.0 |
Revision: $Rev$ |
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) |
Inspired By: Ace 1.x by Turan (turan@gryphon.com) |
Website: http://www.wowace.com/ |
Documentation: http://www.wowace.com/index.php/AceEvent-2.0 |
SVN: http://svn.wowace.com/root/trunk/Ace2/AceEvent-2.0 |
Description: Mixin to allow for event handling, scheduling, and inter-addon |
communication. |
Dependencies: AceLibrary, AceOO-2.0 |
License: LGPL v2.1 |
]] |
local MAJOR_VERSION = "AceEvent-2.0" |
local MINOR_VERSION = "$Revision$" |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end |
local AceOO = AceLibrary:GetInstance("AceOO-2.0") |
local Mixin = AceOO.Mixin |
local AceEvent = Mixin { |
"RegisterEvent", |
"RegisterAllEvents", |
"UnregisterEvent", |
"UnregisterAllEvents", |
"TriggerEvent", |
"ScheduleEvent", |
"ScheduleRepeatingEvent", |
"CancelScheduledEvent", |
"CancelAllScheduledEvents", |
"IsEventRegistered", |
"IsEventScheduled", |
"RegisterBucketEvent", |
"UnregisterBucketEvent", |
"UnregisterAllBucketEvents", |
"IsBucketEventRegistered", |
"ScheduleLeaveCombatAction", |
"CancelAllCombatSchedules", |
} |
local weakKey = {__mode="k"} |
local FAKE_NIL |
local RATE |
local eventsWhichHappenOnce = { |
PLAYER_LOGIN = true, |
AceEvent_FullyInitialized = true, |
VARIABLES_LOADED = true, |
PLAYER_LOGOUT = true, |
} |
local next = next |
local pairs = pairs |
local pcall = pcall |
local type = type |
local GetTime = GetTime |
local gcinfo = gcinfo |
local unpack = unpack |
local geterrorhandler = geterrorhandler |
local new, del |
do |
local cache = setmetatable({}, {__mode='k'}) |
function new(...) |
local t = next(cache) |
if t then |
cache[t] = nil |
for i = 1, select('#', ...) do |
t[i] = select(i, ...) |
end |
return t |
else |
return { ... } |
end |
end |
function del(t) |
for k in pairs(t) do |
t[k] = nil |
end |
cache[t] = true |
return nil |
end |
end |
local registeringFromAceEvent |
--[[---------------------------------------------------------------------------------- |
Notes: |
* Registers the addon with a Blizzard event or a custom AceEvent, which will cause the given method to be called when that is triggered. |
Arguments: |
string - name of the event to register |
[optional] string or function - name of the method or function to call. Default: same name as "event". |
[optional] boolean - whether to have method called only once. Default: false |
------------------------------------------------------------------------------------]] |
function AceEvent:RegisterEvent(event, method, once) |
AceEvent:argCheck(event, 2, "string") |
if self == AceEvent and not registeringFromAceEvent then |
AceEvent:argCheck(method, 3, "function") |
self = method |
else |
AceEvent:argCheck(method, 3, "string", "function", "nil", "boolean", "number") |
if type(method) == "boolean" or type(method) == "number" then |
AceEvent:argCheck(once, 4, "nil") |
once, method = method, event |
end |
end |
AceEvent:argCheck(once, 4, "number", "boolean", "nil") |
if eventsWhichHappenOnce[event] then |
once = true |
end |
local throttleRate |
if type(once) == "number" then |
throttleRate, once = once |
end |
if not method then |
method = event |
end |
if type(method) == "string" and type(self[method]) ~= "function" then |
AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method) |
else |
assert(type(method) == "function" or type(method) == "string") |
end |
local AceEvent_registry = AceEvent.registry |
if not AceEvent_registry[event] then |
AceEvent_registry[event] = new() |
AceEvent.frame:RegisterEvent(event) |
end |
local remember = true |
if AceEvent_registry[event][self] then |
remember = false |
end |
AceEvent_registry[event][self] = method |
local AceEvent_onceRegistry = AceEvent.onceRegistry |
if once then |
if not AceEvent_onceRegistry then |
AceEvent.onceRegistry = {} |
AceEvent_onceRegistry = AceEvent.onceRegistry |
end |
if not AceEvent_onceRegistry[event] then |
AceEvent_onceRegistry[event] = new() |
end |
AceEvent_onceRegistry[event][self] = true |
else |
if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then |
AceEvent_onceRegistry[event][self] = nil |
if not next(AceEvent_onceRegistry[event]) then |
AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event]) |
end |
end |
end |
local AceEvent_throttleRegistry = AceEvent.throttleRegistry |
if throttleRate then |
if not AceEvent_throttleRegistry then |
AceEvent.throttleRegistry = {} |
AceEvent_throttleRegistry = AceEvent.throttleRegistry |
end |
if not AceEvent_throttleRegistry[event] then |
AceEvent_throttleRegistry[event] = new() |
end |
if AceEvent_throttleRegistry[event][self] then |
AceEvent_throttleRegistry[event][self] = nil |
end |
AceEvent_throttleRegistry[event][self] = setmetatable(new(), weakKey) |
local t = AceEvent_throttleRegistry[event][self] |
t[RATE] = throttleRate |
else |
if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] then |
if AceEvent_throttleRegistry[event][self] then |
AceEvent_throttleRegistry[event][self] = nil |
end |
if not next(AceEvent_throttleRegistry[event]) then |
AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event]) |
end |
end |
end |
if remember then |
AceEvent:TriggerEvent("AceEvent_EventRegistered", self, event) |
end |
end |
local ALL_EVENTS |
--[[---------------------------------------------------------------------------------- |
Notes: |
* Registers all events to the given method |
* To access the current event, check AceEvent.currentEvent |
* To access the current event's unique identifier, check AceEvent.currentEventUID |
* This is only for debugging purposes. |
Arguments: |
[optional] string or function - name of the method or function to call. Default: same name as "event". |
------------------------------------------------------------------------------------]] |
function AceEvent:RegisterAllEvents(method) |
if self == AceEvent then |
AceEvent:argCheck(method, 1, "function") |
self = method |
else |
AceEvent:argCheck(method, 1, "string", "function") |
if type(method) == "string" and type(self[method]) ~= "function" then |
AceEvent:error("Cannot register all events to method %q, it does not exist", method) |
end |
end |
local AceEvent_registry = AceEvent.registry |
if not AceEvent_registry[ALL_EVENTS] then |
AceEvent_registry[ALL_EVENTS] = new() |
AceEvent.frame:RegisterAllEvents() |
end |
local remember = not AceEvent_registry[ALL_EVENTS][self] |
AceEvent_registry[ALL_EVENTS][self] = method |
if remember then |
AceEvent:TriggerEvent("AceEvent_EventRegistered", self, "all") |
end |
end |
--[[---------------------------------------------------------------------------------- |
Notes: |
* Trigger a custom AceEvent. |
* This should never be called to simulate fake Blizzard events. |
* Custom events should be in the form of AddonName_SpecificEvent |
Arguments: |
string - name of the event |
tuple - list of arguments to pass along |
------------------------------------------------------------------------------------]] |
function AceEvent:TriggerEvent(event, ...) |
AceEvent:argCheck(event, 2, "string") |
local AceEvent_registry = AceEvent.registry |
if (not AceEvent_registry[event] or not next(AceEvent_registry[event])) and (not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS])) then |
return |
end |
local lastEvent = AceEvent.currentEvent |
AceEvent.currentEvent = event |
local lastEventUID = AceEvent.currentEventUID |
local uid = AceEvent.UID_NUM + 1 |
AceEvent.UID_NUM = uid |
AceEvent.currentEventUID = uid |
local tmp = new() |
local AceEvent_onceRegistry = AceEvent.onceRegistry |
if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then |
for obj, method in pairs(AceEvent_onceRegistry[event]) do |
tmp[obj] = AceEvent_registry[event] and AceEvent_registry[event][obj] or nil |
end |
local obj = next(tmp) |
while obj do |
local method = tmp[obj] |
AceEvent.UnregisterEvent(obj, event) |
if type(method) == "string" then |
local obj_method = obj[method] |
if obj_method then |
local success, err = pcall(obj_method, obj, ...) |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end |
end |
elseif method then -- function |
local success, err = pcall(method, ...) |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end |
end |
tmp[obj] = nil |
obj = next(tmp) |
end |
end |
local AceEvent_throttleRegistry = AceEvent.throttleRegistry |
local throttleTable = AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] |
if AceEvent_registry[event] then |
for obj, method in pairs(AceEvent_registry[event]) do |
tmp[obj] = method |
end |
local obj = next(tmp) |
while obj do |
local continue = nil |
if throttleTable and throttleTable[obj] then |
local a1 = ... |
if a1 == nil then |
a1 = FAKE_NIL |
end |
if not throttleTable[obj][a1] or GetTime() - throttleTable[obj][a1] >= throttleTable[obj][RATE] then |
throttleTable[obj][a1] = GetTime() |
else |
continue = true |
end |
end |
if not continue then |
local method = tmp[obj] |
local t = type(method) |
if t == "string" then |
local obj_method = obj[method] |
if obj_method then |
local success, err = pcall(obj_method, obj, ...) |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end |
end |
elseif t == "function" then -- function |
local success, err = pcall(method, ...) |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end |
else |
AceEvent:error("Cannot trigger event %q. %q's handler, %q, is not a method or function (%s).", event, obj, method, t) |
end |
end |
tmp[obj] = nil |
obj = next(tmp) |
end |
end |
if AceEvent_registry[ALL_EVENTS] then |
for obj, method in pairs(AceEvent_registry[ALL_EVENTS]) do |
tmp[obj] = method |
end |
local obj = next(tmp) |
while obj do |
local method = tmp[obj] |
local t = type(method) |
if t == "string" then |
local obj_method = obj[method] |
if obj_method then |
local success, err = pcall(obj_method, obj, ...) |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end |
end |
elseif t == "function" then |
local success, err = pcall(method, ...) |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end |
else |
AceEvent:error("Cannot trigger event %q. %q's handler, %q, is not a method or function (%s).", event, obj, method, t) |
end |
tmp[obj] = nil |
obj = next(tmp) |
end |
end |
tmp = del(tmp) |
AceEvent.currentEvent = lastEvent |
AceEvent.currentEventUID = lastEventUID |
end |
local delayRegistry |
local OnUpdate |
do |
local tmp = {} |
OnUpdate = function() |
local t = GetTime() |
for k,v in pairs(delayRegistry) do |
tmp[k] = true |
end |
for k in pairs(tmp) do |
local v = delayRegistry[k] |
if v then |
local v_time = v.time |
if not v_time then |
delayRegistry[k] = nil |
elseif v_time <= t then |
local v_repeatDelay = v.repeatDelay |
if v_repeatDelay then |
-- use the event time, not the current time, else timing inaccuracies add up over time |
v.time = v_time + v_repeatDelay |
end |
local event = v.event |
local t = type(event) |
if t == "function" then |
local uid = AceEvent.UID_NUM + 1 |
AceEvent.UID_NUM = uid |
AceEvent.currentEventUID = uid |
local success, err = pcall(event, unpack(v, 1, v.n)) |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end |
AceEvent.currentEventUID = nil |
elseif t == "string" then |
AceEvent:TriggerEvent(event, unpack(v, 1, v.n)) |
else |
AceEvent:error("Cannot trigger event %q, it's not a method or function (%s).", event, t) |
end |
if not v_repeatDelay then |
local x = delayRegistry[k] |
if x and x.time == v_time then -- check if it was manually reset |
if type(k) == "string" then |
del(delayRegistry[k]) |
end |
delayRegistry[k] = nil |
end |
end |
end |
end |
end |
for k in pairs(tmp) do |
tmp[k] = nil |
end |
if not next(delayRegistry) then |
AceEvent.frame:Hide() |
end |
end |
end |
local function ScheduleEvent(self, repeating, event, delay, ...) |
local id |
if type(event) == "string" and type(delay) ~= "number" then |
id, event, delay = event, delay, ... |
AceEvent:argCheck(event, 3, "string", "function", --[[ so message is right ]] "number") |
AceEvent:argCheck(delay, 4, "number") |
self:CancelScheduledEvent(id) |
else |
AceEvent:argCheck(event, 2, "string", "function") |
AceEvent:argCheck(delay, 3, "number") |
end |
if not delayRegistry then |
AceEvent.delayRegistry = {} |
delayRegistry = AceEvent.delayRegistry |
AceEvent.frame:SetScript("OnUpdate", OnUpdate) |
end |
local t |
if id then |
t = new(select(2, ...)) |
t.n = select('#', ...) - 1 |
else |
t = new(...) |
t.n = select('#', ...) |
end |
t.event = event |
t.time = GetTime() + delay |
t.self = self |
t.id = id or t |
t.repeatDelay = repeating and delay |
delayRegistry[t.id] = t |
AceEvent.frame:Show() |
end |
--[[---------------------------------------------------------------------------------- |
Notes: |
* Schedule an event to fire. |
* To fire on the next frame, specify a delay of 0. |
Arguments: |
string or function - name of the event to fire, or a function to call. |
number - the amount of time to wait until calling. |
tuple - a list of arguments to pass along. |
------------------------------------------------------------------------------------]] |
function AceEvent:ScheduleEvent(event, delay, ...) |
if type(event) == "string" and type(delay) ~= "number" then |
AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number") |
AceEvent:argCheck(..., 4, "number") |
else |
AceEvent:argCheck(event, 2, "string", "function") |
AceEvent:argCheck(delay, 3, "number") |
end |
return ScheduleEvent(self, false, event, delay, ...) |
end |
function AceEvent:ScheduleRepeatingEvent(event, delay, ...) |
if type(event) == "string" and type(delay) ~= "number" then |
AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number") |
AceEvent:argCheck(..., 4, "number") |
else |
AceEvent:argCheck(event, 2, "string", "function") |
AceEvent:argCheck(delay, 3, "number") |
end |
return ScheduleEvent(self, true, event, delay, ...) |
end |
function AceEvent:CancelScheduledEvent(t) |
AceEvent:argCheck(t, 2, "string") |
if delayRegistry then |
local v = delayRegistry[t] |
if v then |
if type(t) == "string" then |
del(delayRegistry[t]) |
end |
delayRegistry[t] = nil |
if not next(delayRegistry) then |
AceEvent.frame:Hide() |
end |
return true |
end |
end |
return false |
end |
function AceEvent:IsEventScheduled(t) |
AceEvent:argCheck(t, 2, "string") |
if delayRegistry then |
local v = delayRegistry[t] |
if v then |
return true, v.time - GetTime() |
end |
end |
return false, nil |
end |
function AceEvent:UnregisterEvent(event) |
AceEvent:argCheck(event, 2, "string") |
local AceEvent_registry = AceEvent.registry |
if AceEvent_registry[event] and AceEvent_registry[event][self] then |
AceEvent_registry[event][self] = nil |
local AceEvent_onceRegistry = AceEvent.onceRegistry |
if AceEvent_onceRegistry and AceEvent_onceRegistry[event] and AceEvent_onceRegistry[event][self] then |
AceEvent_onceRegistry[event][self] = nil |
if not next(AceEvent_onceRegistry[event]) then |
AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event]) |
end |
end |
local AceEvent_throttleRegistry = AceEvent.throttleRegistry |
if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] and AceEvent_throttleRegistry[event][self] then |
AceEvent_throttleRegistry[event][self] = nil |
if not next(AceEvent_throttleRegistry[event]) then |
AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event]) |
end |
end |
if not next(AceEvent_registry[event]) then |
AceEvent_registry[event] = del(AceEvent_registry[event]) |
if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then |
AceEvent.frame:UnregisterEvent(event) |
end |
end |
else |
if self == AceEvent then |
error(("Cannot unregister event %q. Improperly unregistering from AceEvent-2.0."):format(event), 2) |
else |
AceEvent:error("Cannot unregister event %q. %q is not registered with it.", event, self) |
end |
end |
AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event) |
end |
function AceEvent:UnregisterAllEvents() |
local AceEvent_registry = AceEvent.registry |
if AceEvent_registry[ALL_EVENTS] and AceEvent_registry[ALL_EVENTS][self] then |
AceEvent_registry[ALL_EVENTS][self] = nil |
if not next(AceEvent_registry[ALL_EVENTS]) then |
AceEvent_registry[ALL_EVENTS] = del(AceEvent_registry[ALL_EVENTS]) |
AceEvent.frame:UnregisterAllEvents() |
for k,v in pairs(AceEvent_registry) do |
AceEvent.frame:RegisterEvent(k) |
end |
end |
end |
if AceEvent_registry.AceEvent_EventUnregistered then |
local event, data = "AceEvent_EventUnregistered", AceEvent_registry.AceEvent_EventUnregistered |
local x = data[self] |
data[self] = nil |
if x then |
if not next(data) then |
if not AceEvent_registry[ALL_EVENTS] then |
AceEvent.frame:UnregisterEvent(event) |
end |
AceEvent_registry[event] = del(AceEvent_registry[event]) |
end |
AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event) |
end |
end |
for event, data in pairs(AceEvent_registry) do |
local x = data[self] |
data[self] = nil |
if x and event ~= ALL_EVENTS then |
if not next(data) then |
if not AceEvent_registry[ALL_EVENTS] then |
AceEvent.frame:UnregisterEvent(event) |
end |
AceEvent_registry[event] = del(AceEvent_registry[event]) |
end |
AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event) |
end |
end |
if AceEvent.onceRegistry then |
for event, data in pairs(AceEvent.onceRegistry) do |
data[self] = nil |
end |
end |
end |
function AceEvent:CancelAllScheduledEvents() |
if delayRegistry then |
for k,v in pairs(delayRegistry) do |
if v.self == self then |
if type(k) == "string" then |
del(delayRegistry[k]) |
end |
delayRegistry[k] = nil |
end |
end |
if not next(delayRegistry) then |
AceEvent.frame:Hide() |
end |
end |
end |
function AceEvent:IsEventRegistered(event) |
AceEvent:argCheck(event, 2, "string") |
local AceEvent_registry = AceEvent.registry |
if self == AceEvent then |
return AceEvent_registry[event] and next(AceEvent_registry[event]) or AceEvent_registry[ALL_EVENTS] and next(AceEvent_registry[ALL_EVENTS]) and true or false |
end |
if AceEvent_registry[event] and AceEvent_registry[event][self] then |
return true, AceEvent_registry[event][self] |
end |
if AceEvent_registry[ALL_EVENTS] and AceEvent_registry[ALL_EVENTS][self] then |
return true, AceEvent_registry[ALL_EVENTS][self] |
end |
return false, nil |
end |
local UnitExists = UnitExists |
local bucketfunc |
function AceEvent:RegisterBucketEvent(event, delay, method, ...) |
AceEvent:argCheck(event, 2, "string", "table") |
if type(event) == "table" then |
for k,v in pairs(event) do |
if type(k) ~= "number" then |
AceEvent:error("All keys to argument #2 to `RegisterBucketEvent' must be numbers.") |
elseif type(v) ~= "string" then |
AceEvent:error("All values to argument #2 to `RegisterBucketEvent' must be strings.") |
end |
end |
end |
AceEvent:argCheck(delay, 3, "number") |
if AceEvent == self then |
AceEvent:argCheck(method, 4, "function") |
self = method |
else |
if type(event) == "string" then |
AceEvent:argCheck(method, 4, "string", "function", "nil") |
if not method then |
method = event |
end |
else |
AceEvent:argCheck(method, 4, "string", "function") |
end |
if type(method) == "string" and type(self[method]) ~= "function" then |
AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method) |
end |
end |
local buckets = AceEvent.buckets |
if not buckets[event] then |
buckets[event] = new() |
end |
if not buckets[event][self] then |
local t = {} |
t.current = {} |
t.self = self |
buckets[event][self] = t |
else |
AceEvent.CancelScheduledEvent(self, buckets[event][self].id) |
end |
local bucket = buckets[event][self] |
bucket.method = method |
local n = select('#', ...) |
if n > 0 then |
for i = 1, n do |
bucket[i] = select(i, ...) |
end |
end |
bucket.n = n |
local func = function(arg1) |
bucket.run = true |
if arg1 then |
bucket.current[arg1] = true |
end |
end |
buckets[event][self].func = func |
local isUnitBucket = true |
if type(event) == "string" then |
AceEvent.RegisterEvent(self, event, func) |
if not event:find("^UNIT_") then |
isUnitBucket = nil |
end |
else |
for _,v in ipairs(event) do |
AceEvent.RegisterEvent(self, v, func) |
if isUnitBucket and not v:find("^UNIT_") then |
isUnitBucket = nil |
end |
end |
end |
bucket.unit = isUnitBucket |
if not bucketfunc then |
bucketfunc = function(bucket) |
if bucket.run then |
local current = bucket.current |
local method = bucket.method |
local self = bucket.self |
if bucket.unit then |
for unit in pairs(current) do |
if not UnitExists(unit) then |
current[unit] = nil |
end |
end |
end |
if type(method) == "string" then |
self[method](self, current, unpack(bucket, 1, bucket.n)) |
elseif method then -- function |
method(current, unpack(bucket, 1, bucket.n)) |
end |
for k in pairs(current) do |
current[k] = nil |
k = nil |
end |
bucket.run = nil |
end |
end |
end |
bucket.id = "AceEvent-Bucket-" .. tostring(bucket) |
AceEvent.ScheduleRepeatingEvent(self, bucket.id, bucketfunc, delay, bucket) |
end |
function AceEvent:IsBucketEventRegistered(event) |
AceEvent:argCheck(event, 2, "string", "table") |
return AceEvent.buckets and AceEvent.buckets[event] and AceEvent.buckets[event][self] |
end |
function AceEvent:UnregisterBucketEvent(event) |
AceEvent:argCheck(event, 2, "string", "table") |
if not AceEvent.buckets or not AceEvent.buckets[event] or not AceEvent.buckets[event][self] then |
AceEvent:error("Cannot unregister bucket event %q. %q is not registered with it.", event, self) |
end |
local bucket = AceEvent.buckets[event][self] |
if type(event) == "string" then |
AceEvent.UnregisterEvent(self, event) |
else |
for _,v in ipairs(event) do |
AceEvent.UnregisterEvent(self, v) |
end |
end |
AceEvent:CancelScheduledEvent(bucket.id) |
bucket.current = nil |
AceEvent.buckets[event][self] = nil |
if not next(AceEvent.buckets[event]) then |
AceEvent.buckets[event] = del(AceEvent.buckets[event]) |
end |
end |
function AceEvent:UnregisterAllBucketEvents() |
if not AceEvent.buckets or not next(AceEvent.buckets) then |
return |
end |
for k,v in pairs(AceEvent.buckets) do |
if v == self then |
AceEvent.UnregisterBucketEvent(self, k) |
k = nil |
end |
end |
end |
local combatSchedules |
function AceEvent:CancelAllCombatSchedules() |
local i = 0 |
while true do |
i = i + 1 |
if not combatSchedules[i] then |
break |
end |
local v = combatSchedules[i] |
if v.self == self then |
v = del(v) |
table.remove(combatSchedules, i) |
i = i - 1 |
end |
end |
end |
local inCombat = false |
function AceEvent:PLAYER_REGEN_DISABLED() |
inCombat = true |
end |
do |
local tmp = {} |
function AceEvent:PLAYER_REGEN_ENABLED() |
inCombat = false |
for i, v in ipairs(combatSchedules) do |
tmp[i] = v |
combatSchedules[i] = nil |
end |
for i, v in ipairs(tmp) do |
local func = v.func |
if func then |
local success, err = pcall(func, unpack(v, 1, v.n)) |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end |
else |
local obj = v.obj or v.self |
local method = v.method |
local obj_method = obj[method] |
if obj_method then |
local success, err = pcall(obj_method, obj, unpack(v, 1, v.n)) |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end |
end |
end |
tmp[i] = del(v) |
end |
end |
end |
function AceEvent:ScheduleLeaveCombatAction(method, ...) |
local style = type(method) |
if self == AceEvent then |
if style == "table" then |
local func = (...) |
AceEvent:argCheck(func, 3, "string") |
if type(method[func]) ~= "function" then |
AceEvent:error("Cannot schedule a combat action to method %q, it does not exist", func) |
end |
else |
AceEvent:argCheck(method, 2, "function", --[[so message is right]] "table") |
end |
self = method |
else |
AceEvent:argCheck(method, 2, "function", "string", "table") |
if style == "string" and type(self[method]) ~= "function" then |
AceEvent:error("Cannot schedule a combat action to method %q, it does not exist", method) |
elseif style == "table" then |
local func = (...) |
AceEvent:argCheck(func, 3, "string") |
if type(method[func]) ~= "function" then |
AceEvent:error("Cannot schedule a combat action to method %q, it does not exist", func) |
end |
end |
end |
if not inCombat then |
local success, err |
if type(method) == "function" then |
success, err = pcall(method, ...) |
elseif type(method) == "table" then |
local func = (...) |
success, err = pcall(method[func], method, select(2, ...)) |
else |
success, err = pcall(self[method], self, ...) |
end |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end |
return |
end |
local t |
local n = select('#', ...) |
if style == "table" then |
t = new(select(2, ...)) |
t.obj = method |
t.method = (...) |
t.n = n-1 |
else |
t = new(...) |
t.n = n |
if style == "function" then |
t.func = method |
else |
t.method = method |
end |
end |
t.self = self |
table.insert(combatSchedules, t) |
end |
function AceEvent:OnEmbedDisable(target) |
self.UnregisterAllEvents(target) |
self.CancelAllScheduledEvents(target) |
self.UnregisterAllBucketEvents(target) |
self.CancelAllCombatSchedules(target) |
end |
function AceEvent:IsFullyInitialized() |
return self.postInit or false |
end |
local function activate(self, oldLib, oldDeactivate) |
AceEvent = self |
self.onceRegistry = oldLib and oldLib.onceRegistry or {} |
self.throttleRegistry = oldLib and oldLib.throttleRegistry or {} |
self.delayRegistry = oldLib and oldLib.delayRegistry or {} |
self.buckets = oldLib and oldLib.buckets or {} |
self.registry = oldLib and oldLib.registry or {} |
self.frame = oldLib and oldLib.frame or CreateFrame("Frame", "AceEvent20Frame") |
self.playerLogin = IsLoggedIn() and true |
self.postInit = oldLib and oldLib.postInit or self.playerLogin and ChatTypeInfo and ChatTypeInfo.WHISPER and ChatTypeInfo.WHISPER.r and true |
self.ALL_EVENTS = oldLib and oldLib.ALL_EVENTS or _G.newproxy() |
self.FAKE_NIL = oldLib and oldLib.FAKE_NIL or _G.newproxy() |
self.RATE = oldLib and oldLib.RATE or _G.newproxy() |
self.combatSchedules = oldLib and oldLib.combatSchedules or {} |
self.UID_NUM = oldLib and oldLib.UID_NUM or 0 |
combatSchedules = self.combatSchedules |
ALL_EVENTS = self.ALL_EVENTS |
FAKE_NIL = self.FAKE_NIL |
RATE = self.RATE |
local inPlw = false |
local blacklist = { |
UNIT_INVENTORY_CHANGED = true, |
BAG_UPDATE = true, |
ITEM_LOCK_CHANGED = true, |
ACTIONBAR_SLOT_CHANGED = true, |
} |
self.frame:SetScript("OnEvent", function(_, event, ...) |
if event == "PLAYER_ENTERING_WORLD" then |
inPlw = false |
elseif event == "PLAYER_LEAVING_WORLD" then |
inPlw = true |
end |
if event and (not inPlw or not blacklist[event]) then |
self:TriggerEvent(event, ...) |
end |
end) |
if self.delayRegistry then |
delayRegistry = self.delayRegistry |
self.frame:SetScript("OnUpdate", OnUpdate) |
end |
self:UnregisterAllEvents() |
self:CancelAllScheduledEvents() |
local function handleFullInit() |
if not self.postInit then |
local function func() |
self.postInit = true |
self:TriggerEvent("AceEvent_FullyInitialized") |
if self.registry["CHAT_MSG_CHANNEL_NOTICE"] and self.registry["CHAT_MSG_CHANNEL_NOTICE"][self] then |
self:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE") |
end |
if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then |
self:UnregisterEvent("MEETINGSTONE_CHANGED") |
end |
end |
registeringFromAceEvent = true |
self:RegisterEvent("MEETINGSTONE_CHANGED", func, true) |
self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE", func, true) |
self:ScheduleEvent("AceEvent_FullyInitialized", func, 10) |
registeringFromAceEvent = nil |
end |
end |
if not self.playerLogin then |
registeringFromAceEvent = true |
self:RegisterEvent("PLAYER_LOGIN", function() |
self.playerLogin = true |
handleFullInit() |
handleFullInit = nil |
end, true) |
registeringFromAceEvent = nil |
else |
handleFullInit() |
handleFullInit = nil |
end |
if not AceEvent20EditBox then |
CreateFrame("Editbox", "AceEvent20EditBox") |
end |
local editbox = AceEvent20EditBox |
function editbox:Execute(line) |
local defaulteditbox = DEFAULT_CHAT_FRAME.editBox |
self:SetAttribute("chatType", defaulteditbox:GetAttribute("chatType")) |
self:SetAttribute("tellTarget", defaulteditbox:GetAttribute("tellTarget")) |
self:SetAttribute("channelTarget", defaulteditbox:GetAttribute("channelTarget")) |
self:SetText(line) |
ChatEdit_SendText(self) |
end |
editbox:Hide() |
_G["SLASH_IN1"] = "/in" |
SlashCmdList["IN"] = function(msg) |
local seconds, command, rest = msg:match("^([^%s]+)%s+(/[^%s]+)(.*)$") |
seconds = tonumber(seconds) |
if not seconds then |
DEFAULT_CHAT_FRAME:AddMessage("Error, bad arguments to /in. Must be in the form of `/in 5 /say hi'") |
return |
end |
if IsSecureCmd(command) then |
DEFAULT_CHAT_FRAME:AddMessage(("Error, /in cannot call secure command: %s"):format(command)) |
return |
end |
self:ScheduleEvent("AceEventSlashIn-" .. math.random(1, 1000000000), editbox.Execute, seconds, editbox, command .. rest) |
end |
registeringFromAceEvent = true |
self:RegisterEvent("PLAYER_REGEN_ENABLED") |
self:RegisterEvent("PLAYER_REGEN_DISABLED") |
self:RegisterEvent("LOOT_OPENED", function() |
SendAddonMessage("LOOT_OPENED", "", "RAID") |
end) |
inCombat = InCombatLockdown() |
registeringFromAceEvent = nil |
self:activate(oldLib, oldDeactivate) |
if oldLib then |
oldDeactivate(oldLib) |
end |
end |
AceLibrary:Register(AceEvent, MAJOR_VERSION, MINOR_VERSION, activate) |
## Interface: 20400 |
## Title: Lib: AceEvent-2.0 |
## Notes: AddOn development framework |
## Author: Ace Development Team |
## LoadOnDemand: 1 |
## X-Website: http://www.wowace.com |
## X-Category: Library |
## X-License: LGPL v2.1 + MIT for AceOO-2.0 |
## Dependencies: AceLibrary, AceOO-2.0 |
AceEvent-2.0.lua |
--[[ |
Name: AceAddon-2.0 |
Revision: $Rev$ |
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) |
Inspired By: Ace 1.x by Turan (turan@gryphon.com) |
Website: http://www.wowace.com/ |
Documentation: http://www.wowace.com/wiki/AceAddon-2.0 |
SVN: http://svn.wowace.com/wowace/trunk/Ace2/AceAddon-2.0 |
Description: Base for all Ace addons to inherit from. |
Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0, (optional) AceConsole-2.0 |
License: LGPL v2.1 |
]] |
local MAJOR_VERSION = "AceAddon-2.0" |
local MINOR_VERSION = "$Revision$" |
-- This ensures the code is only executed if the libary doesn't already exist, or is a newer version |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0.") end |
local function safecall(func,...) |
local success, err = pcall(func,...) |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("\n(.-: )in.-\n") or "") .. err) end |
end |
-- Localization |
local STANDBY, TITLE, NOTES, VERSION, AUTHOR, DATE, CATEGORY, EMAIL, CREDITS, WEBSITE, CATEGORIES, ABOUT, LICENSE, PRINT_ADDON_INFO, DONATE, DONATE_DESC, HOWTO_DONATE_WINDOWS, HOWTO_DONATE_MAC |
if GetLocale() == "deDE" then |
STANDBY = "|cffff5050(Standby)|r" -- capitalized |
TITLE = "Titel" |
NOTES = "Anmerkung" |
VERSION = "Version" |
AUTHOR = "Autor" |
DATE = "Datum" |
CATEGORY = "Kategorie" |
EMAIL = "E-Mail" |
WEBSITE = "Webseite" |
CREDITS = "Credits" -- fix |
LICENSE = "License" -- fix |
ABOUT = "Ãber" |
PRINT_ADDON_INFO = "Gibt Addondaten aus" |
DONATE = "Donate" -- fix |
DONATE_DESC = "Give a much-needed donation to the author of this addon." -- fix |
HOWTO_DONATE_WINDOWS = "Press Ctrl-A to select the link, then Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix |
HOWTO_DONATE_MAC = "Press Cmd-A to select the link, then Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix |
CATEGORIES = { |
["Action Bars"] = "Aktionsleisten", |
["Auction"] = "Auktion", |
["Audio"] = "Audio", |
["Battlegrounds/PvP"] = "Schlachtfeld/PvP", |
["Buffs"] = "Stärkungszauber", |
["Chat/Communication"] = "Chat/Kommunikation", |
["Druid"] = "Druide", |
["Hunter"] = "Jäger", |
["Mage"] = "Magier", |
["Paladin"] = "Paladin", |
["Priest"] = "Priester", |
["Rogue"] = "Schurke", |
["Shaman"] = "Schamane", |
["Warlock"] = "Hexenmeister", |
["Warrior"] = "Krieger", |
["Healer"] = "Heiler", |
["Tank"] = "Tank", |
["Caster"] = "Zauberer", |
["Combat"] = "Kampf", |
["Compilations"] = "Zusammenstellungen", |
["Data Export"] = "Datenexport", |
["Development Tools"] = "Entwicklungs Tools", |
["Guild"] = "Gilde", |
["Frame Modification"] = "Frame Veränderungen", |
["Interface Enhancements"] = "Interface Verbesserungen", |
["Inventory"] = "Inventar", |
["Library"] = "Bibliotheken", |
["Map"] = "Karte", |
["Mail"] = "Post", |
["Miscellaneous"] = "Diverses", |
["Quest"] = "Quest", |
["Raid"] = "Schlachtzug", |
["Tradeskill"] = "Beruf", |
["UnitFrame"] = "Einheiten-Fenster", |
} |
elseif GetLocale() == "frFR" then |
STANDBY = "|cffff5050(attente)|r" |
TITLE = "Titre" |
NOTES = "Notes" |
VERSION = "Version" |
AUTHOR = "Auteur" |
DATE = "Date" |
CATEGORY = "Catégorie" |
EMAIL = "E-mail" |
WEBSITE = "Site web" |
CREDITS = "Credits" -- fix |
LICENSE = "License" -- fix |
ABOUT = "A propos" |
PRINT_ADDON_INFO = "Afficher les informations sur l'addon" |
DONATE = "Donate" -- fix |
DONATE_DESC = "Give a much-needed donation to the author of this addon." -- fix |
HOWTO_DONATE_WINDOWS = "Press Ctrl-A to select the link, then Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix |
HOWTO_DONATE_MAC = "Press Cmd-A to select the link, then Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix |
CATEGORIES = { |
["Action Bars"] = "Barres d'action", |
["Auction"] = "Hôtel des ventes", |
["Audio"] = "Audio", |
["Battlegrounds/PvP"] = "Champs de bataille/JcJ", |
["Buffs"] = "Buffs", |
["Chat/Communication"] = "Chat/Communication", |
["Druid"] = "Druide", |
["Hunter"] = "Chasseur", |
["Mage"] = "Mage", |
["Paladin"] = "Paladin", |
["Priest"] = "Prêtre", |
["Rogue"] = "Voleur", |
["Shaman"] = "Chaman", |
["Warlock"] = "Démoniste", |
["Warrior"] = "Guerrier", |
["Healer"] = "Soigneur", |
["Tank"] = "Tank", |
["Caster"] = "Casteur", |
["Combat"] = "Combat", |
["Compilations"] = "Compilations", |
["Data Export"] = "Exportation de données", |
["Development Tools"] = "Outils de développement", |
["Guild"] = "Guilde", |
["Frame Modification"] = "Modification des fenêtres", |
["Interface Enhancements"] = "Améliorations de l'interface", |
["Inventory"] = "Inventaire", |
["Library"] = "Bibliothèques", |
["Map"] = "Carte", |
["Mail"] = "Courrier", |
["Miscellaneous"] = "Divers", |
["Quest"] = "Quêtes", |
["Raid"] = "Raid", |
["Tradeskill"] = "Métiers", |
["UnitFrame"] = "Fenêtres d'unité", |
} |
elseif GetLocale() == "koKR" then |
STANDBY = "|cffff5050(ì¬ì©ê°ë¥)|r" |
TITLE = "ì 목" |
NOTES = "ë ¸í¸" |
VERSION = "ë²ì " |
AUTHOR = "ì ìì" |
DATE = "ë ì§" |
CATEGORY = "ë¶ë¥" |
EMAIL = "ì ì ì°í¸" |
WEBSITE = "ì¹ ì¬ì´í¸" |
CREDITS = "ê³µë¡ì" |
LICENSE = "ë¼ì´ì¼ì¤" |
ABOUT = "ì ë³´" |
PRINT_ADDON_INFO = "ì ëì¨ì ëí ì 보를 ì¶ë ¥í©ëë¤." |
DONATE = "기ë¶" |
DONATE_DESC = "ì´ ì ëì¨ì ì ìììê² ê¸°ë¶ë¥¼ í©ëë¤." |
HOWTO_DONATE_WINDOWS = "Ctrl-A를 ëë ¤ ë§í¬ë¥¼ ì íí, Ctrl-Cë¡ ë³µì¬í©ëë¤. Alt-Tab ëë ¤ ê²ìì¼ë¡ ë¶í° ëê°í ì¹ ë¸ë¼ì°ì 를 ì½ëë¤. ë³µì¬ë ë§í¬ë¥¼ 주ì ì°½ì ë¶ì¬ë£ê¸° í©ëë¤." |
HOWTO_DONATE_MAC = "Cmd-A를 ëë ¤ ë§í¬ë¥¼ ì íí, Cmd-Cë¡ ë³µì¬í©ëë¤. Cmd-Tab ëë ¤ ê²ìì¼ë¡ ë¶í° ëê°í ì¹ ë¸ë¼ì°ì 를 ì½ëë¤. ë³µì¬ë ë§í¬ë¥¼ 주ì ì°½ì ë¶ì¬ë£ê¸° í©ëë¤." |
CATEGORIES = { |
["Action Bars"] = "ì¡ì ë°", |
["Auction"] = "경매", |
["Audio"] = "ìí¥", |
["Battlegrounds/PvP"] = "ì ì¥/PvP", |
["Buffs"] = "ë²í", |
["Chat/Communication"] = "ëí/ìì¬ìíµ", |
["Druid"] = "ë루ì´ë", |
["Hunter"] = "ì¬ë¥ê¾¼", |
["Mage"] = "ë§ë²ì¬", |
["Paladin"] = "ì±ê¸°ì¬", |
["Priest"] = "ì¬ì ", |
["Rogue"] = "ëì ", |
["Shaman"] = "주ì ì¬", |
["Warlock"] = "íë§ë²ì¬", |
["Warrior"] = "ì ì¬", |
["Healer"] = "íë¬", |
["Tank"] = "í±ì»¤", |
["Caster"] = "ìºì¤í°", |
["Combat"] = "ì í¬", |
["Compilations"] = "ë³µí©", |
["Data Export"] = "ìë£ ì¶ë ¥", |
["Development Tools"] = "ê°ë° ë구", |
["Guild"] = "길ë", |
["Frame Modification"] = "구조 ë³ê²½", |
["Interface Enhancements"] = "ì¸í°íì´ì¤ ê°í", |
["Inventory"] = "ì¸ë²¤í 리", |
["Library"] = "ë¼ì´ë¸ë¬ë¦¬", |
["Map"] = "ì§ë", |
["Mail"] = "ì°í¸", |
["Miscellaneous"] = "기í", |
["Quest"] = "íì¤í¸", |
["Raid"] = "공격ë", |
["Tradeskill"] = "ì 문기ì ", |
["UnitFrame"] = "ì ë íë ì", |
} |
elseif GetLocale() == "zhTW" then |
STANDBY = "|cffff5050(å¾ å½)|r" |
TITLE = "æ¨é¡" |
NOTES = "註è¨" |
VERSION = "çæ¬" |
AUTHOR = "ä½è " |
DATE = "æ¥æ" |
CATEGORY = "é¡å¥" |
EMAIL = "é»åéµä»¶" |
WEBSITE = "網ç«" |
CREDITS = "ç¹å¥æè¬" |
LICENSE = "çæ¬" |
ABOUT = "éæ¼" |
PRINT_ADDON_INFO = "顯示æ件è³è¨ã" |
DONATE = "æè´" |
DONATE_DESC = "æè´éé¢çµ¦æ件ä½è ã" |
HOWTO_DONATE_WINDOWS = "è«æCtrl-Aé¸æ網ç«é£çµï¼Ctrl-Cè¤è£½ç¶²åï¼Alt-Tabåæå°é»è ¦æ¡é¢ï¼æéç覽å¨ï¼å¨ç¶²ååè²¼ä¸ç¶²åã" |
HOWTO_DONATE_MAC = "è«æCmd-Aé¸æ網ç«é£çµï¼Cmd-Cè¤è£½ç¶²åï¼Cmd-Tabåæå°é»è ¦æ¡é¢ï¼æéç覽å¨ï¼å¨ç¶²ååè²¼ä¸ç¶²åã" |
CATEGORIES = { |
["Action Bars"] = "åä½æ¢", |
["Auction"] = "æè³£", |
["Audio"] = "é³æ", |
["Battlegrounds/PvP"] = "æ°å ´/PvP", |
["Buffs"] = "å¢ç", |
["Chat/Communication"] = "è天/éè¨", |
["Druid"] = "å¾·é¯ä¼", |
["Hunter"] = "çµäºº", |
["Mage"] = "æ³å¸«", |
["Paladin"] = "èé¨å£«", |
["Priest"] = "ç§å¸«", |
["Rogue"] = "çè³", |
["Shaman"] = "è©æ»¿", |
["Warlock"] = "è¡å£«", |
["Warrior"] = "æ°å£«", |
["Healer"] = "æ²»çè ", |
["Tank"] = "å¦å ", |
["Caster"] = "æ½æ³è ", |
["Combat"] = "æ°é¬¥", |
["Compilations"] = "æ´å", |
["Data Export"] = "è³æå¯åº", |
["Development Tools"] = "éç¼å·¥å ·", |
["Guild"] = "å ¬æ", |
["Frame Modification"] = "æ¡æ¶ä¿®æ¹", |
["Interface Enhancements"] = "ä»é¢å¢å¼·", |
["Inventory"] = "庫å", |
["Library"] = "ç¨å¼åº«", |
["Map"] = "å°å", |
["Mail"] = "éµä»¶", |
["Miscellaneous"] = "éé ", |
["Quest"] = "ä»»å", |
["Raid"] = "åé", |
["Tradeskill"] = "交ææè½", |
["UnitFrame"] = "å®ä½æ¡æ¶", |
} |
elseif GetLocale() == "zhCN" then |
STANDBY = "|cffff5050(ææ)|r" |
TITLE = "æ é¢" |
NOTES = "é注" |
VERSION = "çæ¬" |
AUTHOR = "ä½è " |
DATE = "æ¥æ" |
CATEGORY = "åç±»" |
EMAIL = "çµåé®ä»¶" |
WEBSITE = "ç½ç«" |
CREDITS = "Credits" -- fix |
LICENSE = "License" -- fix |
ABOUT = "å ³äº" |
PRINT_ADDON_INFO = "å°ååºæ件信æ¯" |
DONATE = "Donate" -- fix |
DONATE_DESC = "Give a much-needed donation to the author of this addon." -- fix |
HOWTO_DONATE_WINDOWS = "Press Ctrl-A to select the link, then Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix |
HOWTO_DONATE_MAC = "Press Cmd-A to select the link, then Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix |
CATEGORIES = { |
["Action Bars"] = "å¨ä½æ¡", |
["Auction"] = "æå", |
["Audio"] = "é³é¢", |
["Battlegrounds/PvP"] = "æåº/PvP", |
["Buffs"] = "å¢çéæ³", |
["Chat/Communication"] = "è天/交æµ", |
["Druid"] = "å¾·é²ä¼", |
["Hunter"] = "ç人", |
["Mage"] = "æ³å¸", |
["Paladin"] = "å£éªå£«", |
["Priest"] = "ç§å¸", |
["Rogue"] = "çè´¼", |
["Shaman"] = "è¨æ»¡ç¥å¸", |
["Warlock"] = "æ¯å£«", |
["Warrior"] = "æ士", |
["Healer"] = "Healer", |
["Tank"] = "Tank", |
["Caster"] = "Caster", |
["Combat"] = "ææ", |
["Compilations"] = "ç¼è¯", |
["Data Export"] = "æ°æ®å¯¼åº", |
["Development Tools"] = "å¼åå·¥å ·", |
["Guild"] = "å ¬ä¼", |
["Frame Modification"] = "æ¡æ¶ä¿®æ¹", |
["Interface Enhancements"] = "çé¢å¢å¼º", |
["Inventory"] = "èå ", |
["Library"] = "åº", |
["Map"] = "å°å¾", |
["Mail"] = "é®ä»¶", |
["Miscellaneous"] = "æ项", |
["Quest"] = "ä»»å¡", |
["Raid"] = "å¢é", |
["Tradeskill"] = "åä¸æè½", |
["UnitFrame"] = "头åæ¡æ¶", |
} |
elseif GetLocale() == "esES" then |
STANDBY = "|cffff5050(espera)|r" |
TITLE = "TÃtulo" |
NOTES = "Notas" |
VERSION = "Versión" |
AUTHOR = "Autor" |
DATE = "Fecha" |
CATEGORY = "CategorÃa" |
EMAIL = "E-mail" |
WEBSITE = "Web" |
CREDITS = "Créditos" |
LICENSE = "License" -- fix |
ABOUT = "Acerca de" |
PRINT_ADDON_INFO = "Muestra información acerca del accesorio." |
DONATE = "Donate" -- fix |
DONATE_DESC = "Give a much-needed donation to the author of this addon." -- fix |
HOWTO_DONATE_WINDOWS = "Press Ctrl-A to select the link, then Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix |
HOWTO_DONATE_MAC = "Press Cmd-A to select the link, then Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix |
CATEGORIES = { |
["Action Bars"] = "Barras de Acción", |
["Auction"] = "Subasta", |
["Audio"] = "Audio", |
["Battlegrounds/PvP"] = "Campos de Batalla/JcJ", |
["Buffs"] = "Buffs", |
["Chat/Communication"] = "Chat/Comunicación", |
["Druid"] = "Druida", |
["Hunter"] = "Cazador", |
["Mage"] = "Mago", |
["Paladin"] = "PaladÃn", |
["Priest"] = "Sacerdote", |
["Rogue"] = "PÃcaro", |
["Shaman"] = "Chamán", |
["Warlock"] = "Brujo", |
["Warrior"] = "Guerrero", |
["Healer"] = "Sanador", |
["Tank"] = "Tanque", |
["Caster"] = "Conjurador", |
["Combat"] = "Combate", |
["Compilations"] = "Compilaciones", |
["Data Export"] = "Exportar Datos", |
["Development Tools"] = "Herramientas de Desarrollo", |
["Guild"] = "Hermandad", |
["Frame Modification"] = "Modificación de Marcos", |
["Interface Enhancements"] = "Mejoras de la Interfaz", |
["Inventory"] = "Inventario", |
["Library"] = "Biblioteca", |
["Map"] = "Mapa", |
["Mail"] = "Correo", |
["Miscellaneous"] = "Misceláneo", |
["Quest"] = "Misión", |
["Raid"] = "Banda", |
["Tradeskill"] = "Habilidad de Comercio", |
["UnitFrame"] = "Marco de Unidades", |
} |
else -- enUS |
STANDBY = "|cffff5050(standby)|r" |
TITLE = "Title" |
NOTES = "Notes" |
VERSION = "Version" |
AUTHOR = "Author" |
DATE = "Date" |
CATEGORY = "Category" |
EMAIL = "E-mail" |
WEBSITE = "Website" |
CREDITS = "Credits" |
LICENSE = "License" |
ABOUT = "About" |
PRINT_ADDON_INFO = "Show information about the addon." |
DONATE = "Donate" |
DONATE_DESC = "Give a much-needed donation to the author of this addon." |
HOWTO_DONATE_WINDOWS = "Press Ctrl-A to select the link, then Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar." |
HOWTO_DONATE_MAC = "Press Cmd-A to select the link, then Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar." |
CATEGORIES = { |
["Action Bars"] = "Action Bars", |
["Auction"] = "Auction", |
["Audio"] = "Audio", |
["Battlegrounds/PvP"] = "Battlegrounds/PvP", |
["Buffs"] = "Buffs", |
["Chat/Communication"] = "Chat/Communication", |
["Druid"] = "Druid", |
["Hunter"] = "Hunter", |
["Mage"] = "Mage", |
["Paladin"] = "Paladin", |
["Priest"] = "Priest", |
["Rogue"] = "Rogue", |
["Shaman"] = "Shaman", |
["Warlock"] = "Warlock", |
["Warrior"] = "Warrior", |
["Healer"] = "Healer", |
["Tank"] = "Tank", |
["Caster"] = "Caster", |
["Combat"] = "Combat", |
["Compilations"] = "Compilations", |
["Data Export"] = "Data Export", |
["Development Tools"] = "Development Tools", |
["Guild"] = "Guild", |
["Frame Modification"] = "Frame Modification", |
["Interface Enhancements"] = "Interface Enhancements", |
["Inventory"] = "Inventory", |
["Library"] = "Library", |
["Map"] = "Map", |
["Mail"] = "Mail", |
["Miscellaneous"] = "Miscellaneous", |
["Quest"] = "Quest", |
["Raid"] = "Raid", |
["Tradeskill"] = "Tradeskill", |
["UnitFrame"] = "UnitFrame", |
} |
end |
setmetatable(CATEGORIES, { __index = function(self, key) -- case-insensitive |
local lowerKey = key:lower() |
for k,v in pairs(CATEGORIES) do |
if k:lower() == lowerKey then |
self[lowerKey] = v |
return v |
end |
end |
end }) |
-- Create the library object |
local AceOO = AceLibrary("AceOO-2.0") |
local AceAddon = AceOO.Class() |
local AceEvent |
local AceConsole |
local AceModuleCore |
function AceAddon:GetLocalizedCategory(name) |
self:argCheck(name, 2, "string") |
return CATEGORIES[name] or UNKNOWN |
end |
function AceAddon:ToString() |
return "AceAddon" |
end |
local function print(text) |
DEFAULT_CHAT_FRAME:AddMessage(text) |
end |
function AceAddon:ADDON_LOADED(name) |
local unregister = true |
local initAddon = {} |
while #self.nextAddon > 0 do |
local addon = table.remove(self.nextAddon, 1) |
if addon.possibleNames[name] then |
table.insert(initAddon, addon) |
else |
unregister = nil |
table.insert(self.skipAddon, addon) |
end |
end |
self.nextAddon, self.skipAddon = self.skipAddon, self.nextAddon |
if unregister then |
AceAddon:UnregisterEvent("ADDON_LOADED") |
end |
while #initAddon > 0 do |
local addon = table.remove(initAddon, 1) |
table.insert(self.addons, addon) |
if not self.addons[name] then |
self.addons[name] = addon |
end |
addon.possibleNames = nil |
self:InitializeAddon(addon, name) |
end |
end |
local function RegisterOnEnable(self) |
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage then -- HACK |
AceAddon.playerLoginFired = true |
end |
if AceAddon.playerLoginFired then |
AceAddon.addonsStarted[self] = true |
if (type(self.IsActive) ~= "function" or self:IsActive()) and (not AceModuleCore or not AceModuleCore:IsModule(self) or AceModuleCore:IsModuleActive(self)) then |
AceAddon:ManualEnable(self) |
end |
else |
if not AceAddon.addonsToOnEnable then |
AceAddon.addonsToOnEnable = {} |
end |
table.insert(AceAddon.addonsToOnEnable, self) |
end |
end |
function AceAddon:InitializeAddon(addon, name) |
if addon.name == nil then |
addon.name = name |
end |
if GetAddOnMetadata then |
-- TOC checks |
if addon.title == nil then |
addon.title = GetAddOnMetadata(name, "Title") |
end |
if type(addon.title) == "string" then |
local num = addon.title:find(" |cff7fff7f %-Ace2%-|r$") |
if num then |
addon.title = addon.title:sub(1, num - 1) |
end |
addon.title = addon.title:trim() |
end |
if addon.notes == nil then |
addon.notes = GetAddOnMetadata(name, "Notes") |
end |
if type(addon.notes) == "string" then |
addon.notes = addon.notes:trim() |
end |
if addon.version == nil then |
addon.version = GetAddOnMetadata(name, "Version") |
end |
if type(addon.version) == "string" then |
if addon.version:find("%$Revision: (%d+) %$") then |
addon.version = addon.version:gsub("%$Revision: (%d+) %$", "%1") |
elseif addon.version:find("%$Rev: (%d+) %$") then |
addon.version = addon.version:gsub("%$Rev: (%d+) %$", "%1") |
elseif addon.version:find("%$LastChangedRevision: (%d+) %$") then |
addon.version = addon.version:gsub("%$LastChangedRevision: (%d+) %$", "%1") |
end |
addon.version = addon.version:trim() |
end |
if addon.author == nil then |
addon.author = GetAddOnMetadata(name, "Author") |
end |
if type(addon.author) == "string" then |
addon.author = addon.author:trim() |
end |
if addon.credits == nil then |
addon.credits = GetAddOnMetadata(name, "X-Credits") |
end |
if type(addon.credits) == "string" then |
addon.credits = addon.credits:trim() |
end |
if addon.donate == nil then |
addon.donate = GetAddOnMetadata(name, "X-Donate") |
end |
if type(addon.donate) == "string" then |
addon.donate = addon.donate:trim() |
end |
if addon.date == nil then |
addon.date = GetAddOnMetadata(name, "X-Date") or GetAddOnMetadata(name, "X-ReleaseDate") |
end |
if type(addon.date) == "string" then |
if addon.date:find("%$Date: (.-) %$") then |
addon.date = addon.date:gsub("%$Date: (.-) %$", "%1") |
elseif addon.date:find("%$LastChangedDate: (.-) %$") then |
addon.date = addon.date:gsub("%$LastChangedDate: (.-) %$", "%1") |
end |
addon.date = addon.date:trim() |
end |
if addon.category == nil then |
addon.category = GetAddOnMetadata(name, "X-Category") |
end |
if type(addon.category) == "string" then |
addon.category = addon.category:trim() |
end |
if addon.email == nil then |
addon.email = GetAddOnMetadata(name, "X-eMail") or GetAddOnMetadata(name, "X-Email") |
end |
if type(addon.email) == "string" then |
addon.email = addon.email:trim() |
end |
if addon.license == nil then |
addon.license = GetAddOnMetadata(name, "X-License") |
end |
if type(addon.license) == "string" then |
addon.license = addon.license:trim() |
end |
if addon.website == nil then |
addon.website = GetAddOnMetadata(name, "X-Website") |
end |
if type(addon.website) == "string" then |
addon.website = addon.website:trim() |
end |
end |
local current = addon.class |
while true do |
if current == AceOO.Class or not current then |
break |
end |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedInitialize) == "function" then |
mixin:OnEmbedInitialize(addon, name) |
end |
end |
end |
current = current.super |
end |
local n = AceAddon.addonsToOnEnable and #AceAddon.addonsToOnEnable or 0 |
if type(addon.OnInitialize) == "function" then |
safecall(addon.OnInitialize, addon, name) |
end |
if AceEvent then |
AceEvent:TriggerEvent("Ace2_AddonInitialized", addon) |
end |
RegisterOnEnable(addon) |
local n2 = AceAddon.addonsToOnEnable and #AceAddon.addonsToOnEnable or 0 |
if n2 - n > 1 then |
local mine = table.remove(AceAddon.addonsToOnEnable) |
table.insert(AceAddon.addonsToOnEnable, n+1, mine) |
end |
end |
local aboutFrame |
local function createAboutFrame() |
aboutFrame = CreateFrame("Frame", "AceAddon20AboutFrame", UIParent, "DialogBoxFrame") |
aboutFrame:SetWidth(500) |
aboutFrame:SetHeight(400) |
aboutFrame:SetPoint("CENTER") |
aboutFrame:SetBackdrop({ |
bgFile = [[Interface\DialogFrame\UI-DialogBox-Background]], |
edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], |
tile = true, tileSize = 16, edgeSize = 16, |
insets = { left = 5, right = 5, top = 5, bottom = 5 } |
}) |
aboutFrame:SetBackdropColor(0,0,0,1) |
local donateButton = CreateFrame("Button", "AceAddon20AboutFrameDonateButton", aboutFrame, "UIPanelButtonTemplate2") |
aboutFrame.donateButton = donateButton |
donateButton:SetPoint("BOTTOMRIGHT", -20, 20) |
_G.AceAddon20AboutFrameDonateButtonText:SetText(DONATE) |
donateButton:SetWidth(_G.AceAddon20AboutFrameDonateButtonText:GetWidth()+20) |
donateButton:SetScript("OnClick", function() |
aboutFrame.currentAddon:OpenDonationFrame() |
end) |
local text = aboutFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge") |
aboutFrame.title = text |
text:SetPoint("TOP", 0, -5) |
aboutFrame:Hide() |
aboutFrame.lefts = {} |
aboutFrame.rights = {} |
aboutFrame.textLefts = {} |
aboutFrame.textRights = {} |
function aboutFrame:Clear() |
self.title:SetText("") |
for i = 1, #self.lefts do |
self.lefts[i] = nil |
self.rights[i] = nil |
end |
end |
function aboutFrame:AddLine(left, right) |
aboutFrame.lefts[#aboutFrame.lefts+1] = left |
aboutFrame.rights[#aboutFrame.rights+1] = right |
end |
local aboutFrame_Show = aboutFrame.Show |
function aboutFrame:Show(...) |
local maxLeftWidth = 0 |
local maxRightWidth = 0 |
local textHeight = 0 |
for i = 1, #self.lefts do |
if not self.textLefts[i] then |
local left = aboutFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal") |
self.textLefts[i] = left |
local right = aboutFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlight") |
self.textRights[i] = right |
if i == 1 then |
left:SetPoint("TOPRIGHT", aboutFrame, "TOPLEFT", 75, -35) |
else |
left:SetPoint("TOPRIGHT", self.textLefts[i-1], "BOTTOMRIGHT", 0, -5) |
end |
right:SetPoint("LEFT", left, "RIGHT", 5, 0) |
end |
self.textLefts[i]:SetText(self.lefts[i] .. ":") |
self.textRights[i]:SetText(self.rights[i]) |
local leftWidth = self.textLefts[i]:GetWidth() |
local rightWidth = self.textRights[i]:GetWidth() |
textHeight = self.textLefts[i]:GetHeight() |
if maxLeftWidth < leftWidth then |
maxLeftWidth = leftWidth |
end |
if maxRightWidth < rightWidth then |
maxRightWidth = rightWidth |
end |
end |
for i = #self.lefts+1, #self.textLefts do |
self.textLefts[i]:SetText('') |
self.textRights[i]:SetText('') |
end |
aboutFrame:SetWidth(75 + maxRightWidth + 20) |
aboutFrame:SetHeight(#self.lefts * (textHeight + 5) + 100) |
aboutFrame_Show(self, ...) |
end |
aboutFrame:Hide() |
createAboutFrame = nil |
end |
local donateFrame |
local function unobfuscateEmail(email) |
return email:gsub(" AT ", "@"):gsub(" DOT ", ".") |
end |
local function isGoodVariable(var) |
return type(var) == "string" or type(var) == "number" |
end |
function AceAddon.prototype:PrintAddonInfo() |
if createAboutFrame then |
createAboutFrame() |
end |
aboutFrame:Clear() |
local x |
if isGoodVariable(self.title) then |
x = tostring(self.title) |
elseif isGoodVariable(self.name) then |
x = tostring(self.name) |
else |
x = "<" .. tostring(self.class) .. " instance>" |
end |
if type(self.IsActive) == "function" then |
if not self:IsActive() then |
x = x .. " " .. STANDBY |
end |
end |
aboutFrame.title:SetText(x) |
if isGoodVariable(self.version) then |
aboutFrame:AddLine(VERSION, tostring(self.version)) |
end |
if isGoodVariable(self.notes) then |
aboutFrame:AddLine(NOTES, tostring(self.notes)) |
end |
if isGoodVariable(self.author) then |
aboutFrame:AddLine(AUTHOR, tostring(self.author)) |
end |
if isGoodVariable(self.credits) then |
aboutFrame:AddLine(CREDITS, tostring(self.credits)) |
end |
if isGoodVariable(self.date) then |
aboutFrame:AddLine(DATE, tostring(self.date)) |
end |
if isGoodVariable(self.category) then |
local category = CATEGORIES[self.category] |
aboutFrame:AddLine(CATEGORY, category or tostring(self.category)) |
end |
if isGoodVariable(self.email) then |
aboutFrame:AddLine(EMAIL, unobfuscateEmail(tostring(self.email))) |
end |
if isGoodVariable(self.website) then |
aboutFrame:AddLine(WEBSITE, tostring(self.website)) |
end |
if isGoodVariable(self.license) then |
aboutFrame:AddLine(LICENSE, tostring(self.license)) |
end |
if donateFrame and donateFrame:IsShown() then |
donateFrame:Hide() |
end |
aboutFrame.currentAddon = self |
aboutFrame:Show() |
if self.donate then |
aboutFrame.donateButton:Show() |
else |
aboutFrame.donateButton:Hide() |
end |
end |
local function createDonateFrame() |
donateFrame = CreateFrame("Frame", "AceAddon20Frame", UIParent, "DialogBoxFrame") |
donateFrame:SetWidth(500) |
donateFrame:SetHeight(200) |
donateFrame:SetPoint("CENTER") |
donateFrame:SetBackdrop({ |
bgFile = [[Interface\DialogFrame\UI-DialogBox-Background]], |
edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], |
tile = true, tileSize = 16, edgeSize = 16, |
insets = { left = 5, right = 5, top = 5, bottom = 5 } |
}) |
donateFrame:SetBackdropColor(0,0,0,1) |
local text = donateFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge") |
text:SetPoint("TOP", 0, -5) |
text:SetText(DONATE) |
local howto = donateFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlight") |
howto:SetPoint("TOP", text, "BOTTOM", 0, -5) |
howto:SetPoint("LEFT", 16, 0) |
howto:SetPoint("RIGHT", -16, 0) |
if not IsMacClient() then |
-- Windows or Linux |
howto:SetText(HOWTO_DONATE_WINDOWS) |
else |
howto:SetText(HOWTO_DONATE_MAC) |
end |
local scrollFrame = CreateFrame("ScrollFrame", "AceAddon20FrameScrollFrame", donateFrame, "UIPanelScrollFrameTemplate") |
scrollFrame:SetToplevel(true) |
scrollFrame:SetPoint("TOP", -10, -76) |
scrollFrame:SetWidth(455) |
scrollFrame:SetHeight(70) |
howto:SetPoint("BOTTOM", scrollFrame, "TOP") |
local editBox = CreateFrame("EditBox", nil, scrollFrame) |
donateFrame.editBox = editBox |
scrollFrame:SetScrollChild(editBox) |
editBox:SetFontObject(ChatFontNormal) |
editBox:SetMultiLine(true) |
editBox:SetMaxLetters(99999) |
editBox:SetWidth(450) |
editBox:SetHeight(54) |
editBox:SetPoint("BOTTOM", 5, 0) |
editBox:SetJustifyH("LEFT") |
editBox:SetJustifyV("TOP") |
editBox:SetAutoFocus(false) |
editBox:SetScript("OnTextChanged", function(this) |
if this:GetText() ~= this.text then |
this:SetText(this.text) |
end |
end) |
editBox:SetScript("OnEscapePressed", function(this) |
this:ClearFocus() |
end) |
createDonateFrame = nil |
end |
local function fix(char) |
return ("%%%02x"):format(char:byte()) |
end |
local function urlencode(text) |
return text:gsub("[^0-9A-Za-z]", fix) |
end |
function AceAddon.prototype:OpenDonationFrame() |
if createDonateFrame then |
createDonateFrame() |
end |
local donate = self.donate |
if type(donate) ~= "string" then |
donate = "Wowace" |
end |
local style, data = (":"):split(donate, 2) |
style = style:lower() |
if style ~= "website" and style ~= "paypal" then |
style = "wowace" |
end |
if style == "wowace" then |
donateFrame.editBox.text = "http://www.wowace.com/wiki/Donations" |
elseif style == "website" then |
donateFrame.editBox.text = data |
else -- PayPal |
local text = "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=" .. urlencode(unobfuscateEmail(data)) |
local name |
if type(self.title) == "string" then |
name = self.title |
elseif type(self.name) == "string" then |
name = self.name |
end |
if name then |
name = name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "") |
text = text .. "&item_name=" .. urlencode(name) |
end |
donateFrame.editBox.text = text |
end |
donateFrame.editBox:SetText(donateFrame.editBox.text) |
if aboutFrame and aboutFrame:IsShown() then |
aboutFrame:Hide() |
end |
donateFrame:Show() |
donateFrame.editBox:SetFocus() |
end |
local options |
function AceAddon:GetAceOptionsDataTable(target) |
return { |
about = { |
name = ABOUT, |
desc = PRINT_ADDON_INFO, |
type = "execute", |
func = "PrintAddonInfo", |
order = -1, |
}, |
donate = { |
name = DONATE, |
desc = DONATE_DESC, |
type = "execute", |
func = "OpenDonationFrame", |
order = -1, |
hidden = function() |
return not target.donate |
end |
} |
} |
end |
function AceAddon:PLAYER_LOGIN() |
self.playerLoginFired = true |
if self.addonsToOnEnable then |
while #self.addonsToOnEnable > 0 do |
local addon = table.remove(self.addonsToOnEnable, 1) |
self.addonsStarted[addon] = true |
if (type(addon.IsActive) ~= "function" or addon:IsActive()) and (not AceModuleCore or not AceModuleCore:IsModule(addon) or AceModuleCore:IsModuleActive(addon)) then |
AceAddon:ManualEnable(addon) |
end |
end |
self.addonsToOnEnable = nil |
end |
end |
function AceAddon.prototype:Inject(t) |
AceAddon:argCheck(t, 2, "table") |
for k,v in pairs(t) do |
self[k] = v |
end |
end |
function AceAddon.prototype:init() |
if not AceEvent then |
error(MAJOR_VERSION .. " requires AceEvent-2.0", 4) |
end |
AceAddon.super.prototype.init(self) |
self.super = self.class.prototype |
AceAddon:RegisterEvent("ADDON_LOADED", "ADDON_LOADED") |
local names = {} |
for i = 1, GetNumAddOns() do |
if IsAddOnLoaded(i) then names[GetAddOnInfo(i)] = true end |
end |
self.possibleNames = names |
table.insert(AceAddon.nextAddon, self) |
end |
function AceAddon.prototype:ToString() |
local x |
if type(self.title) == "string" then |
x = self.title |
elseif type(self.name) == "string" then |
x = self.name |
else |
x = "<" .. tostring(self.class) .. " instance>" |
end |
if (type(self.IsActive) == "function" and not self:IsActive()) or (AceModuleCore and AceModuleCore:IsModule(addon) and AceModuleCore:IsModuleActive(addon)) then |
x = x .. " " .. STANDBY |
end |
return x |
end |
AceAddon.new = function(self, ...) |
local class = AceAddon:pcall(AceOO.Classpool, self, ...) |
return class:new() |
end |
function AceAddon:ManualEnable(addon) |
AceAddon:argCheck(addon, 2, "table") |
local first = nil |
if AceOO.inherits(addon, "AceAddon-2.0") then |
if AceAddon.addonsEnabled and not AceAddon.addonsEnabled[addon] then |
first = true |
AceAddon.addonsEnabled[addon] = true |
end |
end |
local current = addon.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedEnable) == "function" then |
safecall(mixin.OnEmbedEnable, mixin, addon, first) |
end |
end |
end |
current = current.super |
end |
if type(addon.OnEnable) == "function" then |
safecall(addon.OnEnable, addon, first) |
end |
if AceEvent then |
AceEvent:TriggerEvent("Ace2_AddonEnabled", addon, first) |
end |
end |
function AceAddon:ManualDisable(addon) |
AceAddon:argCheck(addon, 2, "table") |
local current = addon.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedDisable) == "function" then |
safecall(mixin.OnEmbedDisable, mixin, addon) |
end |
end |
end |
current = current.super |
end |
if type(module.OnDisable) == "function" then |
safecall(module.OnDisable, addon) |
end |
if AceEvent then |
AceEvent:TriggerEvent("Ace2_AddonDisabled", addon) |
end |
end |
local function external(self, major, instance) |
if major == "AceEvent-2.0" then |
AceEvent = instance |
AceEvent:embed(self) |
self:RegisterEvent("PLAYER_LOGIN", "PLAYER_LOGIN", true) |
elseif major == "AceConsole-2.0" then |
AceConsole = instance |
local slashCommands = { "/ace2" } |
local _,_,_,enabled,loadable = GetAddOnInfo("Ace") |
if not enabled or not loadable then |
table.insert(slashCommands, "/ace") |
end |
local function listAddon(addon, depth) |
if not depth then |
depth = 0 |
end |
local s = (" "):rep(depth) .. " - " .. tostring(addon) |
if rawget(addon, 'version') then |
s = s .. " - |cffffff7f" .. tostring(addon.version) .. "|r" |
end |
if rawget(addon, 'slashCommand') then |
s = s .. " |cffffff7f(" .. tostring(addon.slashCommand) .. ")|r" |
end |
print(s) |
if type(rawget(addon, 'modules')) == "table" then |
local i = 0 |
for k,v in pairs(addon.modules) do |
i = i + 1 |
if i == 6 then |
print((" "):rep(depth + 1) .. " - more...") |
break |
else |
listAddon(v, depth + 1) |
end |
end |
end |
end |
local function listNormalAddon(i) |
local name,_,_,enabled,loadable = GetAddOnInfo(i) |
if not loadable then |
enabled = false |
end |
if self.addons[name] then |
listAddon(self.addons[name]) |
else |
local s = " - " .. tostring(GetAddOnMetadata(i, "Title") or name) |
local version = GetAddOnMetadata(i, "Version") |
if version then |
if version:find("%$Revision: (%d+) %$") then |
version = version:gsub("%$Revision: (%d+) %$", "%1") |
elseif version:find("%$Rev: (%d+) %$") then |
version = version:gsub("%$Rev: (%d+) %$", "%1") |
elseif version:find("%$LastChangedRevision: (%d+) %$") then |
version = version:gsub("%$LastChangedRevision: (%d+) %$", "%1") |
end |
s = s .. " - |cffffff7f" .. version .. "|r" |
end |
if not enabled then |
s = s .. " |cffff0000(disabled)|r" |
end |
if IsAddOnLoadOnDemand(i) then |
s = s .. " |cff00ff00[LoD]|r" |
end |
print(s) |
end |
end |
local function mySort(alpha, bravo) |
return tostring(alpha) < tostring(bravo) |
end |
AceConsole.RegisterChatCommand(self, slashCommands, { |
desc = "AddOn development framework", |
name = "Ace2", |
type = "group", |
args = { |
about = { |
desc = "Get information about Ace2", |
name = "About", |
type = "execute", |
func = function() |
print("|cffffff7fAce2|r - |cffffff7f2.0." .. MINOR_VERSION:gsub("%$Revision: (%d+) %$", "%1") .. "|r - AddOn development framework") |
print(" - |cffffff7f" .. AUTHOR .. ":|r Ace Development Team") |
print(" - |cffffff7f" .. WEBSITE .. ":|r http://www.wowace.com/") |
end |
}, |
list = { |
desc = "List addons", |
name = "List", |
type = "group", |
args = { |
ace2 = { |
desc = "List addons using Ace2", |
name = "Ace2", |
type = "execute", |
func = function() |
print("|cffffff7fAddon list:|r") |
table.sort(self.addons, mySort) |
for _,v in ipairs(self.addons) do |
listAddon(v) |
end |
end |
}, |
all = { |
desc = "List all addons", |
name = "All", |
type = "execute", |
func = function() |
print("|cffffff7fAddon list:|r") |
local count = GetNumAddOns() |
for i = 1, count do |
listNormalAddon(i) |
end |
end |
}, |
enabled = { |
desc = "List all enabled addons", |
name = "Enabled", |
type = "execute", |
func = function() |
print("|cffffff7fAddon list:|r") |
local count = GetNumAddOns() |
for i = 1, count do |
local _,_,_,enabled,loadable = GetAddOnInfo(i) |
if enabled and loadable then |
listNormalAddon(i) |
end |
end |
end |
}, |
disabled = { |
desc = "List all disabled addons", |
name = "Disabled", |
type = "execute", |
func = function() |
print("|cffffff7fAddon list:|r") |
local count = GetNumAddOns() |
for i = 1, count do |
local _,_,_,enabled,loadable = GetAddOnInfo(i) |
if not enabled or not loadable then |
listNormalAddon(i) |
end |
end |
end |
}, |
lod = { |
desc = "List all LoadOnDemand addons", |
name = "LoadOnDemand", |
type = "execute", |
func = function() |
print("|cffffff7fAddon list:|r") |
local count = GetNumAddOns() |
for i = 1, count do |
if IsAddOnLoadOnDemand(i) then |
listNormalAddon(i) |
end |
end |
end |
}, |
ace1 = { |
desc = "List all addons using Ace1", |
name = "Ace 1.x", |
type = "execute", |
func = function() |
print("|cffffff7fAddon list:|r") |
local count = GetNumAddOns() |
for i = 1, count do |
local dep1, dep2, dep3, dep4 = GetAddOnDependencies(i) |
if dep1 == "Ace" or dep2 == "Ace" or dep3 == "Ace" or dep4 == "Ace" then |
listNormalAddon(i) |
end |
end |
end |
}, |
libs = { |
desc = "List all libraries using AceLibrary", |
name = "Libraries", |
type = "execute", |
func = function() |
if type(AceLibrary) == "table" and type(AceLibrary.libs) == "table" then |
print("|cffffff7fLibrary list:|r") |
for name, data in pairs(AceLibrary.libs) do |
local s |
if data.minor then |
s = " - " .. tostring(name) .. "." .. tostring(data.minor) |
else |
s = " - " .. tostring(name) |
end |
if rawget(AceLibrary(name), 'slashCommand') then |
s = s .. " |cffffff7f(" .. tostring(AceLibrary(name).slashCommand) .. "|cffffff7f)" |
end |
print(s) |
end |
end |
end |
}, |
search = { |
desc = "Search by name", |
name = "Search", |
type = "text", |
usage = "<keyword>", |
input = true, |
get = false, |
set = function(...) |
local arg = { ... } |
for i,v in ipairs(arg) do |
arg[i] = v:gsub('%*', '.*'):gsub('%%', '%%%%'):lower() |
end |
local count = GetNumAddOns() |
for i = 1, count do |
local name = GetAddOnInfo(i) |
local good = true |
for _,v in ipairs(arg) do |
if not name:lower():find(v) then |
good = false |
break |
end |
end |
if good then |
listNormalAddon(i) |
end |
end |
end |
} |
}, |
}, |
enable = { |
desc = "Enable addon(s).", |
name = "Enable", |
type = "text", |
usage = "<addon 1> <addon 2> ...", |
get = false, |
input = true, |
set = function(...) |
for i = 1, select("#", ...) do |
local addon = select(i, ...) |
local name, title, _, enabled, _, reason = GetAddOnInfo(addon) |
if reason == "MISSING" then |
print(("|cffffff7fAce2:|r AddOn %q does not exist."):format(addon)) |
elseif not enabled then |
EnableAddOn(addon) |
print(("|cffffff7fAce2:|r %s is now enabled."):format(addon or name)) |
else |
print(("|cffffff7fAce2:|r %s is already enabled."):format(addon or name)) |
end |
end |
end, |
}, |
disable = { |
desc = "Disable addon(s).", |
name = "Disable", |
type = "text", |
usage = "<addon 1> <addon 2> ...", |
get = false, |
input = true, |
set = function(...) |
for i = 1, select("#", ...) do |
local addon = select(i, ...) |
local name, title, _, enabled, _, reason = GetAddOnInfo(addon) |
if reason == "MISSING" then |
print(("|cffffff7fAce2:|r AddOn %q does not exist."):format(addon)) |
elseif enabled then |
DisableAddOn(addon) |
print(("|cffffff7fAce2:|r %s is now disabled."):format(addon or name)) |
else |
print(("|cffffff7fAce2:|r %s is already disabled."):format(addon or name)) |
end |
end |
end, |
}, |
load = { |
desc = "Load addon(s).", |
name = "Load", |
type = "text", |
usage = "<addon 1> <addon 2> ...", |
get = false, |
input = true, |
set = function(...) |
for i = 1, select("#", ...) do |
local addon = select(i, ...) |
local name, title, _, _, loadable, reason = GetAddOnInfo(addon) |
if reason == "MISSING" then |
print(("|cffffff7fAce2:|r AddOn %q does not exist."):format(addon)) |
elseif not loadable then |
print(("|cffffff7fAce2:|r AddOn %q is not loadable. Reason: %s."):format(addon, reason)) |
else |
LoadAddOn(addon) |
print(("|cffffff7fAce2:|r %s is now loaded."):format(addon or name)) |
end |
end |
end |
}, |
info = { |
desc = "Display information", |
name = "Information", |
type = "execute", |
func = function() |
local mem, threshold = gcinfo() |
print((" - |cffffff7fMemory usage [|r%.3f MiB|cffffff7f]|r"):format(mem / 1024)) |
if threshold then |
print((" - |cffffff7fThreshold [|r%.3f MiB|cffffff7f]|r"):format(threshold / 1024)) |
end |
print((" - |cffffff7fFramerate [|r%.0f fps|cffffff7f]|r"):format(GetFramerate())) |
local bandwidthIn, bandwidthOut, latency = GetNetStats() |
bandwidthIn, bandwidthOut = floor(bandwidthIn * 1024), floor(bandwidthOut * 1024) |
print((" - |cffffff7fLatency [|r%.0f ms|cffffff7f]|r"):format(latency)) |
print((" - |cffffff7fBandwidth in [|r%.0f B/s|cffffff7f]|r"):format(bandwidthIn)) |
print((" - |cffffff7fBandwidth out [|r%.0f B/s|cffffff7f]|r"):format(bandwidthOut)) |
print((" - |cffffff7fTotal addons [|r%d|cffffff7f]|r"):format(GetNumAddOns())) |
print((" - |cffffff7fAce2 addons [|r%d|cffffff7f]|r"):format(#self.addons)) |
local ace = 0 |
local enabled = 0 |
local disabled = 0 |
local lod = 0 |
for i = 1, GetNumAddOns() do |
local dep1, dep2, dep3, dep4 = GetAddOnDependencies(i) |
if dep1 == "Ace" or dep2 == "Ace" or dep3 == "Ace" or dep4 == "Ace" then |
ace = ace + 1 |
end |
if IsAddOnLoadOnDemand(i) then |
lod = lod + 1 |
end |
local isActive, loadable = select(4, GetAddOnInfo(i)) |
if not isActive or not loadable then |
disabled = disabled + 1 |
else |
enabled = enabled + 1 |
end |
end |
print((" - |cffffff7fAce 1.x addons [|r%d|cffffff7f]|r"):format(ace)) |
print((" - |cffffff7fLoadOnDemand addons [|r%d|cffffff7f]|r"):format(lod)) |
print((" - |cffffff7fenabled addons [|r%d|cffffff7f]|r"):format(enabled)) |
print((" - |cffffff7fdisabled addons [|r%d|cffffff7f]|r"):format(disabled)) |
local libs = 0 |
if type(AceLibrary) == "table" and type(AceLibrary.libs) == "table" then |
for _ in pairs(AceLibrary.libs) do |
libs = libs + 1 |
end |
end |
print((" - |cffffff7fAceLibrary instances [|r%d|cffffff7f]|r"):format(libs)) |
end |
} |
} |
}) |
elseif major == "AceModuleCore-2.0" then |
AceModuleCore = instance |
end |
end |
local function activate(self, oldLib, oldDeactivate) |
AceAddon = self |
self.playerLoginFired = oldLib and oldLib.playerLoginFired or DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage |
self.addonsToOnEnable = oldLib and oldLib.addonsToOnEnable |
self.addons = oldLib and oldLib.addons or {} |
self.nextAddon = oldLib and oldLib.nextAddon or {} |
self.skipAddon = oldLib and oldLib.skipAddon or {} |
self.addonsStarted = oldLib and oldLib.addonsStarted or {} |
self.addonsEnabled = oldLib and oldLib.addonsEnabled or {} |
if oldDeactivate then |
oldDeactivate(oldLib) |
end |
end |
AceLibrary:Register(AceAddon, MAJOR_VERSION, MINOR_VERSION, activate, nil, external) |
## Interface: 20400 |
## Title: Lib: AceAddon-2.0 |
## Notes: AddOn development framework |
## Author: Ace Development Team |
## LoadOnDemand: 1 |
## X-Website: http://www.wowace.com |
## X-Category: Library |
## X-License: LGPL v2.1 + MIT for AceOO-2.0 |
## Dependencies: AceLibrary, AceOO-2.0 |
AceAddon-2.0.lua |
--[[ |
Name: AceDB-2.0 |
Revision: $Rev$ |
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) |
Inspired By: Ace 1.x by Turan (turan@gryphon.com) |
Website: http://www.wowace.com/ |
Documentation: http://www.wowace.com/index.php/AceDB-2.0 |
SVN: http://svn.wowace.com/root/trunk/Ace2/AceDB-2.0 |
Description: Mixin to allow for fast, clean, and featureful saved variable |
access. |
Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0 |
License: LGPL v2.1 |
]] |
local MAJOR_VERSION = "AceDB-2.0" |
local MINOR_VERSION = "$Revision$" |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end |
local function safecall(func,...) |
local success, err = pcall(func,...) |
if not success then geterrorhandler()(err) end |
end |
local ACTIVE, ENABLED, STATE, TOGGLE_ACTIVE, MAP_ACTIVESUSPENDED, SET_PROFILE, SET_PROFILE_USAGE, PROFILE, PLAYER_OF_REALM, CHOOSE_PROFILE_DESC, CHOOSE_PROFILE_GUI, COPY_PROFILE_DESC, COPY_PROFILE_GUI, OTHER_PROFILE_DESC, OTHER_PROFILE_GUI, OTHER_PROFILE_USAGE, RESET_PROFILE, RESET_PROFILE_DESC, CHARACTER_COLON, REALM_COLON, CLASS_COLON, DEFAULT, ALTERNATIVE |
-- Move these into "enUS" when they've been translated in all other locales |
local DELETE_PROFILE = "Delete" |
local DELETE_PROFILE_DESC = "Deletes a profile. Note that no check is made whether this profile is in use by other characters or not." |
local DELETE_PROFILE_USAGE = "<profile name>" |
if GetLocale() == "deDE" then |
DELETE_PROFILE = "L\195\182schen" |
DELETE_PROFILE_DESC = "L\195\182scht ein Profil. Beachte das nicht \195\188berpr\195\188ft wird ob das zu l\195\182schende Profil von anderen Charakteren genutzt wird oder nicht." |
DELETE_PROFILE_USAGE = "<profil name>" |
ACTIVE = "Aktiv" |
ENABLED = "Aktiviert" |
STATE = "Status" |
TOGGLE_ACTIVE = "Stoppt/Aktiviert dieses Addon." |
MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00Aktiv|r", [false] = "|cffff0000Gestoppt|r" } |
SET_PROFILE = "Setzt das Profil f\195\188r dieses Addon." |
SET_PROFILE_USAGE = "{Charakter || Klasse || Realm || <Profilname>}" |
PROFILE = "Profil" |
PLAYER_OF_REALM = "%s von %s" |
CHOOSE_PROFILE_DESC = "W\195\164hle ein Profil." |
CHOOSE_PROFILE_GUI = "W\195\164hle" |
COPY_PROFILE_DESC = "Kopiert Einstellungen von einem anderem Profil." |
COPY_PROFILE_GUI = "Kopiere von" |
OTHER_PROFILE_DESC = "W\195\164hle ein anderes Profil." |
OTHER_PROFILE_GUI = "Anderes" |
OTHER_PROFILE_USAGE = "<Profilname>" |
RESET_PROFILE = "Resette das Profil" |
RESET_PROFILE_DESC = "Entfernt alle Einstellungen des gegenw\195\164rtigen Profils." |
CHARACTER_COLON = "Charakter: " |
REALM_COLON = "Realm: " |
CLASS_COLON = "Klasse: " |
DEFAULT = "Vorgabe" |
ALTERNATIVE = "Alternativ" |
elseif GetLocale() == "frFR" then |
ACTIVE = "Actif" |
ENABLED = "Activ\195\169" |
STATE = "Etat" |
TOGGLE_ACTIVE = "Suspend/active cet addon." |
MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00Actif|r", [false] = "|cffff0000Suspendu|r" } |
SET_PROFILE = "S\195\169lectionne le profil pour cet addon." |
SET_PROFILE_USAGE = "{perso || classe || royaume || <nom de profil>}" |
PROFILE = "Profil" |
PLAYER_OF_REALM = "%s de %s" |
CHOOSE_PROFILE_DESC = "Choisissez un profil." |
CHOOSE_PROFILE_GUI = "Choix" |
COPY_PROFILE_DESC = "Copier les param\195\168tres d'un autre profil." |
COPY_PROFILE_GUI = "Copier \195\160 partir de" |
OTHER_PROFILE_DESC = "Choisissez un autre profil." |
OTHER_PROFILE_GUI = "Autre" |
OTHER_PROFILE_USAGE = "<nom de profil>" |
RESET_PROFILE = "Reset profile" -- fix |
RESET_PROFILE_DESC = "Clear all settings of the current profile." -- fix |
CHARACTER_COLON = "Personnage: " |
REALM_COLON = "Royaume: " |
CLASS_COLON = "Classe: " |
DEFAULT = "Default" -- fix |
ALTERNATIVE = "Alternative" -- fix |
elseif GetLocale() == "koKR" then |
DELETE_PROFILE = "ìì " |
DELETE_PROFILE_DESC = "íë¡íì ìì í©ëë¤." |
DELETE_PROFILE_USAGE = "<íë¡íëª >" |
ACTIVE = "ì¬ì©" |
ENABLED = "ì¬ì©" |
STATE = "ìí" |
TOGGLE_ACTIVE = "ì´ ì ëì¨ ì¤ì§/ë¤ì ìì" |
MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00ì¬ì©|r", [false] = "|cffff0000ì¤ì§|r" } |
SET_PROFILE = "ì´ ì ëì¨ì íë¡í ì¤ì " |
SET_PROFILE_USAGE = "{ìºë¦í°ëª || ì§ì || ìë²ëª || <íë¡íëª >}" |
PROFILE = "íë¡í" |
PLAYER_OF_REALM = "%s (%s ìë²)" |
CHOOSE_PROFILE_DESC = "íë¡íì ì íí©ëë¤." |
CHOOSE_PROFILE_GUI = "ì í" |
COPY_PROFILE_DESC = "ë¤ë¥¸ íë¡í ì¤ì ì ë³µì¬í©ëë¤." |
COPY_PROFILE_GUI = "ë³µì¬" |
OTHER_PROFILE_DESC = "ë¤ë¥¸ íë¡íì ì íí©ëë¤." |
OTHER_PROFILE_GUI = "기í" |
OTHER_PROFILE_USAGE = "<íë¡íëª >" |
RESET_PROFILE = "íë¡í ì´ê¸°í" |
RESET_PROFILE_DESC = "모ë ì¸í ìì íì¬ íë¡íì ì´ê¸°í í©ëë¤." |
CHARACTER_COLON = "ìºë¦í°: " |
REALM_COLON = "ìë²: " |
CLASS_COLON = "ì§ì : " |
DEFAULT = "기본ê°" |
ALTERNATIVE = "ëì²´" |
elseif GetLocale() == "zhTW" then |
DELETE_PROFILE = "åªé¤" |
DELETE_PROFILE_DESC = "åªé¤è¨éæªã注æï¼æå¯è½å¥çè§è²ä¹ä½¿ç¨éåè¨éæªã" |
DELETE_PROFILE_USAGE = "<è¨éæªå稱>" |
ACTIVE = "åå" |
ENABLED = "åç¨" |
STATE = "çæ " |
TOGGLE_ACTIVE = "æ«å/ç¹¼çºä½¿ç¨éåæ件ã" |
MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00åå|r", [false] = "|cffff0000å·²æ«å|r" } |
SET_PROFILE = "è¨å®éæ件çè¨éæªã" |
SET_PROFILE_USAGE = "{è§è² || è·æ¥ || 伺æå¨ || <è¨éæªå稱>}" |
PROFILE = "è¨éæª" |
PLAYER_OF_REALM = "%s - %s" |
CHOOSE_PROFILE_DESC = "é¸æä¸åè¨éæªã" |
CHOOSE_PROFILE_GUI = "é¸æ" |
COPY_PROFILE_DESC = "ç±å ¶ä»è¨éæªè¤è£½è¨å®ã" |
COPY_PROFILE_GUI = "è¤è£½èª" |
OTHER_PROFILE_DESC = "é¸æå ¶ä»è¨éæªã" |
OTHER_PROFILE_GUI = "å ¶ä»" |
OTHER_PROFILE_USAGE = "<è¨éæªå稱>" |
RESET_PROFILE = "éè¨è¨éæª" |
RESET_PROFILE_DESC = "æ¸ é¤ç®åçè¨éæªä¸çææè¨å®ã" |
CHARACTER_COLON = "è§è²: " |
REALM_COLON = "伺æå¨: " |
CLASS_COLON = "è·æ¥: " |
DEFAULT = "é è¨" |
ALTERNATIVE = "æ¿ä»£" |
elseif GetLocale() == "zhCN" then |
ACTIVE = "\230\156\137\230\149\136" |
ENABLED = "\229\144\175\231\148\168" |
STATE = "\231\138\182\230\128\129" |
TOGGLE_ACTIVE = "\230\154\130\229\129\156/\230\129\162\229\164\141 \230\173\164\230\143\146\228\187\182." |
MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00\230\156\137\230\149\136|r", [false] = "|cffff0000\230\154\130\229\129\156|r" } |
SET_PROFILE = "\232\174\190\231\189\174\233\133\141\231\189\174\230\150\135\228\187\182\228\184\186\232\191\153\230\143\146\228\187\182." |
SET_PROFILE_USAGE = "{\229\173\151\231\172\166 || \233\128\137\228\187\182\231\177\187 || \229\159\159 || <\233\133\141\231\189\174\230\150\135\228\187\182\229\144\141\229\173\151>}" |
PROFILE = "\233\133\141\231\189\174\230\150\135\228\187\182" |
PLAYER_OF_REALM = "%s \231\154\132 %s" |
CHOOSE_PROFILE_DESC = "\233\128\137\230\139\169\233\133\141\231\189\174\230\150\135\228\187\182." |
CHOOSE_PROFILE_GUI = "\233\128\137\230\139\169" |
COPY_PROFILE_DESC = "\229\164\141\229\136\182\232\174\190\231\189\174\228\187\142\229\143\166\228\184\128\228\184\170\233\133\141\231\189\174\230\150\135\228\187\182." |
COPY_PROFILE_GUI = "\229\164\141\229\136\182\228\187\142" |
OTHER_PROFILE_DESC = "\233\128\137\230\139\169\229\143\166\228\184\128\228\184\170\233\133\141\231\189\174\230\150\135\228\187\182." |
OTHER_PROFILE_GUI = "\229\133\182\228\187\150" |
OTHER_PROFILE_USAGE = "<\233\133\141\231\189\174\230\150\135\228\187\182\229\144\141\229\173\151>" |
RESET_PROFILE = "Reset profile" -- fix |
RESET_PROFILE_DESC = "Clear all settings of the current profile." -- fix |
CHARACTER_COLON = "\229\173\151\231\172\166: " |
REALM_COLON = "\229\159\159: " |
CLASS_COLON = "\233\128\137\228\187\182\231\177\187: " |
DEFAULT = "Default" -- fix |
ALTERNATIVE = "Alternative" -- fix |
elseif GetLocale() == "esES" then |
ACTIVE = "Activo" |
ENABLED = "Activado" |
STATE = "Estado" |
TOGGLE_ACTIVE = "Parar/Continuar este accesorio" |
MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00Activo|r", [false] = "|cffff0000Parado|r" } |
SET_PROFILE = "Selecciona el perfil para este accesorio." |
SET_PROFILE_USAGE = "{perso || clase || reino || <nombre del perfil>}" |
PROFILE = "Perfil" |
PLAYER_OF_REALM = "%s de %s" |
CHOOSE_PROFILE_DESC = "Elige un perfil." |
CHOOSE_PROFILE_GUI = "Elige" |
COPY_PROFILE_DESC = "Copiar de un perfil a otro" |
COPY_PROFILE_GUI = "Copiar desde" |
OTHER_PROFILE_DESC = "Elige otro perfil." |
OTHER_PROFILE_GUI = "Otro" |
OTHER_PROFILE_USAGE = "<nombre del perfil>" |
RESET_PROFILE = "Reset profile" -- fix |
RESET_PROFILE_DESC = "Clear all settings of the current profile." -- fix |
CHARACTER_COLON = "Personaje: " |
REALM_COLON = "Reino: " |
CLASS_COLON = "Clase: " |
DEFAULT = "Por defecto" |
ALTERNATIVE = "Alternativo" |
else -- enUS |
ACTIVE = "Active" |
ENABLED = "Enabled" |
STATE = "State" |
TOGGLE_ACTIVE = "Suspend/resume this addon." |
MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00Active|r", [false] = "|cffff0000Suspended|r" } |
SET_PROFILE = "Set profile for this addon." |
SET_PROFILE_USAGE = "{char || class || realm || <profile name>}" |
PROFILE = "Profile" |
PLAYER_OF_REALM = "%s of %s" |
CHOOSE_PROFILE_DESC = "Choose a profile." |
CHOOSE_PROFILE_GUI = "Choose" |
COPY_PROFILE_DESC = "Copy settings from another profile." |
COPY_PROFILE_GUI = "Copy from" |
OTHER_PROFILE_DESC = "Choose another profile." |
OTHER_PROFILE_GUI = "Other" |
OTHER_PROFILE_USAGE = "<profile name>" |
RESET_PROFILE = "Reset profile" |
RESET_PROFILE_DESC = "Clear all settings of the current profile." |
CHARACTER_COLON = "Character: " |
REALM_COLON = "Realm: " |
CLASS_COLON = "Class: " |
DEFAULT = "Default" |
ALTERNATIVE = "Alternative" |
end |
local convertFromOldCharID |
do |
local matchStr = "^" .. PLAYER_OF_REALM:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1"):gsub("%%s", "(.+)") .. "$" |
function convertFromOldCharID(str) |
local player, realm = str:match(matchStr) |
if not player then |
return str |
end |
return player .. " - " .. realm |
end |
end |
local AceOO = AceLibrary("AceOO-2.0") |
local AceEvent |
local Mixin = AceOO.Mixin |
local AceDB = Mixin { |
"RegisterDB", |
"RegisterDefaults", |
"ResetDB", |
"SetProfile", |
"GetProfile", |
"CopyProfileFrom", |
"DeleteProfile", |
"ToggleActive", |
"IsActive", |
"AcquireDBNamespace", |
} |
local Dewdrop = AceLibrary:HasInstance("Dewdrop-2.0") and AceLibrary("Dewdrop-2.0") |
local _G = getfenv(0) |
local function inheritDefaults(t, defaults) |
if not defaults then |
return t |
end |
for k,v in pairs(defaults) do |
if k == "*" or k == "**" then |
local v = v |
if type(v) == "table" then |
setmetatable(t, { |
__index = function(self, key) |
if key == nil then |
return nil |
end |
self[key] = {} |
inheritDefaults(self[key], v) |
return self[key] |
end |
} ) |
else |
setmetatable(t, { |
__index = function(self, key) |
if key == nil then |
return nil |
end |
self[key] = v |
return self[key] |
end |
} ) |
end |
for key in pairs(t) do |
if (defaults[key] == nil or key == k) and type(t[key]) == "table" then |
inheritDefaults(t[key], v) |
end |
end |
else |
if type(v) == "table" then |
if type(rawget(t, k)) ~= "table" then |
t[k] = {} |
end |
inheritDefaults(t[k], v) |
if defaults["**"] then |
inheritDefaults(t[k], defaults["**"]) |
end |
elseif rawget(t, k) == nil then |
t[k] = v |
end |
end |
end |
return t |
end |
local _,race = UnitRace("player") |
local faction |
if race == "Orc" or race == "Scourge" or race == "Troll" or race == "Tauren" or race == "BloodElf" then |
faction = FACTION_HORDE |
else |
faction = FACTION_ALLIANCE |
end |
local server = GetRealmName():trim() |
local charID = UnitName("player") .. " - " .. server |
local realmID = server .. " - " .. faction |
local classID = UnitClass("player") |
AceDB.CHAR_ID = charID |
AceDB.REALM_ID = realmID |
AceDB.CLASS_ID = classID |
AceDB.FACTION = faction |
AceDB.REALM = server |
AceDB.NAME = UnitName("player") |
local new, del |
do |
local list = setmetatable({}, {__mode="k"}) |
function new() |
local t = next(list) |
if t then |
list[t] = nil |
return t |
else |
return {} |
end |
end |
function del(t) |
setmetatable(t, nil) |
for k in pairs(t) do |
t[k] = nil |
end |
list[t] = true |
end |
end |
local caseInsensitive_mt = { |
__index = function(self, key) |
if type(key) ~= "string" then |
return nil |
end |
local lowerKey = key:lower() |
for k,v in pairs(self) do |
if k:lower() == lowerKey then |
return self[k] |
end |
end |
end, |
__newindex = function(self, key, value) |
if type(key) ~= "string" then |
return error("table index is nil", 2) |
end |
local lowerKey = key:lower() |
for k in pairs(self) do |
if k:lower() == lowerKey then |
rawset(self, k, nil) |
rawset(self, key, value) |
return |
end |
end |
rawset(self, key, value) |
end |
} |
local db_mt = { __index = function(db, key) |
if key == "char" then |
if db.charName then |
if type(_G[db.charName]) ~= "table" then |
_G[db.charName] = {} |
end |
if type(_G[db.charName].global) ~= "table" then |
_G[db.charName].global = {} |
end |
rawset(db, 'char', _G[db.charName].global) |
else |
if type(db.raw.chars) ~= "table" then |
db.raw.chars = {} |
end |
local id = charID |
if type(db.raw.chars[id]) ~= "table" then |
db.raw.chars[id] = {} |
end |
rawset(db, 'char', db.raw.chars[id]) |
end |
if db.defaults and db.defaults.char then |
inheritDefaults(db.char, db.defaults.char) |
end |
return db.char |
elseif key == "realm" then |
if type(db.raw.realms) ~= "table" then |
db.raw.realms = {} |
end |
local id = realmID |
if type(db.raw.realms[id]) ~= "table" then |
db.raw.realms[id] = {} |
end |
rawset(db, 'realm', db.raw.realms[id]) |
if db.defaults and db.defaults.realm then |
inheritDefaults(db.realm, db.defaults.realm) |
end |
return db.realm |
elseif key == "server" then |
if type(db.raw.servers) ~= "table" then |
db.raw.servers = {} |
end |
local id = server |
if type(db.raw.servers[id]) ~= "table" then |
db.raw.servers[id] = {} |
end |
rawset(db, 'server', db.raw.servers[id]) |
if db.defaults and db.defaults.server then |
inheritDefaults(db.server, db.defaults.server) |
end |
return db.server |
elseif key == "account" then |
if type(db.raw.account) ~= "table" then |
db.raw.account = {} |
end |
rawset(db, 'account', db.raw.account) |
if db.defaults and db.defaults.account then |
inheritDefaults(db.account, db.defaults.account) |
end |
return db.account |
elseif key == "faction" then |
if type(db.raw.factions) ~= "table" then |
db.raw.factions = {} |
end |
local id = faction |
if type(db.raw.factions[id]) ~= "table" then |
db.raw.factions[id] = {} |
end |
rawset(db, 'faction', db.raw.factions[id]) |
if db.defaults and db.defaults.faction then |
inheritDefaults(db.faction, db.defaults.faction) |
end |
return db.faction |
elseif key == "class" then |
if type(db.raw.classes) ~= "table" then |
db.raw.classes = {} |
end |
local id = classID |
if type(db.raw.classes[id]) ~= "table" then |
db.raw.classes[id] = {} |
end |
rawset(db, 'class', db.raw.classes[id]) |
if db.defaults and db.defaults.class then |
inheritDefaults(db.class, db.defaults.class) |
end |
return db.class |
elseif key == "profile" then |
if type(db.raw.profiles) ~= "table" then |
db.raw.profiles = setmetatable({}, caseInsensitive_mt) |
else |
setmetatable(db.raw.profiles, caseInsensitive_mt) |
end |
local id = db.raw.currentProfile[charID] |
if id == "char" then |
id = "char/" .. charID |
elseif id == "class" then |
id = "class/" .. classID |
elseif id == "realm" then |
id = "realm/" .. realmID |
end |
if type(db.raw.profiles[id]) ~= "table" then |
db.raw.profiles[id] = {} |
end |
rawset(db, 'profile', db.raw.profiles[id]) |
if db.defaults and db.defaults.profile then |
inheritDefaults(db.profile, db.defaults.profile) |
end |
return db.profile |
elseif key == "raw" or key == "defaults" or key == "name" or key == "charName" or key == "namespaces" then |
return nil |
end |
error(("Cannot access key %q in db table. You may want to use db.profile[%q]"):format(tostring(key), tostring(key)), 2) |
end, __newindex = function(db, key, value) |
error(("Cannot access key %q in db table. You may want to use db.profile[%q]"):format(tostring(key), tostring(key)), 2) |
end } |
local function RecalculateAceDBCopyFromList(target) |
local db = target.db |
local t = target['acedb-profile-copylist'] |
for k,v in pairs(t) do |
t[k] = nil |
end |
local _,currentProfile = AceDB.GetProfile(target) |
if db and db.raw then |
if db.raw.profiles then |
for k in pairs(db.raw.profiles) do |
if currentProfile ~= k then |
if k:find("^char/") then |
local name = k:sub(6) |
local player, realm = name:match("^(.*) %- (.*)$") |
if player then |
name = PLAYER_OF_REALM:format(player, realm) |
end |
t[k] = CHARACTER_COLON .. name |
elseif k:find("^realm/") then |
local name = k:sub(7) |
t[k] = REALM_COLON .. name |
elseif k:find("^class/") then |
local name = k:sub(7) |
t[k] = CLASS_COLON .. name |
else |
t[k] = k |
end |
end |
end |
end |
if db.raw.namespaces then |
for _,n in pairs(db.raw.namespaces) do |
if n.profiles then |
for k in pairs(n.profiles) do |
if currentProfile ~= k then |
if k:find('^char/') then |
local name = k:sub(6) |
local player, realm = name:match("^(.*) %- (.*)$") |
if player then |
name = PLAYER_OF_REALM:format(player, realm) |
end |
t[k] = CHARACTER_COLON .. name |
elseif k:find('^realm/') then |
local name = k:sub(7) |
t[k] = REALM_COLON .. name |
elseif k:find('^class/') then |
local name = k:sub(7) |
t[k] = CLASS_COLON .. name |
else |
t[k] = k |
end |
end |
end |
end |
end |
end |
end |
if t.Default then |
t.Default = DEFAULT |
end |
if t.Alternative then |
t.Alternative = ALTERNATIVE |
end |
end |
local function RecalculateAceDBProfileList(target) |
local t = target['acedb-profile-list'] |
for k,v in pairs(t) do |
t[k] = nil |
end |
t.char = CHARACTER_COLON .. PLAYER_OF_REALM:format(UnitName("player"), server) |
t.realm = REALM_COLON .. realmID |
t.class = CLASS_COLON .. classID |
t.Default = DEFAULT |
local db = target.db |
if db and db.raw then |
if db.raw.profiles then |
for k in pairs(db.raw.profiles) do |
if not k:find("^char/") and not k:find("^realm/") and not k:find("^class/") then |
t[k] = k |
end |
end |
end |
if db.raw.namespaces then |
for _,n in pairs(db.raw.namespaces) do |
if n.profiles then |
for k in pairs(n.profiles) do |
if not k:find("^char/") and not k:find("^realm/") and not k:find("^class/") then |
t[k] = k |
end |
end |
end |
end |
end |
local curr = db.raw.currentProfile and db.raw.currentProfile[charID] |
if curr and not t[curr] then |
t[curr] = curr |
end |
end |
if t.Alternative then |
t.Alternative = ALTERNATIVE |
end |
end |
local CrawlForSerialization |
local CrawlForDeserialization |
local function SerializeObject(o) |
local t = { o:Serialize() } |
CrawlForSerialization(t) |
t[0] = o.class:GetLibraryVersion() |
return t |
end |
local function DeserializeObject(t) |
CrawlForDeserialization(t) |
local className = t[0] |
t[0] = nil |
return AceLibrary(className):Deserialize(unpack(t)) |
end |
local function IsSerializable(t) |
return AceOO.inherits(t, AceOO.Class) and t.class and type(t.class.Deserialize) == "function" and type(t.Serialize) == "function" and type(t.class.GetLibraryVersion) == "function" |
end |
function CrawlForSerialization(t) |
local tmp = new() |
for k,v in pairs(t) do |
tmp[k] = v |
end |
for k,v in pairs(tmp) do |
if type(v) == "table" and type(rawget(v, 0)) ~= "userdata" then |
if IsSerializable(v) then |
v = SerializeObject(v) |
t[k] = v |
else |
CrawlForSerialization(v) |
end |
end |
if type(k) == "table" and type(rawget(k, 0)) ~= "userdata" then |
if IsSerializable(k) then |
t[k] = nil |
t[SerializeObject(k)] = v |
else |
CrawlForSerialization(k) |
end |
end |
tmp[k] = nil |
k = nil |
end |
tmp = del(tmp) |
end |
local function IsDeserializable(t) |
return type(rawget(t, 0)) == "string" and AceLibrary:HasInstance(rawget(t, 0)) |
end |
function CrawlForDeserialization(t) |
local tmp = new() |
for k,v in pairs(t) do |
tmp[k] = v |
end |
for k,v in pairs(tmp) do |
if type(v) == "table" then |
if IsDeserializable(v) then |
t[k] = DeserializeObject(v) |
del(v) |
v = t[k] |
elseif type(rawget(v, 0)) ~= "userdata" then |
CrawlForDeserialization(v) |
end |
end |
if type(k) == "table" then |
if IsDeserializable(k) then |
t[k] = nil |
t[DeserializeObject(k)] = v |
del(k) |
elseif type(rawget(k, 0)) ~= "userdata" then |
CrawlForDeserialization(k) |
end |
end |
tmp[k] = nil |
k = nil |
end |
tmp = del(tmp) |
end |
local namespace_mt = { __index = function(namespace, key) |
local db = namespace.db |
local name = namespace.name |
if key == "char" then |
if db.charName then |
if type(_G[db.charName]) ~= "table" then |
_G[db.charName] = {} |
end |
if type(_G[db.charName].namespaces) ~= "table" then |
_G[db.charName].namespaces = {} |
end |
if type(_G[db.charName].namespaces[name]) ~= "table" then |
_G[db.charName].namespaces[name] = {} |
end |
rawset(namespace, 'char', _G[db.charName].namespaces[name]) |
else |
if type(db.raw.namespaces) ~= "table" then |
db.raw.namespaces = {} |
end |
if type(db.raw.namespaces[name]) ~= "table" then |
db.raw.namespaces[name] = {} |
end |
if type(db.raw.namespaces[name].chars) ~= "table" then |
db.raw.namespaces[name].chars = {} |
end |
local id = charID |
if type(db.raw.namespaces[name].chars[id]) ~= "table" then |
db.raw.namespaces[name].chars[id] = {} |
end |
rawset(namespace, 'char', db.raw.namespaces[name].chars[id]) |
end |
if namespace.defaults and namespace.defaults.char then |
inheritDefaults(namespace.char, namespace.defaults.char) |
end |
return namespace.char |
elseif key == "realm" then |
if type(db.raw.namespaces) ~= "table" then |
db.raw.namespaces = {} |
end |
if type(db.raw.namespaces[name]) ~= "table" then |
db.raw.namespaces[name] = {} |
end |
if type(db.raw.namespaces[name].realms) ~= "table" then |
db.raw.namespaces[name].realms = {} |
end |
local id = realmID |
if type(db.raw.namespaces[name].realms[id]) ~= "table" then |
db.raw.namespaces[name].realms[id] = {} |
end |
rawset(namespace, 'realm', db.raw.namespaces[name].realms[id]) |
if namespace.defaults and namespace.defaults.realm then |
inheritDefaults(namespace.realm, namespace.defaults.realm) |
end |
return namespace.realm |
elseif key == "server" then |
if type(db.raw.namespaces) ~= "table" then |
db.raw.namespaces = {} |
end |
if type(db.raw.namespaces[name]) ~= "table" then |
db.raw.namespaces[name] = {} |
end |
if type(db.raw.namespaces[name].servers) ~= "table" then |
db.raw.namespaces[name].servers = {} |
end |
local id = server |
if type(db.raw.namespaces[name].servers[id]) ~= "table" then |
db.raw.namespaces[name].servers[id] = {} |
end |
rawset(namespace, 'server', db.raw.namespaces[name].servers[id]) |
if namespace.defaults and namespace.defaults.server then |
inheritDefaults(namespace.server, namespace.defaults.server) |
end |
return namespace.server |
elseif key == "account" then |
if type(db.raw.namespaces) ~= "table" then |
db.raw.namespaces = {} |
end |
if type(db.raw.namespaces[name]) ~= "table" then |
db.raw.namespaces[name] = {} |
end |
if type(db.raw.namespaces[name].account) ~= "table" then |
db.raw.namespaces[name].account = {} |
end |
rawset(namespace, 'account', db.raw.namespaces[name].account) |
if namespace.defaults and namespace.defaults.account then |
inheritDefaults(namespace.account, namespace.defaults.account) |
end |
return namespace.account |
elseif key == "faction" then |
if type(db.raw.namespaces) ~= "table" then |
db.raw.namespaces = {} |
end |
if type(db.raw.namespaces[name]) ~= "table" then |
db.raw.namespaces[name] = {} |
end |
if type(db.raw.namespaces[name].factions) ~= "table" then |
db.raw.namespaces[name].factions = {} |
end |
local id = faction |
if type(db.raw.namespaces[name].factions[id]) ~= "table" then |
db.raw.namespaces[name].factions[id] = {} |
end |
rawset(namespace, 'faction', db.raw.namespaces[name].factions[id]) |
if namespace.defaults and namespace.defaults.faction then |
inheritDefaults(namespace.faction, namespace.defaults.faction) |
end |
return namespace.faction |
elseif key == "class" then |
if type(db.raw.namespaces) ~= "table" then |
db.raw.namespaces = {} |
end |
if type(db.raw.namespaces[name]) ~= "table" then |
db.raw.namespaces[name] = {} |
end |
if type(db.raw.namespaces[name].classes) ~= "table" then |
db.raw.namespaces[name].classes = {} |
end |
local id = classID |
if type(db.raw.namespaces[name].classes[id]) ~= "table" then |
db.raw.namespaces[name].classes[id] = {} |
end |
rawset(namespace, 'class', db.raw.namespaces[name].classes[id]) |
if namespace.defaults and namespace.defaults.class then |
inheritDefaults(namespace.class, namespace.defaults.class) |
end |
return namespace.class |
elseif key == "profile" then |
if type(db.raw.namespaces) ~= "table" then |
db.raw.namespaces = {} |
end |
if type(db.raw.namespaces[name]) ~= "table" then |
db.raw.namespaces[name] = {} |
end |
if type(db.raw.namespaces[name].profiles) ~= "table" then |
db.raw.namespaces[name].profiles = setmetatable({}, caseInsensitive_mt) |
else |
setmetatable(db.raw.namespaces[name].profiles, caseInsensitive_mt) |
end |
local id = db.raw.currentProfile[charID] |
if id == "char" then |
id = "char/" .. charID |
elseif id == "class" then |
id = "class/" .. classID |
elseif id == "realm" then |
id = "realm/" .. realmID |
end |
if type(db.raw.namespaces[name].profiles[id]) ~= "table" then |
db.raw.namespaces[name].profiles[id] = {} |
end |
rawset(namespace, 'profile', db.raw.namespaces[name].profiles[id]) |
if namespace.defaults and namespace.defaults.profile then |
inheritDefaults(namespace.profile, namespace.defaults.profile) |
end |
return namespace.profile |
elseif key == "defaults" or key == "name" or key == "db" then |
return nil |
end |
error(("Cannot access key %q in db table. You may want to use db.profile[%q]"):format(tostring(key), tostring(key)), 2) |
end, __newindex = function(db, key, value) |
error(("Cannot access key %q in db table. You may want to use db.profile[%q]"):format(tostring(key), tostring(key)), 2) |
end } |
local tmp = {} |
function AceDB:InitializeDB(addonName) |
local db = self.db |
if not db then |
if addonName then |
AceDB.addonsLoaded[addonName] = true |
end |
return |
end |
if db.raw then |
-- someone manually initialized |
return |
end |
if type(_G[db.name]) ~= "table" then |
_G[db.name] = {} |
else |
CrawlForDeserialization(_G[db.name]) |
end |
if db.charName then |
if type(_G[db.charName]) ~= "table" then |
_G[db.charName] = {} |
else |
CrawlForDeserialization(_G[db.charName]) |
end |
end |
rawset(db, 'raw', _G[db.name]) |
if not db.raw.currentProfile then |
db.raw.currentProfile = {} |
else |
for k,v in pairs(db.raw.currentProfile) do |
tmp[convertFromOldCharID(k)] = v |
db.raw.currentProfile[k] = nil |
end |
for k,v in pairs(tmp) do |
db.raw.currentProfile[k] = v |
tmp[k] = nil |
end |
end |
if not db.raw.currentProfile[charID] then |
db.raw.currentProfile[charID] = AceDB.registry[self] or "Default" |
end |
if db.raw.profiles then |
for k,v in pairs(db.raw.profiles) do |
local new_k = k |
if k:find("^char/") then |
new_k = "char/" .. convertFromOldCharID(k:sub(6)) |
end |
tmp[new_k] = v |
db.raw.profiles[k] = nil |
end |
for k,v in pairs(tmp) do |
db.raw.profiles[k] = v |
tmp[k] = nil |
end |
end |
if db.raw.disabledModules then -- AceModuleCore-2.0 |
for k,v in pairs(db.raw.disabledModules) do |
local new_k = k |
if k:find("^char/") then |
new_k = "char/" .. convertFromOldCharID(k:sub(6)) |
end |
tmp[new_k] = v |
db.raw.disabledModules[k] = nil |
end |
for k,v in pairs(tmp) do |
db.raw.disabledModules[k] = v |
tmp[k] = nil |
end |
end |
if db.raw.chars then |
for k,v in pairs(db.raw.chars) do |
tmp[convertFromOldCharID(k)] = v |
db.raw.chars[k] = nil |
end |
for k,v in pairs(tmp) do |
db.raw.chars[k] = v |
tmp[k] = nil |
end |
end |
if db.raw.namespaces then |
for l,u in pairs(db.raw.namespaces) do |
if u.chars then |
for k,v in pairs(u.chars) do |
tmp[convertFromOldCharID(k)] = v |
u.chars[k] = nil |
end |
for k,v in pairs(tmp) do |
u.chars[k] = v |
tmp[k] = nil |
end |
end |
end |
end |
if db.raw.disabled then |
setmetatable(db.raw.disabled, caseInsensitive_mt) |
end |
if self['acedb-profile-copylist'] then |
RecalculateAceDBCopyFromList(self) |
end |
if self['acedb-profile-list'] then |
RecalculateAceDBProfileList(self) |
end |
setmetatable(db, db_mt) |
end |
function AceDB:OnEmbedInitialize(target, name) |
if name then |
self:ADDON_LOADED(name) |
end |
self.InitializeDB(target, name) |
end |
function AceDB:RegisterDB(name, charName, defaultProfile) |
AceDB:argCheck(name, 2, "string") |
AceDB:argCheck(charName, 3, "string", "nil") |
AceDB:argCheck(defaultProfile, 4, "string", "nil") |
if self.db then |
AceDB:error("Cannot call \"RegisterDB\" if self.db is set.") |
end |
local stack = debugstack() |
local addonName = stack:gsub(".-\n.-\\AddOns\\(.-)\\.*", "%1") |
self.db = { |
name = name, |
charName = charName |
} |
AceDB.registry[self] = defaultProfile or "Default" |
if AceDB.addonsLoaded[addonName] then |
AceDB.InitializeDB(self, addonName) |
else |
AceDB.addonsToBeInitialized[self] = addonName |
end |
end |
function AceDB:RegisterDefaults(kind, defaults, a3) |
local name |
if a3 then |
name, kind, defaults = kind, defaults, a3 |
AceDB:argCheck(name, 2, "string") |
AceDB:argCheck(kind, 3, "string") |
AceDB:argCheck(defaults, 4, "table") |
else |
AceDB:argCheck(kind, 2, "string") |
AceDB:argCheck(defaults, 3, "table") |
end |
if kind ~= "char" and kind ~= "class" and kind ~= "profile" and kind ~= "account" and kind ~= "realm" and kind ~= "faction" and kind ~= "server" then |
AceDB:error("Bad argument #%d to `RegisterDefaults' (\"char\", \"class\", \"profile\", \"account\", \"realm\", \"server\", or \"faction\" expected, got %q)", a3 and 3 or 2, kind) |
end |
if type(self.db) ~= "table" or type(self.db.name) ~= "string" then |
AceDB:error("Cannot call \"RegisterDefaults\" unless \"RegisterDB\" has been previously called.") |
end |
local db |
if name then |
local namespace = self:AcquireDBNamespace(name) |
if namespace.defaults and namespace.defaults[kind] then |
AceDB:error("\"RegisterDefaults\" has already been called for %q::%q.", name, kind) |
end |
db = namespace |
else |
if self.db.defaults and self.db.defaults[kind] then |
AceDB:error("\"RegisterDefaults\" has already been called for %q.", kind) |
end |
db = self.db |
end |
if not db.defaults then |
rawset(db, 'defaults', {}) |
end |
db.defaults[kind] = defaults |
if rawget(db, kind) then |
inheritDefaults(db[kind], defaults) |
end |
end |
function AceDB:ResetDB(kind, a2) |
local name |
if a2 then |
name, kind = kind, a2 |
AceDB:argCheck(name, 2, "nil", "string") |
AceDB:argCheck(kind, 3, "nil", "string") |
else |
AceDB:argCheck(kind, 2, "nil", "string") |
if kind ~= "char" and kind ~= "class" and kind ~= "profile" and kind ~= "account" and kind ~= "realm" and kind ~= "faction" and kind ~= "server" then |
name, kind = kind, nil |
end |
end |
if not self.db or not self.db.raw then |
AceDB:error("Cannot call \"ResetDB\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.") |
end |
local db = self.db |
if not kind then |
if not name then |
if db.charName then |
_G[db.charName] = nil |
end |
_G[db.name] = nil |
rawset(db, 'raw', nil) |
AceDB.InitializeDB(self) |
if db.namespaces then |
for name,v in pairs(db.namespaces) do |
rawset(v, 'account', nil) |
rawset(v, 'char', nil) |
rawset(v, 'class', nil) |
rawset(v, 'profile', nil) |
rawset(v, 'realm', nil) |
rawset(v, 'server', nil) |
rawset(v, 'faction', nil) |
end |
end |
else |
if db.raw.namespaces then |
db.raw.namespaces[name] = nil |
end |
if db.namespaces then |
local v = db.namespaces[name] |
if v then |
rawset(v, 'account', nil) |
rawset(v, 'char', nil) |
rawset(v, 'class', nil) |
rawset(v, 'profile', nil) |
rawset(v, 'realm', nil) |
rawset(v, 'server', nil) |
rawset(v, 'faction', nil) |
end |
end |
end |
elseif kind == "account" then |
if name then |
db.raw.account = nil |
rawset(db, 'account', nil) |
if db.raw.namespaces then |
for name,v in pairs(db.raw.namespaces) do |
v.account = nil |
end |
end |
if db.namespaces then |
for name,v in pairs(db.namespaces) do |
rawset(v, 'account', nil) |
end |
end |
else |
if db.raw.namespaces and db.raw.namespaces[name] then |
db.raw.namespaces[name].account = nil |
end |
if db.namespaces then |
local v = db.namespaces[name] |
if v then |
rawset(v, 'account', nil) |
end |
end |
end |
elseif kind == "char" then |
if name then |
if db.charName then |
_G[db.charName] = nil |
else |
if db.raw.chars then |
db.raw.chars[charID] = nil |
end |
if db.raw.namespaces then |
for name,v in pairs(db.raw.namespaces) do |
if v.chars then |
v.chars[charID] = nil |
end |
end |
end |
end |
rawset(db, 'char', nil) |
if db.namespaces then |
for name,v in pairs(db.namespaces) do |
rawset(v, 'char', nil) |
end |
end |
else |
if db.charName then |
local x = _G[db.charName] |
if x.namespaces then |
x.namespaces[name] = nil |
end |
else |
if db.raw.namespaces then |
local v = db.namespaces[name] |
if v and v.chars then |
v.chars[charID] = nil |
end |
end |
end |
if db.namespaces then |
local v = db.namespaces[name] |
if v then |
rawset(v, 'char', nil) |
end |
end |
end |
elseif kind == "realm" then |
if not name then |
if db.raw.realms then |
db.raw.realms[realmID] = nil |
end |
rawset(db, 'realm', nil) |
if db.raw.namespaces then |
for name,v in pairs(db.raw.namespaces) do |
if v.realms then |
v.realms[realmID] = nil |
end |
end |
end |
if db.namespaces then |
for name,v in pairs(db.namespaces) do |
rawset(v, 'realm', nil) |
end |
end |
else |
if db.raw.namespaces then |
local v = db.raw.namespaces[name] |
if v and v.realms then |
v.realms[realmID] = nil |
end |
end |
if db.namespaces then |
local v = db.namespaces[name] |
if v then |
rawset(v, 'realm', nil) |
end |
end |
end |
elseif kind == "server" then |
if not name then |
if db.raw.servers then |
db.raw.servers[server] = nil |
end |
rawset(db, 'server', nil) |
if db.raw.namespaces then |
for name,v in pairs(db.raw.namespaces) do |
if v.servers then |
v.servers[server] = nil |
end |
end |
end |
if db.namespaces then |
for name,v in pairs(db.namespaces) do |
rawset(v, 'server', nil) |
end |
end |
else |
if db.raw.namespaces then |
local v = db.raw.namespaces[name] |
if v and v.servers then |
v.servers[server] = nil |
end |
end |
if db.namespaces then |
local v = db.namespaces[name] |
if v then |
rawset(v, 'server', nil) |
end |
end |
end |
elseif kind == "faction" then |
if not name then |
if db.raw.factions then |
db.raw.factions[faction] = nil |
end |
rawset(db, 'faction', nil) |
if db.raw.namespaces then |
for name,v in pairs(db.raw.namespaces) do |
if v.factions then |
v.factions[faction] = nil |
end |
end |
end |
if db.namespaces then |
for name,v in pairs(db.namespaces) do |
rawset(v, 'faction', nil) |
end |
end |
else |
if db.raw.namespaces then |
local v = db.raw.namespaces[name] |
if v and v.factions then |
v.factions[faction] = nil |
end |
end |
if db.namespaces then |
local v = db.namespaces[name] |
if v then |
rawset(v, 'faction', nil) |
end |
end |
end |
elseif kind == "class" then |
if not name then |
if db.raw.realms then |
db.raw.realms[classID] = nil |
end |
rawset(db, 'class', nil) |
if db.raw.namespaces then |
for name,v in pairs(db.raw.namespaces) do |
if v.classes then |
v.classes[classID] = nil |
end |
end |
end |
if db.namespaces then |
for name,v in pairs(db.namespaces) do |
rawset(v, 'class', nil) |
end |
end |
else |
if db.raw.namespaces then |
local v = db.raw.namespaces[name] |
if v and v.classes then |
v.classes[classID] = nil |
end |
end |
if db.namespaces then |
local v = db.namespaces[name] |
if v then |
rawset(v, 'class', nil) |
end |
end |
end |
elseif kind == "profile" then |
local id = db.raw.currentProfile and db.raw.currentProfile[charID] or AceDB.registry[self] or "Default" |
if id == "char" then |
id = "char/" .. charID |
elseif id == "class" then |
id = "class/" .. classID |
elseif id == "realm" then |
id = "realm/" .. realmID |
end |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedProfileDisable) == "function" then |
safecall(mixin.OnEmbedProfileDisable, mixin, self, id) |
end |
end |
end |
current = current.super |
end |
if type(self.OnProfileDisable) == "function" then |
safecall(self.OnProfileDisable, self, id) |
end |
local active = self:IsActive() |
if not name then |
if db.raw.profiles then |
db.raw.profiles[id] = nil |
end |
rawset(db, 'profile', nil) |
if db.raw.namespaces then |
for name,v in pairs(db.raw.namespaces) do |
if v.profiles then |
v.profiles[id] = nil |
end |
end |
end |
if db.namespaces then |
for name,v in pairs(db.namespaces) do |
rawset(v, 'profile', nil) |
end |
end |
else |
if db.raw.namespaces then |
local v = db.raw.namespaces[name] |
if v and v.profiles then |
v.profiles[id] = nil |
end |
end |
if db.namespaces then |
local v = db.namespaces[name] |
if v then |
rawset(v, 'profile', nil) |
end |
end |
end |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedProfileEnable) == "function" then |
safecall(mixin.OnEmbedProfileEnable, mixin, self, id) |
end |
end |
end |
current = current.super |
end |
if type(self.OnProfileEnable) == "function" then |
safecall(self.OnProfileEnable, self, id) |
end |
local newactive = self:IsActive() |
if active ~= newactive then |
if newactive then |
local first = nil |
if AceOO.inherits(self, "AceAddon-2.0") then |
local AceAddon = AceLibrary("AceAddon-2.0") |
if not AceAddon.addonsStarted[self] then |
return |
end |
if AceAddon.addonsEnabled and not AceAddon.addonsEnabled[self] then |
AceAddon.addonsEnabled[self] = true |
first = true |
end |
end |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedEnable) == "function" then |
safecall(mixin.OnEmbedEnable, mixin, self, first) |
end |
end |
end |
current = current.super |
end |
if type(self.OnEnable) == "function" then |
safecall(self.OnEnable, self, first) |
end |
if AceEvent then |
AceEvent:TriggerEvent("Ace2_AddonEnabled", self, first) |
end |
else |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedDisable) == "function" then |
safecall(mixin.OnEmbedDisable, mixin, self) |
end |
end |
end |
current = current.super |
end |
if type(self.OnDisable) == "function" then |
safecall(self.OnDisable, self) |
end |
if AceEvent then |
AceEvent:TriggerEvent("Ace2_AddonDisabled", self) |
end |
end |
end |
else |
return -- skip event |
end |
if AceEvent then |
AceEvent:TriggerEvent("AceDB20_ResetDB", self, self.db.name, kind) |
end |
end |
local function cleanDefaults(t, defaults, blocker) |
if defaults then |
for k,v in pairs(t) do |
if (not blocker or (blocker[k] == nil and blocker['*'] == nil and blocker['**'] == nil)) and (defaults[k] ~= nil or defaults['*'] ~= nil or defaults['**'] ~= nil) then |
local u = defaults[k] |
if u == nil then |
u = defaults['*'] |
if u == nil then |
u = defaults['**'] |
end |
end |
if v == u then |
t[k] = nil |
elseif type(v) == "table" and type(u) == "table" then |
if cleanDefaults(v, u) then |
t[k] = nil |
else |
local w = defaults['**'] |
if w ~= u then |
if cleanDefaults(v, w, u) then |
t[k] = nil |
end |
end |
end |
end |
end |
end |
end |
return t and next(t) == nil |
end |
function AceDB:GetProfile() |
if not self.db or not self.db.raw then |
return nil |
end |
if not self.db.raw.currentProfile then |
self.db.raw.currentProfile = {} |
end |
if not self.db.raw.currentProfile[charID] then |
self.db.raw.currentProfile[charID] = AceDB.registry[self] or "Default" |
end |
local profile = self.db.raw.currentProfile[charID] |
if profile == "char" then |
return "char", "char/" .. charID |
elseif profile == "class" then |
return "class", "class/" .. classID |
elseif profile == "realm" then |
return "realm", "realm/" .. realmID |
end |
return profile, profile |
end |
local function copyTable(to, from) |
setmetatable(to, nil) |
for k,v in pairs(from) do |
if type(k) == "table" then |
k = copyTable({}, k) |
end |
if type(v) == "table" then |
v = copyTable({}, v) |
end |
to[k] = v |
end |
setmetatable(to, from) |
return to |
end |
function AceDB:SetProfile(name) |
AceDB:argCheck(name, 2, "string") |
if not self.db or not self.db.raw then |
AceDB:error("Cannot call \"SetProfile\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.") |
end |
local db = self.db |
local lowerName = name:lower() |
if lowerName:find("^char/") or lowerName:find("^realm/") or lowerName:find("^class/") then |
if lowerName:find("^char/") then |
name = "char" |
else |
name = lowerName:sub(1, 5) |
end |
lowerName = name:lower() |
end |
local oldName = db.raw.currentProfile[charID] |
if oldName:lower() == name:lower() then |
return |
end |
local oldProfileData = db.profile |
local realName = name |
if lowerName == "char" then |
realName = name .. "/" .. charID |
elseif lowerName == "realm" then |
realName = name .. "/" .. realmID |
elseif lowerName == "class" then |
realName = name .. "/" .. classID |
end |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedProfileDisable) == "function" then |
safecall(mixin.OnEmbedProfileDisable, mixin, self, realName) |
end |
end |
end |
current = current.super |
end |
if type(self.OnProfileDisable) == "function" then |
safecall(self.OnProfileDisable, self, realName) |
end |
local active = self:IsActive() |
db.raw.currentProfile[charID] = name |
rawset(db, 'profile', nil) |
if db.namespaces then |
for k,v in pairs(db.namespaces) do |
rawset(v, 'profile', nil) |
end |
end |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedProfileEnable) == "function" then |
safecall(mixin.OnEmbedProfileEnable, mixin, self, oldName, oldProfileData) |
end |
end |
end |
current = current.super |
end |
if type(self.OnProfileEnable) == "function" then |
safecall(self.OnProfileEnable, self, oldName, oldProfileData) |
end |
if cleanDefaults(oldProfileData, db.defaults and db.defaults.profile) then |
db.raw.profiles[oldName] = nil |
if not next(db.raw.profiles) then |
db.raw.profiles = nil |
end |
end |
local newactive = self:IsActive() |
if active ~= newactive then |
local first = nil |
if AceOO.inherits(self, "AceAddon-2.0") then |
local AceAddon = AceLibrary("AceAddon-2.0") |
if not AceAddon.addonsStarted[self] then |
return |
end |
if AceAddon.addonsEnabled and not AceAddon.addonsEnabled[self] then |
first = true |
end |
end |
if newactive then |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedEnable) == "function" then |
safecall(mixin.OnEmbedEnable, mixin, self, first) |
end |
end |
end |
current = current.super |
end |
if type(self.OnEnable) == "function" then |
safecall(self.OnEnable, self, first) |
end |
if AceEvent then |
AceEvent:TriggerEvent("Ace2_AddonEnabled", self, first) |
end |
else |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedDisable) == "function" then |
safecall(mixin.OnEmbedDisable, mixin, self) |
end |
end |
end |
current = current.super |
end |
if type(self.OnDisable) == "function" then |
safecall(self.OnDisable, self) |
end |
if AceEvent then |
AceEvent:TriggerEvent("Ace2_AddonDisabled", self) |
end |
end |
end |
if self['acedb-profile-list'] then |
RecalculateAceDBProfileList(self) |
end |
if self['acedb-profile-copylist'] then |
RecalculateAceDBCopyFromList(self) |
end |
if Dewdrop then |
Dewdrop:Refresh() |
end |
end |
function AceDB:CopyProfileFrom(copyFrom) |
AceDB:argCheck(copyFrom, 2, "string") |
if not self.db or not self.db.raw then |
AceDB:error("Cannot call \"CopyProfileFrom\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.") |
end |
local db = self.db |
local lowerCopyFrom = copyFrom:lower() |
if not db.raw.profiles or not db.raw.profiles[copyFrom] then |
local good = false |
if db.raw.namespaces then |
for _,n in pairs(db.raw.namespaces) do |
if n.profiles and n.profiles[copyFrom] then |
good = true |
break |
end |
end |
end |
if not good then |
AceDB:error("Cannot copy from profile %q, it does not exist.", copyFrom) |
end |
end |
local currentProfile = db.raw.currentProfile[charID] |
if currentProfile:lower() == lowerCopyFrom then |
AceDB:error("Cannot copy from profile %q, it is currently in use.", copyFrom) |
end |
local oldProfileData = db.profile |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedProfileDisable) == "function" then |
safecall(mixin.OnEmbedProfileDisable, mixin, self, currentProfile) |
end |
end |
end |
current = current.super |
end |
if type(self.OnProfileDisable) == "function" then |
safecall(self.OnProfileDisable, self, realName) |
end |
local active = self:IsActive() |
for k,v in pairs(db.profile) do |
db.profile[k] = nil |
end |
if db.raw.profiles[copyFrom] then |
copyTable(db.profile, db.raw.profiles[copyFrom]) |
end |
inheritDefaults(db.profile, db.defaults and db.defaults.profile) |
if db.namespaces then |
for l,u in pairs(db.namespaces) do |
for k,v in pairs(u.profile) do |
u.profile[k] = nil |
end |
if db.raw.namespaces[l].profiles[copyFrom] then |
copyTable(u.profile, db.raw.namespaces[l].profiles[copyFrom]) |
end |
inheritDefaults(u.profile, u.defaults and u.defaults.profile) |
end |
end |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedProfileEnable) == "function" then |
safecall(mixin.OnEmbedProfileEnable, mixin, self, copyFrom, oldProfileData, copyFrom) |
end |
end |
end |
current = current.super |
end |
if type(self.OnProfileEnable) == "function" then |
safecall(self.OnProfileEnable, self, copyFrom, oldProfileData, copyFrom) |
end |
local newactive = self:IsActive() |
if active ~= newactive then |
if AceOO.inherits(self, "AceAddon-2.0") then |
local AceAddon = AceLibrary("AceAddon-2.0") |
if not AceAddon.addonsStarted[self] then |
return |
end |
end |
if newactive then |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedEnable) == "function" then |
safecall(mixin.OnEmbedEnable, mixin, self) |
end |
end |
end |
current = current.super |
end |
if type(self.OnEnable) == "function" then |
safecall(self.OnEnable, self) |
end |
if AceEvent then |
AceEvent:TriggerEvent("Ace2_AddonEnabled", self) |
end |
else |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedDisable) == "function" then |
safecall(mixin.OnEmbedDisable, mixin, self) |
end |
end |
end |
current = current.super |
end |
if type(self.OnDisable) == "function" then |
safecall(self.OnDisable, self) |
end |
if AceEvent then |
AceEvent:TriggerEvent("Ace2_AddonDisabled", self) |
end |
end |
end |
if self['acedb-profile-list'] then |
RecalculateAceDBProfileList(self) |
end |
if self['acedb-profile-copylist'] then |
RecalculateAceDBCopyFromList(self) |
end |
if Dewdrop then |
Dewdrop:Refresh() |
end |
end |
function AceDB:DeleteProfile(profile, noconfirm) |
AceDB:argCheck(profile , 2, "string") |
if not self.db or not self.db.raw then |
AceDB:error("Cannot call \"DeleteProfile\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.") |
end |
local db = self.db |
local currentProfile = db.raw.currentProfile[charID] |
if currentProfile:lower() == profile:lower() then |
AceDB:error("Cannot delete profile %q, it is currently in use.", profile) |
end |
if not (noconfirm or IsShiftKeyDown()) then |
if not StaticPopupDialogs["ACEDB20_CONFIRM_DELETE_DIALOG"] then |
StaticPopupDialogs["ACEDB20_CONFIRM_DELETE_DIALOG"] = {} |
end |
local t = StaticPopupDialogs["ACEDB20_CONFIRM_DELETE_DIALOG"] |
t.text = format("%s: %s?", DELETE_PROFILE, profile) |
t.button1 = DELETE_PROFILE |
t.button2 = CANCEL or "Cancel" |
t.OnAccept = function() |
self:DeleteProfile(profile, true) |
end |
t.timeout = 0 |
t.whileDead = 1 |
t.hideOnEscape = 1 |
StaticPopup_Show("ACEDB20_CONFIRM_DELETE_DIALOG") |
return; |
end |
local good = false |
if db.raw.profiles and db.raw.profiles[profile] then |
good = true; |
db.raw.profiles[profile] = nil; |
end |
if db.raw.namespaces then |
for _,n in pairs(db.raw.namespaces) do |
if n.profiles and n.profiles[profile] then |
n.profiles[profile] = nil; |
good = true |
end |
end |
end |
if not good then |
AceDB:error("Cannot delete profile %q, it does not exist.", profile) |
end |
if self['acedb-profile-list'] then |
RecalculateAceDBProfileList(self) |
end |
if self['acedb-profile-copylist'] then |
RecalculateAceDBCopyFromList(self) |
end |
if Dewdrop then |
Dewdrop:Refresh() |
end |
end |
function AceDB:IsActive() |
return not self.db or not self.db.raw or not self.db.raw.disabled or not self.db.raw.disabled[self.db.raw.currentProfile[charID]] |
end |
function AceDB:ToggleActive(state) |
AceDB:argCheck(state, 2, "boolean", "nil") |
if not self.db or not self.db.raw then |
AceDB:error("Cannot call \"ToggleActive\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.") |
end |
local db = self.db |
if not db.raw.disabled then |
db.raw.disabled = setmetatable({}, caseInsensitive_mt) |
end |
local profile = db.raw.currentProfile[charID] |
local disable |
if state == nil then |
disable = not db.raw.disabled[profile] |
else |
disable = not state |
if disable == db.raw.disabled[profile] then |
return |
end |
end |
db.raw.disabled[profile] = disable or nil |
if AceOO.inherits(self, "AceAddon-2.0") then |
local AceAddon = AceLibrary("AceAddon-2.0") |
if not AceAddon.addonsStarted[self] then |
return |
end |
end |
if not disable then |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedEnable) == "function" then |
safecall(mixin.OnEmbedEnable, mixin, self) |
end |
end |
end |
current = current.super |
end |
if type(self.OnEnable) == "function" then |
safecall(self.OnEnable, self) |
end |
if AceEvent then |
AceEvent:TriggerEvent("Ace2_AddonEnabled", self) |
end |
else |
local current = self.class |
while current and current ~= AceOO.Class do |
if current.mixins then |
for mixin in pairs(current.mixins) do |
if type(mixin.OnEmbedDisable) == "function" then |
safecall(mixin.OnEmbedDisable, mixin, self) |
end |
end |
end |
current = current.super |
end |
if type(self.OnDisable) == "function" then |
safecall(self.OnDisable, self) |
end |
if AceEvent then |
AceEvent:TriggerEvent("Ace2_AddonDisabled", self) |
end |
end |
return not disable |
end |
function AceDB:embed(target) |
self.super.embed(self, target) |
if not AceEvent then |
AceDB:error(MAJOR_VERSION .. " requires AceEvent-2.0") |
end |
end |
function AceDB:ADDON_LOADED(name) |
AceDB.addonsLoaded[name] = true |
for addon, addonName in pairs(AceDB.addonsToBeInitialized) do |
if name == addonName then |
AceDB.InitializeDB(addon, name) |
AceDB.addonsToBeInitialized[addon] = nil |
end |
end |
end |
function AceDB:PLAYER_LOGOUT() |
for addon, defaultProfile in pairs(AceDB.registry) do |
local db = addon.db |
if db then |
if type(addon.OnDatabaseCleanup) == "function" then |
safecall(addon.OnDatabaseCleanup, addon) |
end |
setmetatable(db, nil) |
CrawlForSerialization(db.raw) |
if type(_G[db.charName]) == "table" then |
CrawlForSerialization(_G[db.charName]) |
end |
if db.char and cleanDefaults(db.char, db.defaults and db.defaults.char) then |
if db.charName and _G[db.charName] and _G[db.charName].global == db.char then |
_G[db.charName].global = nil |
if not next(_G[db.charName]) then |
_G[db.charName] = nil |
end |
else |
if db.raw.chars then |
db.raw.chars[charID] = nil |
if not next(db.raw.chars) then |
db.raw.chars = nil |
end |
end |
end |
end |
if db.realm and cleanDefaults(db.realm, db.defaults and db.defaults.realm) then |
if db.raw.realms then |
db.raw.realms[realmID] = nil |
if not next(db.raw.realms) then |
db.raw.realms = nil |
end |
end |
end |
if db.server and cleanDefaults(db.server, db.defaults and db.defaults.server) then |
if db.raw.servers then |
db.raw.servers[server] = nil |
if not next(db.raw.servers) then |
db.raw.servers = nil |
end |
end |
end |
if db.faction and cleanDefaults(db.faction, db.defaults and db.defaults.faction) then |
if db.raw.factions then |
db.raw.factions[faction] = nil |
if not next(db.raw.factions) then |
db.raw.factions = nil |
end |
end |
end |
if db.class and cleanDefaults(db.class, db.defaults and db.defaults.class) then |
if db.raw.classes then |
db.raw.classes[classID] = nil |
if not next(db.raw.classes) then |
db.raw.classes = nil |
end |
end |
end |
if db.account and cleanDefaults(db.account, db.defaults and db.defaults.account) then |
db.raw.account = nil |
end |
if db.profile and cleanDefaults(db.profile, db.defaults and db.defaults.profile) then |
if db.raw.profiles then |
db.raw.profiles[db.raw.currentProfile and db.raw.currentProfile[charID] or defaultProfile or "Default"] = nil |
if not next(db.raw.profiles) then |
db.raw.profiles = nil |
end |
end |
end |
if db.namespaces and db.raw.namespaces then |
for name,v in pairs(db.namespaces) do |
if db.raw.namespaces[name] then |
setmetatable(v, nil) |
if v.char and cleanDefaults(v.char, v.defaults and v.defaults.char) then |
if db.charName and _G[db.charName] and _G[db.charName].namespaces and _G[db.charName].namespaces[name] == v then |
_G[db.charName].namespaces[name] = nil |
if not next(_G[db.charName].namespaces) then |
_G[db.charName].namespaces = nil |
if not next(_G[db.charName]) then |
_G[db.charName] = nil |
end |
end |
else |
if db.raw.namespaces[name].chars then |
db.raw.namespaces[name].chars[charID] = nil |
if not next(db.raw.namespaces[name].chars) then |
db.raw.namespaces[name].chars = nil |
end |
end |
end |
end |
if v.realm and cleanDefaults(v.realm, v.defaults and v.defaults.realm) then |
if db.raw.namespaces[name].realms then |
db.raw.namespaces[name].realms[realmID] = nil |
if not next(db.raw.namespaces[name].realms) then |
db.raw.namespaces[name].realms = nil |
end |
end |
end |
if v.server and cleanDefaults(v.server, v.defaults and v.defaults.server) then |
if db.raw.namespaces[name].servers then |
db.raw.namespaces[name].servers[server] = nil |
if not next(db.raw.namespaces[name].servers) then |
db.raw.namespaces[name].servers = nil |
end |
end |
end |
if v.faction and cleanDefaults(v.faction, v.defaults and v.defaults.faction) then |
if db.raw.namespaces[name].factions then |
db.raw.namespaces[name].factions[faction] = nil |
if not next(db.raw.namespaces[name].factions) then |
db.raw.namespaces[name].factions = nil |
end |
end |
end |
if v.class and cleanDefaults(v.class, v.defaults and v.defaults.class) then |
if db.raw.namespaces[name].classes then |
db.raw.namespaces[name].classes[classID] = nil |
if not next(db.raw.namespaces[name].classes) then |
db.raw.namespaces[name].classes = nil |
end |
end |
end |
if v.account and cleanDefaults(v.account, v.defaults and v.defaults.account) then |
db.raw.namespaces[name].account = nil |
end |
if v.profile and cleanDefaults(v.profile, v.defaults and v.defaults.profile) then |
if db.raw.namespaces[name].profiles then |
db.raw.namespaces[name].profiles[db.raw.currentProfile and db.raw.currentProfile[charID] or defaultProfile or "Default"] = nil |
if not next(db.raw.namespaces[name].profiles) then |
db.raw.namespaces[name].profiles = nil |
end |
end |
end |
if not next(db.raw.namespaces[name]) then |
db.raw.namespaces[name] = nil |
end |
end |
end |
if not next(db.raw.namespaces) then |
db.raw.namespaces = nil |
end |
end |
if db.raw.disabled and not next(db.raw.disabled) then |
db.raw.disabled = nil |
end |
if db.raw.currentProfile then |
for k,v in pairs(db.raw.currentProfile) do |
if v:lower() == (defaultProfile or "Default"):lower() then |
db.raw.currentProfile[k] = nil |
end |
end |
if not next(db.raw.currentProfile) then |
db.raw.currentProfile = nil |
end |
end |
if _G[db.name] and not next(_G[db.name]) then |
_G[db.name] = nil |
end |
end |
end |
end |
function AceDB:AcquireDBNamespace(name) |
AceDB:argCheck(name, 2, "string") |
local db = self.db |
if not db then |
AceDB:error("Cannot call `AcquireDBNamespace' before `RegisterDB' has been called.", 2) |
end |
if not db.namespaces then |
rawset(db, 'namespaces', {}) |
end |
if not db.namespaces[name] then |
local namespace = {} |
db.namespaces[name] = namespace |
namespace.db = db |
namespace.name = name |
setmetatable(namespace, namespace_mt) |
end |
return db.namespaces[name] |
end |
function AceDB:GetAceOptionsDataTable(target) |
if not target['acedb-profile-list'] then |
target['acedb-profile-list'] = setmetatable({}, caseInsensitive_mt) |
RecalculateAceDBProfileList(target) |
end |
if not target['acedb-profile-copylist'] then |
target['acedb-profile-copylist'] = setmetatable({}, caseInsensitive_mt) |
RecalculateAceDBCopyFromList(target) |
end |
return { |
standby = { |
cmdName = STATE, |
guiName = ENABLED, |
name = ACTIVE, |
desc = TOGGLE_ACTIVE, |
type = "toggle", |
get = "IsActive", |
set = "ToggleActive", |
map = MAP_ACTIVESUSPENDED, |
order = -3, |
}, |
profile = { |
type = 'group', |
name = PROFILE, |
desc = SET_PROFILE, |
order = -3.5, |
get = "GetProfile", |
args = { |
choose = { |
guiName = CHOOSE_PROFILE_GUI, |
cmdName = PROFILE, |
desc = CHOOSE_PROFILE_DESC, |
type = 'text', |
get = "GetProfile", |
set = "SetProfile", |
validate = target['acedb-profile-list'] |
}, |
copy = { |
guiName = COPY_PROFILE_GUI, |
cmdName = PROFILE, |
desc = COPY_PROFILE_DESC, |
type = 'text', |
get = false, |
set = "CopyProfileFrom", |
validate = target['acedb-profile-copylist'], |
disabled = function() |
return not next(target['acedb-profile-copylist']) |
end, |
}, |
other = { |
guiName = OTHER_PROFILE_GUI, |
cmdName = PROFILE, |
desc = OTHER_PROFILE_DESC, |
usage = OTHER_PROFILE_USAGE, |
type = 'text', |
get = "GetProfile", |
set = "SetProfile", |
}, |
delete = { |
name = DELETE_PROFILE, |
desc = DELETE_PROFILE_DESC, |
usage = DELETE_PROFILE_USAGE, |
type = 'text', |
set = "DeleteProfile", |
get = false, |
validate = target['acedb-profile-copylist'], |
disabled = function() |
return not next(target['acedb-profile-copylist']) |
end, |
}, |
reset = { |
name = RESET_PROFILE, |
desc = RESET_PROFILE_DESC, |
type = 'execute', |
func = function() |
target:ResetDB('profile') |
end, |
confirm = true, |
} |
} |
}, |
} |
end |
local function activate(self, oldLib, oldDeactivate) |
AceDB = self |
AceEvent = AceLibrary:HasInstance("AceEvent-2.0") and AceLibrary("AceEvent-2.0") |
self.addonsToBeInitialized = oldLib and oldLib.addonsToBeInitialized or {} |
self.addonsLoaded = oldLib and oldLib.addonsLoaded or {} |
self.registry = oldLib and oldLib.registry or {} |
for k, v in pairs(self.registry) do |
if v == true then |
self.registry[k] = "Default" |
end |
end |
self:activate(oldLib, oldDeactivate) |
for t in pairs(self.embedList) do |
if t.db then |
rawset(t.db, 'char', nil) |
rawset(t.db, 'realm', nil) |
rawset(t.db, 'class', nil) |
rawset(t.db, 'account', nil) |
rawset(t.db, 'server', nil) |
rawset(t.db, 'faction', nil) |
rawset(t.db, 'profile', nil) |
setmetatable(t.db, db_mt) |
end |
end |
if oldLib then |
oldDeactivate(oldLib) |
end |
end |
local function external(self, major, instance) |
if major == "AceEvent-2.0" then |
AceEvent = instance |
AceEvent:embed(self) |
self:RegisterEvent("ADDON_LOADED") |
self:RegisterEvent("PLAYER_LOGOUT") |
elseif major == "Dewdrop-2.0" then |
Dewdrop = instance |
end |
end |
AceLibrary:Register(AceDB, MAJOR_VERSION, MINOR_VERSION, activate, nil, external) |
AceDB = AceLibrary(MAJOR_VERSION) |
## Interface: 20400 |
## Title: Lib: AceDB-2.0 |
## Notes: AddOn development framework |
## Author: Ace Development Team |
## LoadOnDemand: 1 |
## X-Website: http://www.wowace.com |
## X-Category: Library |
## X-License: LGPL v2.1 + MIT for AceOO-2.0 |
## Dependencies: AceLibrary, AceEvent-2.0, AceOO-2.0 |
AceDB-2.0.lua |
--[[ |
Name: AceDebug-2.0 |
Revision: $Rev$ |
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) |
Inspired By: Ace 1.x by Turan (turan@gryphon.com) |
Website: http://www.wowace.com/ |
Documentation: http://www.wowace.com/index.php/AceDebug-2.0 |
SVN: http://svn.wowace.com/root/trunk/Ace2/AceDebug-2.0 |
Description: Mixin to allow for simple debugging capabilities. |
Dependencies: AceLibrary, AceOO-2.0 |
License: LGPL v2.1 |
]] |
local MAJOR_VERSION = "AceDebug-2.0" |
local MINOR_VERSION = "$Revision$" |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end |
local function safecall(func,...) |
local success, err = pcall(func,...) |
if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("\n(.-: )in.-\n") or "") .. err) end |
end |
local DEBUGGING, TOGGLE_DEBUGGING |
if GetLocale() == "frFR" then |
DEBUGGING = "D\195\169boguage" |
TOGGLE_DEBUGGING = "Activer/d\195\169sactiver le d\195\169boguage" |
elseif GetLocale() == "deDE" then |
DEBUGGING = "Debuggen" |
TOGGLE_DEBUGGING = "Aktiviert/Deaktiviert Debugging." |
elseif GetLocale() == "koKR" then |
DEBUGGING = "ëë²ê¹ " |
TOGGLE_DEBUGGING = "ëë²ê¹ ê¸°ë¥ ì¬ì©í¨/ì¬ì©ìí¨" |
elseif GetLocale() == "zhTW" then |
DEBUGGING = "é¤é¯" |
TOGGLE_DEBUGGING = "åç¨/åç¨é¤é¯åè½ã" |
elseif GetLocale() == "zhCN" then |
DEBUGGING = "\232\176\131\232\175\149" |
TOGGLE_DEBUGGING = "\229\144\175\231\148\168/\231\166\129\231\148\168 \232\176\131\232\175\149." |
elseif GetLocale() == "esES" then |
DEBUGGING = "Debugging" |
TOGGLE_DEBUGGING = "Activar/desactivar Debugging." |
else -- enUS |
DEBUGGING = "Debugging" |
TOGGLE_DEBUGGING = "Toggle debugging for this addon." |
end |
local AceOO = AceLibrary:GetInstance("AceOO-2.0") |
local AceDebug = AceOO.Mixin { |
"Debug", |
"CustomDebug", |
"IsDebugging", |
"SetDebugging", |
"SetDebugLevel", |
"LevelDebug", |
"CustomLevelDebug", |
"GetDebugLevel", |
"GetDebugPrefix", |
} |
local function print(text, r, g, b, frame, delay) |
(frame or DEFAULT_CHAT_FRAME):AddMessage(text, r, g, b, 1, delay or 5) |
end |
local tmp = {} |
function AceDebug:CustomDebug(r, g, b, frame, delay, a1, ...) |
if not self.debugging then |
return |
end |
local output = self:GetDebugPrefix() |
a1 = tostring(a1) |
if a1:find("%%") and select('#', ...) >= 1 then |
for i = 1, select('#', ...) do |
tmp[i] = tostring((select(i, ...))) |
end |
output = output .. " " .. a1:format(unpack(tmp)) |
for i = 1, select('#', ...) do |
tmp[i] = nil |
end |
else |
-- This block dynamically rebuilds the tmp array stopping on the first nil. |
tmp[1] = output |
tmp[2] = a1 |
for i = 1, select('#', ...) do |
tmp[i+2] = tostring((select(i, ...))) |
end |
output = table.concat(tmp, " ") |
for i = 1, select('#', ...) + 2 do |
tmp[i] = nil |
end |
end |
print(output, r, g, b, frame or self.debugFrame, delay) |
end |
function AceDebug:Debug(...) |
AceDebug.CustomDebug(self, nil, nil, nil, nil, nil, ...) |
end |
function AceDebug:IsDebugging() |
return self.debugging |
end |
function AceDebug:SetDebugging(debugging) |
if debugging then |
self.debugging = debugging |
if type(self.OnDebugEnable) == "function" then |
safecall(self.OnDebugEnable, self) |
end |
else |
if type(self.OnDebugDisable) == "function" then |
safecall(self.OnDebugDisable, self) |
end |
self.debugging = debugging |
end |
end |
-- Takes a number 1-3 |
-- Level 1: Critical messages that every user should receive |
-- Level 2: Should be used for local debugging (function calls, etc) |
-- Level 3: Very verbose debugging, will dump everything and anything |
-- If set to nil, you will receive no debug information |
function AceDebug:SetDebugLevel(level) |
AceDebug:argCheck(level, 1, "number", "nil") |
if not level then |
self.debuglevel = nil |
return |
end |
if level < 1 or level > 3 then |
AceDebug:error("Bad argument #1 to `SetDebugLevel`, must be a number 1-3") |
end |
self.debuglevel = level |
end |
function AceDebug:GetDebugPrefix() |
return ("|cff7fff7f(DEBUG) %s:[%s.%3d]|r"):format( tostring(self), date("%H:%M:%S"), (GetTime() % 1) * 1000) |
end |
function AceDebug:GetDebugLevel() |
return self.debuglevel |
end |
function AceDebug:CustomLevelDebug(level, r, g, b, frame, delay, a1, ...) |
if not self.debugging or not self.debuglevel then return end |
AceDebug:argCheck(level, 1, "number") |
if level < 1 or level > 3 then |
AceDebug:error("Bad argument #1 to `LevelDebug`, must be a number 1-3") |
end |
if level > self.debuglevel then return end |
local output = self:GetDebugPrefix() |
a1 = tostring(a1) |
if a1:find("%%") and select('#', ...) >= 1 then |
for i = 1, select('#', ...) do |
tmp[i] = tostring((select(i, ...))) |
end |
output = output .. " " .. a1:format(unpack(tmp)) |
for i = 1, select('#', ...) do |
tmp[i] = nil |
end |
else |
-- This block dynamically rebuilds the tmp array stopping on the first nil. |
tmp[1] = output |
tmp[2] = a1 |
for i = 1, select('#', ...) do |
tmp[i+2] = tostring((select(i, ...))) |
end |
output = table.concat(tmp, " ") |
for i = 1, select('#', ...) + 2 do |
tmp[i] = nil |
end |
end |
print(output, r, g, b, frame or self.debugFrame, delay) |
end |
function AceDebug:LevelDebug(level, ...) |
if not self.debugging or not self.debuglevel then return end |
AceDebug:argCheck(level, 1, "number") |
if level < 1 or level > 3 then |
AceDebug:error("Bad argument #1 to `LevelDebug`, must be a number 1-3") |
end |
if level > self.debuglevel then return end |
AceDebug.CustomLevelDebug(self, level, nil, nil, nil, nil, nil, ...) |
end |
local options |
function AceDebug:GetAceOptionsDataTable(target) |
if not options then |
options = { |
debug = { |
name = DEBUGGING, |
desc = TOGGLE_DEBUGGING, |
type = "toggle", |
get = "IsDebugging", |
set = "SetDebugging", |
order = -2, |
} |
} |
end |
return options |
end |
AceLibrary:Register(AceDebug, MAJOR_VERSION, MINOR_VERSION, AceDebug.activate) |
AceDebug = AceLibrary(MAJOR_VERSION) |
## Interface: 20400 |
## Title: Lib: AceDebug-2.0 |
## Notes: AddOn development framework |
## Author: Ace Development Team |
## LoadOnDemand: 1 |
## X-Website: http://www.wowace.com |
## X-Category: Library |
## X-License: LGPL v2.1 + MIT for AceOO-2.0 |
## Dependencies: AceLibrary, AceOO-2.0 |
AceDebug-2.0.lua |
--[[ |
Name: LibBabble-Boss-3.0 |
Revision: $Rev$ |
Author(s): ckknight (ckknight@gmail.com) |
Website: http://ckknight.wowinterface.com/ |
Description: A library to provide localizations for bosses. |
Dependencies: None |
License: MIT |
]] |
local MAJOR_VERSION = "LibBabble-Boss-3.0" |
local MINOR_VERSION = "$Revision$" |
-- #AUTODOC_NAMESPACE prototype |
local GAME_LOCALE = GetLocale() |
do |
-- LibBabble-Core-3.0 is hereby placed in the Public Domain |
-- Credits: ckknight |
local LIBBABBLE_MAJOR, LIBBABBLE_MINOR = "LibBabble-3.0", 2 |
local LibBabble = LibStub:NewLibrary(LIBBABBLE_MAJOR, LIBBABBLE_MINOR) |
if LibBabble then |
local data = LibBabble.data or {} |
for k,v in pairs(LibBabble) do |
LibBabble[k] = nil |
end |
LibBabble.data = data |
local tablesToDB = {} |
for namespace, db in pairs(data) do |
for k,v in pairs(db) do |
tablesToDB[v] = db |
end |
end |
local function warn(message) |
local _, ret = pcall(error, message, 3) |
geterrorhandler()(ret) |
end |
local lookup_mt = { __index = function(self, key) |
local db = tablesToDB[self] |
local current_key = db.current[key] |
if current_key then |
self[key] = current_key |
return current_key |
end |
local base_key = db.base[key] |
local real_MAJOR_VERSION |
for k,v in pairs(data) do |
if v == db then |
real_MAJOR_VERSION = k |
break |
end |
end |
if not real_MAJOR_VERSION then |
real_MAJOR_VERSION = LIBBABBLE_MAJOR |
end |
if base_key then |
warn(("%s: Translation %q not found for locale %q"):format(real_MAJOR_VERSION, key, GAME_LOCALE)) |
rawset(self, key, base_key) |
return base_key |
end |
warn(("%s: Translation %q not found."):format(real_MAJOR_VERSION, key)) |
rawset(self, key, key) |
return key |
end } |
local function initLookup(module, lookup) |
local db = tablesToDB[module] |
for k in pairs(lookup) do |
lookup[k] = nil |
end |
setmetatable(lookup, lookup_mt) |
tablesToDB[lookup] = db |
db.lookup = lookup |
return lookup |
end |
local function initReverse(module, reverse) |
local db = tablesToDB[module] |
for k in pairs(reverse) do |
reverse[k] = nil |
end |
for k,v in pairs(db.current) do |
reverse[v] = k |
end |
tablesToDB[reverse] = db |
db.reverse = reverse |
db.reverseIterators = nil |
return reverse |
end |
local prototype = {} |
local prototype_mt = {__index = prototype} |
--[[--------------------------------------------------------------------------- |
Notes: |
* If you try to access a nonexistent key, it will warn but allow the code to pass through. |
Returns: |
A lookup table for english to localized words. |
Example: |
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want. |
local BL = B:GetLookupTable() |
assert(BL["Some english word"] == "Some localized word") |
DoSomething(BL["Some english word that doesn't exist"]) -- warning! |
-----------------------------------------------------------------------------]] |
function prototype:GetLookupTable() |
local db = tablesToDB[self] |
local lookup = db.lookup |
if lookup then |
return lookup |
end |
return initLookup(self, {}) |
end |
--[[--------------------------------------------------------------------------- |
Notes: |
* If you try to access a nonexistent key, it will return nil. |
Returns: |
A lookup table for english to localized words. |
Example: |
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want. |
local B_has = B:GetUnstrictLookupTable() |
assert(B_has["Some english word"] == "Some localized word") |
assert(B_has["Some english word that doesn't exist"] == nil) |
-----------------------------------------------------------------------------]] |
function prototype:GetUnstrictLookupTable() |
local db = tablesToDB[self] |
return db.current |
end |
--[[--------------------------------------------------------------------------- |
Notes: |
* If you try to access a nonexistent key, it will return nil. |
* This is useful for checking if the base (English) table has a key, even if the localized one does not have it registered. |
Returns: |
A lookup table for english to localized words. |
Example: |
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want. |
local B_hasBase = B:GetBaseLookupTable() |
assert(B_hasBase["Some english word"] == "Some english word") |
assert(B_hasBase["Some english word that doesn't exist"] == nil) |
-----------------------------------------------------------------------------]] |
function prototype:GetBaseLookupTable() |
local db = tablesToDB[self] |
return db.base |
end |
--[[--------------------------------------------------------------------------- |
Notes: |
* If you try to access a nonexistent key, it will return nil. |
* This will return only one English word that it maps to, if there are more than one to check, see :GetReverseIterator("word") |
Returns: |
A lookup table for localized to english words. |
Example: |
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want. |
local BR = B:GetReverseLookupTable() |
assert(BR["Some localized word"] == "Some english word") |
assert(BR["Some localized word that doesn't exist"] == nil) |
-----------------------------------------------------------------------------]] |
function prototype:GetReverseLookupTable() |
local db = tablesToDB[self] |
local reverse = db.reverse |
if reverse then |
return reverse |
end |
return initReverse(self, {}) |
end |
local blank = {} |
local weakVal = {__mode='v'} |
--[[--------------------------------------------------------------------------- |
Arguments: |
string - the localized word to chek for. |
Returns: |
An iterator to traverse all English words that map to the given key |
Example: |
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want. |
for word in B:GetReverseIterator("Some localized word") do |
DoSomething(word) |
end |
-----------------------------------------------------------------------------]] |
function prototype:GetReverseIterator(key) |
local db = tablesToDB[self] |
local reverseIterators = db.reverseIterators |
if not reverseIterators then |
reverseIterators = setmetatable({}, weakVal) |
db.reverseIterators = reverseIterators |
elseif reverseIterators[key] then |
return pairs(reverseIterators[key]) |
end |
local t |
for k,v in pairs(db.current) do |
if v == key then |
if not t then |
t = {} |
end |
t[k] = true |
end |
end |
reverseIterators[key] = t or blank |
return pairs(reverseIterators[key]) |
end |
--[[--------------------------------------------------------------------------- |
Returns: |
An iterator to traverse all translations English to localized. |
Example: |
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want. |
for english, localized in B:Iterate() do |
DoSomething(english, localized) |
end |
-----------------------------------------------------------------------------]] |
function prototype:Iterate() |
local db = tablesToDB[self] |
return pairs(db.current) |
end |
-- #NODOC |
-- modules need to call this to set the base table |
function prototype:SetBaseTranslations(base) |
local db = tablesToDB[self] |
local oldBase = db.base |
if oldBase then |
for k in pairs(oldBase) do |
oldBase[k] = nil |
end |
for k, v in pairs(base) do |
oldBase[k] = v |
end |
base = oldBase |
else |
db.base = base |
end |
for k,v in pairs(base) do |
if v == true then |
base[k] = k |
end |
end |
end |
local function init(module) |
local db = tablesToDB[module] |
if db.lookup then |
initLookup(module, db.lookup) |
end |
if db.reverse then |
initReverse(module, db.reverse) |
end |
db.reverseIterators = nil |
end |
-- #NODOC |
-- modules need to call this to set the current table. if current is true, use the base table. |
function prototype:SetCurrentTranslations(current) |
local db = tablesToDB[self] |
if current == true then |
db.current = db.base |
else |
local oldCurrent = db.current |
if oldCurrent then |
for k in pairs(oldCurrent) do |
oldCurrent[k] = nil |
end |
for k, v in pairs(current) do |
oldCurrent[k] = v |
end |
current = oldCurrent |
else |
db.current = current |
end |
end |
init(self) |
end |
for namespace, db in pairs(data) do |
setmetatable(db.module, prototype_mt) |
init(db.module) |
end |
-- #NODOC |
-- modules need to call this to create a new namespace. |
function LibBabble:New(namespace, minor) |
local module, oldminor = LibStub:NewLibrary(namespace, minor) |
if not module then |
return |
end |
if not oldminor then |
local db = { |
module = module, |
} |
data[namespace] = db |
tablesToDB[module] = db |
else |
for k,v in pairs(module) do |
module[k] = nil |
end |
end |
setmetatable(module, prototype_mt) |
return module |
end |
end |
end |
local lib = LibStub("LibBabble-3.0"):New(MAJOR_VERSION, MINOR_VERSION) |
if not lib then |
return |
end |
lib:SetBaseTranslations { |
--Ahn'Qiraj |
["Anubisath Defender"] = true, |
["Battleguard Sartura"] = true, |
["C'Thun"] = true, |
["Emperor Vek'lor"] = true, |
["Emperor Vek'nilash"] = true, |
["Eye of C'Thun"] = true, |
["Fankriss the Unyielding"] = true, |
["Lord Kri"] = true, |
["Ouro"] = true, |
["Princess Huhuran"] = true, |
["Princess Yauj"] = true, |
["The Bug Family"] = true, |
["The Prophet Skeram"] = true, |
["The Twin Emperors"] = true, |
["Vem"] = true, |
["Viscidus"] = true, |
--Auchindoun |
--Auchenai Crypts |
["Exarch Maladaar"] = true, |
["Shirrak the Dead Watcher"] = true, |
--Mana-Tombs |
["Nexus-Prince Shaffar"] = true, |
["Pandemonius"] = true, |
["Tavarok"] = true, |
--Shadow Labyrinth |
["Ambassador Hellmaw"] = true, |
["Blackheart the Inciter"] = true, |
["Grandmaster Vorpil"] = true, |
["Murmur"] = true, |
--Sethekk Halls |
["Anzu"] = true, |
["Darkweaver Syth"] = true, |
["Talon King Ikiss"] = true, |
--Blackfathom Deeps |
["Aku'mai"] = true, |
["Baron Aquanis"] = true, |
["Gelihast"] = true, |
["Ghamoo-ra"] = true, |
["Lady Sarevess"] = true, |
["Old Serra'kis"] = true, |
["Twilight Lord Kelris"] = true, |
--Blackrock Depths |
["Ambassador Flamelash"] = true, |
["Anger'rel"] = true, |
["Anub'shiah"] = true, |
["Bael'Gar"] = true, |
["Chest of The Seven"] = true, |
["Doom'rel"] = true, |
["Dope'rel"] = true, |
["Emperor Dagran Thaurissan"] = true, |
["Eviscerator"] = true, |
["Fineous Darkvire"] = true, |
["General Angerforge"] = true, |
["Gloom'rel"] = true, |
["Golem Lord Argelmach"] = true, |
["Gorosh the Dervish"] = true, |
["Grizzle"] = true, |
["Hate'rel"] = true, |
["Hedrum the Creeper"] = true, |
["High Interrogator Gerstahn"] = true, |
["High Priestess of Thaurissan"] = true, |
["Houndmaster Grebmar"] = true, |
["Hurley Blackbreath"] = true, |
["Lord Incendius"] = true, |
["Lord Roccor"] = true, |
["Magmus"] = true, |
["Ok'thor the Breaker"] = true, |
["Panzor the Invincible"] = true, |
["Phalanx"] = true, |
["Plugger Spazzring"] = true, |
["Princess Moira Bronzebeard"] = true, |
["Pyromancer Loregrain"] = true, |
["Ribbly Screwspigot"] = true, |
["Seeth'rel"] = true, |
["The Seven Dwarves"] = true, |
["Verek"] = true, |
["Vile'rel"] = true, |
["Warder Stilgiss"] = true, |
--Blackrock Spire |
--Lower |
["Bannok Grimaxe"] = true, |
["Burning Felguard"] = true, |
["Crystal Fang"] = true, |
["Ghok Bashguud"] = true, |
["Gizrul the Slavener"] = true, |
["Halycon"] = true, |
["Highlord Omokk"] = true, |
["Mor Grayhoof"] = true, |
["Mother Smolderweb"] = true, |
["Overlord Wyrmthalak"] = true, |
["Quartermaster Zigris"] = true, |
["Shadow Hunter Vosh'gajin"] = true, |
["Spirestone Battle Lord"] = true, |
["Spirestone Butcher"] = true, |
["Spirestone Lord Magus"] = true, |
["Urok Doomhowl"] = true, |
["War Master Voone"] = true, |
--Upper |
["General Drakkisath"] = true, |
["Goraluk Anvilcrack"] = true, |
["Gyth"] = true, |
["Jed Runewatcher"] = true, |
["Lord Valthalak"] = true, |
["Pyroguard Emberseer"] = true, |
["Solakar Flamewreath"] = true, |
["The Beast"] = true, |
["Warchief Rend Blackhand"] = true, |
--Blackwing Lair |
["Broodlord Lashlayer"] = true, |
["Chromaggus"] = true, |
["Ebonroc"] = true, |
["Firemaw"] = true, |
["Flamegor"] = true, |
["Grethok the Controller"] = true, |
["Lord Victor Nefarius"] = true, |
["Nefarian"] = true, |
["Razorgore the Untamed"] = true, |
["Vaelastrasz the Corrupt"] = true, |
--Black Temple |
["Essence of Anger"] = true, |
["Essence of Desire"] = true, |
["Essence of Suffering"] = true, |
["Gathios the Shatterer"] = true, |
["Gurtogg Bloodboil"] = true, |
["High Nethermancer Zerevor"] = true, |
["High Warlord Naj'entus"] = true, |
["Illidan Stormrage"] = true, |
["Illidari Council"] = true, |
["Lady Malande"] = true, |
["Mother Shahraz"] = true, |
["Reliquary of Souls"] = true, |
["Shade of Akama"] = true, |
["Supremus"] = true, |
["Teron Gorefiend"] = true, |
["The Illidari Council"] = true, |
["Veras Darkshadow"] = true, |
--Caverns of Time |
--Old Hillsbrad Foothills |
["Captain Skarloc"] = true, |
["Epoch Hunter"] = true, |
["Lieutenant Drake"] = true, |
--The Black Morass |
["Aeonus"] = true, |
["Chrono Lord Deja"] = true, |
["Medivh"] = true, |
["Temporus"] = true, |
--Coilfang Reservoir |
--Serpentshrine Cavern |
["Coilfang Elite"] = true, |
["Coilfang Strider"] = true, |
["Fathom-Lord Karathress"] = true, |
["Hydross the Unstable"] = true, |
["Lady Vashj"] = true, |
["Leotheras the Blind"] = true, |
["Morogrim Tidewalker"] = true, |
["Pure Spawn of Hydross"] = true, |
["Shadow of Leotheras"] = true, |
["Tainted Spawn of Hydross"] = true, |
["The Lurker Below"] = true, |
["Tidewalker Lurker"] = true, |
--The Slave Pens |
["Mennu the Betrayer"] = true, |
["Quagmirran"] = true, |
["Rokmar the Crackler"] = true, |
["Ahune"] = true, |
--The Steamvault |
["Hydromancer Thespia"] = true, |
["Mekgineer Steamrigger"] = true, |
["Warlord Kalithresh"] = true, |
--The Underbog |
["Claw"] = true, |
["Ghaz'an"] = true, |
["Hungarfen"] = true, |
["Overseer Tidewrath"] = true, |
["Swamplord Musel'ek"] = true, |
["The Black Stalker"] = true, |
--Dire Maul |
--Arena |
["Mushgog"] = true, |
["Skarr the Unbreakable"] = true, |
["The Razza"] = true, |
--East |
["Alzzin the Wildshaper"] = true, |
["Hydrospawn"] = true, |
["Isalien"] = true, |
["Lethtendris"] = true, |
["Pimgib"] = true, |
["Pusillin"] = true, |
["Zevrim Thornhoof"] = true, |
--North |
["Captain Kromcrush"] = true, |
["Cho'Rush the Observer"] = true, |
["Guard Fengus"] = true, |
["Guard Mol'dar"] = true, |
["Guard Slip'kik"] = true, |
["King Gordok"] = true, |
["Knot Thimblejack's Cache"] = true, |
["Stomper Kreeg"] = true, |
--West |
["Illyanna Ravenoak"] = true, |
["Immol'thar"] = true, |
["Lord Hel'nurath"] = true, |
["Magister Kalendris"] = true, |
["Prince Tortheldrin"] = true, |
["Tendris Warpwood"] = true, |
["Tsu'zee"] = true, |
--Gnomeregan |
["Crowd Pummeler 9-60"] = true, |
["Dark Iron Ambassador"] = true, |
["Electrocutioner 6000"] = true, |
["Grubbis"] = true, |
["Mekgineer Thermaplugg"] = true, |
["Techbot"] = true, |
["Viscous Fallout"] = true, |
--Gruul's Lair |
["Blindeye the Seer"] = true, |
["Gruul the Dragonkiller"] = true, |
["High King Maulgar"] = true, |
["Kiggler the Crazed"] = true, |
["Krosh Firehand"] = true, |
["Olm the Summoner"] = true, |
--Hellfire Citadel |
--Hellfire Ramparts |
["Nazan"] = true, |
["Omor the Unscarred"] = true, |
["Vazruden the Herald"] = true, |
["Vazruden"] = true, |
["Watchkeeper Gargolmar"] = true, |
--Magtheridon's Lair |
["Hellfire Channeler"] = true, |
["Magtheridon"] = true, |
--The Blood Furnace |
["Broggok"] = true, |
["Keli'dan the Breaker"] = true, |
["The Maker"] = true, |
--The Shattered Halls |
["Blood Guard Porung"] = true, |
["Grand Warlock Nethekurse"] = true, |
["Warbringer O'mrogg"] = true, |
["Warchief Kargath Bladefist"] = true, |
--Hyjal Summit |
["Anetheron"] = true, |
["Archimonde"] = true, |
["Azgalor"] = true, |
["Kaz'rogal"] = true, |
["Rage Winterchill"] = true, |
--Karazhan |
["Arcane Watchman"] = true, |
["Attumen the Huntsman"] = true, |
["Chess Event"] = true, |
["Dorothee"] = true, |
["Dust Covered Chest"] = true, |
["Grandmother"] = true, |
["Hyakiss the Lurker"] = true, |
["Julianne"] = true, |
["Kil'rek"] = true, |
["King Llane Piece"] = true, |
["Maiden of Virtue"] = true, |
["Midnight"] = true, |
["Moroes"] = true, |
["Netherspite"] = true, |
["Nightbane"] = true, |
["Prince Malchezaar"] = true, |
["Restless Skeleton"] = true, |
["Roar"] = true, |
["Rokad the Ravager"] = true, |
["Romulo & Julianne"] = true, |
["Romulo"] = true, |
["Shade of Aran"] = true, |
["Shadikith the Glider"] = true, |
["Strawman"] = true, |
["Terestian Illhoof"] = true, |
["The Big Bad Wolf"] = true, |
["The Crone"] = true, |
["The Curator"] = true, |
["Tinhead"] = true, |
["Tito"] = true, |
["Warchief Blackhand Piece"] = true, |
-- Magisters' Terrace |
--["Kael'thas Sunstrider"] = true, |
["Priestess Delrissa"] = true, |
["Selin Fireheart"] = true, |
["Vexallus"] = true, |
--Maraudon |
["Celebras the Cursed"] = true, |
["Gelk"] = true, |
["Kolk"] = true, |
["Landslide"] = true, |
["Lord Vyletongue"] = true, |
["Magra"] = true, |
["Maraudos"] = true, |
["Meshlok the Harvester"] = true, |
["Noxxion"] = true, |
["Princess Theradras"] = true, |
["Razorlash"] = true, |
["Rotgrip"] = true, |
["Tinkerer Gizlock"] = true, |
["Veng"] = true, |
--Molten Core |
["Baron Geddon"] = true, |
["Cache of the Firelord"] = true, |
["Garr"] = true, |
["Gehennas"] = true, |
["Golemagg the Incinerator"] = true, |
["Lucifron"] = true, |
["Magmadar"] = true, |
["Majordomo Executus"] = true, |
["Ragnaros"] = true, |
["Shazzrah"] = true, |
["Sulfuron Harbinger"] = true, |
--Naxxramas |
["Anub'Rekhan"] = true, |
["Deathknight Understudy"] = true, |
["Feugen"] = true, |
["Four Horsemen Chest"] = true, |
["Gluth"] = true, |
["Gothik the Harvester"] = true, |
["Grand Widow Faerlina"] = true, |
["Grobbulus"] = true, |
["Heigan the Unclean"] = true, |
["Highlord Mograine"] = true, |
["Instructor Razuvious"] = true, |
["Kel'Thuzad"] = true, |
["Lady Blaumeux"] = true, |
["Loatheb"] = true, |
["Maexxna"] = true, |
["Noth the Plaguebringer"] = true, |
["Patchwerk"] = true, |
["Sapphiron"] = true, |
["Sir Zeliek"] = true, |
["Stalagg"] = true, |
["Thaddius"] = true, |
["Thane Korth'azz"] = true, |
["The Four Horsemen"] = true, |
--Onyxia's Lair |
["Onyxia"] = true, |
--Ragefire Chasm |
["Bazzalan"] = true, |
["Jergosh the Invoker"] = true, |
["Maur Grimtotem"] = true, |
["Taragaman the Hungerer"] = true, |
--Razorfen Downs |
["Amnennar the Coldbringer"] = true, |
["Glutton"] = true, |
["Mordresh Fire Eye"] = true, |
["Plaguemaw the Rotting"] = true, |
["Ragglesnout"] = true, |
["Tuten'kash"] = true, |
--Razorfen Kraul |
["Agathelos the Raging"] = true, |
["Blind Hunter"] = true, |
["Charlga Razorflank"] = true, |
["Death Speaker Jargba"] = true, |
["Earthcaller Halmgar"] = true, |
["Overlord Ramtusk"] = true, |
--Ruins of Ahn'Qiraj |
["Anubisath Guardian"] = true, |
["Ayamiss the Hunter"] = true, |
["Buru the Gorger"] = true, |
["General Rajaxx"] = true, |
["Kurinnaxx"] = true, |
["Lieutenant General Andorov"] = true, |
["Moam"] = true, |
["Ossirian the Unscarred"] = true, |
--Scarlet Monastery |
--Armory |
["Herod"] = true, |
--Cathedral |
["High Inquisitor Fairbanks"] = true, |
["High Inquisitor Whitemane"] = true, |
["Scarlet Commander Mograine"] = true, |
--Graveyard |
["Azshir the Sleepless"] = true, |
["Bloodmage Thalnos"] = true, |
["Fallen Champion"] = true, |
["Interrogator Vishas"] = true, |
["Ironspine"] = true, |
["Headless Horseman"] = true, |
--Library |
["Arcanist Doan"] = true, |
["Houndmaster Loksey"] = true, |
--Scholomance |
["Blood Steward of Kirtonos"] = true, |
["Darkmaster Gandling"] = true, |
["Death Knight Darkreaver"] = true, |
["Doctor Theolen Krastinov"] = true, |
["Instructor Malicia"] = true, |
["Jandice Barov"] = true, |
["Kirtonos the Herald"] = true, |
["Kormok"] = true, |
["Lady Illucia Barov"] = true, |
["Lord Alexei Barov"] = true, |
["Lorekeeper Polkelt"] = true, |
["Marduk Blackpool"] = true, |
["Ras Frostwhisper"] = true, |
["Rattlegore"] = true, |
["The Ravenian"] = true, |
["Vectus"] = true, |
--Shadowfang Keep |
["Archmage Arugal"] = true, |
["Arugal's Voidwalker"] = true, |
["Baron Silverlaine"] = true, |
["Commander Springvale"] = true, |
["Deathsworn Captain"] = true, |
["Fenrus the Devourer"] = true, |
["Odo the Blindwatcher"] = true, |
["Razorclaw the Butcher"] = true, |
["Wolf Master Nandos"] = true, |
--Stratholme |
["Archivist Galford"] = true, |
["Balnazzar"] = true, |
["Baron Rivendare"] = true, |
["Baroness Anastari"] = true, |
["Black Guard Swordsmith"] = true, |
["Cannon Master Willey"] = true, |
["Crimson Hammersmith"] = true, |
["Fras Siabi"] = true, |
["Hearthsinger Forresten"] = true, |
["Magistrate Barthilas"] = true, |
["Maleki the Pallid"] = true, |
["Nerub'enkan"] = true, |
["Postmaster Malown"] = true, |
["Ramstein the Gorger"] = true, |
["Skul"] = true, |
["Stonespine"] = true, |
["The Unforgiven"] = true, |
["Timmy the Cruel"] = true, |
--Sunwell Plateau |
["Kalecgos"] = true, |
["Sathrovarr the Corruptor"] = true, |
["Brutallus"] = true, |
["Felmyst"] = true, |
["Kil'jaeden"] = true, |
["M'uru"] = true, |
["Entropius"] = true, |
["The Eredar Twins"] = true, |
["Lady Sacrolash"] = true, |
["Grand Warlock Alythess"] = true, |
--Tempest Keep |
--The Arcatraz |
["Dalliah the Doomsayer"] = true, |
["Harbinger Skyriss"] = true, |
["Warden Mellichar"] = true, |
["Wrath-Scryer Soccothrates"] = true, |
["Zereketh the Unbound"] = true, |
--The Botanica |
["Commander Sarannis"] = true, |
["High Botanist Freywinn"] = true, |
["Laj"] = true, |
["Thorngrin the Tender"] = true, |
["Warp Splinter"] = true, |
--The Eye |
["Al'ar"] = true, |
["Cosmic Infuser"] = true, |
["Devastation"] = true, |
["Grand Astromancer Capernian"] = true, |
["High Astromancer Solarian"] = true, |
["Infinity Blades"] = true, |
["Kael'thas Sunstrider"] = true, |
["Lord Sanguinar"] = true, |
["Master Engineer Telonicus"] = true, |
["Netherstrand Longbow"] = true, |
["Phaseshift Bulwark"] = true, |
["Solarium Agent"] = true, |
["Solarium Priest"] = true, |
["Staff of Disintegration"] = true, |
["Thaladred the Darkener"] = true, |
["Void Reaver"] = true, |
["Warp Slicer"] = true, |
--The Mechanar |
["Gatewatcher Gyro-Kill"] = true, |
["Gatewatcher Iron-Hand"] = true, |
["Mechano-Lord Capacitus"] = true, |
["Nethermancer Sepethrea"] = true, |
["Pathaleon the Calculator"] = true, |
--The Deadmines |
["Brainwashed Noble"] = true, |
["Captain Greenskin"] = true, |
["Cookie"] = true, |
["Edwin VanCleef"] = true, |
["Foreman Thistlenettle"] = true, |
["Gilnid"] = true, |
["Marisa du'Paige"] = true, |
["Miner Johnson"] = true, |
["Mr. Smite"] = true, |
["Rhahk'Zor"] = true, |
["Sneed"] = true, |
["Sneed's Shredder"] = true, |
--The Stockade |
["Bazil Thredd"] = true, |
["Bruegal Ironknuckle"] = true, |
["Dextren Ward"] = true, |
["Hamhock"] = true, |
["Kam Deepfury"] = true, |
["Targorr the Dread"] = true, |
--The Temple of Atal'Hakkar |
["Atal'alarion"] = true, |
["Avatar of Hakkar"] = true, |
["Dreamscythe"] = true, |
["Gasher"] = true, |
["Hazzas"] = true, |
["Hukku"] = true, |
["Jade"] = true, |
["Jammal'an the Prophet"] = true, |
["Kazkaz the Unholy"] = true, |
["Loro"] = true, |
["Mijan"] = true, |
["Morphaz"] = true, |
["Ogom the Wretched"] = true, |
["Shade of Eranikus"] = true, |
["Veyzhak the Cannibal"] = true, |
["Weaver"] = true, |
["Zekkis"] = true, |
["Zolo"] = true, |
["Zul'Lor"] = true, |
--Uldaman |
["Ancient Stone Keeper"] = true, |
["Archaedas"] = true, |
["Baelog"] = true, |
["Digmaster Shovelphlange"] = true, |
["Galgann Firehammer"] = true, |
["Grimlok"] = true, |
["Ironaya"] = true, |
["Obsidian Sentinel"] = true, |
["Revelosh"] = true, |
--Wailing Caverns |
["Boahn"] = true, |
["Deviate Faerie Dragon"] = true, |
["Kresh"] = true, |
["Lady Anacondra"] = true, |
["Lord Cobrahn"] = true, |
["Lord Pythas"] = true, |
["Lord Serpentis"] = true, |
["Mad Magglish"] = true, |
["Mutanus the Devourer"] = true, |
["Skum"] = true, |
["Trigore the Lasher"] = true, |
["Verdan the Everliving"] = true, |
--World Bosses |
["Avalanchion"] = true, |
["Azuregos"] = true, |
["Baron Charr"] = true, |
["Baron Kazum"] = true, |
["Doom Lord Kazzak"] = true, |
["Doomwalker"] = true, |
["Emeriss"] = true, |
["High Marshal Whirlaxis"] = true, |
["Lethon"] = true, |
["Lord Skwol"] = true, |
["Prince Skaldrenox"] = true, |
["Princess Tempestria"] = true, |
["Taerar"] = true, |
["The Windreaver"] = true, |
["Ysondre"] = true, |
--Zul'Aman |
["Akil'zon"] = true, |
["Halazzi"] = true, |
["Jan'alai"] = true, |
["Malacrass"] = true, |
["Nalorakk"] = true, |
["Zul'jin"] = true, |
["Hex Lord Malacrass"] = true, |
--Zul'Farrak |
["Antu'sul"] = true, |
["Chief Ukorz Sandscalp"] = true, |
["Dustwraith"] = true, |
["Gahz'rilla"] = true, |
["Hydromancer Velratha"] = true, |
["Murta Grimgut"] = true, |
["Nekrum Gutchewer"] = true, |
["Oro Eyegouge"] = true, |
["Ruuzlu"] = true, |
["Sandarr Dunereaver"] = true, |
["Sandfury Executioner"] = true, |
["Sergeant Bly"] = true, |
["Shadowpriest Sezz'ziz"] = true, |
["Theka the Martyr"] = true, |
["Witch Doctor Zum'rah"] = true, |
["Zerillis"] = true, |
["Zul'Farrak Dead Hero"] = true, |
--Zul'Gurub |
["Bloodlord Mandokir"] = true, |
["Gahz'ranka"] = true, |
["Gri'lek"] = true, |
["Hakkar"] = true, |
["Hazza'rah"] = true, |
["High Priest Thekal"] = true, |
["High Priest Venoxis"] = true, |
["High Priestess Arlokk"] = true, |
["High Priestess Jeklik"] = true, |
["High Priestess Mar'li"] = true, |
["Jin'do the Hexxer"] = true, |
["Renataki"] = true, |
["Wushoolay"] = true, |
--Ring of Blood (where? an instance? should be in other file?) |
["Brokentoe"] = true, |
["Mogor"] = true, |
["Murkblood Twin"] = true, |
["Murkblood Twins"] = true, |
["Rokdar the Sundered Lord"] = true, |
["Skra'gath"] = true, |
["The Blue Brothers"] = true, |
["Warmaul Champion"] = true, |
} |
if GAME_LOCALE == "enUS" then |
lib:SetCurrentTranslations(true) |
elseif GAME_LOCALE == "deDE" then |
lib:SetCurrentTranslations { |
--Ahn'Qiraj |
["Anubisath Defender"] = "Verteidiger des Anubisath", |
["Battleguard Sartura"] = "Schlachtwache Sartura", |
["C'Thun"] = "C'Thun", |
["Emperor Vek'lor"] = "Imperator Vek'lor", |
["Emperor Vek'nilash"] = "Imperator Vek'nilash", |
["Eye of C'Thun"] = "Auge von C'Thun", |
["Fankriss the Unyielding"] = "Fankriss der Unnachgiebige", |
["Lord Kri"] = "Lord Kri", |
["Ouro"] = "Ouro", |
["Princess Huhuran"] = "Prinzessin Huhuran", |
["Princess Yauj"] = "Prinzessin Yauj", |
["The Bug Family"] = "Die Käferfamilie", |
["The Prophet Skeram"] = "Der Prophet Skeram", |
["The Twin Emperors"] = "Die Zwillings-Imperatoren", |
["Vem"] = "Vem", |
["Viscidus"] = "Viscidus", |
--Auchindoun |
--Auchenai Crypts |
["Exarch Maladaar"] = "Exarch Maladaar", |
["Shirrak the Dead Watcher"] = "Shirrak der Totenwächter", |
--Mana-Tombs |
["Nexus-Prince Shaffar"] = "Nexusprinz Shaffar", |
["Pandemonius"] = "Pandemonius", |
["Tavarok"] = "Tavarok", |
--Shadow Labyrinth |
["Ambassador Hellmaw"] = "Botschafter Höllenschlund", |
["Blackheart the Inciter"] = "Schwarzherz der Hetzer", |
["Grandmaster Vorpil"] = "GroÃmeister Vorpil", |
["Murmur"] = "Murmur", |
--Sethekk Halls |
["Anzu"] = "Anzu", |
["Darkweaver Syth"] = "Dunkelwirker Syth", |
["Talon King Ikiss"] = "Klauenkönig Ikiss", |
--Blackfathom Deeps |
["Aku'mai"] = "Aku'mai", |
["Baron Aquanis"] = "Baron Aquanis", |
["Gelihast"] = "Gelihast", |
["Ghamoo-ra"] = "Ghamoo-ra", |
["Lady Sarevess"] = "Lady Sarevess", |
["Old Serra'kis"] = "Old Serra'kis", |
["Twilight Lord Kelris"] = "Lord des Schattenhammers Kelris", |
--Blackrock Depths |
["Ambassador Flamelash"] = "Botschafter Flammenschlag", |
["Anger'rel"] = "Anger'rel", |
["Anub'shiah"] = "Anub'shiah", |
["Bael'Gar"] = "Bael'Gar", |
["Chest of The Seven"] = "Truhe der Sieben", |
["Doom'rel"] = "Un'rel", |
["Dope'rel"] = "Trott'rel", |
["Emperor Dagran Thaurissan"] = "Imperator Dagran Thaurissan", |
["Eviscerator"] = "Ausweider", |
["Fineous Darkvire"] = "Fineous Dunkelader", |
["General Angerforge"] = "General Zornesschmied", |
["Gloom'rel"] = "Dunk'rel", |
["Golem Lord Argelmach"] = "Golemlord Argelmach", |
["Gorosh the Dervish"] = "Gorosh der Derwisch", |
["Grizzle"] = "Grizzle", |
["Hate'rel"] = "Hass'rel", |
["Hedrum the Creeper"] = "Hedrum der Krabbler", |
["High Interrogator Gerstahn"] = "Verhörmeisterin Gerstahn", |
["High Priestess of Thaurissan"] = " Hohepriesterin von Thaurissan", |
["Houndmaster Grebmar"] = "Hundemeister Grebmar", |
["Hurley Blackbreath"] = "Hurley Pestatem", |
["Lord Incendius"] = "Lord Incendius", |
["Lord Roccor"] = "Lord Roccor", |
["Magmus"] = "Magmus", |
["Ok'thor the Breaker"] = "Ok'thor der Zerstörer", |
["Panzor the Invincible"] = "Panzor der Unbesiegbare", |
["Phalanx"] = "Phalanx", |
["Plugger Spazzring"] = "Stöpsel Zapfring", |
["Princess Moira Bronzebeard"] = "Prinzessin Moira Bronzebeard", |
["Pyromancer Loregrain"] = "Pyromant Weisenkorn", |
["Ribbly Screwspigot"] = "Ribbly Schraubstutz", |
["Seeth'rel"] = "Wut'rel", |
["The Seven Dwarves"] = "Die Sieben Zwerge", |
["Verek"] = "Verek", |
["Vile'rel"] = "Bös'rel", |
["Warder Stilgiss"] = " Wärter Stilgiss", |
--Blackrock Spire |
--Lower |
["Bannok Grimaxe"] = "Bannok Grimmaxt", |
["Burning Felguard"] = "Brennende Teufelswache", |
["Crystal Fang"] = "Kristallfangzahn", |
["Ghok Bashguud"] = "Ghok Haudrauf", |
["Gizrul the Slavener"] = "Gizrul der Geifernde", |
["Halycon"] = "Halycon", |
["Highlord Omokk"] = "Hochlord Omokk", |
["Mor Grayhoof"] = "Mor Grauhuf", |
["Mother Smolderweb"] = "Mutter Glimmernetz", |
["Overlord Wyrmthalak"] = "Oberanführer Wyrmthalak", |
["Quartermaster Zigris"] = "Rüstmeister Zigris", |
["Shadow Hunter Vosh'gajin"] = "Schattenjägerin Vosh'gajin", |
["Spirestone Battle Lord"] = "Kampflord der Felsspitzoger", |
["Spirestone Butcher"] = "Metzger der Felsspitzoger", |
["Spirestone Lord Magus"] = "Maguslord der Felsspitzoger", |
["Urok Doomhowl"] = "Urok Schreckensbote", |
["War Master Voone"] = "Kriegsmeister Voone", |
--Upper |
["General Drakkisath"] = "General Drakkisath", |
["Goraluk Anvilcrack"] = "Goraluk Hammerbruch", |
["Gyth"] = "Gyth", |
["Jed Runewatcher"] = "Jed Runenblick", |
["Lord Valthalak"] = "Lord Valthalak", |
["Pyroguard Emberseer"] = "Feuerwache Glutseher", |
["Solakar Flamewreath"] = "Solakar Feuerkrone", |
["The Beast"] = "Die Bestie", |
["Warchief Rend Blackhand"] = "Kriegshäuptling Rend Schwarzfaust", |
--Blackwing Lair |
["Broodlord Lashlayer"] = "Brutwächter Dreschbringer", |
["Chromaggus"] = "Chromaggus", |
["Ebonroc"] = "Schattenschwinge", |
["Firemaw"] = "Feuerschwinge", |
["Flamegor"] = "Flammenmaul", |
["Grethok the Controller"] = "Grethok der Aufseher", |
["Lord Victor Nefarius"] = "Lord Victor Nefarius", |
["Nefarian"] = "Nefarian", |
["Razorgore the Untamed"] = "Razorgore der Ungezähmte", |
["Vaelastrasz the Corrupt"] = "Vaelastrasz der Verdorbene", |
--Black Temple |
["Essence of Anger"] = "Essenz des Zorns", |
["Essence of Desire"] = "Essenz der Begierde", |
["Essence of Suffering"] = "Essenz des Leidens", |
["Gathios the Shatterer"] = "Gathios der Zerschmetterer", |
["Gurtogg Bloodboil"] = "Gurtogg Siedeblut", |
["High Nethermancer Zerevor"] = "Hochnethermant Zerevor", |
["High Warlord Naj'entus"] = "Oberster Kriegsfürst Naj'entus", |
["Illidan Stormrage"] = "Illidan Sturmgrimm", |
["Illidari Council"] = "Rat der Illidari", |
["Lady Malande"] = "Lady Malande", |
["Mother Shahraz"] = "Mutter Shahraz", |
["Reliquary of Souls"] = "Reliquium der Seelen", |
["Shade of Akama"] = "Akamas Schemen", |
["Supremus"] = "Supremus", |
["Teron Gorefiend"] = "Teron Blutschatten", |
["The Illidari Council"] = "Rat der Illidari", |
["Veras Darkshadow"] = "Veras Schwarzschatten", |
--Caverns of Time |
--Old Hillsbrad Foothills |
["Captain Skarloc"] = "Kapitän Skarloc", |
["Epoch Hunter"] = "Epochenjäger", |
["Lieutenant Drake"] = "Leutnant Drach", |
--The Black Morass |
["Aeonus"] = "Aeonus", |
["Chrono Lord Deja"] = "Chronolord Deja", |
["Medivh"] = "Medivh", |
["Temporus"] = "Temporus", |
--Coilfang Reservoir |
--Serpentshrine Cavern |
["Coilfang Elite"] = "Elitesoldat des Echsenkessels", |
["Coilfang Strider"] = "Schreiter des Echsenkessels", |
["Fathom-Lord Karathress"] = "Tiefenlord Karathress", |
["Hydross the Unstable"] = "Hydross der Unstete", |
["Lady Vashj"] = "Lady Vashj", |
["Leotheras the Blind"] = "Leotheras der Blinde", |
["Morogrim Tidewalker"] = "Morogrim Gezeitenwandler", |
["Pure Spawn of Hydross"] = "Gereinigter Nachkomme Hydross'", |
["Shadow of Leotheras"] = "Schatten von Leotheras", |
["Tainted Spawn of Hydross"] = "Besudelter Nachkomme Hydross'", |
["The Lurker Below"] = "Das Grauen aus der Tiefe", |
["Tidewalker Lurker"] = "Lauerer der Gezeitenwandler", |
--The Slave Pens |
["Mennu the Betrayer"] = "Mennu der Verräter", |
["Quagmirran"] = "Quagmirran", |
["Rokmar the Crackler"] = "Rokmar der Zerquetscher", |
["Ahune"] = "Ahune", |
--The Steamvault |
["Hydromancer Thespia"] = "Wasserbeschwörerin Thespia", |
["Mekgineer Steamrigger"] = "Robogenieur Dampfhammer", |
["Warlord Kalithresh"] = "Kriegsherr Kalithresh", |
--The Underbog |
["Claw"] = "Klaue", |
["Ghaz'an"] = "Ghaz'an", |
["Hungarfen"] = "Hungarfenn", |
["Overseer Tidewrath"] = "Overseer Tidewrath", |
["Swamplord Musel'ek"] = "Sumpffürst Musel'ek", |
["The Black Stalker"] = "Die Schattenmutter", |
--Dire Maul |
--Arena |
["Mushgog"] = "Mushgog", |
["Skarr the Unbreakable"] = "Skarr der Unbezwingbare", |
["The Razza"] = "Der Razza", |
--East |
["Alzzin the Wildshaper"] = "Alzzin der Wildformer", |
["Hydrospawn"] = "Hydrobrut", |
["Isalien"] = "Isalien", |
["Lethtendris"] = "Lethtendris", |
["Pimgib"] = "Pimgib", |
["Pusillin"] = "Pusillin", |
["Zevrim Thornhoof"] = "Zevrim Dornhuf", |
--North |
["Captain Kromcrush"] = "Hauptmann Krombruch", |
["Cho'Rush the Observer"] = "Cho'Rush der Beobachter", |
["Guard Fengus"] = "Wache Fengus", |
["Guard Mol'dar"] = "Wache Mol'dar", |
["Guard Slip'kik"] = "Wache Slip'kik", |
["King Gordok"] = "König Gordok", |
["Knot Thimblejack's Cache"] = "Knot Thimblejacks Truhe", |
["Stomper Kreeg"] = "Stampfer Kreeg", |
--West |
["Illyanna Ravenoak"] = "Illyanna Rabeneiche", |
["Immol'thar"] = "Immol'thar", |
["Lord Hel'nurath"] = "Lord Hel'nurath", |
["Magister Kalendris"] = "Magister Kalendris", |
["Prince Tortheldrin"] = "Prinz Tortheldrin", |
["Tendris Warpwood"] = "Tendris Wucherborke", |
["Tsu'zee"] = "Tsu'zee", |
--Gnomeregan |
["Crowd Pummeler 9-60"] = "Meuteverprügler 9-60", |
["Dark Iron Ambassador"] = "Botschafter der Dunkeleisenzwerge", |
["Electrocutioner 6000"] = "Elektrokutor 6000", |
["Grubbis"] = "Grubbis", |
["Mekgineer Thermaplugg"] = "Robogenieur Thermadraht", |
["Techbot"] = "Techbot", |
["Viscous Fallout"] = "Verflüssigte Ablagerung", |
--Gruul's Lair |
["Blindeye the Seer"] = "Blindauge der Seher", |
["Gruul the Dragonkiller"] = "Gruul der Drachenschlächter", |
["High King Maulgar"] = "Hochkönig Maulgar", |
["Kiggler the Crazed"] = "Kiggler the Crazed", |
["Krosh Firehand"] = "Krosh Feuerhand", |
["Olm the Summoner"] = "Olm der Beschwörer", |
--Hellfire Citadel |
--Hellfire Ramparts |
["Nazan"] = "Nazan", |
["Omor the Unscarred"] = "Omor der Narbenlose", |
["Vazruden the Herald"] = "Vazruden der Herold", |
["Vazruden"] = "Vazruden", |
["Watchkeeper Gargolmar"] = "Wachhabender Gargolmar", |
--Magtheridon's Lair |
["Hellfire Channeler"] = "Kanalisierer des Höllenfeuers", |
["Magtheridon"] = "Magtheridon", |
--The Blood Furnace |
["Broggok"] = "Broggok", |
["Keli'dan the Breaker"] = "Keli'dan der Zerstörer", |
["The Maker"] = "Der Schöpfer", |
--The Shattered Halls |
["Blood Guard Porung"] = "Blutwache Porung", |
["Grand Warlock Nethekurse"] = "GroÃhexenmeister Nethekurse", |
["Warbringer O'mrogg"] = "Kriegshetzer O'mrogg", |
["Warchief Kargath Bladefist"] = "Kriegshäuptling Kargath Messerfaust", |
--Hyjal Summit |
["Anetheron"] = "Anetheron", |
["Archimonde"] = "Archimonde", |
["Azgalor"] = "Azgalor", |
["Kaz'rogal"] = "Kaz'rogal", |
["Rage Winterchill"] = "Furor Winterfrost", |
--Karazhan |
["Arcane Watchman"] = "Arkanwachmann", |
["Attumen the Huntsman"] = "Attumen der Jäger", |
["Chess Event"] = "Chess Event", |
["Dorothee"] = "Dorothee", |
["Dust Covered Chest"] = "Staub Bedeckter Kasten", |
["Grandmother"] = "GroÃmutter", |
["Hyakiss the Lurker"] = "Hyakiss der Lauerer", |
["Julianne"] = "Julianne", |
["Kil'rek"] = "Kil'rek", |
["King Llane Piece"] = "König Llane", |
["Maiden of Virtue"] = "Tugendhafte Maid", |
["Midnight"] = "Mittnacht", |
["Moroes"] = "Moroes", |
["Netherspite"] = "Nethergroll", |
["Nightbane"] = "Schrecken der Nacht", |
["Prince Malchezaar"] = "Prinz Malchezaar", |
["Restless Skeleton"] = "Ruheloses Skelett", |
["Roar"] = "Brüller", |
["Rokad the Ravager"] = "Rokad der Verheerer", |
["Romulo & Julianne"] = "Romulo & Julianne", |
["Romulo"] = "Romulo", |
["Shade of Aran"] = "Arans Schemen", |
["Shadikith the Glider"] = "Shadikith der Segler", |
["Strawman"] = "Strohmann", |
["Terestian Illhoof"] = "Terestian Siechhuf", |
["The Big Bad Wolf"] = "Der groÃe böse Wolf", |
["The Crone"] = "Die böse Hexe", |
["The Curator"] = "Der Kurator", |
["Tinhead"] = "Blechkopf", |
["Tito"] = "Tito", |
["Warchief Blackhand Piece"] = "Kriegshäuptling Schwarzfaust", |
-- Magisters' Terrace |
["Kael'thas Sunstrider"] = "Kael'thas Sonnenwanderer", |
["Priestess Delrissa"] = "Priesterin Delrissa", |
["Selin Fireheart"] = "Selin Feuerherz", |
["Vexallus"] = "Vexallus", |
--Maraudon |
["Celebras the Cursed"] = "Celebras der Verfluchte", |
["Gelk"] = "Gelk", |
["Kolk"] = "Kolk", |
["Landslide"] = "Erdrutsch", |
["Lord Vyletongue"] = "Lord Schlangenzunge", |
["Magra"] = "Magra", |
["Maraudos"] = "Maraudos", |
["Meshlok the Harvester"] = "Meshlok der Ernter", |
["Noxxion"] = "Noxxion", |
["Princess Theradras"] = "Prinzessin Theradras", |
["Razorlash"] = "Schlingwurzler", |
["Rotgrip"] = "Faulschnapper", |
["Tinkerer Gizlock"] = "Tüftler Gizlock", |
["Veng"] = "Veng", |
--Molten Core |
["Baron Geddon"] = "Baron Geddon", |
["Cache of the Firelord"] = "Truhe des Feuerlords", |
["Garr"] = "Garr", |
["Gehennas"] = "Gehennas", |
["Golemagg the Incinerator"] = "Golemagg der Verbrenner", |
["Lucifron"] = "Lucifron", |
["Magmadar"] = "Magmadar", |
["Majordomo Executus"] = "Majordomus Exekutus", |
["Ragnaros"] = "Ragnaros", |
["Shazzrah"] = "Shazzrah", |
["Sulfuron Harbinger"] = "Sulfuronherold", |
--Naxxramas |
["Anub'Rekhan"] = "Anub'Rekhan", |
["Deathknight Understudy"] = "Reservist der Todesritter", |
["Feugen"] = "Feugen", |
["Four Horsemen Chest"] = "Die Vier Reiter Kiste", |
["Gluth"] = "Gluth", |
["Gothik the Harvester"] = "Gothik der Seelenjäger", |
["Grand Widow Faerlina"] = "GroÃwitwe Faerlina", |
["Grobbulus"] = "Grobbulus", |
["Heigan the Unclean"] = "Heigan der Unreine", |
["Highlord Mograine"] = "Hochlord Mograine", |
["Instructor Razuvious"] = "Instrukteur Razuvious", |
["Kel'Thuzad"] = "Kel'Thuzad", |
["Lady Blaumeux"] = "Lady Blaumeux", |
["Loatheb"] = "Loatheb", |
["Maexxna"] = "Maexxna", |
["Noth the Plaguebringer"] = "Noth der Seuchenfürst", |
["Patchwerk"] = "Flickwerk", |
["Sapphiron"] = "Saphiron", |
["Sir Zeliek"] = "Sire Zeliek", |
["Stalagg"] = "Stalagg", |
["Thaddius"] = "Thaddius", |
["Thane Korth'azz"] = "Thane Korth'azz", |
["The Four Horsemen"] = "Die Vier Reiter", |
--Onyxia's Lair |
["Onyxia"] = "Onyxia", |
--Ragefire Chasm |
["Bazzalan"] = "Bazzalan", |
["Jergosh the Invoker"] = "Jergosh der Herbeirufer", |
["Maur Grimtotem"] = "Maur Grimmtotem", |
["Taragaman the Hungerer"] = "Taragaman der Hungerleider", |
--Razorfen Downs |
["Amnennar the Coldbringer"] = "Amnennar der Kältebringer", |
["Glutton"] = "Nimmersatt", |
["Mordresh Fire Eye"] = "Mordresh Feuerauge", |
["Plaguemaw the Rotting"] = "Seuchenschlund der Faulende", |
["Ragglesnout"] = "Struppmähne", |
["Tuten'kash"] = "Tuten'kash", |
--Razorfen Kraul |
["Agathelos the Raging"] = "Agathelos der Tobende", |
["Blind Hunter"] = "Blinder Jäger", |
["Charlga Razorflank"] = "Charlga Klingenflanke", |
["Death Speaker Jargba"] = "Todessprecher Jargba", |
["Earthcaller Halmgar"] = "Erdenrufer Halmgar", |
["Overlord Ramtusk"] = "Oberanführer Rammhauer", |
--Ruins of Ahn'Qiraj |
["Anubisath Guardian"] = "Beschützer des Anubisath", |
["Ayamiss the Hunter"] = "Ayamiss der Jäger", |
["Buru the Gorger"] = "Buru der Verschlinger", |
["General Rajaxx"] = "General Rajaxx", |
["Kurinnaxx"] = "Kurinnaxx", |
["Lieutenant General Andorov"] = "Generallieutenant Andorov", |
["Moam"] = "Moam", |
["Ossirian the Unscarred"] = "Ossirian der Narbenlose", |
--Scarlet Monastery |
--Armory |
["Herod"] = "Herod", |
--Cathedral |
["High Inquisitor Fairbanks"] = "Hochinquisitor Fairbanks", |
["High Inquisitor Whitemane"] = "Hochinquisitor WeiÃsträhne", |
["Scarlet Commander Mograine"] = "Scharlachroter Kommandant Mograine", |
--Graveyard |
["Azshir the Sleepless"] = "Azshir der Schlaflose", |
["Bloodmage Thalnos"] = "Blutmagier Thalnos", |
["Fallen Champion"] = "Gestürzter Held", |
["Interrogator Vishas"] = "Befrager Vishas", |
["Ironspine"] = "Eisenrücken", |
["Headless Horseman"] = "Der kopflose Reiter", |
--Library |
["Arcanist Doan"] = "Arkanist Doan", |
["Houndmaster Loksey"] = "Hundemeister Loksey", |
--Scholomance |
["Blood Steward of Kirtonos"] = "Blutdiener von Kirtonos", |
["Darkmaster Gandling"] = "Dunkelmeister Gandling", |
["Death Knight Darkreaver"] = "Todesritter Schattensichel", |
["Doctor Theolen Krastinov"] = "Doktor Theolen Krastinov", |
["Instructor Malicia"] = "Instrukteurin Malicia", |
["Jandice Barov"] = "Jandice Barov", |
["Kirtonos the Herald"] = "Kirtonos der Herold", |
["Kormok"] = "Kormok", |
["Lady Illucia Barov"] = "Lady Illucia Barov", |
["Lord Alexei Barov"] = "Lord Alexei Barov", |
["Lorekeeper Polkelt"] = "Hüter des Wissens Polkelt", |
["Marduk Blackpool"] = "Marduk Blackpool", |
["Ras Frostwhisper"] = "Ras Frostraunen", |
["Rattlegore"] = "Blutrippe", |
["The Ravenian"] = "Der Ravenier", |
["Vectus"] = "Vectus", |
--Shadowfang Keep |
["Archmage Arugal"] = "Erzmagier Arugal", |
["Arugal's Voidwalker"] = "Arugals Leerwandler", |
["Baron Silverlaine"] = "Baron Silberlein", |
["Commander Springvale"] = "Kommandant Springvale", |
["Deathsworn Captain"] = "Todeshöriger Captain", |
["Fenrus the Devourer"] = "Fenrus der Verschlinger", |
["Odo the Blindwatcher"] = "Odo der Blindseher", |
["Razorclaw the Butcher"] = "Klingenklaue der Metzger", |
["Wolf Master Nandos"] = "Wolfmeister Nados", |
--Stratholme |
["Archivist Galford"] = "Archivar Galford", |
["Balnazzar"] = "Balnazzar", |
["Baron Rivendare"] = "Baron Totenschwur", |
["Baroness Anastari"] = "Baroness Anastari", |
["Black Guard Swordsmith"] = "Schwertschmied der schwarzen Wache", |
["Cannon Master Willey"] = "Kanonenmeister Willey", |
["Crimson Hammersmith"] = "Purpurroter Hammerschmied", |
["Fras Siabi"] = "Fras Siabi", |
["Hearthsinger Forresten"] = "Herdsinger Forresten", |
["Magistrate Barthilas"] = "Magistrat Barthilas", |
["Maleki the Pallid"] = "Maleki der Leichenblasse", |
["Nerub'enkan"] = "Nerub'enkan", |
["Postmaster Malown"] = "Postmeister Malown", |
["Ramstein the Gorger"] = "Ramstein der Verschlinger", |
["Skul"] = "Skul", |
["Stonespine"] = "Steinbuckel", |
["The Unforgiven"] = "Der Unverziehene", |
["Timmy the Cruel"] = "Timmy der Grausame", |
--Sunwell Plateau |
["Kalecgos"] = "Kalecgos", |
["Sathrovarr the Corruptor"] = "Sathrovarr der Verderber", |
["Brutallus"] = "Brutallus", |
["Felmyst"] = "Teufelsruch", |
["Kil'jaeden"] = "Kil'jaeden", |
["M'uru"] = "M'uru", |
["Entropius"] = "Entropius", |
["The Eredar Twins"] = "Die Eredar Zwillinge", |
["Lady Sacrolash"] = "Lady Sacrolash", |
["Grand Warlock Alythess"] = "GroÃhexenmeisterin Alythess", |
--Tempest Keep |
--The Arcatraz |
["Dalliah the Doomsayer"] = "Dalliah die Verdammnisverkünderin", |
["Harbinger Skyriss"] = "Herold Horizontiss", |
["Warden Mellichar"] = "Aufseher Mellichar", |
["Wrath-Scryer Soccothrates"] = "Zornseher Soccothrates", |
["Zereketh the Unbound"] = "Zereketh der Unabhängige", |
--The Botanica |
["Commander Sarannis"] = "Kommandant Sarannis", |
["High Botanist Freywinn"] = "Hochbotaniker Freywinn", |
["Laj"] = "Laj", |
["Thorngrin the Tender"] = "Dorngrin der Hüter", |
["Warp Splinter"] = "Warpzweig", |
--The Eye |
["Al'ar"] = "Al'ar", |
["Cosmic Infuser"] = "Kosmische Macht", |
["Devastation"] = "Verwüstung", |
["Grand Astromancer Capernian"] = "GroÃastronom Capernian", |
["High Astromancer Solarian"] = "Hochastromantin Solarian", |
["Infinity Blades"] = "Klinge der Unendlichkeit", |
["Kael'thas Sunstrider"] = "Kael'thas Sonnenwanderer", |
["Lord Sanguinar"] = "Fürst Blutdurst", |
["Master Engineer Telonicus"] = "Meisteringenieur Telonicus", |
["Netherstrand Longbow"] = "Netherbespannter Langbogen", |
["Phaseshift Bulwark"] = "Phasenverschobenes Bollwerk", |
["Solarium Agent"] = "Solarian Agent", |
["Solarium Priest"] = "Solarian Priester", |
["Staff of Disintegration"] = "Stab der Auflösung", |
["Thaladred the Darkener"] = "Thaladred der Verfinsterer", |
["Void Reaver"] = "Leerhäscher", |
["Warp Slicer"] = "Warpschnitter", |
--The Mechanar |
["Gatewatcher Gyro-Kill"] = "Torwächter Gyrotot", |
["Gatewatcher Iron-Hand"] = "Torwächter Eisenhand", |
["Mechano-Lord Capacitus"] = "Mechanolord Kapazitus", |
["Nethermancer Sepethrea"] = "Nethermant Sepethrea", |
["Pathaleon the Calculator"] = "Pathaleon der Kalkulator", |
--The Deadmines |
["Brainwashed Noble"] = "Manipulierter Adliger", |
["Captain Greenskin"] = "Kapitän Grünhaut", |
["Cookie"] = "Krümel", |
["Edwin VanCleef"] = "Edwin van Cleef", |
["Foreman Thistlenettle"] = "GroÃknecht Distelklette", |
["Gilnid"] = "Gilnid", |
["Marisa du'Paige"] = "Marisa du'Paige", |
["Miner Johnson"] = "Minenarbeiter Johnson", |
["Mr. Smite"] = "Handlanger Pein", |
["Rhahk'Zor"] = "Rhahk'Zor", |
["Sneed"] = "Sneed", |
["Sneed's Shredder"] = "Sneeds Schredder", |
--The Stockade |
["Bazil Thredd"] = "Bazil Thredd", |
["Bruegal Ironknuckle"] = "Bruegal Eisenfaust", |
["Dextren Ward"] = "Dextren Ward", |
["Hamhock"] = "Hamhock", |
["Kam Deepfury"] = "Kam Tiefenzorn", |
["Targorr the Dread"] = "Targorr der Schreckliche", |
--The Temple of Atal'Hakkar |
["Atal'alarion"] = "Atal'alarion", |
["Avatar of Hakkar"] = "Avatar von Hakkar", |
["Dreamscythe"] = "Traumsense", |
["Gasher"] = "Schlitzer", |
["Hazzas"] = "Hazzas", |
["Hukku"] = "Hukku", |
["Jade"] = "Jade", |
["Jammal'an the Prophet"] = "Jammal'an der Prophet", |
["Kazkaz the Unholy"] = "Kazkaz der Unheilige", |
["Loro"] = "Loro", |
["Mijan"] = "Mijan", |
["Morphaz"] = "Morphaz", |
["Ogom the Wretched"] = "Ogom der Elende", |
["Shade of Eranikus"] = "Eranikus' Schemen", |
["Veyzhak the Cannibal"] = "Veyzhack der Kannibale", |
["Weaver"] = "Wirker", |
["Zekkis"] = "Zekkis", |
["Zolo"] = "Zolo", |
["Zul'Lor"] = "Zul'Lor", |
--Uldaman |
["Ancient Stone Keeper"] = "Uralter Steinbewahrer", |
["Archaedas"] = "Archaedas", |
["Baelog"] = "Baelog", |
["Digmaster Shovelphlange"] = "Grubenmeister Schaufelphlansch", |
["Galgann Firehammer"] = "Galgann Feuerhammer", |
["Grimlok"] = "Grimlok", |
["Ironaya"] = "Ironaya", |
["Obsidian Sentinel"] = "Obsidianschildwache", |
["Revelosh"] = "Revelosh", |
--Wailing Caverns |
["Boahn"] = "Boahn", |
["Deviate Faerie Dragon"] = "Deviatfeendrache", |
["Kresh"] = "Kresh", |
["Lady Anacondra"] = "Lady Anacondra", |
["Lord Cobrahn"] = "Lord Kobrahn", |
["Lord Pythas"] = "Lord Pythas", |
["Lord Serpentis"] = "Lord Serpentis", |
["Mad Magglish"] = "Zausel der Verrückte", |
["Mutanus the Devourer"] = "Mutanus der Verschlinger", |
["Skum"] = "Skum", |
["Trigore the Lasher"] = "Trigore der Peitscher", |
["Verdan the Everliving"] = "Verdan der Ewiglebende", |
--World Bosses |
["Avalanchion"] = "Avalanchion", |
["Azuregos"] = "Azuregos", |
["Baron Charr"] = "Baron Glutarr", |
["Baron Kazum"] = "Baron Kazum", |
["Doom Lord Kazzak"] = "Verdammnislord Kazzak", |
["Doomwalker"] = "Verdammniswandler", |
["Emeriss"] = "Smariss", |
["High Marshal Whirlaxis"] = "Hochmarschall Whirlaxis", |
["Lethon"] = "Lethon", |
["Lord Skwol"] = "Lord Skwol", |
["Prince Skaldrenox"] = "Prince Skaldrenox", |
["Princess Tempestria"] = "Prinzessin Tempestria", |
["Taerar"] = "Taerar", |
["The Windreaver"] = "Der Windhäscher", |
["Ysondre"] = "Ysondre", |
--Zul'Aman |
["Akil'zon"] = "Akil'zon", |
["Halazzi"] = "Halazzi", |
["Jan'alai"] = "Jan'alai", |
["Malacrass"] = "Malacrass", |
["Nalorakk"] = "Nalorakk", |
["Zul'jin"] = "Zul'jin", |
["Hex Lord Malacrass"] = "Hexlord Malacrass", |
--Zul'Farrak |
["Antu'sul"] = "Antu'sul", |
["Chief Ukorz Sandscalp"] = "Häuptling Ukorz Sandwüter", |
["Dustwraith"] = "Karaburan", |
["Gahz'rilla"] = "Gahz'rilla", |
["Hydromancer Velratha"] = "Wasserbeschwörerin Velratha", |
["Murta Grimgut"] = "Murta Bauchgrimm", |
["Nekrum Gutchewer"] = "Nekrum der Ausweider", |
["Oro Eyegouge"] = "Oro Hohlauge", |
["Ruuzlu"] = "Ruuzlu", |
["Sandarr Dunereaver"] = "Sandarr der Wüstenräuber", |
["Sandfury Executioner"] = "Henker der Sandwüter", |
["Sergeant Bly"] = "Unteroffizier Bly", |
["Shadowpriest Sezz'ziz"] = "Schattenpriester Sezz'ziz", |
["Theka the Martyr"] = "Theka der Märtyrer", |
["Witch Doctor Zum'rah"] = "Hexendoktor Zum'rah" , |
["Zerillis"] = "Zerillis", |
["Zul'Farrak Dead Hero"] = "Untoter Held aus Zul'Farrak", |
--Zul'Gurub |
["Bloodlord Mandokir"] = "Blutfürst Mandokir", |
["Gahz'ranka"] = "Gahz'ranka", |
["Gri'lek"] = "Gri'lek", |
["Hakkar"] = "Hakkar", |
["Hazza'rah"] = "Hazza'rah", |
["High Priest Thekal"] = "Hohepriester Thekal", |
["High Priest Venoxis"] = "Hohepriester Venoxis", |
["High Priestess Arlokk"] = "Hohepriesterin Arlokk", |
["High Priestess Jeklik"] = "Hohepriesterin Jeklik", |
["High Priestess Mar'li"] = "Hohepriesterin Mar'li", |
["Jin'do the Hexxer"] = "Jin'do der Verhexer", |
["Renataki"] = "Renataki", |
["Wushoolay"] = "Wushoolay", |
--Ring of Blood (where? an instnace? should be in other file?) |
["Brokentoe"] = "Schmetterzehe", |
["Mogor"] = "Mogor", |
["Murkblood Twin"] = "Zwilling der Finsterblut", |
["Murkblood Twins"] = "Zwillinge der Finsterblut", |
["Rokdar the Sundered Lord"] = "Rokdar der Zerklüftete", |
["Skra'gath"] = "Skra'gath", |
["The Blue Brothers"] = "Die Blaumänner", |
["Warmaul Champion"] = "Champion der Totschläger", |
} |
elseif GAME_LOCALE == "frFR" then |
lib:SetCurrentTranslations { |
--Ahn'Qiraj |
["Anubisath Defender"] = "Défenseur Anubisath", |
["Battleguard Sartura"] = "Garde de guerre Sartura", |
["C'Thun"] = "C'Thun", |
["Emperor Vek'lor"] = "Empereur Vek'lor", |
["Emperor Vek'nilash"] = "Empereur Vek'nilash", |
["Eye of C'Thun"] = "Åil de C'Thun", |
["Fankriss the Unyielding"] = "Fankriss l'Inflexible", |
["Lord Kri"] = "Seigneur Kri", |
["Ouro"] = "Ouro", |
["Princess Huhuran"] = "Princesse Huhuran", |
["Princess Yauj"] = "Princesse Yauj", |
["The Bug Family"] = "La famille insecte", |
["The Prophet Skeram"] = "Le Prophète Skeram", |
["The Twin Emperors"] = "Les Empereurs jumeaux", |
["Vem"] = "Vem", |
["Viscidus"] = "Viscidus", |
--Auchindoun |
--Auchenai Crypts |
["Exarch Maladaar"] = "Exarque Maladaar", |
["Shirrak the Dead Watcher"] = "Shirrak le Veillemort", |
--Mana-Tombs |
["Nexus-Prince Shaffar"] = "Prince-nexus Shaffar", |
["Pandemonius"] = "Pandemonius", |
["Tavarok"] = "Tavarok", |
--Shadow Labyrinth |
["Ambassador Hellmaw"] = "Ambassadeur Gueule-d'enfer", |
["Blackheart the Inciter"] = "Coeur-noir le Séditieux", |
["Grandmaster Vorpil"] = "Grand Maître Vorpil", |
["Murmur"] = "Marmon", |
--Sethekk Halls |
["Anzu"] = "Anzu", |
["Darkweaver Syth"] = "Tisseur d'ombre Syth", |
["Talon King Ikiss"] = "Roi-serre Ikiss", |
--Blackfathom Deeps |
["Aku'mai"] = "Aku'mai", |
["Baron Aquanis"] = "Baron Aquanis", |
["Gelihast"] = "Gelihast", |
["Ghamoo-ra"] = "Ghamoo-ra", |
["Lady Sarevess"] = "Dame Sarevess", |
["Old Serra'kis"] = "Vieux Serra'kis", |
["Twilight Lord Kelris"] = "Seigneur du crépuscule Kelris", |
--Blackrock Depths |
["Ambassador Flamelash"] = "Ambassadeur Cinglefouet", |
["Anger'rel"] = "Colé'rel", |
["Anub'shiah"] = "Anub'shiah", |
["Bael'Gar"] = "Bael'Gar", |
["Chest of The Seven"] = "Coffre des sept", |
["Doom'rel"] = "Tragi'rel", |
["Dope'rel"] = "Demeu'rel", |
["Emperor Dagran Thaurissan"] = "Empereur Dagran Thaurissan", |
["Eviscerator"] = "Eviscérateur", |
["Fineous Darkvire"] = "Fineous Sombrevire", |
["General Angerforge"] = "Général Forgehargne", |
["Gloom'rel"] = "Funéb'rel", |
["Golem Lord Argelmach"] = "Seigneur golem Argelmach", |
["Gorosh the Dervish"] = "Gorosh le Derviche", |
["Grizzle"] = "Grison", |
["Hate'rel"] = "Haine'rel", |
["Hedrum the Creeper"] = "Hedrum le Rampant", |
["High Interrogator Gerstahn"] = "Grand Interrogateur Gerstahn", |
["High Priestess of Thaurissan"] = "Grande prêtresse de Thaurissan", |
["Houndmaster Grebmar"] = "Maître-chien Grebmar", |
["Hurley Blackbreath"] = "Hurley Soufflenoir", |
["Lord Incendius"] = "Seigneur Incendius", |
["Lord Roccor"] = "Seigneur Roccor", |
["Magmus"] = "Magmus", |
["Ok'thor the Breaker"] = "Ok'thor le Briseur", |
["Panzor the Invincible"] = "Panzor l'Invincible", |
["Phalanx"] = "Phalange", |
["Plugger Spazzring"] = "Lanfiche Brouillecircuit", |
["Princess Moira Bronzebeard"] = "Princesse Moira Barbe-de-bronze", |
["Pyromancer Loregrain"] = "Pyromancien Blé-du-savoir", |
["Ribbly Screwspigot"] = "Ribbly Fermevanne", |
["Seeth'rel"] = "Fulmi'rel", |
["The Seven Dwarves"] = "Les sept nains", |
["Verek"] = "Verek", |
["Vile'rel"] = "Ignobl'rel", |
["Warder Stilgiss"] = "Gardien Stilgiss", |
--Blackrock Spire |
--Lower |
["Bannok Grimaxe"] = "Bannok Hache-sinistre", |
["Burning Felguard"] = "Gangregarde ardent", |
["Crystal Fang"] = "Croc cristallin", |
["Ghok Bashguud"] = "Ghok Bounnebaffe", |
["Gizrul the Slavener"] = "Gizrul l'esclavagiste", |
["Halycon"] = "Halycon", |
["Highlord Omokk"] = "Généralissime Omokk", |
["Mor Grayhoof"] = "Mor Sabot-gris", |
["Mother Smolderweb"] = "Matriarche Couveuse", |
["Overlord Wyrmthalak"] = "Seigneur Wyrmthalak", |
["Quartermaster Zigris"] = "Intendant Zigris", |
["Shadow Hunter Vosh'gajin"] = "Chasseresse des ombres Vosh'gajin", |
["Spirestone Battle Lord"] = "Seigneur de bataille Pierre-du-pic", |
["Spirestone Butcher"] = "Boucher Pierre-du-pic", |
["Spirestone Lord Magus"] = "Seigneur magus Pierre-du-pic", |
["Urok Doomhowl"] = "Urok Hurleruine", |
["War Master Voone"] = "Maître de guerre Voone", |
--Upper |
["General Drakkisath"] = "Général Drakkisath", |
["Goraluk Anvilcrack"] = "Goraluk Brisenclume", |
["Gyth"] = "Gyth", |
["Jed Runewatcher"] = "Jed Guette-runes", |
["Lord Valthalak"] = "Seigneur Valthalak", |
["Pyroguard Emberseer"] = "Pyrogarde Prophète ardent", |
["Solakar Flamewreath"] = "Solakar Voluteflamme", |
["The Beast"] = "La Bête", |
["Warchief Rend Blackhand"] = "Chef de guerre Rend Main-noire", |
--Blackwing Lair |
["Broodlord Lashlayer"] = "Seigneur des couvées Lanistaire", |
["Chromaggus"] = "Chromaggus", |
["Ebonroc"] = "Rochébène", |
["Firemaw"] = "Gueule-de-feu", |
["Flamegor"] = "Flamegor", |
["Grethok the Controller"] = "Grethok le Contrôleur", |
["Lord Victor Nefarius"] = "Seigneur Victor Nefarius", |
["Nefarian"] = "Nefarian", |
["Razorgore the Untamed"] = "Tranchetripe l'Indompté", |
["Vaelastrasz the Corrupt"] = "Vaelastrasz le Corrompu", |
--Black Temple |
["Essence of Anger"] = "Essence de la colère", |
["Essence of Desire"] = "Essence du désir", |
["Essence of Suffering"] = "Essence de la souffrance", |
["Gathios the Shatterer"] = "Gathios le Briseur", |
["Gurtogg Bloodboil"] = "Gurtogg Fièvresang", |
["High Nethermancer Zerevor"] = "Grand néantomancien Zerevor", |
["High Warlord Naj'entus"] = "Grand seigneur de guerre Naj'entus", |
["Illidan Stormrage"] = "Illidan Hurlorage", |
["Illidari Council"] = "Conseil illidari", |
["Lady Malande"] = "Dame Malande", |
["Mother Shahraz"] = "Mère Shahraz", |
["Reliquary of Souls"] = "Le reliquaire des âmes", |
["Shade of Akama"] = "Ombre d'Akama", |
["Supremus"] = "Supremus", |
["Teron Gorefiend"] = "Teron Fielsang", |
["The Illidari Council"] = "Le conseil illidari", |
["Veras Darkshadow"] = "Veras Ombrenoir", |
--Caverns of Time |
--Old Hillsbrad Foothills |
["Captain Skarloc"] = "Capitaine Skarloc", |
["Epoch Hunter"] = "Chasseur d'époques", |
["Lieutenant Drake"] = "Lieutenant Drake", |
--The Black Morass |
["Aeonus"] = "Aeonus", |
["Chrono Lord Deja"] = "Chronoseigneur Déjà ", |
["Medivh"] = "Medivh", |
["Temporus"] = "Temporus", |
--Coilfang Reservoir |
--Serpentshrine Cavern |
["Coilfang Elite"] = "Elite de Glissecroc", |
["Coilfang Strider"] = "Trotteur de Glissecroc", |
["Fathom-Lord Karathress"] = "Seigneur des fonds Karathress", |
["Hydross the Unstable"] = "Hydross l'Instable", |
["Lady Vashj"] = "Dame Vashj", |
["Leotheras the Blind"] = "Leotheras l'Aveugle", |
["Morogrim Tidewalker"] = "Morogrim Marcheur-des-flots", |
["Pure Spawn of Hydross"] = "Pur rejeton d'Hydross", |
["Shadow of Leotheras"] = "Ombre de Leotheras", |
["Tainted Spawn of Hydross"] = "Rejeton d'Hydross souillé", |
["The Lurker Below"] = "Le Rôdeur d'En bas", |
["Tidewalker Lurker"] = "Rôdeur marcheur-des-flots", |
--The Slave Pens |
["Ahune"] = "Ahune", |
["Mennu the Betrayer"] = "Mennu le Traître", |
["Quagmirran"] = "Bourbierreux", |
["Rokmar the Crackler"] = "Rokmar le Crépitant", |
--The Steamvault |
["Hydromancer Thespia"] = "Hydromancienne Thespia", |
["Mekgineer Steamrigger"] = "Mékgénieur Montevapeur", |
["Warlord Kalithresh"] = "Seigneur de guerre Kalithresh", |
--The Underbog |
["Claw"] = "Griffe", |
["Ghaz'an"] = "Ghaz'an", |
["Hungarfen"] = "Hungarfen", |
["Overseer Tidewrath"] = "Surveillant Tidewrath", |
["Swamplord Musel'ek"] = "Seigneur des marais Musel'ek", |
["The Black Stalker"] = "La Traqueuse noire", |
--Dire Maul |
--Arena |
["Mushgog"] = "Mushgog", |
["Skarr the Unbreakable"] = "Bâlhafr l'Invaincu", |
["The Razza"] = "La Razza", |
--East |
["Alzzin the Wildshaper"] = "Alzzin le Modeleur", |
["Hydrospawn"] = "Hydrogénos", |
["Isalien"] = "Isalien", |
["Lethtendris"] = "Lethtendris", |
["Pimgib"] = "Pimgib", |
["Pusillin"] = "Pusillin", |
["Zevrim Thornhoof"] = "Zevrim Sabot-de-ronce", |
--North |
["Captain Kromcrush"] = "Capitaine Kromcrush", |
["Cho'Rush the Observer"] = "Cho'Rush l'Observateur", |
["Guard Fengus"] = "Garde Fengus", |
["Guard Mol'dar"] = "Garde Mol'dar", |
["Guard Slip'kik"] = "Garde Slip'kik", |
["King Gordok"] = "Roi Gordok", |
["Knot Thimblejack's Cache"] = "Réserve de Noué Dédodevie", |
["Stomper Kreeg"] = "Kreeg le Marteleur", |
--West |
["Illyanna Ravenoak"] = "Illyanna Corvichêne", |
["Immol'thar"] = "Immol'thar", |
["Lord Hel'nurath"] = "Seigneur Hel'nurath", |
["Magister Kalendris"] = "Magistère Kalendris", |
["Prince Tortheldrin"] = "Prince Tortheldrin", |
["Tendris Warpwood"] = "Tendris Crochebois", |
["Tsu'zee"] = "Tsu'zee", |
--Gnomeregan |
["Crowd Pummeler 9-60"] = "Faucheur de foule 9-60", |
["Dark Iron Ambassador"] = "Ambassadeur Sombrefer", |
["Electrocutioner 6000"] = "Electrocuteur 6000", |
["Grubbis"] = "Grubbis", |
["Mekgineer Thermaplugg"] = "Mekgénieur Thermojoncteur", |
["Techbot"] = "Techbot", |
["Viscous Fallout"] = "Retombée visqueuse", |
--Gruul's Lair |
["Blindeye the Seer"] = "Oeillaveugle le Voyant", |
["Gruul the Dragonkiller"] = "Gruul le Tue-dragon", |
["High King Maulgar"] = "Haut Roi Maulgar", |
["Kiggler the Crazed"] = "Kiggler le Cinglé", |
["Krosh Firehand"] = "Krosh Brasemain", |
["Olm the Summoner"] = "Olm l'Invocateur", |
--Hellfire Citadel |
--Hellfire Ramparts |
["Nazan"] = "Nazan", |
["Omor the Unscarred"] = "Omor l'Intouché", |
["Vazruden the Herald"] = "Vazruden le Héraut", |
["Vazruden"] = "Vazruden", |
["Watchkeeper Gargolmar"] = "Gardien des guetteurs Gargolmar", |
--Magtheridon's Lair |
["Hellfire Channeler"] = "Canaliste des Flammes infernales", |
["Magtheridon"] = "Magtheridon", |
--The Blood Furnace |
["Broggok"] = "Broggok", |
["Keli'dan the Breaker"] = "Keli'dan le Briseur", |
["The Maker"] = "Le Faiseur", |
--The Shattered Halls |
["Blood Guard Porung"] = "Garde de sang Porung", |
["Grand Warlock Nethekurse"] = "Grand démoniste Néanathème", |
["Warbringer O'mrogg"] = "Porteguerre O'mrogg", |
["Warchief Kargath Bladefist"] = "Chef de guerre Kargath Lamepoing", |
--Hyjal Summit |
["Anetheron"] = "Anetheron", |
["Archimonde"] = "Archimonde", |
["Azgalor"] = "Azgalor", |
["Kaz'rogal"] = "Kaz'rogal", |
["Rage Winterchill"] = "Rage Froidhiver", |
--Karazhan |
["Arcane Watchman"] = "Veilleur arcanique", |
["Attumen the Huntsman"] = "Attumen le Veneur", |
["Chess Event"] = "Partie d'échec", |
["Dorothee"] = "Dorothée", |
["Dust Covered Chest"] = "Coffre couvert de poussière", |
["Grandmother"] = "Mère-grand", |
["Hyakiss the Lurker"] = "Hyakiss le rôdeur", |
["Julianne"] = "Julianne", |
["Kil'rek"] = "Kil'rek", |
["King Llane Piece"] = "Pion du Roi Llane", |
["Maiden of Virtue"] = "Damoiselle de vertu", |
["Midnight"] = "Minuit", |
["Moroes"] = "Moroes", |
["Netherspite"] = "Dédain-du-Néant", |
["Nightbane"] = "Plaie-de-nuit", |
["Prince Malchezaar"] = "Prince Malchezaar", |
["Restless Skeleton"] = "Squelette sans repos", |
["Roar"] = "Graou", |
["Rokad the Ravager"] = "Rodak le ravageur", |
["Romulo & Julianne"] = "Romulo & Julianne", |
["Romulo"] = "Romulo", |
["Shade of Aran"] = "Ombre d'Aran", |
["Shadikith the Glider"] = "Shadikith le glisseur", |
["Strawman"] = "Homme de paille", |
["Terestian Illhoof"] = "Terestian Malsabot", |
["The Big Bad Wolf"] = "Le Grand Méchant Loup", |
["The Crone"] = "La Mégère", |
["The Curator"] = "Le conservateur", |
["Tinhead"] = "Tête de fer-blanc", |
["Tito"] = "Tito", |
["Warchief Blackhand Piece"] = "Pion du Chef de guerre Main-noire", |
-- Magisters' Terrace |
--["Kael'thas Sunstrider"] = "Kael'thas Haut-soleil", |
["Priestess Delrissa"] = "Prêtresse Delrissa", |
["Selin Fireheart"] = "Selin Coeur-de-feu", |
["Vexallus"] = "Vexallus", |
--Maraudon |
["Celebras the Cursed"] = "Celebras le Maudit", |
["Gelk"] = "Gelk", |
["Kolk"] = "Kolk", |
["Landslide"] = "Glissement de terrain", |
["Lord Vyletongue"] = "Seigneur Vylelangue", |
["Magra"] = "Magra", |
["Maraudos"] = "Maraudos", |
["Meshlok the Harvester"] = "Meshlok le Moissonneur", |
["Noxxion"] = "Noxcion", |
["Princess Theradras"] = "Princesse Theradras", |
["Razorlash"] = "Tranchefouet", |
["Rotgrip"] = "Grippe-charogne", |
["Tinkerer Gizlock"] = "Bricoleur Kadenaz", |
["Veng"] = "Veng", |
--Molten Core |
["Baron Geddon"] = "Baron Geddon", |
["Cache of the Firelord"] = "Cachette du Seigneur du feu", |
["Garr"] = "Garr", |
["Gehennas"] = "Gehennas", |
["Golemagg the Incinerator"] = "Golemagg l'Incinérateur", |
["Lucifron"] = "Lucifron", |
["Magmadar"] = "Magmadar", |
["Majordomo Executus"] = "Chambellan Executus", |
["Ragnaros"] = "Ragnaros", |
["Shazzrah"] = "Shazzrah", |
["Sulfuron Harbinger"] = "Messager de Sulfuron", |
--Naxxramas |
["Anub'Rekhan"] = "Anub'Rekhan", |
["Deathknight Understudy"] = "Doublure de chevalier de la mort", |
["Feugen"] = "Feugen", |
["Four Horsemen Chest"] = "Coffre des quatre cavaliers", |
["Gluth"] = "Gluth", |
["Gothik the Harvester"] = "Gothik le Moissonneur", |
["Grand Widow Faerlina"] = "Grande veuve Faerlina", |
["Grobbulus"] = "Grobbulus", |
["Heigan the Unclean"] = "Heigan l'Impur", |
["Highlord Mograine"] = "Généralissime Mograine", |
["Instructor Razuvious"] = "Instructeur Razuvious", |
["Kel'Thuzad"] = "Kel'Thuzad", |
["Lady Blaumeux"] = "Dame Blaumeux", |
["Loatheb"] = "Horreb", |
["Maexxna"] = "Maexxna", |
["Noth the Plaguebringer"] = "Noth le Porte-peste", |
["Patchwerk"] = "Le Recousu", |
["Sapphiron"] = "Saphiron", |
["Sir Zeliek"] = "Sire Zeliek", |
["Stalagg"] = "Stalagg", |
["Thaddius"] = "Thaddius", |
["Thane Korth'azz"] = "Thane Korth'azz", |
["The Four Horsemen"] = "Les quatre cavaliers", |
--Onyxia's Lair |
["Onyxia"] = "Onyxia", |
--Ragefire Chasm |
["Bazzalan"] = "Bazzalan", |
["Jergosh the Invoker"] = "Jergosh l'Invocateur", |
["Maur Grimtotem"] = "Maur Totem-sinistre", |
["Taragaman the Hungerer"] = "Taragaman l'Affameur", |
--Razorfen Downs |
["Amnennar the Coldbringer"] = "Amnennar le Porte-froid", |
["Glutton"] = "Glouton", |
["Mordresh Fire Eye"] = "Mordresh Oeil-de-feu", |
["Plaguemaw the Rotting"] = "Pestegueule le Pourrissant", |
["Ragglesnout"] = "Groinfendu", |
["Tuten'kash"] = "Tuten'kash", |
--Razorfen Kraul |
["Agathelos the Raging"] = "Agathelos le Déchaîné", |
["Blind Hunter"] = "Chasseur aveugle", |
["Charlga Razorflank"] = "Charlga Trancheflanc", |
["Death Speaker Jargba"] = "Nécrorateur Jargba", |
["Earthcaller Halmgar"] = "Implorateur de la terre Halmgar", |
["Overlord Ramtusk"] = "Seigneur Brusquebroche", |
--Ruins of Ahn'Qiraj |
["Anubisath Guardian"] = "Gardien Anubisath", |
["Ayamiss the Hunter"] = "Ayamiss le Chasseur", |
["Buru the Gorger"] = "Buru Grandgosier", |
["General Rajaxx"] = "Général Rajaxx", |
["Kurinnaxx"] = "Kurinnaxx", |
["Lieutenant General Andorov"] = "Général de division Andorov", |
["Moam"] = "Moam", |
["Ossirian the Unscarred"] = "Ossirian l'Intouché", |
--Scarlet Monastery |
--Armory |
["Herod"] = "Hérode", |
--Cathedral |
["High Inquisitor Fairbanks"] = "Grand Inquisiteur Fairbanks", |
["High Inquisitor Whitemane"] = "Grand Inquisiteur Blanchetête", |
["Scarlet Commander Mograine"] = "Commandant écarlate Mograine", |
--Graveyard |
["Azshir the Sleepless"] = "Azshir le Sans-sommeil", |
["Bloodmage Thalnos"] = "Mage de sang Thalnos", |
["Fallen Champion"] = "Champion mort", |
["Headless Horseman"] = "Cavalier sans tête", |
["Interrogator Vishas"] = "Interrogateur Vishas", |
["Ironspine"] = "Echine-de-fer", |
--Library |
["Arcanist Doan"] = "Arcaniste Doan", |
["Houndmaster Loksey"] = "Maître-chien Loksey", |
--Scholomance |
["Blood Steward of Kirtonos"] = "Régisseuse sanglante de Kirtonos", |
["Darkmaster Gandling"] = "Sombre Maître Gandling", |
["Death Knight Darkreaver"] = "Chevalier de la mort Ravassombre", |
["Doctor Theolen Krastinov"] = "Docteur Theolen Krastinov", |
["Instructor Malicia"] = "Instructeur Malicia", |
["Jandice Barov"] = "Jandice Barov", |
["Kirtonos the Herald"] = "Kirtonos le Héraut", |
["Kormok"] = "Kormok", |
["Lady Illucia Barov"] = "Dame Illucia Barov", |
["Lord Alexei Barov"] = "Seigneur Alexei Barov", |
["Lorekeeper Polkelt"] = "Gardien du savoir Polkelt", |
["Marduk Blackpool"] = "Marduk Noirétang", |
["Ras Frostwhisper"] = "Ras Murmegivre", |
["Rattlegore"] = "Cliquettripes", |
["The Ravenian"] = "Le Voracien", |
["Vectus"] = "Vectus", |
--Shadowfang Keep |
["Archmage Arugal"] = "Archimage Arugal", |
["Arugal's Voidwalker"] = "Marcheur du Vide d'Arugal", |
["Baron Silverlaine"] = "Baron d'Argelaine", |
["Commander Springvale"] = "Commandant Springvale", |
["Deathsworn Captain"] = "Capitaine Ligemort", |
["Fenrus the Devourer"] = "Fenrus le Dévoreur", |
["Odo the Blindwatcher"] = "Odo l'Aveugle", |
["Razorclaw the Butcher"] = "Tranchegriffe le Boucher", |
["Wolf Master Nandos"] = "Maître-loup Nandos", |
--Stratholme |
["Archivist Galford"] = "Archiviste Galford", |
["Balnazzar"] = "Balnazzar", |
["Baron Rivendare"] = "Baron Vaillefendre", |
["Baroness Anastari"] = "Baronne Anastari", |
["Black Guard Swordsmith"] = "Fabricant d'épées de la Garde noire", |
["Cannon Master Willey"] = "Maître canonnier Willey", |
["Crimson Hammersmith"] = "Forgeur de marteaux cramoisi", |
["Fras Siabi"] = "Fras Siabi", |
["Hearthsinger Forresten"] = "Chanteloge Forrestin", |
["Magistrate Barthilas"] = "Magistrat Barthilas", |
["Maleki the Pallid"] = "Maleki le Blafard", |
["Nerub'enkan"] = "Nerub'enkan", |
["Postmaster Malown"] = "Postier Malown", |
["Ramstein the Gorger"] = "Ramstein Grandgosier", |
["Skul"] = "Krân", |
["Stonespine"] = "Echine-de-pierre", |
["The Unforgiven"] = "Le Condamné", |
["Timmy the Cruel"] = "Timmy le Cruel", |
--Sunwell Plateau |
["Kalecgos"] = "Kalecgos", |
["Sathrovarr the Corruptor"] = "Sathrovarr le Corrupteur", |
["Brutallus"] = "Brutallus", |
["Felmyst"] = "Gangrebrume", |
["Kil'jaeden"] = "Kil'jaeden", |
["M'uru"] = "M'uru", |
["Entropius"] = "Entropius", |
["The Eredar Twins"] = "Les jumelles érédars", |
["Lady Sacrolash"] = "Dame Sacrocingle", |
["Grand Warlock Alythess"] = "Grande démoniste Alythess", |
--Tempest Keep |
--The Arcatraz |
["Dalliah the Doomsayer"] = "Dalliah l'Auspice-funeste", |
["Harbinger Skyriss"] = "Messager Cieuriss", |
["Warden Mellichar"] = "Gardien Mellichar", |
["Wrath-Scryer Soccothrates"] = "Scrute-courroux Soccothrates", |
["Zereketh the Unbound"] = "Zereketh le Délié", |
--The Botanica |
["Commander Sarannis"] = "Commandant Sarannis", |
["High Botanist Freywinn"] = "Grand botaniste Freywinn", |
["Laj"] = "Laj", |
["Thorngrin the Tender"] = "Rirépine le Tendre", |
["Warp Splinter"] = "Brise-dimension", |
--The Eye |
["Al'ar"] = "Al'ar", |
["Cosmic Infuser"] = "Masse d'infusion cosmique", |
["Devastation"] = "Dévastation", |
["Grand Astromancer Capernian"] = "Grande astromancienne Capernian", |
["High Astromancer Solarian"] = "Grande astromancienne Solarian", |
["Infinity Blades"] = "Lames d'infinité", |
["Kael'thas Sunstrider"] = "Kael'thas Haut-soleil", |
["Lord Sanguinar"] = "Seigneur Sanguinar", |
["Master Engineer Telonicus"] = "Maître ingénieur Telonicus", |
["Netherstrand Longbow"] = "Arc long brins-de-Néant", |
["Phaseshift Bulwark"] = "Rempart de déphasage", |
["Solarium Agent"] = "Agent du Solarium", |
["Solarium Priest"] = "Prêtre du Solarium", |
["Staff of Disintegration"] = "Bâton de désintégration", |
["Thaladred the Darkener"] = "Thaladred l'Assombrisseur", |
["Void Reaver"] = "Saccageur du Vide", |
["Warp Slicer"] = "Tranchoir dimensionnel", |
--The Mechanar |
["Gatewatcher Gyro-Kill"] = "Gardien de porte Gyro-Meurtre", |
["Gatewatcher Iron-Hand"] = "Gardien de porte Main-en-fer", |
["Mechano-Lord Capacitus"] = "Mécano-seigneur Capacitus", |
["Nethermancer Sepethrea"] = "Néantomancien Sepethrea", |
["Pathaleon the Calculator"] = "Pathaleon le Calculateur", |
--The Deadmines |
["Brainwashed Noble"] = "Noble manipulé", |
["Captain Greenskin"] = "Capitaine Vertepeau", |
["Cookie"] = "Macaron", |
["Edwin VanCleef"] = "Edwin VanCleef", |
["Foreman Thistlenettle"] = "Contremaître Crispechardon", |
["Gilnid"] = "Gilnid", |
["Marisa du'Paige"] = "Marisa du'Paige", |
["Miner Johnson"] = "Mineur Johnson", |
["Mr. Smite"] = "M. Châtiment", |
["Rhahk'Zor"] = "Rhahk'Zor", |
["Sneed"] = "Sneed", |
["Sneed's Shredder"] = "Déchiqueteur de Sneed", |
--The Stockade |
["Bazil Thredd"] = "Bazil Thredd", |
["Bruegal Ironknuckle"] = "Bruegal Poing-de-fer", |
["Dextren Ward"] = "Dextren Ward", |
["Hamhock"] = "Hamhock", |
["Kam Deepfury"] = "Kam Furie-du-fond", |
["Targorr the Dread"] = "Targorr le Terrifiant", |
--The Temple of Atal'Hakkar |
["Atal'alarion"] = "Atal'alarion", |
["Avatar of Hakkar"] = "Avatar d'Hakkar", |
["Dreamscythe"] = "Fauche-rêve", |
["Gasher"] = "Gasher", |
["Hazzas"] = "Hazzas", |
["Hukku"] = "Hukku", |
["Jade"] = "Jade", |
["Jammal'an the Prophet"] = "Jammal'an le prophète", |
["Kazkaz the Unholy"] = "Kazkaz l'Impie", |
["Loro"] = "Loro", |
["Mijan"] = "Mijan", |
["Morphaz"] = "Morphaz", |
["Ogom the Wretched"] = "Ogom le Misérable", |
["Shade of Eranikus"] = "Ombre d'Eranikus", |
["Veyzhak the Cannibal"] = "Veyzhak le Cannibale", |
["Weaver"] = "Tisserand", |
["Zekkis"] = "Zekkis", |
["Zolo"] = "Zolo", |
["Zul'Lor"] = "Zul'Lor", |
--Uldaman |
["Ancient Stone Keeper"] = "Ancien Gardien des pierres", |
["Archaedas"] = "Archaedas", |
["Baelog"] = "Baelog", |
["Digmaster Shovelphlange"] = "Maître des fouilles Pellaphlange", |
["Galgann Firehammer"] = "Galgann Martel-de-feu", |
["Grimlok"] = "Grimlok", |
["Ironaya"] = "Ironaya", |
["Obsidian Sentinel"] = "Sentinelle d'obsidienne", |
["Revelosh"] = "Revelosh", |
--Wailing Caverns |
["Boahn"] = "Boahn", |
["Deviate Faerie Dragon"] = "Dragon féérique déviant", |
["Kresh"] = "Kresh", |
["Lady Anacondra"] = "Dame Anacondra", |
["Lord Cobrahn"] = "Seigneur Cobrahn", |
["Lord Pythas"] = "Seigneur Pythas", |
["Lord Serpentis"] = "Seigneur Serpentis", |
["Mad Magglish"] = "Magglish le Dingue", |
["Mutanus the Devourer"] = "Mutanus le Dévoreur", |
["Skum"] = "Skum", |
["Trigore the Lasher"] = "Trigore le Flagelleur", |
["Verdan the Everliving"] = "Verdan l'Immortel", |
--World Bosses |
["Avalanchion"] = "Avalanchion", |
["Azuregos"] = "Azuregos", |
["Baron Charr"] = "Baron Charr", |
["Baron Kazum"] = "Baron Kazum", |
["Doom Lord Kazzak"] = "Seigneur funeste Kazzak", |
["Doomwalker"] = "Marche-funeste", |
["Emeriss"] = "Emeriss", |
["High Marshal Whirlaxis"] = "Haut maréchal Trombe", |
["Lethon"] = "Léthon", |
["Lord Skwol"] = "Seigneur Skwol", |
["Prince Skaldrenox"] = "Prince Skaldrenox ", |
["Princess Tempestria"] = "Princesse Tempestria", |
["Taerar"] = "Taerar", |
["The Windreaver"] = "Ouraganien", |
["Ysondre"] = "Ysondre", |
--Zul'Aman |
["Akil'zon"] = "Akil'zon", |
["Halazzi"] = "Halazzi", |
["Jan'alai"] = "Jan'alai", |
["Malacrass"] = "Malacrass", |
["Nalorakk"] = "Nalorakk", |
["Zul'jin"] = "Zul'jin", |
["Hex Lord Malacrass"] = "Seigneur des maléfices Malacrass", |
--Zul'Farrak |
["Antu'sul"] = "Antu'sul", |
["Chief Ukorz Sandscalp"] = "Chef Ukorz Scalpessable", |
["Dustwraith"] = "Ame en peine poudreuse", |
["Gahz'rilla"] = "Gahz'rilla", |
["Hydromancer Velratha"] = "Hydromancienne Velratha", |
["Murta Grimgut"] = "Murta Mornentraille", |
["Nekrum Gutchewer"] = "Nekrum Mâchetripes", |
["Oro Eyegouge"] = "Oro Crève-oeil ", |
["Ruuzlu"] = "Ruuzlu", |
["Sandarr Dunereaver"] = "Sandarr Ravadune", |
["Sandfury Executioner"] = "Bourreau Furie-des-sables", |
["Sergeant Bly"] = "Sergent Bly", |
["Shadowpriest Sezz'ziz"] = "Prêtre des ombres Sezz'ziz", |
["Theka the Martyr"] = "Theka le Martyr", |
["Witch Doctor Zum'rah"] = "Sorcier-docteur Zum'rah", |
["Zerillis"] = "Zerillis", |
["Zul'Farrak Dead Hero"] = "Héros mort de Zul'Farrak", |
--Zul'Gurub |
["Bloodlord Mandokir"] = "Seigneur sanglant Mandokir", |
["Gahz'ranka"] = "Gahz'ranka", |
["Gri'lek"] = "Gri'lek", |
["Hakkar"] = "Hakkar", |
["Hazza'rah"] = "Hazza'rah", |
["High Priest Thekal"] = "Grand prêtre Thekal", |
["High Priest Venoxis"] = "Grand prêtre Venoxis", |
["High Priestess Arlokk"] = "Grande prêtresse Arlokk", |
["High Priestess Jeklik"] = "Grande prêtresse Jeklik", |
["High Priestess Mar'li"] = "Grande prêtresse Mar'li", |
["Jin'do the Hexxer"] = "Jin'do le Maléficieur", |
["Renataki"] = "Renataki", |
["Wushoolay"] = "Wushoolay", |
--Ring of Blood (where? an instance? should be in other file?) |
["Brokentoe"] = "Brisorteil", |
["Mogor"] = "Mogor", |
["Murkblood Twin"] = "Jumeau bourbesang", |
["Murkblood Twins"] = "Jumeaux bourbesang", |
["Rokdar the Sundered Lord"] = "Rokdar le Seigneur scindé", |
["Skra'gath"] = "Skra'gath", |
["The Blue Brothers"] = "Les Grands Bleus", |
["Warmaul Champion"] = "Champion Cogneguerre", |
} |
elseif GAME_LOCALE == "zhCN" then |
lib:SetCurrentTranslations { |
--Ahn'Qiraj |
["Anubisath Defender"] = "é¿åªæ¯è¨æ¯é²å¾¡è ", |
["Battleguard Sartura"] = "æ²å°å¾æ", |
["C'Thun"] = "å èæ©", |
["Emperor Vek'lor"] = "ç»´å æ´å°å¤§å¸", |
["Emperor Vek'nilash"] = "ç»´å å°¼ææ¯å¤§å¸", |
["Eye of C'Thun"] = "å èæ©ä¹ç¼", |
["Fankriss the Unyielding"] = "顽强çèå çæ¯", |
["Lord Kri"] = "å éåçµ", |
["Ouro"] = "奥ç½", |
["Princess Huhuran"] = "åéå °å ¬ä¸»", |
["Princess Yauj"] = "äºå°åºå ¬ä¸»", |
["The Bug Family"] = "è«åä¸å®¶", |
["The Prophet Skeram"] = "é¢è¨è æ¯å æå§", |
["The Twin Emperors"] = "ååçå¸", |
["Vem"] = "ç»´å§", |
["Viscidus"] = "ç»´å¸åº¦æ¯", |
--Auchindoun |
--Auchenai Crypts |
["Exarch Maladaar"] = "大主æçæè¾¾å°", |
["Shirrak the Dead Watcher"] = "æ»äº¡è§å¯è å¸å°æå ", |
--Mana-Tombs |
["Nexus-Prince Shaffar"] = "èç¹äº²çæ²æ³å°", |
["Pandemonius"] = "æ½å¾·è«åªæ¯", |
["Tavarok"] = "å¡ç¦æ´å ", |
--Shadow Labyrinth |
["Ambassador Hellmaw"] = "赫å°é»å¤§ä½¿", |
["Blackheart the Inciter"] = "ç ½å¨è å¸è±å¡ç¹", |
["Grandmaster Vorpil"] = "æ²å¹å°å¤§å¸", |
["Murmur"] = "æ©æ©å°", |
--Sethekk Halls |
["Anzu"] = "å®è", |
["Darkweaver Syth"] = "é»æç¼ç»è å¡æ¯", |
["Talon King Ikiss"] = "å©çªä¹çè¾åæ¯", |
--Blackfathom Deeps |
["Aku'mai"] = "é¿åºéº¦å°", |
["Baron Aquanis"] = "é¿å¥å°¼æ¯ç·çµ", |
["Gelihast"] = "æ ¼éåæ¯ç¹", |
["Ghamoo-ra"] = "å æ©æ", |
["Lady Sarevess"] = "è¨å©ç»´ä¸", |
["Old Serra'kis"] = "çæåæ¯", |
["Twilight Lord Kelris"] = "梦游è å å°éæ¯", |
--Blackrock Depths |
["Ambassador Flamelash"] = "å¼è±ææ¯å¤§ä½¿", |
["Anger'rel"] = "å®æ ¼é·å°", |
["Anub'shiah"] = "é¿åªå¸å°", |
["Bael'Gar"] = "è´å°å ", |
["Chest of The Seven"] = "ä¸è´¤ä¹ç®±",--ä¸è´¤çå®ç®± |
["Doom'rel"] = "æå§é·å°", |
["Dope'rel"] = "å¤æ®é·å°", |
["Emperor Dagran Thaurissan"] = "è¾¾æ ¼å °Â·ç´¢ç森大å¸", |
["Eviscerator"] = "åç¼è ", |
["Fineous Darkvire"] = "å¼è¯ºæ¯Â·è¾¾å ç»´å°", |
["General Angerforge"] = "å®æ ¼å¼å°å", |
["Gloom'rel"] = "æ ¼é²é·å°", |
["Golem Lord Argelmach"] = "åå¡ç»å¸ é¿æ ¼æ¼å¥", |
["Gorosh the Dervish"] = "ä¿®è¡è é«ç½ä»", |
["Grizzle"] = "æ ¼éå ¹å°", |
["Hate'rel"] = "é»ç¹é·å°", |
["Hedrum the Creeper"] = "ç¬è¡è 赫æå§", |
["High Interrogator Gerstahn"] = "审讯å®æ ¼æ¯å¡æ©", |
["High Priestess of Thaurissan"] = "ç´¢ç森é«é¶å¥³ç¥å¸", |
["Houndmaster Grebmar"] = "驯ç¬è æ ¼é·å¸çå°", |
["Hurley Blackbreath"] = "éå°é·Â·é»é¡»", |
["Lord Incendius"] = "ä¼æ£®è¿ªå¥¥æ¯", |
["Lord Roccor"] = "æ´èå°", |
["Magmus"] = "çæ ¼å§æ¯", |
["Ok'thor the Breaker"] = "ç ´åè 奥ç§ç´¢å°", |
["Panzor the Invincible"] = "æ æçæ½ä½å°", |
["Phalanx"] = "æ¹éµ", |
["Plugger Spazzring"] = "æ®ææ ¼", |
["Princess Moira Bronzebeard"] = "éçå ¡å ¬ä¸»èè¾æ·éé¡»", |
["Pyromancer Loregrain"] = "æ§ç«å¸ç½æ ¼é·æ©", |
["Ribbly Screwspigot"] = "é·å¸é·æ¯åºæ¯æ ¼ç¹", |
["Seeth'rel"] = "西æ¯é·å°", |
["The Seven Dwarves"] = "ä¸è´¤ç®äºº", |
["Verek"] = "ç»´é·å ", |
["Vile'rel"] = "ç¦åé·å°", |
["Warder Stilgiss"] = "å ¸ç±å®æ¯è¿ªå°åºæ¯", |
--Blackrock Spire |
--Lower é»ä¸ |
["Bannok Grimaxe"] = "ç诺å ·巨æ§", |
["Burning Felguard"] = "çç§å°ç±å«å£«",--check ç¿»è¯æ2ç§ çç§å°ç±å®å« |
["Crystal Fang"] = "æ°´æ¶ä¹ç", |
["Ghok Bashguud"] = "éå ·巴ä»å¤å¾·", |
["Gizrul the Slavener"] = "奴役è åºå ¹é²å°", |
["Halycon"] = "åé·è¯", |
["Highlord Omokk"] = "欧è«å 大ç", |
["Mor Grayhoof"] = "è«å°Â·ç°è¹", |
["Mother Smolderweb"] = "çç½èå", |
["Overlord Wyrmthalak"] = "ç»´å§è¨æå ", |
["Quartermaster Zigris"] = "åéå®å ¹æ ¼é·æ¯", |
["Shadow Hunter Vosh'gajin"] = "æå½±çææ²ä»å æ¯", |
["Spirestone Battle Lord"] = "å°ç³ç»å¸ ", |
["Spirestone Butcher"] = "å°ç³å± 夫", |
["Spirestone Lord Magus"] = "å°ç³é¦å¸æ³å¸", |
["Urok Doomhowl"] = "ä¹æ´å ", |
["War Master Voone"] = "ææ¥å®æ²æ©", |
--Upper é»ä¸ |
["General Drakkisath"] = "è¾¾åºè¨æ¯å°å", |
["Goraluk Anvilcrack"] = "å¤æé²å ", |
["Gyth"] = "çæ¯", |
["Jed Runewatcher"] = "æ°å¾·", |
["Lord Valthalak"] = "ç¦å¡æå å ¬çµ", |
["Pyroguard Emberseer"] = "çç°å«å£«è¾åå¸å°", |
["Solakar Flamewreath"] = "ç´¢æå¡Â·ç«å ", |
["The Beast"] = "æ¯æ¯å·¨å ½", |
["Warchief Rend Blackhand"] = "大é é¿é·å¾·Â·é»æ", |
--Blackwing Lair |
["Broodlord Lashlayer"] = "åä»é·å°", |
["Chromaggus"] = "å æ´çå¤æ¯", |
["Ebonroc"] = "åå诺å ", |
["Firemaw"] = "è´¹å°é»", |
["Flamegor"] = "å¼è±æ ¼å°", |
["Grethok the Controller"] = "é»ç¿¼æ§å¶è ", |
["Lord Victor Nefarius"] = "ç»´å å¤Â·å¥æ³é奥æ¯", |
["Nefarian"] = "å¥æ³å©å®", |
["Razorgore the Untamed"] = "çéçæä½æ ¼å°", |
["Vaelastrasz the Corrupt"] = "å è½çç¦ææ¯å¡å ¹", |
--Black Temple |
["Essence of Anger"] = "æ¤æç²¾å", |
["Essence of Desire"] = "欲æç²¾å", |
["Essence of Suffering"] = "è¦çç²¾å", |
["Gathios the Shatterer"] = "å»ç¢è å 西奥æ¯", |
["Gurtogg Bloodboil"] = "å¤å°å¾æ ¼Â·è¡æ²¸", |
["High Nethermancer Zerevor"] = "é«é¶çµæ¯å¸å¡åæ²å°", |
["High Warlord Naj'entus"] = "é«é¶ç£å纳å å¾æ¯", |
["Illidan Stormrage"] = "ä¼å©ä¸¹Â·æé£", |
["Illidari Council"] = "ä¼å©è¾¾é·è®®ä¼", |
["Lady Malande"] = "å¥³å ¬çµçå °å¾·", |
["Mother Shahraz"] = "è赫æä¸ä¸»æ¯", |
["Reliquary of Souls"] = "çµéä¹å£", |
["Shade of Akama"] = "é¿å¡çä¹å½±", |
["Supremus"] = "èæ®é·å§æ¯", |
["Teron Gorefiend"] = "å¡é·è¡é", |
["The Illidari Council"] = "ä¼å©è¾¾é·è®®ä¼", |
["Veras Darkshadow"] = "ç»´å°è±æ¯Â·æ·±å½±", |
--Caverns of Time |
--Old Hillsbrad Foothills |
["Captain Skarloc"] = "æ¯å¡æ´å ä¸å°", |
["Epoch Hunter"] = "æ¶ç©ºçæ", |
["Lieutenant Drake"] = "å¾·æå ä¸å°", |
--The Black Morass |
["Aeonus"] = "å欧åªæ¯", |
["Chrono Lord Deja"] = "æ¶ç©ºé¢ä¸»å¾·äº", |
["Medivh"] = "麦迪æ", |
["Temporus"] = "å¦æ®å¢æ¯", |
--Coilfang Reservoir |
--Serpentshrine Cavern |
["Coilfang Elite"] = "ççç²¾è±", |
["Coilfang Strider"] = "ççå·¡é»è ", |
["Fathom-Lord Karathress"] = "深水é¢ä¸»å¡æçé·æ¯", |
["Hydross the Unstable"] = "ä¸ç¨³å®ç海度æ¯", |
["Lady Vashj"] = "ç¦ä¸çª", |
["Leotheras the Blind"] = "ç²ç¼è è±æ¬§çææ¯", |
["Morogrim Tidewalker"] = "è«æ´æ ¼é·è¸æ½®è ", |
["Pure Spawn of Hydross"] = "纯åç海度æ¯çªç", |
["Shadow of Leotheras"] = "è±æ¬§çææ¯ä¹å½±", |
["Tainted Spawn of Hydross"] = "污æç海度æ¯çªç", |
["The Lurker Below"] = "é±¼æ¯æ", |
["Tidewalker Lurker"] = "è¸æ½®æ½ä¼è ", |
--The Slave Pens |
["Mennu the Betrayer"] = "èåè é¨åª", |
["Quagmirran"] = "å¤¸æ ¼ç±³æ", |
["Rokmar the Crackler"] = "å·¨é³é²å çå°", |
["Ahune"] = "åéæ©", |
--The Steamvault |
["Hydromancer Thespia"] = "æ°´æ¯å¸çä¸æ¯å¨ ", |
["Mekgineer Steamrigger"] = "æºæ¢°å¸æ¯èéæ ¼", |
["Warlord Kalithresh"] = "ç£åå¡å©çéæ¯", |
--The Underbog |
["Claw"] = "å å³æ©", |
["Ghaz'an"] = "å å ¹å®", |
["Hungarfen"] = "éå å°è¬", |
["Overseer Tidewrath"] = "工头泰德ç¦æ¯", |
["Swamplord Musel'ek"] = "æ²¼å°é¢ä¸»ç©å¡é·å ", |
["The Black Stalker"] = "é»è²éæ¥è ", |
--Dire Maul åè¿ |
--Arena ç«æåº |
["Mushgog"] = "å§æ¯é«æ ¼", |
["Skarr the Unbreakable"] = "æ æçæ¯å¡å°", |
["The Razza"] = "ææå°", |
--East |
["Alzzin the Wildshaper"] = "å¥¥å ¹æ©", |
["Hydrospawn"] = "æµ·å¤æ¯åæ©", |
["Isalien"] = "ä¼è¨å©æ©", |
["Lethtendris"] = "è¾çå¡èä¸", |
["Pimgib"] = "å¹å§åå¸", |
["Pusillin"] = "æ®å¸æ", |
["Zevrim Thornhoof"] = "çé·å§Â·åºè¹", |
--North |
["Captain Kromcrush"] = "å ç½å¡æ¯", |
["Cho'Rush the Observer"] = "è§å¯è å é²ä»", |
["Guard Fengus"] = "å«å µè¬å¤æ¯", |
["Guard Mol'dar"] = "å«å µæ©å°è¾¾", |
["Guard Slip'kik"] = "å«å µæ¯éåºå ", |
["King Gordok"] = "æå¤å 大ç", |
["Knot Thimblejack's Cache"] = "诺ç¹Â·å¸å§å å çå¨ç©ç®±", |
["Stomper Kreeg"] = "è·µè¸è å é·æ ¼", |
--West |
["Illyanna Ravenoak"] = "ä¼ç³å¨Â·ææ¨", |
["Immol'thar"] = "ä¼è«å¡å°", |
["Lord Hel'nurath"] = "赫å°åªææ¯", |
["Magister Kalendris"] = "å¡é·è¿ªæ¯éé¿", |
["Prince Tortheldrin"] = "æå¡å¾·æçå", |
["Tendris Warpwood"] = "ç¹è¿ªæ¯Â·ææ¨", |
["Tsu'zee"] = "èæ¯", |
--Gnomeregan |
["Crowd Pummeler 9-60"] = "群ä½æå»è 9-60", |
["Dark Iron Ambassador"] = "é»é大å¸", |
["Electrocutioner 6000"] = "çµåå¨6000å", |
["Grubbis"] = "æ ¼é²æ¯æ¯", |
["Mekgineer Thermaplugg"] = "麦å å°¼å°Â·ççæ®ææ ¼", |
["Techbot"] = "å°ç«¯æºå¨äºº", |
["Viscous Fallout"] = "ç²æ§è¾å°å°", |
--Gruul's Lair |
["Blindeye the Seer"] = "ç²ç¼å ç¥", |
["Gruul the Dragonkiller"] = "å± é¾è æ ¼é²å°", |
["High King Maulgar"] = "è«å å°å¤§ç", |
["Kiggler the Crazed"] = "ç¯ççåºæå°", |
["Krosh Firehand"] = "å æ´ä»Â·ç«æ³", |
["Olm the Summoner"] = "å¬å¤è æ²å°å§", |
--Hellfire Citadel |
--Hellfire Ramparts |
["Nazan"] = "纳æ", |
["Omor the Unscarred"] = "æ ç¤è 奥æ©å°", |
["Vazruden the Herald"] = "ä¼ ä»¤å®ç¦å ¹å¾·", |
["Vazruden"] = "ç¦å ¹å¾·", |
["Watchkeeper Gargolmar"] = "å·¡è§è å æç", |
--Magtheridon's Lair |
["Hellfire Channeler"] = "å°ç±ç«å¯¼éè ", |
["Magtheridon"] = "ççéé¡¿", |
--The Blood Furnace |
["Broggok"] = "å¸æ´æå ", |
["Keli'dan the Breaker"] = "å»ç¢è å é丹", |
["The Maker"] = "å¶é è ", |
--The Shattered Halls |
["Blood Guard Porung"] = "è¡å«å£«ä¼¯é²æ©", |
["Grand Warlock Nethekurse"] = "é«é¶æ¯å£«å¥çåºæ¯", |
["Warbringer O'mrogg"] = "æäºä½¿è æ²å§ç½æ ¼", |
["Warchief Kargath Bladefist"] = "é é¿å¡å æ¯Â·åæ³", |
--Hyjal Summit |
["Anetheron"] = "å®çº³å¡é", |
["Archimonde"] = "é¿å èå¾·", |
["Azgalor"] = "é¿å ¹å æ´", |
["Kaz'rogal"] = "å¡å ¹æ´å ", |
["Rage Winterchill"] = "é·åºÂ·å¬å¯", |
--Karazhan |
["Arcane Watchman"] = "奥æ¯çå®", |
["Attumen the Huntsman"] = "çæé¿å¾é¨", |
["Chess Event"] = "å½é 象æ£", |
["Dorothee"] = "å¤èè", |
["Dust Covered Chest"] = "ç°å°è¦ççç®±å",--ngaæ°æ®åº |
["Grandmother"] = "è奶奶", |
["Hyakiss the Lurker"] = "æ½ä¼è å¸äºå ¶æ¯", |
["Julianne"] = "æ±ä¸½å¶", |
["Kil'rek"] = "åºå°éå ", |
["King Llane Piece"] = "è±æ©å½ç", |
["Maiden of Virtue"] = "è´èå£å¥³", |
["Midnight"] = "åå¤", |
["Moroes"] = "è«ç½æ¯", |
["Netherspite"] = "è空幽é¾", |
["Nightbane"] = "å¤ä¹é", |
["Prince Malchezaar"] = "çå æå°çå", |
["Restless Skeleton"] = "æ æ³å®æ¯çéª·é« ", |
["Roar"] = "èå°çç®å", |
["Rokad the Ravager"] = "è¹èºè æ´å¡å¾·", |
["Romulo & Julianne"] = "ç½å¯æ¬§ä¸æ±ä¸½å¶", |
["Romulo"] = "ç½å¯æ¬§", |
["Shade of Aran"] = "åå °ä¹å½±", |
["Shadikith the Glider"] = "æ»ç¿è æ²å¾·åºæ¯", |
["Strawman"] = "稻è人", |
["Terestian Illhoof"] = "ç¹é·æ¯å¦Â·éªè¹", |
["The Big Bad Wolf"] = "大ç°ç¼", |
["The Crone"] = "å·«å©", |
["The Curator"] = "é¦é¿", |
["Tinhead"] = "éç®äºº", |
["Tito"] = "ææ", |
["Warchief Blackhand Piece"] = "é»æé é¿", |
-- Magisters' Terrace (é导å¸å¹³å°) |
["Kael'thas Sunstrider"] = "å¯å°è¨æ¯Â·éæ¥è ", |
["Priestess Delrissa"] = "女ç¥å¸å¾·èå¸äº", |
["Selin Fireheart"] = "å¡æ·ç«å¿", |
["Vexallus"] = "ç»´è¨é²æ¯", |
--Maraudon |
["Celebras the Cursed"] = "è¢«è¯ åçå¡é·å¸ææ¯", |
["Gelk"] = "åå°å ", |
["Kolk"] = "èå°å ", |
["Landslide"] = "å °æ¯å©å¾·", |
["Lord Vyletongue"] = "ç»´å©å¡æ©", |
["Magra"] = "çæ ¼æ", |
["Maraudos"] = "çæå¤æ¯", |
["Meshlok the Harvester"] = "æ¶å²è 麦ä»æ´å ", |
["Noxxion"] = "诺å èµæ©", |
["Princess Theradras"] = "çè±å¾·ä¸å ¬ä¸»", |
["Razorlash"] = "éåºéç¬è ", |
["Rotgrip"] = "æ´ç¹æ ¼éæ®", |
["Tinkerer Gizlock"] = "å·¥å åå ¹æ´å ", |
["Veng"] = "æ¸©æ ¼", |
--Molten Core |
["Baron Geddon"] = "迦顿ç·çµ", |
["Cache of the Firelord"] = "ç«ç°ä¹ççå®ç®±", |
["Garr"] = "å å°", |
["Gehennas"] = "åºèµ«çº³æ¯", |
["Golemagg the Incinerator"] = "çåè å¤é·æ¼æ ¼", |
["Lucifron"] = "é²è¥¿å¼é", |
["Magmadar"] = "çæ ¼æ¼è¾¾", |
["Majordomo Executus"] = "管çè åå ç´¢å¾æ¯", |
["Ragnaros"] = "ææ ¼çº³ç½æ¯", |
["Shazzrah"] = "æ²æ¯æå°", |
["Sulfuron Harbinger"] = "è¨å¼éå 驱è ", |
--Naxxramas |
["Anub'Rekhan"] = "é¿åªå¸é·å", |
["Deathknight Understudy"] = "è§ä¹ æ»äº¡éªå£«", |
["Feugen"] = "è´¹å°æ ¹", |
["Four Horsemen Chest"] = "åéªå£«ä¹ç®±", |
["Gluth"] = "æ ¼ææ¯", |
["Gothik the Harvester"] = "æ¶å²è ææå ", |
["Grand Widow Faerlina"] = "é»å¥³å·«æ³ç³å¨", |
["Grobbulus"] = "æ ¼ç½å¸é²æ¯", |
["Heigan the Unclean"] = "è®èçå¸å°ç", |
["Highlord Mograine"] = "大é¢ä¸»è«æ ¼è±å°¼", |
["Instructor Razuvious"] = "æå®æè维奥æ¯", |
["Kel'Thuzad"] = "å å°èå å¾·", |
["Lady Blaumeux"] = "å¥³å ¬çµå¸å³ç¼ªå ä¸", |
["Loatheb"] = "æ´æ¬§å¡å¸", |
["Maexxna"] = "è¿å æ¯çº³", |
["Noth the Plaguebringer"] = "çç«ä½¿è 诺æ¯", |
["Patchwerk"] = "å¸å¥ç»´å ", |
["Sapphiron"] = "è¨è²é", |
["Sir Zeliek"] = "çéè¶å çµå£«", |
["Stalagg"] = "æ¯å¡ææ ¼", |
["Thaddius"] = "å¡è¿ªä¹æ¯", |
["Thane Korth'azz"] = "åºå°å¡å ¹é¢ä¸»", |
["The Four Horsemen"] = "åéªå£«", |
--Onyxia's Lair |
["Onyxia"] = "奥妮å å¸äº", |
--Ragefire Chasm |
["Bazzalan"] = "å·´æå °", |
["Jergosh the Invoker"] = "ç¥æ±è è¶æä»", |
["Maur Grimtotem"] = "çå°Â·ææå¾è ¾", |
["Taragaman the Hungerer"] = "饥饿è å¡æå æ¼", |
--Razorfen Downs |
["Amnennar the Coldbringer"] = "å¯å°ä¹çäºé¨çº³å°", |
["Glutton"] = "æ´é£è ", |
["Mordresh Fire Eye"] = "ç«ç¼è«å¾·é·æ¯", |
["Plaguemaw the Rotting"] = "è ççæ®é·è«å°", |
["Ragglesnout"] = "æææ¯è¯ºç¹", |
["Tuten'kash"] = "å¾ç¹å¡ä»", |
--Razorfen Kraul |
["Agathelos the Raging"] = "æ´æçé¿è¿¦èµç½æ¯", |
["Blind Hunter"] = "ç²ç¼çæ", |
["Charlga Razorflank"] = "å¡å°å ·åºè", |
["Death Speaker Jargba"] = "亡è¯è è´¾æ ¼å·´", |
["Earthcaller Halmgar"] = "å¤å°è åç©å ", |
["Overlord Ramtusk"] = "主宰æå§å¡æ¯", |
--Ruins of Ahn'Qiraj |
["Anubisath Guardian"] = "é¿åªæ¯è¨æ¯å®å«è ", |
["Ayamiss the Hunter"] = "ç©çè é¿äºç±³æ¯", |
["Buru the Gorger"] = "åå½è å¸é²", |
["General Rajaxx"] = "æè´¾å æ¯å°å", |
["Kurinnaxx"] = "åºæ纳å æ¯", |
["Lieutenant General Andorov"] = "å®å¤æ´å¤«ä¸å°", |
["Moam"] = "è«é¿å§", |
["Ossirian the Unscarred"] = "æ ç¤è 奥æ¯éå®", |
--Scarlet Monastery |
--Armory |
["Herod"] = "赫æ´å¾·", |
--Cathedral |
["High Inquisitor Fairbanks"] = "大æ£å¯å®æ³å°çå æ¯", |
["High Inquisitor Whitemane"] = "大æ£å¯å®æç¹è¿æ©", |
["Scarlet Commander Mograine"] = "è¡è²åååææ¥å®è«æ ¼è±å°¼", |
--Graveyard |
["Azshir the Sleepless"] = "æ°¸éçè¾å¸å°", |
["Bloodmage Thalnos"] = "è¡æ³å¸è¨å°è¯ºæ¯", |
["Fallen Champion"] = "æ»çµå士", |
["Interrogator Vishas"] = "审讯åé¦æ²æ¯", |
["Ironspine"] = "éèæ»çµ", |
["Headless Horseman"] = "æ 头éªå£«", |
--Library |
["Arcanist Doan"] = "奥æ³å¸æå®", |
["Houndmaster Loksey"] = "驯ç¬è æ´å å¸", |
--Scholomance |
["Blood Steward of Kirtonos"] = "åºå°å¾è¯ºæ¯çå«å£«", |
["Darkmaster Gandling"] = "é»æé¢é¿å ä¸", |
["Death Knight Darkreaver"] = "æ»äº¡éªå£«è¾¾å é·å°", |
["Doctor Theolen Krastinov"] = "çå°æ·å¡æ¯è¿ªè¯ºå¤«ææ", |
["Instructor Malicia"] = "讲å¸ç丽å¸äº", |
["Jandice Barov"] = "詹迪æ¯Â·å·´ç½å¤«", |
["Kirtonos the Herald"] = "ä¼ ä»¤å®åºå°å¾è¯ºæ¯", |
["Kormok"] = "åºå°è«å ", |
["Lady Illucia Barov"] = "ä¼é²å¸äºÂ·å·´ç½å¤«", |
["Lord Alexei Barov"] = "é¿é·å æ¯Â·å·´ç½å¤«", |
["Lorekeeper Polkelt"] = "åå¦è æ®å å°ç¹", |
["Marduk Blackpool"] = "马æå ·å¸è±å æ³¢å°", |
["Ras Frostwhisper"] = "è±æ¯Â·éè¯", |
["Rattlegore"] = "è¡éª¨åå¡", |
["The Ravenian"] = "ææå°¼äº", |
["Vectus"] = "ç»´å å¾æ¯", |
--Shadowfang Keep |
["Archmage Arugal"] = "大æ³å¸é¿é²é«", |
["Arugal's Voidwalker"] = "é¿é²é«çè空è¡è ", |
["Baron Silverlaine"] = "å¸ç¦è±æ©ç·çµ", |
["Commander Springvale"] = "ææ¥å®æ¯æ®æç¦å°", |
["Deathsworn Captain"] = "æ»äº¡ä¹èª", |
["Fenrus the Devourer"] = "åå¬è è¬é²æ¯", |
["Odo the Blindwatcher"] = "ç²ç¼å®å«å¥¥æ", |
["Razorclaw the Butcher"] = "å± å¤«æä½å å³", |
["Wolf Master Nandos"] = "ç¼çåææ¯", |
--Stratholme |
["Archivist Galford"] = "æ¡£æ¡ç®¡çåå å°ç¦ç¹", |
["Balnazzar"] = "巴纳æå°", |
["Baron Rivendare"] = "çææ´å°ç·çµ", |
["Baroness Anastari"] = "å®å¨ä¸å¡ä¸½ç·çµå¤«äºº", |
["Black Guard Swordsmith"] = "é»è¡£å®å«é¸åå¸", |
["Cannon Master Willey"] = "ç®æå¨å©", |
["Crimson Hammersmith"] = "红衣é¸é¤å¸", |
["Fras Siabi"] = "å¼ææ¯Â·å¸äºæ¯", |
["Hearthsinger Forresten"] = "å¼é·æ¯ç¹æ©", |
["Magistrate Barthilas"] = "å·´çææ¯éé¿", |
["Maleki the Pallid"] = "èç½ççååº", |
["Nerub'enkan"] = "å¥é²å¸æ©å", |
["Postmaster Malown"] = "é®å·®é©¬é¾", |
["Ramstein the Gorger"] = "åå½è æå§æ¯ç»", |
["Skul"] = "æ¯åºå°", |
["Stonespine"] = "ç³è", |
["The Unforgiven"] = "ä¸å¯å®½æè ", |
["Timmy the Cruel"] = "æ²æ¨çæç±³", |
--Sunwell Plateau (太é³ä¹äºé«å°) |
["Kalecgos"] = "å¡é·èæ¯", |
["Sathrovarr the Corruptor"] = "è èè è¨ç´¢ç¦å°", |
["Brutallus"] = "å¸é²å¡å¢æ¯", |
["Felmyst"] = "è²ç±³ä¸", |
["Kil'jaeden"] = "åºå°å 丹", |
["M'uru"] = "ç©é²", |
["Entropius"] = "çµé", |
["The Eredar Twins"] = "è¾çè¾¾åå", |
["Lady Sacrolash"] = "è¨æ´æä¸å¥³ç", |
["Grand Warlock Alythess"] = "é«é¶æ¯å£«å¥¥è¾å¡ä¸", |
--Tempest Keep |
--The Arcatraz |
["Dalliah the Doomsayer"] = "æ«æ¥é¢è¨è è¾¾å°èå®", |
["Harbinger Skyriss"] = "é¢è¨è æ¯å çæ¯", |
["Warden Mellichar"] = "çæ¤è æ¢ éå¡å°", |
["Wrath-Scryer Soccothrates"] = "天æé¢è¨è èå æåº", |
["Zereketh the Unbound"] = "èªç±ççé·å¯æ¯", |
--The Botanica |
["Commander Sarannis"] = "ææ¥å®è¨æ妮ä¸", |
["High Botanist Freywinn"] = "é«çº§æ¤ç©å¦å®¶å¼é·æ¸©", |
["Laj"] = "æä¼", |
["Thorngrin the Tender"] = "ç管è ç´¢æ©æ ¼æ", |
["Warp Splinter"] = "è¿è·ææ¨", |
--The Eye |
["Al'ar"] = "奥", |
["Cosmic Infuser"] = "å®å®ç注è ", |
["Devastation"] = "æ¯å", |
["Grand Astromancer Capernian"] = "ææ¯å¸å¡æ³¢å¦®å¨ ", |
["High Astromancer Solarian"] = "大ææ¯å¸ç´¢å °èå®", |
["Infinity Blades"] = "æ å°½ä¹å", |
["Kael'thas Sunstrider"] = "å¯å°è¨æ¯Â·éæ¥è ", |
["Lord Sanguinar"] = "è¨å¤çº³å°ç·çµ", |
["Master Engineer Telonicus"] = "é¦å¸æå¸å¡éå°¼åºæ¯", |
["Netherstrand Longbow"] = "çµå¼¦é¿å¼", |
["Phaseshift Bulwark"] = "ç¸ä½å£å", |
["Solarium Agent"] = "æ¥æ·å¯æ¢", |
["Solarium Priest"] = "æ¥æ·ç¥å¸", |
["Staff of Disintegration"] = "ç¦è§£æ³æ", |
["Thaladred the Darkener"] = "亵æ¸è è¨æå¾·é·", |
["Void Reaver"] = "空çµæºç²", |
["Warp Slicer"] = "è¿è·åå²è ", |
--The Mechanar |
["Gatewatcher Gyro-Kill"] = "çå®è çç½åºå°", |
["Gatewatcher Iron-Hand"] = "çå®è åéæ±", |
["Mechano-Lord Capacitus"] = "æºæ¢°é¢ä¸»å¡å¸è¥¿å¾æ¯", |
["Nethermancer Sepethrea"] = "çµæ¯å¸å¡æ¯çè¾", |
["Pathaleon the Calculator"] = "计ç®è å¸è¨é·æ©", |
--The Deadmines |
["Brainwashed Noble"] = "被æ´èçè´µæ", |
["Captain Greenskin"] = "绿ç®éé¿", |
["Cookie"] = "æ²å¥", |
["Edwin VanCleef"] = "è¾å¾·æ¸©Â·èå é夫", |
["Foreman Thistlenettle"] = "工头å¸æ¯èç¹", |
["Gilnid"] = "åºå°å°¼æ ¼", |
["Marisa du'Paige"] = "çéè·ææ´¾æ ¼", |
["Miner Johnson"] = "ç¿å·¥çº¦ç¿°æ£®", |
["Mr. Smite"] = "éæ³å ç", |
["Rhahk'Zor"] = "æå ä½", |
["Sneed"] = "æ¯å°¼å¾·", |
["Sneed's Shredder"] = "æ¯å°¼å¾·çä¼æ¨æº", |
--The Stockade |
["Bazil Thredd"] = "å·´åºå°Â·æ¯çå¾·", |
["Bruegal Ironknuckle"] = "å¸é²é«Â·éæ³", |
["Dextren Ward"] = "迪å æ¯ç¹Â·ç¦å¾·", |
["Hamhock"] = "åå§éå ", |
["Kam Deepfury"] = "å¡å§Â·æ·±æ", |
["Targorr the Dread"] = "å¯æçå¡æ ¼å°", |
--The Temple of Atal'Hakkar |
["Atal'alarion"] = "é¿å¡æå©æ©", |
["Avatar of Hakkar"] = "åå¡çå身", |
["Dreamscythe"] = "å¾·å§å¡å¡å°", |
["Gasher"] = "å ä»å°", |
["Hazzas"] = "åææ¯", |
["Hukku"] = "è¡åº", |
["Jade"] = "çé¾", |
["Jammal'an the Prophet"] = "é¢è¨è 迦çå °", |
["Kazkaz the Unholy"] = "éªæ¶çå¡è¨å¡å ¹", |
["Loro"] = "æ´è¥å°", |
["Mijan"] = "ç±³æ", |
["Morphaz"] = "æ©å¼ææ¯", |
["Ogom the Wretched"] = "å¯æ²ç奥æå§", |
["Shade of Eranikus"] = "ä¼å °å°¼åºæ¯çé´å½±", |
["Veyzhak the Cannibal"] = "é£å°¸è ç»´è¨å ", |
["Weaver"] = "å¾·æç»´æ²å°", |
["Zekkis"] = "æ³½åºæ¯", |
["Zolo"] = "ç¥ç½", |
["Zul'Lor"] = "ç¥ç½å°", |
--Uldaman |
["Ancient Stone Keeper"] = "å¤ä»£çç³å¤´çå®è ", |
["Archaedas"] = "é¿æè¾¾æ¯", |
["Baelog"] = "å·´å°æ´æ", |
["Digmaster Shovelphlange"] = "ææä¸å®¶èå°å¼ææ ¼", |
["Galgann Firehammer"] = "å å æ©Â·ç«é¤", |
["Grimlok"] = "æ ¼çå§æ´å ", |
["Ironaya"] = "è¾é纳äº", |
["Obsidian Sentinel"] = "é»æç³å¨å µ", |
["Revelosh"] = "é²ç»´ç½ä»", |
--Wailing Caverns |
["Boahn"] = "åè¾æ©", |
["Deviate Faerie Dragon"] = "åå¼ç²¾çµé¾", |
["Kresh"] = "å é·ä»", |
["Lady Anacondra"] = "å®å¨ç§å¾·æ", |
["Lord Cobrahn"] = "èå¸è±æ©", |
["Lord Pythas"] = "ç®è¨æ¯", |
["Lord Serpentis"] = "çè¬è¿ªæ¯", |
["Mad Magglish"] = "ç¯ççé©¬æ ¼å©ä»", |
["Mutanus the Devourer"] = "åå¬è ç©å¦åªæ¯", |
["Skum"] = "æ¯å¡å§", |
["Trigore the Lasher"] = "éç¬è ç¹éé«é·", |
["Verdan the Everliving"] = "æ°¸çè æ²å°ä¸¹", |
--World Bosses |
["Avalanchion"] = "é¿ç¦å °å¥å¥¥", |
["Azuregos"] = "è¾ç´¢é·èæ¯", |
["Baron Charr"] = "ç«ç°ç·çµæ¥å°", |
["Baron Kazum"] = "å¡èå§ç·çµ", |
["Doom Lord Kazzak"] = "æ«æ¥é¢ä¸»å¡æå ", |
["Doomwalker"] = "æ«æ¥è¡è ", |
["Emeriss"] = "è¾è«èä¸", |
["High Marshal Whirlaxis"] = "大å å¸ ç»´æå¸æ¯", |
["Lethon"] = "è±ç´¢æ©", |
["Lord Skwol"] = "æ¯å¤æ©ç·çµ", |
["Prince Skaldrenox"] = "æ¯å¡å¾·è¯ºå æ¯çå", |
["Princess Tempestria"] = "æ³°æ¯æ¯èäºå ¬ä¸»", |
["Taerar"] = "æ³°æå°", |
["The Windreaver"] = "çé£æ 夺è ", |
["Ysondre"] = "ä¼æ£®å¾·é·", |
--Zul'Aman Add new bosses for 2.3 |
["Akil'zon"] = "ååºå°æ¾", |
["Halazzi"] = "åå°æå ¹", |
["Jan'alai"] = "å äºè±", |
["Malacrass"] = "çæå¡æ¯", |
["Nalorakk"] = "纳æ´æå ", |
["Zul'jin"] = "ç¥å°é", |
["Hex Lord Malacrass"] = "å¦æ¯é¢ä¸»çæå¡æ¯", |
--Zul'Farrak |
["Antu'sul"] = "å®å¾èå°", |
["Chief Ukorz Sandscalp"] = "ä¹å å ¹Â·æ²é¡¶", |
["Dustwraith"] = "ç°å°æ¨çµ", |
["Gahz'rilla"] = "å å ¹çæ", |
["Hydromancer Velratha"] = "æ°´å å¸ç»´è¾è¨", |
["Murta Grimgut"] = "ç©å°å¡", |
["Nekrum Gutchewer"] = "èå é²å§", |
["Oro Eyegouge"] = "欧ç½Â·è¡ç¼", |
["Ruuzlu"] = "å¢å ¹é²", |
["Sandarr Dunereaver"] = "æè¾¾å°Â·æ²æ è ", |
["Sandfury Executioner"] = "æ²æå½åæ", |
["Sergeant Bly"] = "å¸è±ä¸å£«", |
["Shadowpriest Sezz'ziz"] = "æå½±ç¥å¸å¡çæ¯", |
["Theka the Martyr"] = "æ®æè å¡å¡", |
["Witch Doctor Zum'rah"] = "å·«å»ç¥ç©ææ©", |
["Zerillis"] = "æ³½é·å©æ¯", |
["Zul'Farrak Dead Hero"] = "ç¥å°æ³æå éµäº¡è±é", |
--Zul'Gurub |
["Bloodlord Mandokir"] = "è¡é¢ä¸»æ¼å¤åºå°", |
["Gahz'ranka"] = "å å ¹å °å¡", |
["Gri'lek"] = "æ ¼éé·å ", |
["Hakkar"] = "åå¡", |
["Hazza'rah"] = "åææå°", |
["High Priest Thekal"] = "é«é¶ç¥å¸å¡å¡å°", |
["High Priest Venoxis"] = "é«é¶ç¥å¸æ¸©è¯ºå¸æ¯", |
["High Priestess Arlokk"] = "é«é¶ç¥å¸å¨ å°ç½", |
["High Priestess Jeklik"] = "é«é¶ç¥å¸è¶å éå ", |
["High Priestess Mar'li"] = "é«é¶ç¥å¸çå°é", |
["Jin'do the Hexxer"] = "å¦æ¯å¸é度", |
["Renataki"] = "é·çº³å¡åº", |
["Wushoolay"] = "ä¹èé·", |
--Ring of Blood ä½äº çº³æ ¼å ° |
["Brokentoe"] = "æè¹", |
["Mogor"] = "ç©æå°", |
["Murkblood Twin"] = "æè¡åå", |
["Murkblood Twins"] = "æè¡åå", |
["Rokdar the Sundered Lord"] = "è£ç³ä¹çæ´å¡è¾¾å°", |
["Skra'gath"] = "çå æå æ¯", |
["The Blue Brothers"] = "èè²å å¼",--é²è¡ç«æåº |
["Warmaul Champion"] = "ææ§å士", |
} |
elseif GAME_LOCALE == "zhTW" then |
lib:SetCurrentTranslations { |
--Ahn'Qiraj |
["Anubisath Defender"] = "é¿åªæ¯è©æ¯é²è¡è ", |
["Battleguard Sartura"] = "æ²ç¾åæ", |
["C'Thun"] = "å èæ©", |
["Emperor Vek'lor"] = "ç¶å æ´ç¾å¤§å¸", |
["Emperor Vek'nilash"] = "ç¶å å°¼ææ¯å¤§å¸", |
["Eye of C'Thun"] = "å èæ©ä¹ç¼", |
["Fankriss the Unyielding"] = "ä¸å±çèå éæ¯", |
["Lord Kri"] = "å éé 主", |
["Ouro"] = "å¥§ç¾ ", |
["Princess Huhuran"] = "åéèå ¬ä¸»", |
["Princess Yauj"] = "äºç¾åºå ¬ä¸»", |
["The Bug Family"] = "è²å家æ", |
["The Prophet Skeram"] = "é è¨è æ¯å æå§", |
["The Twin Emperors"] = "éåçå¸", |
["Vem"] = "ç¶å§", |
["Viscidus"] = "ç¶å¸åº¦æ¯", |
--Auchindoun |
--Auchenai Crypts |
["Exarch Maladaar"] = "主æçªæéç¾", |
["Shirrak the Dead Watcher"] = "æ»äº¡çå®è è¾çå ", |
--Mana-Tombs |
["Nexus-Prince Shaffar"] = "å¥è©æ¯çåè©æ³ç¾", |
["Pandemonius"] = "çæèå°¼åæ¯", |
["Tavarok"] = "å¡ç¦æ´å ", |
--Shadow Labyrinth |
["Ambassador Hellmaw"] = "æµ·ç¾çªå¤§ä½¿", |
["Blackheart the Inciter"] = "ç ½åè é»å¿", |
["Grandmaster Vorpil"] = "é å°è ç¦ç®æ", |
["Murmur"] = "è«ç¾å¢¨", |
--Sethekk Halls |
["Anzu"] = "å®ç¥", |
["Darkweaver Syth"] = "ææ³å¸«å¸æ¯", |
["Talon King Ikiss"] = "é·¹çä¼å¥æ¯", |
--Blackfathom Deeps |
["Aku'mai"] = "é¿åº«éº¥ç¾", |
["Baron Aquanis"] = "é¿å¥å°¼æ¯ç·çµ", |
["Gelihast"] = "æ ¼éåæ¯ç¹", |
["Ghamoo-ra"] = "å æ©æ", |
["Lady Sarevess"] = "è©å©ç¶çµ²å¥³å£«", |
["Old Serra'kis"] = "çæåæ¯", |
["Twilight Lord Kelris"] = "æ®å é 主å ç¾éæ¯", |
--Blackrock Depths |
["Ambassador Flamelash"] = "å¼èææ¯å¤§ä½¿", |
["Anger'rel"] = "å®æ ¼é·ç¾", |
["Anub'shiah"] = "é¿åªå¸ç¾", |
["Bael'Gar"] = "è²ç¾å ", |
["Chest of The Seven"] = "ä¸è³¢ä¹ç®±", |
["Doom'rel"] = "æå§é·ç¾", |
["Dope'rel"] = "å¤æ®é·ç¾", |
["Emperor Dagran Thaurissan"] = "éæ ¼è·索ç森大å¸", |
["Eviscerator"] = "åç¼è ", |
["Fineous Darkvire"] = "å¼è«¾æ¯Â·éå ç¶ç¾", |
["General Angerforge"] = "å®æ ¼å¼å°è»", |
["Gloom'rel"] = "æ ¼é¯é·ç¾", |
["Golem Lord Argelmach"] = "éåé 主é¿æ ¼æ¼å¥", |
["Gorosh the Dervish"] = "ãä¿®è¡è ãé«ç¾ ä»", |
["Grizzle"] = "æ ¼éè²ç¾", |
["Hate'rel"] = "é»ç¹é·ç¾", |
["Hedrum the Creeper"] = "ãç¬è¡è ã赫æå§", |
["High Interrogator Gerstahn"] = "審è¨å®æ ¼æ¯å¡æ©", |
["High Priestess of Thaurissan"] = "ç´¢ç森é«é女ç¥å¸", |
["Houndmaster Grebmar"] = "馴ç¬è æ ¼é·å¸çªç¾", |
["Hurley Blackbreath"] = "éç¾é·Â·é»é¬", |
["Lord Incendius"] = "ä¼æ£®è¿ªå¥§æ¯é 主", |
["Lord Roccor"] = "æ´èç¾é 主", |
["Magmus"] = "çªæ ¼å§æ¯", |
["Ok'thor the Breaker"] = "ãç ´å£è ã奧ç§ç´¢ç¾", |
["Panzor the Invincible"] = "ç¡æµçæ½ä½ç¾", |
["Phalanx"] = "æ³æå æ¯", |
["Plugger Spazzring"] = "æ®ææ ¼", |
["Princess Moira Bronzebeard"] = "èè¾æ·é é¬å ¬ä¸»", |
["Pyromancer Loregrain"] = "æ§ç«å¸«ç¾ æ ¼é·æ©", |
["Ribbly Screwspigot"] = "é·å¸é·æ¯åº«æ¯æ ¼ç¹", |
["Seeth'rel"] = "西æ¯é·ç¾", |
["The Seven Dwarves"] = "ä¸è³¢äºº", |
["Verek"] = "ç¶é·å ", |
["Vile'rel"] = "ç¦åé·ç¾", |
["Warder Stilgiss"] = "å®è¡æ¯è¿ªç¾åºæ¯", |
--Blackrock Spire |
--Lower |
["Bannok Grimaxe"] = "ç諾å ·巨æ§", |
["Burning Felguard"] = "ççæ¡éå®è¡", |
["Crystal Fang"] = "æ°´æ¶ä¹ç", |
["Ghok Bashguud"] = "éå ·巴ä»å¤å¾·", |
["Gizrul the Slavener"] = "ã奴役è ãåºè²ç§ç¾", |
["Halycon"] = "åé·è¯", |
["Highlord Omokk"] = "æè«å 大ç", |
["Mor Grayhoof"] = "è«ç¾Â·ç°è¹", |
["Mother Smolderweb"] = "ç 網èå", |
["Overlord Wyrmthalak"] = "ç¶å§è©æå 主宰", |
["Quartermaster Zigris"] = "è»éå®è²æ ¼é·æ¯", |
["Shadow Hunter Vosh'gajin"] = "æå½±çµææ²è¨±å æ¯", |
["Spirestone Battle Lord"] = "å°ç³æ°é¬¥çµ±å¸¥", |
["Spirestone Butcher"] = "å°ç³å± 夫", |
["Spirestone Lord Magus"] = "å°ç³é¦å¸éå°å¸«", |
["Urok Doomhowl"] = "çæ´å ", |
["War Master Voone"] = "ææ®å®æ²æ©", |
--Upper |
["General Drakkisath"] = "éåºè©æ¯å°è»", |
["Goraluk Anvilcrack"] = "å¤æé¯å ", |
["Gyth"] = "èæ¯", |
["Jed Runewatcher"] = "åå¾·", |
["Lord Valthalak"] = "ç¦è©æå é 主", |
["Pyroguard Emberseer"] = "çç°è¡å£«è¾åå¸ç¾", |
["Solakar Flamewreath"] = "ç´¢æå¡Â·ç«å ", |
["The Beast"] = "æ¯æ¯å·¨ç¸", |
["Warchief Rend Blackhand"] = "大é é·é·å¾·Â·é»æ", |
--Blackwing Lair |
["Broodlord Lashlayer"] = "é¾é 主å西é·ç¾", |
["Chromaggus"] = "å æ´çªå¤æ¯", |
["Ebonroc"] = "åå諾å ", |
["Firemaw"] = "è²»ç¾é»", |
["Flamegor"] = "å¼èæ ¼ç¾", |
["Grethok the Controller"] = "ãæ§å¶è ãèçæå ", |
["Lord Victor Nefarius"] = "ç¶å å¤Â·å¥æ³å©æ¯é 主", |
["Nefarian"] = "å¥æ³å©å®", |
["Razorgore the Untamed"] = "çéçæä½æ ¼ç¾", |
["Vaelastrasz the Corrupt"] = "墮è½çç¦ææ¯å¡è²", |
--Black Temple |
["Essence of Anger"] = "æ¤æç²¾è¯", |
["Essence of Desire"] = "æ ¾æç²¾è¯", |
["Essence of Suffering"] = "åé£ç²¾è¯", |
["Gathios the Shatterer"] = "ç²ç¢è é«å¸æ", |
["Gurtogg Bloodboil"] = "èå¡æ ¼Â·è¡æ²¸", |
["High Nethermancer Zerevor"] = "é«çè空è¡å¸«æçä½", |
["High Warlord Naj'entus"] = "é«éç£è»ç´çå¡æ¯", |
["Illidan Stormrage"] = "ä¼å©ä¸¹Â·æ風", |
["Illidari Council"] = "ä¼å©éçè°äº", |
["Lady Malande"] = "çªèé»å¥³å£«", |
["Mother Shahraz"] = "è©æè²å¥³å£«", |
["Reliquary of Souls"] = "ééä¹å£", |
["Shade of Akama"] = "é¿å¡çªçé»æé¢", |
["Supremus"] = "çæ®è«æ¯", |
["Teron Gorefiend"] = "æ³°æ·è¡é", |
["The Illidari Council"] = "ä¼å©éçè°äº", |
["Veras Darkshadow"] = "ç¶ææ¯Â·æ·±å½±", |
--Caverns of Time |
--Old Hillsbrad Foothills |
["Captain Skarloc"] = "å²å¡æå ä¸å°", |
["Epoch Hunter"] = "ç´å ç©çµè ", |
["Lieutenant Drake"] = "ä¸å°å´å ", |
--The Black Morass |
["Aeonus"] = "è¾å¥§é£æ¯", |
["Chrono Lord Deja"] = "æéé 主迪è³", |
["Medivh"] = "麥迪æ", |
["Temporus"] = "å¦æ®ææ¯", |
--Coilfang Reservoir |
--Serpentshrine Cavern |
["Coilfang Elite"] = "ç¤çç²¾è±", |
["Coilfang Strider"] = "ç¤çæ è¡è ", |
["Fathom-Lord Karathress"] = "深淵ä¹çå¡æè©çæ¯", |
["Hydross the Unstable"] = "ä¸ç©©å®è æµ·åå¸", |
["Lady Vashj"] = "ç¦è¨±å¥³å£«", |
["Leotheras the Blind"] = "ãç²ç®è ãæ奧è©ææ¯", |
["Morogrim Tidewalker"] = "è«æ´èå©å§Â·æ½®è¡è ", |
["Pure Spawn of Hydross"] = "ç´æ£çæµ·åå¸åå£", |
["Shadow of Leotheras"] = "æ奧è©ææ¯çé°å½±", |
["Tainted Spawn of Hydross"] = "è åçæµ·åå¸ä¹å", |
["The Lurker Below"] = "æµ·åºæ½ä¼è ", |
["Tidewalker Lurker"] = "æ½®è¡è æ½ä¼è ", |
--The Slave Pens |
["Mennu the Betrayer"] = "èåè æ¼ç´", |
["Quagmirran"] = "å¥å ç±³ç", |
["Rokmar the Crackler"] = "çè£è æ´å çª", |
["Ahune"] = "è¾è¡æ©", |
--The Steamvault |
["Hydromancer Thespia"] = "æµ·æ³å¸«å¸æ¯æ¯äº", |
["Mekgineer Steamrigger"] = "ç±³å åå·è¸æ°£ææ§è ", |
["Warlord Kalithresh"] = "ç£è»å¡å©æ¯ç", |
--The Underbog |
["Claw"] = "è£çª", |
["Ghaz'an"] = "é«è©å®", |
["Hungarfen"] = "飢é¤ä¹ç", |
["Overseer Tidewrath"] = "ç£ç£è æ³°æ´æ¯", |
["Swamplord Musel'ek"] = "沼澤ä¹çè«æ¯èå ", |
["The Black Stalker"] = "é»è²æçµè ", |
--Dire Maul |
--Arena |
["Mushgog"] = "å§æ¯é«æ ¼", |
["Skarr the Unbreakable"] = "ç¡æµçæ¯å¡ç¾", |
["The Razza"] = "ææ", |
--East |
["Alzzin the Wildshaper"] = "ãçéè®å½¢è ã奧è²æ©", |
["Hydrospawn"] = "æµ·å¤æ¯åæ©", |
["Isalien"] = "ä¾è©å©æ©", |
["Lethtendris"] = "è¾çå¡èçµ²", |
["Pimgib"] = "å¹å§åå¸", |
["Pusillin"] = "æ®å¸æ", |
["Zevrim Thornhoof"] = "çé·å§Â·åºè¹", |
--North |
["Captain Kromcrush"] = "å ç¾ å¡æ¯", |
["Cho'Rush the Observer"] = "ãè§å¯è ãå é¯ä»", |
["Guard Fengus"] = "è¡å µè¬å¤æ¯", |
["Guard Mol'dar"] = "è¡å µæ©ç¾é", |
["Guard Slip'kik"] = "è¡å µæ¯éåºå ", |
["King Gordok"] = "æå¤å 大ç", |
["Knot Thimblejack's Cache"] = "諾ç¹Â·å¸å§å å çå²ç©ç®±", |
["Stomper Kreeg"] = "è¸è¸è å é·æ ¼", |
--West |
["Illyanna Ravenoak"] = "ä¼ç³å¨Â·é´æ©¡", |
["Immol'thar"] = "ä¼è«å¡ç¾", |
["Lord Hel'nurath"] = "赫ç¾åªææ¯é 主", |
["Magister Kalendris"] = "å¡é·è¿ªæ¯é®é·", |
["Prince Tortheldrin"] = "æå¡å¾·æçå", |
["Tendris Warpwood"] = "ç¹è¿ªæ¯Â·ææ¨", |
["Tsu'zee"] = "èæ¯", |
--Gnomeregan |
["Crowd Pummeler 9-60"] = "群é«ææè 9-60", |
["Dark Iron Ambassador"] = "é»éµå¤§ä½¿", |
["Electrocutioner 6000"] = "é»åå¨6000å", |
["Grubbis"] = "æ ¼é¯æ¯æ¯", |
["Mekgineer Thermaplugg"] = "麥å å°¼ç¾Â·ççªæ®ææ ¼", |
["Techbot"] = "å°ç«¯æ©å¨äºº", |
["Viscous Fallout"] = "ç²æ§è¼»å°å¡µ", |
--Gruul's Lair |
["Blindeye the Seer"] = "å ç¥ç²ç¼", |
["Gruul the Dragonkiller"] = "å¼é¾è æé¯ç¾", |
["High King Maulgar"] = "大åçè«å¡ç¾", |
["Kiggler the Crazed"] = "çç²è å¥å å", |
["Krosh Firehand"] = "å ç¾ æ¯Â·ç«æ", |
["Olm the Summoner"] = "å¬åè æè«", |
--Hellfire Citadel |
--Hellfire Ramparts |
["Nazan"] = "ç´æ¡", |
["Omor the Unscarred"] = "ç¡ç¤è æçªç¾", |
["Vazruden the Herald"] = "ã信使ãç¶æ¯è·¯ç»", |
["Vazruden"] = "ç¶æ¯è·¯ç»", |
["Watchkeeper Gargolmar"] = "çè·è å¡ç¾å¤çª", |
--Magtheridon's Lair |
["Hellfire Channeler"] = "å°çç«å°é師", |
["Magtheridon"] = "çªçéé ", |
--The Blood Furnace |
["Broggok"] = "å¸æ´å ", |
["Keli'dan the Breaker"] = "ãç ´å£è ãå±å©ä¸¹", |
["The Maker"] = "åµé è ", |
--The Shattered Halls |
["Blood Guard Porung"] = "è¡è¡å£«æ³¢æ´å ", |
["Grand Warlock Nethekurse"] = "大è¡å£«å¥å¾·å æ¯", |
["Warbringer O'mrogg"] = "æ°ç製é è ·æå§ææ ¼", |
["Warchief Kargath Bladefist"] = "大é é·å¡å æ¯Â·åæ³", |
--Hyjal Summit |
["Anetheron"] = "å®ç´å¡é", |
["Archimonde"] = "é¿å èå¾·", |
["Azgalor"] = "äºè²å æ´", |
["Kaz'rogal"] = "å¡è²æ´å ", |
["Rage Winterchill"] = "çé½Â·åå¬", |
--Karazhan |
["Arcane Watchman"] = "ç§æ³è¦åè ", |
["Attumen the Huntsman"] = "çµäººé¿åæ¼", |
["Chess Event"] = "西æ´æ£äºä»¶", |
["Dorothee"] = "æ¡æ¨çµ²", |
["Dust Covered Chest"] = "滿ä½ç°å¡µç®±å", |
["Grandmother"] = "å¤å©", |
["Hyakiss the Lurker"] = "æ½ä¼è äºå¥æ¯", |
["Julianne"] = "è±éºè", |
["Kil'rek"] = "åºçå ", |
["King Llane Piece"] = "èæ©çæ£å", |
["Maiden of Virtue"] = "è²æ½è女", |
["Midnight"] = "åå¤", |
["Moroes"] = "æ©æ´", |
["Netherspite"] = "尼德æ¯", |
["Nightbane"] = "å¤ç¦", |
["Prince Malchezaar"] = "è«å æçå", |
["Restless Skeleton"] = "æ°¸ä¸å®æ¯ç骷é«", |
["Roar"] = "ç å", |
["Rokad the Ravager"] = "å«æ¯è æå¡", |
["Romulo & Julianne"] = "ç¾ æ æèè±éºè", |
["Romulo"] = "ç¾ æ æ", |
["Shade of Aran"] = "åèä¹å½±", |
["Shadikith the Glider"] = "æ»ç¿è è迪ä¾æ¯", |
["Strawman"] = "稻è人", |
["Terestian Illhoof"] = "æ³°çæ¯æå®Â·ç«è¹", |
["The Big Bad Wolf"] = "大éç¼", |
["The Crone"] = "èå·«å©", |
["The Curator"] = "館é·", |
["Tinhead"] = "æ©å¨äºº", |
["Tito"] = "å¤å¤", |
["Warchief Blackhand Piece"] = "é»æ大é é·æ£å", |
-- Magisters' Terrace |
["Kael'thas Sunstrider"] = "å±ç¾è©æ¯Â·éæ¥è ", |
["Priestess Delrissa"] = "女ç§å¸«æ´å©è", |
["Selin Fireheart"] = "è³½æ·çå¿", |
["Vexallus"] = "ç¶å ç´¢é¯æ¯", |
--Maraudon |
["Celebras the Cursed"] = "被è©åçå¡é·å¸ææ¯", |
["Gelk"] = "åç¾å ", |
["Kolk"] = "èç¾å ", |
["Landslide"] = "èæ¯å©å¾·", |
["Lord Vyletongue"] = "ç¶å©å¡æ©é 主", |
["Magra"] = "çªæ ¼æ", |
["Maraudos"] = "çªæå¤æ¯", |
["Meshlok the Harvester"] = "ãæ¶å²è ã麥ä»æ´å ", |
["Noxxion"] = "諾å è³½æ©", |
["Princess Theradras"] = "çèå¾·çµ²å ¬ä¸»", |
["Razorlash"] = "é³åºéç¬è ", |
["Rotgrip"] = "æ´ç¹æ ¼éæ®", |
["Tinkerer Gizlock"] = "æå·¥åè²æ´å ", |
["Veng"] = "æº«æ ¼", |
--Molten Core |
["Baron Geddon"] = "迦é ç·çµ", |
["Cache of the Firelord"] = "ç«ç°ä¹çç寶箱", |
["Garr"] = "å ç¾", |
["Gehennas"] = "åºèµ«ç´æ¯", |
["Golemagg the Incinerator"] = "ãçåè ãå¤é·æ¼æ ¼", |
["Lucifron"] = "é¯è¥¿å¼é", |
["Magmadar"] = "çªæ ¼æ¼é", |
["Majordomo Executus"] = "管çè åå ç´¢åæ¯", |
["Ragnaros"] = "ææ ¼ç´ç¾ æ¯", |
["Shazzrah"] = "æ²æ¯æç¾", |
["Sulfuron Harbinger"] = "è©å¼éå é© è ", |
--Naxxramas |
["Anub'Rekhan"] = "é¿åªæ¯çå æ¼¢", |
["Deathknight Understudy"] = "æ»äº¡é¨å£«å¯¦ç¿è ", |
["Feugen"] = "ä¼æ¨", |
["Four Horsemen Chest"] = "åé¨å£«ç®±å", |
["Gluth"] = "å¤é¯æ¯", |
["Gothik the Harvester"] = "ãæ¶å²è ãé«å¸", |
["Grand Widow Faerlina"] = "大寡婦費ç³å¨", |
["Grobbulus"] = "èç¾ å·´æ¯", |
["Heigan the Unclean"] = "ã骯é«è ãæµ·æ ¹", |
["Highlord Mograine"] = "大é 主è«æ ¼èå°¼", |
["Instructor Razuvious"] = "è¬å¸«æç¥ç¶æ¯", |
["Kel'Thuzad"] = "ç§ç¾èå å¾·", |
["Lady Blaumeux"] = "å¸æ´è«æ¯å¥³å£«", |
["Loatheb"] = "ææ¨è ", |
["Maexxna"] = "æ¢ å çµ²å¨", |
["Noth the Plaguebringer"] = "ãçç«ä½¿è ã諾æ¯", |
["Patchwerk"] = "縫è£è ", |
["Sapphiron"] = "è©è²é", |
["Sir Zeliek"] = "æéå çµå£«", |
["Stalagg"] = "æ¯å¡ææ ¼", |
["Thaddius"] = "泰迪æ¯", |
["Thane Korth'azz"] = "å¯æ¯è¾è²æé·", |
["The Four Horsemen"] = "åé¨å£«", |
--Onyxia's Lair |
["Onyxia"] = "奧妮å å¸äº", |
--Ragefire Chasm |
["Bazzalan"] = "å·´æè", |
["Jergosh the Invoker"] = "ãå¡è½å¸«ãè¶æä»", |
["Maur Grimtotem"] = "çªç¾Â·ææå騰", |
["Taragaman the Hungerer"] = "ã飢é¤è ãå¡æå æ¼", |
--Razorfen Downs |
["Amnennar the Coldbringer"] = "ãå¯å°ä½¿è ãäºéç´ç¾", |
["Glutton"] = "æ´é£è ", |
["Mordresh Fire Eye"] = "ç«ç¼è«å¾·é·æ¯", |
["Plaguemaw the Rotting"] = "è ççæ®é·è«ç¾", |
["Ragglesnout"] = "æææ¯è«¾ç¹", |
["Tuten'kash"] = "åç¹å¡ä»", |
--Razorfen Kraul |
["Agathelos the Raging"] = "æ´æçé¿è¿¦è³½ç¾ æ¯", |
["Blind Hunter"] = "ç²ç¼çµæ", |
["Charlga Razorflank"] = "å¡ç¾å ·åºè", |
["Death Speaker Jargba"] = "亡èªè è³æ ¼å·´", |
["Earthcaller Halmgar"] = "åå°è åç©å ", |
["Overlord Ramtusk"] = "æå§å¡æ¯ä¸»å®°", |
--Ruins of Ahn'Qiraj |
["Anubisath Guardian"] = "é¿åªæ¯è©æ¯å®è¡è ", |
["Ayamiss the Hunter"] = "ãç©çµè ãé¿äºç±³æ¯", |
["Buru the Gorger"] = "ãæ´é£è ãå¸é¯", |
["General Rajaxx"] = "æè³å æ¯å°è»", |
["Kurinnaxx"] = "庫æç´å æ¯", |
["Lieutenant General Andorov"] = "å®å¤æ´å¤«ä¸å°", |
["Moam"] = "è«é¿å§", |
["Ossirian the Unscarred"] = "ãç¡ç¤è ã奧æ¯éå®", |
--Scarlet Monastery |
--Armory |
["Herod"] = "赫æ´å¾·", |
--Cathedral |
["High Inquisitor Fairbanks"] = "é«ç審å¤å®æ³ç¾çå æ¯", |
["High Inquisitor Whitemane"] = "é«ç審å¤å®æ·ç¹éæ©", |
["Scarlet Commander Mograine"] = "è¡è²ååè»ææ®å®è«æ ¼èå°¼", |
--Graveyard |
["Azshir the Sleepless"] = "ä¸ç çè¾å¸ç¾", |
["Bloodmage Thalnos"] = "è¡æ³å¸«è©ç¾è«¾æ¯", |
["Fallen Champion"] = "亡éå士", |
["Interrogator Vishas"] = "審è¨å¡éæ²æ¯", |
["Ironspine"] = "éµèæ»é", |
["Headless Horseman"] = "ç¡é é¨å£«", |
--Library |
["Arcanist Doan"] = "ç§æ³å¸«æå®", |
["Houndmaster Loksey"] = "馴ç¬è æ´å å¸", |
--Scholomance |
["Blood Steward of Kirtonos"] = "åºç¾å諾æ¯çè¡å£«", |
["Darkmaster Gandling"] = "é»æé¢é·å ä¸", |
["Death Knight Darkreaver"] = "æ»äº¡é¨å£«éå é·ç¾", |
["Doctor Theolen Krastinov"] = "çç¾æ·å¡æ¯è¿ªè«¾å¤«ææ", |
["Instructor Malicia"] = "è¬å¸«çªéºå¸äº", |
["Jandice Barov"] = "詹迪æ¯Â·å·´ç¾ 夫", |
["Kirtonos the Herald"] = "å³ä»¤å®åºç¾å諾æ¯", |
["Kormok"] = "ç§ç¾è«å ", |
["Lady Illucia Barov"] = "ä¼é²å¸äºÂ·å·´ç¾ 夫女士", |
["Lord Alexei Barov"] = "é¿èå æ¯Â·å·´ç¾ 夫é 主", |
["Lorekeeper Polkelt"] = "åå¸è æ®å ç¾ç¹", |
["Marduk Blackpool"] = "馬æå ·å¸èå æ³¢ç¾", |
["Ras Frostwhisper"] = "èæ¯Â·éèª", |
["Rattlegore"] = "è¡éª¨åå¡", |
["The Ravenian"] = "ææå°¼äº", |
["Vectus"] = "ç¶å åæ¯", |
--Shadowfang Keep |
["Archmage Arugal"] = "大æ³å¸«é¿é¯é«", |
["Arugal's Voidwalker"] = "é¿é¯é«çèç¡è¡è ", |
["Baron Silverlaine"] = "å¸ç¦èæ©ç·çµ", |
["Commander Springvale"] = "ææ®å®æ¯æ®æç¦ç¾", |
["Deathsworn Captain"] = "æ»äº¡èªè¨è éé·", |
["Fenrus the Devourer"] = "ãåå¬è ãè¬é¯æ¯", |
["Odo the Blindwatcher"] = "ãç²ç¼å®è¡ã奧æ", |
["Razorclaw the Butcher"] = "å± å¤«æä½å å", |
["Wolf Master Nandos"] = "ç¼çåææ¯", |
--Stratholme |
["Archivist Galford"] = "æªæ¡ç®¡çå¡å ç¾ç¦ç¹", |
["Balnazzar"] = "å·´ç´æç¾", |
["Baron Rivendare"] = "çææ´ç¾ç·çµ", |
["Baroness Anastari"] = "å®å¨çµ²å¡éºç·çµå¤«äºº", |
["Black Guard Swordsmith"] = "é»è¡£å®è¡éå師", |
["Cannon Master Willey"] = "ç ²æå¨å©", |
["Crimson Hammersmith"] = "ç´ è¡£éé師", |
["Fras Siabi"] = "å¼ææ¯Â·å¸äºæ¯", |
["Hearthsinger Forresten"] = "å¼é·æ¯ç¹æ©", |
["Magistrate Barthilas"] = "å·´çææ¯é®é·", |
["Maleki the Pallid"] = "è¼ç½ççªååº", |
["Nerub'enkan"] = "å¥å¹½å¸æ©å", |
["Postmaster Malown"] = "éµå·®çªç¾ æ©", |
["Ramstein the Gorger"] = "ãæ´é£è ãæå§æ¯ç»", |
["Skul"] = "æ¯åº«ç¾", |
["Stonespine"] = "ç³è", |
["The Unforgiven"] = "ä¸å¯å¯¬æè ", |
["Timmy the Cruel"] = "æ²æ çæç±³", |
--Sunwell Plateau |
["Kalecgos"] = "å¡é·èæ¯", |
["Sathrovarr the Corruptor"] = "ã墮è½è ãå¡æ¯è«¾ç¦", |
["Brutallus"] = "å¸é¯æé¯æ¯", |
["Felmyst"] = "éé¾è¬é§", |
["The Eredar Twins"] = "åé·éç¾éå", |
["Kil'jaeden"] = "åºç¾å 丹", |
["M'uru"] = "è«é¯", |
["Entropius"] = "å®åæ®æ¯", |
["Lady Sacrolash"] = "èçè¾å¸å¥³å£«", |
["Grand Warlock Alythess"] = "大è¡å£«è¾é»ççµ²", |
--Tempest Keep |
--The Arcatraz |
["Dalliah the Doomsayer"] = "æ«æ¥é è¨è éå©äº", |
["Harbinger Skyriss"] = "å é© è å²èåå¸", |
["Warden Mellichar"] = "çå®è ç±³å©æ°ç¾", |
["Wrath-Scryer Soccothrates"] = "æé®è ç´¢å¯æ¯çç¹", |
["Zereketh the Unbound"] = "ç¡ç´æçå¸çå¥æ¯", |
--The Botanica |
["Commander Sarannis"] = "ææ®å®è©çå°¼æ¯", |
["High Botanist Freywinn"] = "大æ¤ç©å¸å®¶è²»çè¡æ©", |
["Laj"] = "ææ°", |
["Thorngrin the Tender"] = "ãç管è ãç´¢å¤æ", |
["Warp Splinter"] = "ææ²åè£è ", |
--The Eye |
["Al'ar"] = "æç¾", |
["Cosmic Infuser"] = "å®å®çæºè ", |
["Devastation"] = "æ¯æ» ", |
["Grand Astromancer Capernian"] = "大æè¡å¸«å¡æ®å°¼æ©", |
["High Astromancer Solarian"] = "é«éæè¡å¸«ç´¢æçæ©", |
["Infinity Blades"] = "ç¡ç¡ä¹å", |
["Kael'thas Sunstrider"] = "å±ç¾è©æ¯Â·éæ¥è ", |
["Lord Sanguinar"] = "æ¡å¤ç´ç¾é 主", |
["Master Engineer Telonicus"] = "å·¥ç¨å¤§å¸«æ³°éå°¼å¡æ¯", |
["Netherstrand Longbow"] = "è空ä¹çµé·å¼", |
["Phaseshift Bulwark"] = "ç¸ä½å£å£", |
["Solarium Agent"] = "æ¥å ä¹å®¤å¯æ¢", |
["Solarium Priest"] = "æ¥å ä¹å®¤ç§å¸«", |
["Staff of Disintegration"] = "ç¦è§£ä¹æ", |
["Thaladred the Darkener"] = "ææ²é è¨å®¶è©æçå¾·", |
["Void Reaver"] = "èç¡æ¶å¥ªè ", |
["Warp Slicer"] = "ææ²åå²è ", |
--The Mechanar |
["Gatewatcher Gyro-Kill"] = "çå®è èæ´å¥æ", |
["Gatewatcher Iron-Hand"] = "çå®è éµæ", |
["Mechano-Lord Capacitus"] = "æ©æ¢°çå¡å¸å¸ç¹æ¯", |
["Nethermancer Sepethrea"] = "è空è¡å¸«è³½è²çé ", |
["Pathaleon the Calculator"] = "æ縱è å¸è©éæ", |
--The Deadmines |
["Brainwashed Noble"] = "被æ´è ¦çè²´æ", |
["Captain Greenskin"] = "ç¶ ç®éé·", |
["Cookie"] = "å»å¸«", |
["Edwin VanCleef"] = "è¾å¾·æº«Â·èå é夫", |
["Foreman Thistlenettle"] = "å·¥é å¸æ¯èç¹", |
["Gilnid"] = "åºç¾å°¼æ ¼", |
["Marisa du'Paige"] = "çªéè·ææ´¾æ ¼", |
["Miner Johnson"] = "礦工ç´ç¿°æ£®", |
["Mr. Smite"] = "éæ³å ç", |
["Rhahk'Zor"] = "æå ä½", |
["Sneed"] = "æ¯å°¼å¾·", |
["Sneed's Shredder"] = "æ¯å°¼å¾·çä¼æ¨æ©", |
--The Stockade |
["Bazil Thredd"] = "å·´åºç¾Â·æ¯çå¾·", |
["Bruegal Ironknuckle"] = "å¸é¯æ·è¾ç¾å ç´å¯", |
["Dextren Ward"] = "迪å æ¯ç¹Â·ç¦å¾·", |
["Hamhock"] = "åå§éå ", |
["Kam Deepfury"] = "å¡å§Â·æ·±æ", |
["Targorr the Dread"] = "å¯æçå¡é«ç¾", |
--The Temple of Atal'Hakkar |
["Atal'alarion"] = "é¿å¡æå©æ©", |
["Avatar of Hakkar"] = "åå¡çå身", |
["Dreamscythe"] = "å¾·å§å¡å¡ç¾", |
["Gasher"] = "å ä»ç¾", |
["Hazzas"] = "åææ¯", |
["Hukku"] = "è¡åº«", |
["Jade"] = "çé¾", |
["Jammal'an the Prophet"] = "ãé è¨è ã迦çªè", |
["Kazkaz the Unholy"] = "éªæ¡çå¡è©å¡è²", |
["Loro"] = "æ´è¥ç¾", |
["Mijan"] = "ç±³æ", |
["Morphaz"] = "æ©å¼ææ¯", |
["Ogom the Wretched"] = "å¯æ²ç奧æå§", |
["Shade of Eranikus"] = "ä¼è尼庫æ¯çé°å½±", |
["Veyzhak the Cannibal"] = "ãé£äººè ãç¶è©å ", |
["Weaver"] = "å¾·æç¶æ²ç¾", |
["Zekkis"] = "澤åºæ¯", |
["Zolo"] = "ç¥ç¾ ", |
["Zul'Lor"] = "ç¥ç¾ ç¾", |
--Uldaman |
["Ancient Stone Keeper"] = "å¤ä»£çç³é çå®è ", |
["Archaedas"] = "é¿æéæ¯", |
["Baelog"] = "å·´ç¾æ´æ", |
["Digmaster Shovelphlange"] = "ææå°å®¶èç¾å¼ææ ¼", |
["Galgann Firehammer"] = "å å æ©Â·ç«é", |
["Grimlok"] = "æ ¼çå§æ´å ", |
["Ironaya"] = "è¾éç´äº", |
["Obsidian Sentinel"] = "é»æç³å¨å µ", |
["Revelosh"] = "é¯ç¶ç¾ ä»", |
--Wailing Caverns |
["Boahn"] = "åè¾æ©", |
["Deviate Faerie Dragon"] = "è®ç°ç²¾éé¾", |
["Kresh"] = "å é·ä»", |
["Lady Anacondra"] = "å®å¨ç§å¾·æ", |
["Lord Cobrahn"] = "èå¸èæ©é 主", |
["Lord Pythas"] = "ç®è©æ¯é 主", |
["Lord Serpentis"] = "çè¬è¿ªæ¯é 主", |
["Mad Magglish"] = "çççé¦¬æ ¼å©ä»", |
["Mutanus the Devourer"] = "ãåå¬è ãç©å¦åªæ¯", |
["Skum"] = "æ¯å¡å§", |
["Trigore the Lasher"] = "ãéç¬è ãç¹éé«é·", |
["Verdan the Everliving"] = "æ°¸ççæ²ç¾ä¸¹", |
--World Bosses |
["Avalanchion"] = "é¿ç¦èå¥å¥§", |
["Azuregos"] = "è¾ç´¢é·èæ¯", |
["Baron Charr"] = "ç«ç°ç·çµæ¥ç¾", |
["Baron Kazum"] = "å¡èå§ç·çµ", |
["Doom Lord Kazzak"] = "æ¯æ» é 主å¡æå ", |
["Doomwalker"] = "åéè¡è ", |
["Emeriss"] = "è¾è«èçµ²", |
["High Marshal Whirlaxis"] = "大å 帥ç¶æå¸æ¯", |
["Lethon"] = "é·ç´¢", |
["Lord Skwol"] = "æ¯å¤æ©é 主", |
["Prince Skaldrenox"] = "æ¯å¡å¾·è«¾å æ¯çå", |
["Princess Tempestria"] = "æ³°æ¯æ¯èäºå ¬ä¸»", |
["Taerar"] = "æ³°æç¾", |
["The Windreaver"] = "ç風æ¶å¥ªè ", |
["Ysondre"] = "ä¼ç´¢å¾·é·", |
--Zul'Aman |
["Akil'zon"] = "é¿å¥ç¾æ£®", |
["Halazzi"] = "åæé½", |
["Jan'alai"] = "è³ç´é·", |
["Malacrass"] = "çªæå é·æ¯", |
["Nalorakk"] = "ç´ç¾ æå ", |
["Zul'jin"] = "ç¥ç¾é", |
["Hex Lord Malacrass"] = "å¦è¡é 主çªæå é·æ¯", -- confirm ? |
--Zul'Farrak |
["Antu'sul"] = "å®åèç¾", |
["Chief Ukorz Sandscalp"] = "çå è²Â·æ²é ", |
["Dustwraith"] = "ç°å¡µæ¨é", |
["Gahz'rilla"] = "å è²çæ", |
["Hydromancer Velratha"] = "æ°´å 師ç¶è¾è©", |
["Murta Grimgut"] = "è«ç¾å¡", |
["Nekrum Gutchewer"] = "èå é¯å§", |
["Oro Eyegouge"] = "æé¯Â·é¿ç¼", |
["Ruuzlu"] = "ç§è²é¯", |
["Sandarr Dunereaver"] = "æéç¾Â·æ²æ è ", |
["Sandfury Executioner"] = "æ²æååæ", |
["Sergeant Bly"] = "å¸èä¸å£«", |
["Shadowpriest Sezz'ziz"] = "æå½±ç¥å¸å¡çæ¯", |
["Theka the Martyr"] = "ãæ®æè ãå¡å¡", |
["Witch Doctor Zum'rah"] = "å·«é«Â·ç¥ç©ææ©", |
["Zerillis"] = "澤é·å©æ¯", |
["Zul'Farrak Dead Hero"] = "ç¥ç¾æ³æå é£äº¡è±é", |
--Zul'Gurub |
["Bloodlord Mandokir"] = "è¡é 主æ¼å¤åºç¾", |
["Gahz'ranka"] = "å è²èå¡", |
["Gri'lek"] = "æ ¼éé·å ", |
["Hakkar"] = "åå¡", |
["Hazza'rah"] = "åææç¾", |
["High Priest Thekal"] = "é«éç¥å¸å¡å¡ç¾", |
["High Priest Venoxis"] = "é«éç¥å¸æº«è«¾å¸æ¯", |
["High Priestess Arlokk"] = "åå¡èå ç¥", |
["High Priestess Jeklik"] = "é«éç¥å¸è¶å éå ", |
["High Priestess Mar'li"] = "åå¡èå®éè ", |
["Jin'do the Hexxer"] = "ãå¦è¡å¸«ãé度", |
["Renataki"] = "é·ç´å¡åº", |
["Wushoolay"] = "çèé·", |
--Ring of Blood (where? an instnace? should be in other file?) |
["Brokentoe"] = "æ·è¶¾", |
["Mogor"] = "è«å¤", |
["Murkblood Twin"] = "é»æä¹è¡éå", |
["Murkblood Twins"] = "é»æä¹è¡éå", |
["Rokdar the Sundered Lord"] = "ãç¢è£é 主ãæ´å é", |
["Skra'gath"] = "å²å¡æå æ¯", |
["The Blue Brothers"] = "æ鬱å å¼é»¨", |
["Warmaul Champion"] = "æ°æ§å士", |
} |
elseif GAME_LOCALE == "koKR" then |
lib:SetCurrentTranslations { |
--Ahn'Qiraj |
["Anubisath Defender"] = "ìëë¹ì¬ì¤ 문ì§ê¸°", |
["Battleguard Sartura"] = "ì í¬ê°ìë³ ì´í¬ë¼", |
["C'Thun"] = "ì¨", |
["Emperor Vek'lor"] = "ì ì ë² í´ë¡ì´", |
["Emperor Vek'nilash"] = "ì ì ë² í¬ëë¼ì¬", |
["Eye of C'Thun"] = "ì¨ì ë", |
["Fankriss the Unyielding"] = "ë¶êµ´ì íí¬ë¦¬ì¤", |
["Lord Kri"] = "군주 í¬ë¦¬", |
["Ouro"] = "ìì°ë¡", |
["Princess Huhuran"] = "공주 ííë", |
["Princess Yauj"] = "공주 ì¼ì°ì¦", |
["The Bug Family"] = "ë²ë 무리", |
["The Prophet Skeram"] = "ìì¸ì ì¤ì¼ë", |
["The Twin Emperors"] = "ìë¥ì´ ì ì", |
["Vem"] = "ë²°", |
["Viscidus"] = "ë¹ìëì°ì¤", |
--Auchindoun |
--Auchenai Crypts |
["Exarch Maladaar"] = "ì´ë ë§ë¼ë¤ë¥´", |
["Shirrak the Dead Watcher"] = "죽ìì ê°ìì¸ ì´ë¼í¬", |
--Mana-Tombs |
["Nexus-Prince Shaffar"] = "ì°í©ìì ì¤í르", |
["Pandemonius"] = "í¬ë모ëì°ì¤", |
["Tavarok"] = "íë°ë¡í¬", |
--Shadow Labyrinth |
["Ambassador Hellmaw"] = "ì¬ì ì§ì¥ìê·", |
["Blackheart the Inciter"] = "ì ëì ê²ìì¬ì¥", |
["Grandmaster Vorpil"] = "ë¨ì¥ 보르í", |
["Murmur"] = "ì¸ë¦¼", |
--Sethekk Halls |
["Anzu"] = "ì주", --summoned boss |
["Darkweaver Syth"] = "íë§ì ì¬ ìì¤", |
["Talon King Ikiss"] = "ê°í´ëì ì´í¤ì¤", |
--Blackfathom Deeps |
["Aku'mai"] = "ìì¿ ë§ì´", |
["Baron Aquanis"] = "ë¨ì ìì¿ ìëì¤", |
["Gelihast"] = "ê²ë¦¬íì¤í¸", |
["Ghamoo-ra"] = "ê°ë¬´ë¼ ", |
["Lady Sarevess"] = "ì¬ì ì¬ë ë² ì¤", |
["Old Serra'kis"] = "ëì ì¸ë¼í¤ì¤", |
["Twilight Lord Kelris"] = "í©í¼ì 군주 ì¼ë¦¬ì¤", |
--Blackrock Depths |
["Ambassador Flamelash"] = "ì¬ì íì¼ì±ì°", |
["Anger'rel"] = "ê²©ë ¸ì 문ì§ê¸°", |
["Anub'shiah"] = "ìëì¬ì", |
["Bael'Gar"] = "벨ê°ë¥´", |
["Chest of The Seven"] = "Chest of The Seven", |
["Doom'rel"] = "ì´ëª ì 문ì§ê¸°", |
["Dope'rel"] = "ìµë©´ì 문ì§ê¸°", |
["Emperor Dagran Thaurissan"] = "ì ì ë¤ê·¸ë íì°ë¦¿ì°", |
["Eviscerator"] = "ì ì¶ì", |
["Fineous Darkvire"] = "íì´ëì¤ ë¤í¬ë°ì´ì´", |
["General Angerforge"] = "ì¬ë ¹ê´ ìµê±°í¬ì§", |
["Gloom'rel"] = "ê·¸ëì 문ì§ê¸°", |
["Golem Lord Argelmach"] = "골ë 군주 ìì ¤ë§í¬", |
["Gorosh the Dervish"] = "ê´ì ì ê³ ë¡ì¬", --check |
["Grizzle"] = "그리ì¦", |
["Hate'rel"] = "ì¦ì¤ì 문ì§ê¸°", |
["Hedrum the Creeper"] = "ì거미 í¤ë룸", |
["High Interrogator Gerstahn"] = "ëì¬ë¬¸ê´ ê²ë¥´ì¤í", |
["High Priestess of Thaurissan"] = "íì°ë¦¿ì°ì ëì¬ì¬ì ", |
["Houndmaster Grebmar"] = "ì¬ë¥ê°ì¡°ë ¨ì¬ ê·¸ë ë§ë¥´", |
["Hurley Blackbreath"] = "íë ì´ ë¸ëë¸ë ì¤", |
["Lord Incendius"] = "군주 ì¸ì¼ëì°ì¤", |
["Lord Roccor"] = "ë¶ì군주 ë¡ì½ë¥´", |
["Magmus"] = "ë§ê·¸ë¬´ì¤", |
["Ok'thor the Breaker"] = "íê´´ì ì¤í¬í 르", |
["Panzor the Invincible"] = "무ì ì íì ", |
["Phalanx"] = "íëì¤", |
["Plugger Spazzring"] = "íë¬ê±°ì¤íì¦ë§", |
["Princess Moira Bronzebeard"] = "공주 모ì´ë¼ ë¸ë¡ ì¦ë¹ì´ë", |
["Pyromancer Loregrain"] = "íì¼ì ì¬ ë¡ì´ê·¸ë ì¸", |
["Ribbly Screwspigot"] = "리ë¸ë¦¬ ì¤í¬ë¥ì¤í¼ê³³", |
["Seeth'rel"] = "ë¶ìì 문ì§ê¸°", |
["The Seven Dwarves"] = "The Seven Dwarves", |
["Verek"] = "ë² ë í¬", |
["Vile'rel"] = "íë½ì 문ì§ê¸°", |
["Warder Stilgiss"] = "문ì§ê¸° ì¤í¸ê¸°ì¤", |
--Blackrock Spire |
--Lower |
["Bannok Grimaxe"] = "ë°ë ¸í¬ 그림ì¡ì¤", |
["Burning Felguard"] = "ë¶íë ì§ì¥ìí¸ë³", |
["Crystal Fang"] = "ìì 맹ë 거미", |
["Ghok Bashguud"] = "ê³ í¬ ë°°ì구ë", |
["Gizrul the Slavener"] = "íí¬í 기ì¦ë£°", |
["Halycon"] = "í 리ì½", |
["Highlord Omokk"] = "ë군주 ì¤ëª¨í¬", |
["Mor Grayhoof"] = "모르 ê·¸ë ì´íí", |
["Mother Smolderweb"] = "ì¬ì ë¶ê·¸ë¬¼ê±°ë¯¸", |
["Overlord Wyrmthalak"] = "ë군주 ìíë¼í¬", |
["Quartermaster Zigris"] = "ë³ì°¸ì¥êµ ì§ê·¸ë¦¬ì¤", |
["Shadow Hunter Vosh'gajin"] = "ì´ë ì¬ë¥ê¾¼ ë³´ì¬ê°ì§", |
["Spirestone Battle Lord"] = "뾰족ë°ìì¼ì¡± ì í¬ëì¥", |
["Spirestone Butcher"] = "뾰족ë°ìì¼ì¡± íì´ì", |
["Spirestone Lord Magus"] = "뾰족ë°ìì¼ì¡± ë§ë²ì¬ì¥", |
["Urok Doomhowl"] = "ì°ë¥´í¬ ë íì¸", |
["War Master Voone"] = "ëì¥êµ° ë¶ë¤", |
--Upper |
["General Drakkisath"] = "ì¬ë ¹ê´ ëë¼í¤ì¬ì¤", |
["Goraluk Anvilcrack"] = "ê³ ëë£¨í¬ ì¤ë¹í¬ë", |
["Gyth"] = "기ì¤", |
["Jed Runewatcher"] = "ì ë 룬ìì²", |
["Lord Valthalak"] = "군주 ë°íë¼í¬", |
["Pyroguard Emberseer"] = "ë¶ì ìí¸ì ì ë²ìì´", |
["Solakar Flamewreath"] = "íì¼ê³ 리 ìë¼ì¹´ë¥´", |
["The Beast"] = "ê´´ì", |
["Warchief Rend Blackhand"] = "ëì¡±ì¥ ë ë ë¸ëí¸ë", |
--Blackwing Lair |
["Broodlord Lashlayer"] = "ì©ê¸°ëì¥ ëì¬ë ì´ì´", |
["Chromaggus"] = "í¬ë¡ë§êµ¬ì¤", |
["Ebonroc"] = "ì본ë¡í¬", |
["Firemaw"] = "íì¼ìê·", |
["Flamegor"] = "íë ìê³ ë¥´", |
["Grethok the Controller"] = "ê°ìì ê·¸ë í í¬", |
["Lord Victor Nefarius"] = "군주 ë¹ í° ë¤í리ì°ì¤", |
["Nefarian"] = "ë¤í리ì", |
["Razorgore the Untamed"] = "íêµ° ìì¬ì¡ê³³ë", |
["Vaelastrasz the Corrupt"] = "íë½í ë°¸ë¼ì¤í¸ë¼ì¦", |
--Black Temple |
["Essence of Anger"] = "ê²©ë ¸ì ì ì", |
["Essence of Desire"] = "ìë§ì ì ì", |
["Essence of Suffering"] = "ê³ ëì ì ì", |
["Gathios the Shatterer"] = "íê´´ì ê°ëì¤ì¤", |
["Gurtogg Bloodboil"] = "구르í ê·¸ ë¸ë¬ëë³´ì¼", -- check |
["High Nethermancer Zerevor"] = "ê³ ì í©ì²ì ì¬ ì ë 보르", |
["High Warlord Naj'entus"] = "ëì¥êµ° ëì í¬ì¤", |
["Illidan Stormrage"] = "ì¼ë¦¬ë¨ ì¤í°ë ì´ì§", |
["Illidari Council"] = "ì¼ë¦¬ë¤ë¦¬ ìí", |
["Lady Malande"] = "ì¬êµ°ì£¼ ë§ëë°", |
["Mother Shahraz"] = "ë모 ì¤ë¼ì¦", |
["Reliquary of Souls"] = "ìí¼ì ì±ë¬¼í¨", |
["Shade of Akama"] = "ìì¹´ë§ì ë§ë ¹", |
["Supremus"] = "ê¶ê·¹ì ì¬ì°", |
["Teron Gorefiend"] = "í ë¡ ê³ ì´íë", |
["The Illidari Council"] = "ì¼ë¦¬ë¤ë¦¬ ìí", -- check |
["Veras Darkshadow"] = "ë² ë¼ì¤ ë¤í¬ìë", |
--Caverns of Time |
--Old Hillsbrad Foothills |
["Captain Skarloc"] = "ê²½ë¹ëì¥ ì¤ì¹¼ë¡", |
["Epoch Hunter"] = "ìëì ì¬ë¥ê¾¼", |
["Lieutenant Drake"] = "ë¶ê´ ëë ì´í¬", |
--The Black Morass |
["Aeonus"] = "ììëì¤", |
["Chrono Lord Deja"] = "ìê°ì 군주 ë°ì", |
["Medivh"] = "ë©ëë¸", |
["Temporus"] = "í í¼ë£¨ì¤", |
--Coilfang Reservoir |
--Serpentshrine Cavern |
["Coilfang Elite"] = "ê°í´ì¡ê³³ë ì ìë³", |
["Coilfang Strider"] = "ê°í´ì¡ê³³ë í¬ìì", |
["Fathom-Lord Karathress"] = "ì¬ì°ì 군주 ì¹´ë¼ëë ì¤", |
["Hydross the Unstable"] = "ë¶ìì í íëë¡ì¤", |
["Lady Vashj"] = "ì¬êµ°ì£¼ ë°ì¬", |
["Leotheras the Blind"] = "ë먼 ë ì¤í ë¼ì¤", |
["Morogrim Tidewalker"] = "ê² ë¥íë 모ë¡ê·¸ë¦¼", |
["Pure Spawn of Hydross"] = "ììí íëë¡ì¤ì í¼ì¡°ë¬¼", |
["Shadow of Leotheras"] = "ë ì¤í ë¼ì¤ì 그림ì", |
["Tainted Spawn of Hydross"] = "ì¤ì¼ë íëë¡ì¤ì í¼ì¡°ë¬¼", |
["The Lurker Below"] = "ì¬ì°ì ì 복꾼", |
["Tidewalker Lurker"] = "ê² ë¥íë ì 복꾼", |
--The Slave Pens |
["Mennu the Betrayer"] = "ë°°ë°ì ë©ë", |
["Quagmirran"] = "ì¿ ì그미ë", |
["Rokmar the Crackler"] = "ë±ë±ì´ ë¡í¬ë§ë¥´", |
["Ahune"] = "ìí", |
--The Steamvault |
["Hydromancer Thespia"] = "íìì¬ ì¸ì¤í¼ì", |
["Mekgineer Steamrigger"] = "기ê³ê³µíì ì¤í리거", |
["Warlord Kalithresh"] = "ì¥êµ° 칼리ì¤ë ì¬", |
--The Underbog |
["Claw"] = "í´ë¡", |
["Ghaz'an"] = "ê°ì¦ì", |
["Hungarfen"] = "íê°ë¥´í", |
["Overseer Tidewrath"] = "ì°ë머리 ì±ëíë", |
["Swamplord Musel'ek"] = "ëªêµ°ì£¼ 뮤ì¦ë í¬", |
["The Black Stalker"] = "ê²ì ì¶ì ì", |
--Dire Maul |
--Arena |
["Mushgog"] = "머ì¬ê³ ê·¸", |
["Skarr the Unbreakable"] = "무ì ì ì¤ì¹´ë¥´", |
["The Razza"] = "ë¼ì", |
--East |
["Alzzin the Wildshaper"] = "ì¹¼ë ë°ë ìì§", |
["Hydrospawn"] = "íëë¡ì¤í°", |
["Isalien"] = "ì´ì´ë¦¬ì", |
["Lethtendris"] = "ë ì¤í ë리ì¤", |
["Pimgib"] = "í기ë¸", |
["Pusillin"] = "í¸ì¤ë¦°", |
["Zevrim Thornhoof"] = "ì ë¸ë¦¼ ìíí", |
--North |
["Captain Kromcrush"] = "ëì¥ í¬ë¡¬í¬ë¬ì¬", |
["Cho'Rush the Observer"] = "ì ì°°ë³ ì´ë£¨ì¬", |
["Guard Fengus"] = "ê²½ë¹ë³ í구ì¤", |
["Guard Mol'dar"] = "ê²½ë¹ë³ 몰ë¤ë¥´", |
["Guard Slip'kik"] = "ê²½ê¸°ë³ ì¬ë¦½í¥", |
["King Gordok"] = "ì ê³ ë¥´ë ", |
["Knot Thimblejack's Cache"] = "ë ¸í¸ íë¸ì ì ìëí", -- check |
["Stomper Kreeg"] = "ì²ë¥ë° í¬ë¦¬ê·¸", |
--West |
["Illyanna Ravenoak"] = "ì¼ì¨ë ë ì´ë¸í¸í¬", |
["Immol'thar"] = "ì´ëª°í르", |
["Lord Hel'nurath"] = "군주 í¬ëë¼ì¤", |
["Magister Kalendris"] = "ë§ë²ì¬ ì¹¼ë ë리ì¤", |
["Prince Tortheldrin"] = "ìì í 르í ë린", |
["Tendris Warpwood"] = "êµ½ì´ë무 í ë리ì¤", |
["Tsu'zee"] = "ì¸ì§", |
--Gnomeregan |
["Crowd Pummeler 9-60"] = "ê³ ì² ìì¶ê¸° 9-60", |
["Dark Iron Ambassador"] = "ê²ì무ì ë¨ ì¬ì ", |
["Electrocutioner 6000"] = "기ê³í 문ì§ê¸° 6000", |
["Grubbis"] = "그루ë¹ì¤ ", |
["Mekgineer Thermaplugg"] = "ë©ê¸°ëì´ í ë§íë¬ê·¸", |
["Techbot"] = "첨ë¨ë¡ë´", |
["Viscous Fallout"] = "ë°©ì¬ì± í기물", |
--Gruul's Lair |
["Blindeye the Seer"] = "íì ë¸ë¼ì¸ëìì´", |
["Gruul the Dragonkiller"] = "ì© íì´ì 그룰", |
["High King Maulgar"] = "ìì¤ì ë§ì¸ê°ë¥´", |
["Kiggler the Crazed"] = "ê´ê¸°ì í¤ê¸ë¬", |
["Krosh Firehand"] = "í¬ë¡ì¬ íì´ì´í¸ë", |
["Olm the Summoner"] = "ìíì¬ ì¬ë¦", |
--Hellfire Citadel |
--Hellfire Ramparts |
["Nazan"] = "ëì", |
["Omor the Unscarred"] = "무ì ì ì¤ëª¨ë¥´", |
["Vazruden the Herald"] = "ì¬ì ë°ì¦ë£¨ë´", |
["Vazruden"] = "ë°ì¦ë£¨ë´", |
["Watchkeeper Gargolmar"] = "ê°ìì ê°ë¥´ê³¨ë§ë¥´", |
--Magtheridon's Lair |
["Hellfire Channeler"] = "ì§ì¥ë¶ ìì ì¬", |
["Magtheridon"] = "ë§ê·¸í 리ë", |
--The Blood Furnace |
["Broggok"] = "ë¸ë¡ê³ í¬", |
["Keli'dan the Breaker"] = "íê´´ì ì¼ë¦¬ë¨", |
["The Maker"] = "ì¬ìì 창조ì", |
--The Shattered Halls |
["Blood Guard Porung"] = "íí¬ì¬ í¬ë£½", |
["Grand Warlock Nethekurse"] = "ëíë§ë²ì¬ ë¤ëì¿ ë¥´ì¤", |
["Warbringer O'mrogg"] = "ë격ëì¥ ì¤ë¯ë¡ê·¸", |
["Warchief Kargath Bladefist"] = "ëì¡±ì¥ ì¹´ë¥´ê°ì¤ ë¸ë ì´ëí¼ì¤í¸", |
--Hyjal Summit |
["Anetheron"] = "ìë¤í ë¡ ", |
["Archimonde"] = "ìí¤ëª¬ë", |
["Azgalor"] = "ìì¦ê°ë¡", |
["Kaz'rogal"] = "ì¹´ì¦ë¡ê°", |
["Rage Winterchill"] = "ê²©ë ¸í ìí°ì¹ ", |
--Karazhan |
["Arcane Watchman"] = "ë¹ì ë³´ì´", |
["Attumen the Huntsman"] = "ì¬ë¥ê¾¼ ì´íë©", |
["Chess Event"] = "Chess Event", |
["Dorothee"] = "ëë¡ì", |
["Dust Covered Chest"] = "Dust Covered Chest", |
["Grandmother"] = "í 머ë", |
["Hyakiss the Lurker"] = "ì 복꾼 íìí¤ì¤", |
["Julianne"] = "ì¤ë¦¬ì", |
["Kil'rek"] = "í¬ë ", |
["King Llane Piece"] = "êµì ë ì¸", |
["Maiden of Virtue"] = "ê³ ê²°ì ì¬ì ", |
["Midnight"] = "ì²ë¥ì´", |
["Moroes"] = "모ë¡ì¤", |
["Netherspite"] = "í©ì²ì ìë ¹", |
["Nightbane"] = "í멸ì ì´ë ", |
["Prince Malchezaar"] = "ê³µì ë§ì²´ì르", |
["Restless Skeleton"] = "ì 못 ëë í´ê³¨", |
["Roar"] = "ì´í¥ì´", |
["Rokad the Ravager"] = "íê´´ì ë¡ì¹´ë", |
["Romulo & Julianne"] = "ë¡ë°ë¡ & ì¤ë¦¬ì", |
["Romulo"] = "ë¡ë°ë¡", |
["Shade of Aran"] = "ìëì ë§ë ¹", |
["Shadikith the Glider"] = "íê°ì ì¤ëí¤ì¤", |
["Strawman"] = "íììë¹", |
["Terestian Illhoof"] = "í ë ì¤í°ì ì¼íí", |
["The Big Bad Wolf"] = "커ë¤ë ëì ëë", |
["The Crone"] = "ë§ë ", |
["The Curator"] = "ì ì ê´ë¦¬ì¸", |
["Tinhead"] = "ìì² ë무꾼", |
["Tito"] = "í°í ", |
["Warchief Blackhand Piece"] = "ëì¡±ì¥ ë¸ëí¸ë", |
-- Magisters' Terrace |
["Kael'thas Sunstrider"] = "ìºíì¤ ì ì¤í¸ë¼ì´ë", |
["Priestess Delrissa"] = "ì¬ì¬ì ë¸ë¦¬ì¬", |
["Selin Fireheart"] = "ì 린 íì´ì´íí¸", |
["Vexallus"] = "벡ì´ë£¨ì¤", |
--Maraudon |
["Celebras the Cursed"] = "ì 주ë°ì ì ë ë¸ë¼ì¤", |
["Gelk"] = "ê²í¬", |
["Kolk"] = "ì½í¬", |
["Landslide"] = "ì°ì¬í", |
["Lord Vyletongue"] = "군주 ë°ì¼í ", |
["Magra"] = "ë§ê·¸ë¼", |
["Maraudos"] = "ë§ë¼ì°ëì¤", |
["Meshlok the Harvester"] = "ì ìì¬ ë©ì¬ë¡í¬", |
["Noxxion"] = "ë ¹ìì¨", |
["Princess Theradras"] = "공주 í ë¼ëë¼ì¤", |
["Razorlash"] = "ì¹¼ë ì±ì°", |
["Rotgrip"] = "ì©ì ìê·", |
["Tinkerer Gizlock"] = "ëì¥ì´ 기ì¦ë¡", |
["Veng"] = "ë²µ", |
--Molten Core |
["Baron Geddon"] = "ë¨ì ê²ë", |
["Cache of the Firelord"] = "Cache of the Firelord", |
["Garr"] = "ê°ë¥´", |
["Gehennas"] = "ê²í¨ëì¤", |
["Golemagg the Incinerator"] = "ì´ì´ì 골ë ë§ê·¸", |
["Lucifron"] = "루ìíë¡ ", |
["Magmadar"] = "ë§ê·¸ë§ë¤ë¥´", |
["Majordomo Executus"] = "ì²ì§ê¸° ì´ê·¸ì íí¬ì¤", |
["Ragnaros"] = "ë¼ê·¸ëë¡ì¤", |
["Shazzrah"] = "ì¤ì¦ë¼", |
["Sulfuron Harbinger"] = "ì¤í¼ë¡ ì¬ì", |
--Naxxramas |
["Anub'Rekhan"] = "ìëë 칸", |
["Deathknight Understudy"] = "죽ìì ê¸°ì¬ ììµì", |
["Feugen"] = "í¨ì§", |
["Four Horsemen Chest"] = "Four Horsemen Chest", |
["Gluth"] = "ê¸ë£¨ì¤", |
["Gothik the Harvester"] = "ìí¼ì ì°©ì·¨ì ê³ ë", |
["Grand Widow Faerlina"] = "ê·ë¶ì¸ í°ë¦¬ë", |
["Grobbulus"] = "ê·¸ë¼ë¶ë£¨ì¤", |
["Heigan the Unclean"] = "ë¶ì ì í¤ì´ê±´", |
["Highlord Mograine"] = "ëì주 모그ë ì¸", |
["Instructor Razuvious"] = "íë ¨êµê´ ë¼ì£¼ë¹ì´ì¤", |
["Kel'Thuzad"] = "ì¼í¬ìë", |
["Lady Blaumeux"] = "ì¬êµ°ì£¼ ë¸ë¼ë¯¸ì°ì¤", |
["Loatheb"] = "ë¡ë°ë¸", |
["Maexxna"] = "맥ì¤ë", |
["Noth the Plaguebringer"] = "ìë³ì ì¬ ë ¸ì¤", |
["Patchwerk"] = "í¨ì¹ìí¬", |
["Sapphiron"] = "ì¬í¼ë¡ ", |
["Sir Zeliek"] = "ì ¤ë¦¬ìí¬ ê²½", |
["Stalagg"] = "ì¤íë¼ê·¸", |
["Thaddius"] = "íëì°ì¤", |
["Thane Korth'azz"] = "ì주 ì½ì¤ìì¦", |
["The Four Horsemen"] = "4ì¸ì 기ë³ë", |
--Onyxia's Lair |
["Onyxia"] = "ì¤ëìì", |
--Ragefire Chasm |
["Bazzalan"] = "ë°ìë", |
["Jergosh the Invoker"] = "기ìì¬ ì ë¡ì¬", |
["Maur Grimtotem"] = "ë§ì°ë¥´ 그림í í ", |
["Taragaman the Hungerer"] = "ìë§ì íë¼ê°ë§", |
--Razorfen Downs |
["Amnennar the Coldbringer"] = "í¹íì ìë¤ë르", |
["Glutton"] = "ê²ê±¸ë¨¹ë³´", |
["Mordresh Fire Eye"] = "ë¶ê½ë 모ëë ì¬", |
["Plaguemaw the Rotting"] = "ì©ì´ê°ë ìë³ìê·", |
["Ragglesnout"] = "ëë주ë¥ì´", |
["Tuten'kash"] = "í¬í ì¹´ì¬", |
--Razorfen Kraul |
["Agathelos the Raging"] = "íí¬í ìê°í ë¡ì¤", |
["Blind Hunter"] = "ì¥ë ì¬ë¥ê¾¼", |
["Charlga Razorflank"] = "ìì¬ê¹ 차를ê°", |
["Death Speaker Jargba"] = "죽ìì ìì¸ì ìê·¸ë°", |
["Earthcaller Halmgar"] = "ëì§ì ì¬ í¨ê°ë¥´", |
["Overlord Ramtusk"] = "ë군주 ë¨í°ì¤í¬", |
--Ruins of Ahn'Qiraj |
["Anubisath Guardian"] = "ìëë¹ì¬ì¤ ê°ìì", |
["Ayamiss the Hunter"] = "ì¬ë¥ê¾¼ ìì¼ë¯¸ì¤", |
["Buru the Gorger"] = "먹보 ë¶ë£¨", |
["General Rajaxx"] = "ì¥êµ° ë¼ìì¤", |
["Kurinnaxx"] = "ì¿ ë¦°ëì¤", |
["Lieutenant General Andorov"] = "ì¬ë ¹ê´ ìëë¡ë¸", |
["Moam"] = "모ì", |
["Ossirian the Unscarred"] = "무ì ì ì¤ì리ì", |
--Scarlet Monastery |
--Armory |
["Herod"] = "í¤ë¡ë", |
--Cathedral |
["High Inquisitor Fairbanks"] = "ì¢ êµì¬íê´ íì´ë± í¬ì¤", |
["High Inquisitor Whitemane"] = "ì¢ êµì¬íê´ íì´í¸ë©ì¸", |
["Scarlet Commander Mograine"] = "ë¶ìììêµ° ì¬ë ¹ê´ 모그ë ì¸", |
--Graveyard |
["Azshir the Sleepless"] = "ì ë¤ì§ ìë ìì¦ì르", |
["Bloodmage Thalnos"] = "íë²ì¬ íë ¸ì¤", |
["Fallen Champion"] = "íë½í ì©ì¬", |
["Interrogator Vishas"] = "ì¬ë¬¸ê´ ë¹ì¤ì¤", |
["Ironspine"] = "무ì í´ê³¨", |
["Headless Horseman"] = "ì 주ë°ì 기ì¬", |
--Library |
["Arcanist Doan"] = "ì ë¹ì ì¬ ëì", |
["Houndmaster Loksey"] = "ì¬ë¥ê° ì¡°ë ¨ì¬ ë¡ì", |
--Scholomance |
["Blood Steward of Kirtonos"] = "í¤ë¥´í ë ¸ì¤ì íì§ê¸°", |
["Darkmaster Gandling"] = "ìíì¤ì¹ ê°íë§", |
["Death Knight Darkreaver"] = "죽ìì ê¸°ì¬ ë¤í¬ë¦¬ë²", |
["Doctor Theolen Krastinov"] = "íì í ì¬ë¦° í¬ë¼ì¤í°ë ¸ë¸", |
["Instructor Malicia"] = "ì¡°êµ ë§ë¦¬ìì", |
["Jandice Barov"] = "ìë¤ì´ì¤ ë°ë¡ë¸", |
["Kirtonos the Herald"] = "ì¬ì í¤ë¥´í ë ¸ì¤", |
["Kormok"] = "ì½ë¥´ëª¨í¬", |
["Lady Illucia Barov"] = "ì¬êµ°ì£¼ ì¼ë£¨ìì ë°ë¡ë¸", |
["Lord Alexei Barov"] = "군주 ìë ì¸ì´ ë°ë¡ë¸", |
["Lorekeeper Polkelt"] = "íì í´ì¼í¸", |
["Marduk Blackpool"] = "ë§ë¥´ëí¬ ë¸ëí", |
["Ras Frostwhisper"] = "ë¼ì¤ íë¡ì¤í¸ìì¤í¼", |
["Rattlegore"] = "ë¤ì°½ì´ê¸ë", |
["The Ravenian"] = "ë¼ë² ëì", |
["Vectus"] = "벡í¬ì¤", |
--Shadowfang Keep |
["Archmage Arugal"] = "ëë§ë²ì¬ ì루ê°", |
["Arugal's Voidwalker"] = "ì루ê°ì ë³´ì´ëì커", |
["Baron Silverlaine"] = "ë¨ì ì¤ë²ë ì¸", |
["Commander Springvale"] = "ì¬ë ¹ê´ ì¤íë§ë² ì¼", |
["Deathsworn Captain"] = "죽ìì ê²½ë¹ëì¥", -- check |
["Fenrus the Devourer"] = "í멸ì í루ì¤", |
["Odo the Blindwatcher"] = "ë먼ê°ìì ì¤ë", |
["Razorclaw the Butcher"] = "ëì´ì ì¹¼ë ë°í±", |
["Wolf Master Nandos"] = "ëëì ëëì¤", |
--Stratholme |
["Archivist Galford"] = "기ë¡ê´ ê°í¬ë", |
["Balnazzar"] = "ë°ëì르", |
["Baron Rivendare"] = "ë¨ì 리ë¸ë°ì´", |
["Baroness Anastari"] = "ë¨ìë¶ì¸ ìëì¤í리", |
["Black Guard Swordsmith"] = "ê²ìí¸ìë ê²ì ìì", |
["Cannon Master Willey"] = "í¬ë³ëì¥ ì리", |
["Crimson Hammersmith"] = "ì§íììêµ° ëì¥ì¥ì´", |
["Fras Siabi"] = "íë¼ì¤ ì¤ë¹", |
["Hearthsinger Forresten"] = "íì¤ì±ì´ í¬ë ì¤í´", |
["Magistrate Barthilas"] = "ì§ì ê´ ë°ì¤ë¼ì¤", |
["Maleki the Pallid"] = "ëíí ë§ë í¤", |
["Nerub'enkan"] = "ë¤ë£¹ì칸", |
["Postmaster Malown"] = "ì°ì²´êµì¥ ë§ë¡ì´", |
["Ramstein the Gorger"] = "먹보 ëì¤íì¸", |
["Skul"] = "ì¤ì»¬", |
["Stonespine"] = "뾰족ë°ì", |
["The Unforgiven"] = "ì©ìë°ì§ 못í ì", |
["Timmy the Cruel"] = "ìí¹í í°ë¯¸", |
--Sunwell Plateau |
["Kalecgos"] = "ì¹¼ë ê³ ì¤", |
["Sathrovarr the Corruptor"] = "íë½ì ì¬ì¤ë¡ë°ë¥´", |
["Brutallus"] = "ë¸ë£¨í루ì¤", |
["Felmyst"] = "ì§ì¥ìê°", |
["Kil'jaeden"] = "í¬ì ë´", |
["M'uru"] = "ë¯ì°ë£¨", |
["Entropius"] = "ìí¸ë¡í¼ì°ì¤", |
["The Eredar Twins"] = "ìë ë¤ë¥´ ìë¥ì´", |
["Lady Sacrolash"] = "ì¬êµ°ì£¼ ì¬í¬ë¡ëì¬", |
["Grand Warlock Alythess"] = "ëíë§ë²ì¬ ì리í ì¤", |
--Tempest Keep |
--The Arcatraz |
["Dalliah the Doomsayer"] = "í멸ì ìì¸ì ë¬ë¦¬ì", |
["Harbinger Skyriss"] = "ì 구ì ì¤í¤ë¦¬ì¤", |
["Warden Mellichar"] = "êµëê´ ë©ë¦¬ì± 르", |
["Wrath-Scryer Soccothrates"] = "ê²©ë ¸ì ì ì ì¬ ìì½ëë¼í ì¤", |
["Zereketh the Unbound"] = "ìë°ì´ í린 ì ë ì¼ì¤", |
--The Botanica |
["Commander Sarannis"] = "ì§íê´ ìëëì¤", |
["High Botanist Freywinn"] = "ê³ ì ì물íì íë ì´ì", |
["Laj"] = "ë¼ì¦", |
["Thorngrin the Tender"] = "ê°ìì¸ ì그린", |
["Warp Splinter"] = "ì°¨ìì ë¶ë¦¬ì", |
--The Eye |
["Al'ar"] = "ìë¼ë¥´", |
["Cosmic Infuser"] = "ë¶ê´´ì ì§í¡ì´", |
["Devastation"] = "í©íì ëë¼", |
["Grand Astromancer Capernian"] = "ëì ì±ì ì¬ ì¹´í¼ëì", |
["High Astromancer Solarian"] = "ê³ ì ì ì±ì ì¬ ìë¼ë¦¬ì", |
["Infinity Blades"] = "무íì ë¹ì", |
["Kael'thas Sunstrider"] = "ìºíì¤ ì ì¤í¸ë¼ì´ë", |
["Lord Sanguinar"] = "군주 ìê·ë르", |
["Master Engineer Telonicus"] = "ìì기ì ì í ë¡ëì¿ ì¤", |
["Netherstrand Longbow"] = "í©ì²ë§¤ë ì¥ê¶", |
["Phaseshift Bulwark"] = "ìì ë³íì 보루방í¨", |
["Solarium Agent"] = "íìì ì ë¹ ìì", |
["Solarium Priest"] = "íìì ì ë¹ ì¬ì ", |
["Staff of Disintegration"] = "ì°ì£¼ ìëì§ ì£¼ì 기", |
["Thaladred the Darkener"] = "ìíì ì¸ëì íë¼ëë ë", |
["Void Reaver"] = "ê³µíì ì ë¨ê¸°", |
["Warp Slicer"] = "ì°¨ìì ì ë¨ê¸°", |
--The Mechanar |
["Gatewatcher Gyro-Kill"] = "문ì§ê¸° íì í±ë ", |
["Gatewatcher Iron-Hand"] = "문ì§ê¸° 무ì 주먹", |
["Mechano-Lord Capacitus"] = "기ê³êµ°ì£¼ ìºí¼ìí¬ì¤", |
["Nethermancer Sepethrea"] = "í©ì²ì ì¬ ì¸íì¤ë ì", |
["Pathaleon the Calculator"] = "ì² ëì² ë¯¸í íí리ì¨", |
--The Deadmines |
["Brainwashed Noble"] = "ì¸ëë¹í ê·ì¡±", |
["Captain Greenskin"] = "ì ì¥ ê·¸ë¦°ì¤í¨", |
["Cookie"] = "ì¿ í¤", |
["Edwin VanCleef"] = "ìëì ë°´í´ë¦¬í", |
["Foreman Thistlenettle"] = "íì¥ê°ë ìì¬ë¤í", |
["Gilnid"] = "길ëë", |
["Marisa du'Paige"] = "ë§ë¦¬ì¬ ëíì´ì§", |
["Miner Johnson"] = "ê´ë¶ ì¡´ì¨", |
["Mr. Smite"] = "미ì¤í° ì¤ë§ì´í¸", |
["Rhahk'Zor"] = "ë¼í¬ì¡°ë¥´", |
["Sneed"] = "ì¤ëë", |
["Sneed's Shredder"] = "ì¤ëëì ë²ëª©ê¸°", |
--The Stockade |
["Bazil Thredd"] = "ë°ì§ ì¤ë ë", |
["Bruegal Ironknuckle"] = "무ì 주먹 ë¸ë£¨ê°", |
["Dextren Ward"] = "ë±ì¤í¸ë ìë", |
["Hamhock"] = "íí¹", |
["Kam Deepfury"] = "ìº ë¥í¨ë¦¬", |
["Targorr the Dread"] = "íì ë² íê³ ë¥´", |
--The Temple of Atal'Hakkar |
["Atal'alarion"] = "ìíìë¼ë¦¬ì¨", |
["Avatar of Hakkar"] = "í카르ì íì ", |
["Dreamscythe"] = "ë림ì¬ì´ë", |
["Gasher"] = "ê²ì´ì ", |
["Hazzas"] = "íìì¤", |
["Hukku"] = "íì¿ ", |
["Jade"] = "ì ì´ë", |
["Jammal'an the Prophet"] = "ìì¸ì ì ë§ë", |
["Kazkaz the Unholy"] = "íë½í ì¹´ì¦ì¹´ì¦", |
["Loro"] = "ë¡ë¡", |
["Mijan"] = "ë§ì´ì", |
["Morphaz"] = "몰íì¦", |
["Ogom the Wretched"] = "ë¹ì´ì ì¤ê·¸ì´", |
["Shade of Eranikus"] = "ìë¼ëì¿ ì¤ì ì¬ë ¹", |
["Veyzhak the Cannibal"] = "ìì¸í¸ë¡¤ ë² ì´ì", |
["Weaver"] = "ìë²", |
["Zekkis"] = "ì í¤ì¤", |
["Zolo"] = "졸ë¡", |
["Zul'Lor"] = "ì¤ë¡", |
--Uldaman |
["Ancient Stone Keeper"] = "ê³ ë ë°ì 문ì§ê¸°", |
["Archaedas"] = "ìì¹´ìë¤ì¤", |
["Baelog"] = "ë°¸ë¡ê·¸", |
["Digmaster Shovelphlange"] = "ë°êµ´ë¨ì¥ ì¼ë²¨íëì§", |
["Galgann Firehammer"] = "ê°ê° íì´ì´í´ë¨¸", |
["Grimlok"] = "그림ë¡í¬", |
["Ironaya"] = "ìì´ë¡ëì¼", |
["Obsidian Sentinel"] = "íìì íìê¾¼", |
["Revelosh"] = "ë 벨ë¡ì¬", |
--Wailing Caverns |
["Boahn"] = "ë³´ì", |
["Deviate Faerie Dragon"] = "ëì°ë³ì´ ìì ì©", |
["Kresh"] = "í¬ë ì¬", |
["Lady Anacondra"] = "ì¬êµ°ì£¼ ìëì½ëë¼", |
["Lord Cobrahn"] = "군주 ì½ë¸ë", |
["Lord Pythas"] = "군주 í¼íì¤", |
["Lord Serpentis"] = "군주 ìíëì¤", |
["Mad Magglish"] = "ê´ê¸°ì 매ê¸ë¦¬ì", |
["Mutanus the Devourer"] = "걸ì ë¤ë¦° 무íëì¤", |
["Skum"] = "ì¤ì»´", |
["Trigore the Lasher"] = "ì±ì°ê¼¬ë¦¬ í¸ë¦¬ê³ ì´", |
["Verdan the Everliving"] = "ììì ë² ë¥´ë¨", |
--World Bosses |
["Avalanchion"] = "ìë°ëì¹ì¨", |
["Azuregos"] = "ì주ì´ê³ ì¤", |
["Baron Charr"] = "ë¨ì 차르", |
["Baron Kazum"] = "ë¨ì ì¹´ì¤", |
["Doom Lord Kazzak"] = "í멸ì 군주 ì¹´ìí¬", |
["Doomwalker"] = "í멸ì ì ë¨ê¸°", |
["Emeriss"] = "ìë©ë¦¬ì¤", |
["High Marshal Whirlaxis"] = "ëì¥êµ° í ë½ìì¤", -- check |
["Lethon"] = "ë ì", |
["Lord Skwol"] = "군주 ì¤í", |
["Prince Skaldrenox"] = "ìì ì¤ì¹¼ë ë ¹ì¤", |
["Princess Tempestria"] = "공주 í íì¤í¸ë¦¬ì", |
["Taerar"] = "íìë¼", |
["The Windreaver"] = "ì¹¼ë ë°ë", |
["Ysondre"] = "ì´ìëë ", |
--Zul'Aman |
["Akil'zon"] = "ìí¬ì¡´", |
["Halazzi"] = "í ë¼ì§", |
["Jan'alai"] = "ììë¼ì´", |
["Malacrass"] = "ë§ë¼í¬ë¼ì¤", -- check |
["Nalorakk"] = "ë ë¡ë¼í¬", |
["Zul'jin"] = "ì¤ì§", |
["Hex Lord Malacrass"] = "주ì 군주 ë§ë¼í¬ë¼ì¤", |
--Zul'Farrak |
["Antu'sul"] = "ìí¬ì ", |
["Chief Ukorz Sandscalp"] = "ì¡±ì¥ ì°ì½ë¥´ì¦ ìëì¤ì¹¼í", |
["Dustwraith"] = "ëì¤í¸ë ì´ì¤", |
["Gahz'rilla"] = "ê°ì¦ë¦´ë¼", |
["Hydromancer Velratha"] = "ì ì²´ì ì¬ ë²¨ë¼í", |
["Murta Grimgut"] = "무르í 그림구í¸", |
["Nekrum Gutchewer"] = "ë¤í¬ë£¸ ê±°í¸ì¸ì´", |
["Oro Eyegouge"] = "ì¤ë¡ ìì´ê°ì°ì§", |
["Ruuzlu"] = "루ì¦ë£¨", |
["Sandarr Dunereaver"] = "Sandarr Dunereaver", |
["Sandfury Executioner"] = "ì±ë모ëë¶ì¡± ì¬íì§íì¸", |
["Sergeant Bly"] = "íì¬ê´ ë¸ë¼ì´", |
["Shadowpriest Sezz'ziz"] = "ì´ë ìì¬ì ì¸ì¦ì§ì¦", |
["Theka the Martyr"] = "ìêµì ë°ì¹´", |
["Witch Doctor Zum'rah"] = "ìì ì¬ ì¤ë¼", |
["Zerillis"] = "ì 릴리ì¤", |
["Zul'Farrak Dead Hero"] = "ì¤íë½ ì£½ìì ìì ", |
--Zul'Gurub |
["Bloodlord Mandokir"] = "í군주 ë§ëí¤ë¥´", |
["Gahz'ranka"] = "ê°ì¦ëì¹´", |
["Gri'lek"] = "그리ë ", |
["Hakkar"] = "í카르", |
["Hazza'rah"] = "íìë¼", |
["High Priest Thekal"] = "ëì¬ì ë°ì¹¼", |
["High Priest Venoxis"] = "ëì¬ì ë² ë ¹ìì¤", |
["High Priestess Arlokk"] = "ëì¬ì¬ì ìë¡í¬", |
["High Priestess Jeklik"] = "ëì¬ì¬ì ì í´ë¦", |
["High Priestess Mar'li"] = "ëì¬ì¬ì ë§ë¦¬", |
["Jin'do the Hexxer"] = "주ì ì¬ ì§ë", |
["Renataki"] = "ë ëíí¤", |
["Wushoolay"] = "ì°ì¬ë ì´", |
--Ring of Blood (where? an instance? should be in other file?) |
["Brokentoe"] = "ë§ì¹ë°êµ½", |
["Mogor"] = "ëª¨ê³ ë¥´", |
["Murkblood Twin"] = "ìë í¼ì¼ì¡± ìë¥ì´", |
["Murkblood Twins"] = "ìë í¼ì¼ì¡± ìë¥ì´", |
["Rokdar the Sundered Lord"] = "íê´´ì 군주 ë¡í¬ë¤ë¥´", |
["Skra'gath"] = "ì¤í¬ë¼ê°ì¤", |
["The Blue Brothers"] = "í¸ë¥¸ íì ë¤", |
["Warmaul Champion"] = "ì ìë§ì¹ì¼ì¡± ì©ì¬", |
} |
elseif GAME_LOCALE == "esES" then |
lib:SetCurrentTranslations { |
--Ahn'Qiraj |
["Anubisath Defender"] = "Defensor Anubisath", |
["Battleguard Sartura"] = "Guardia de batalla Sartura", |
["C'Thun"] = "C'Thun", |
["Emperor Vek'lor"] = "Emperador Vek'lor", |
["Emperor Vek'nilash"] = "Emperador Vek'nilash", |
["Eye of C'Thun"] = "Ojo de C'Thun", |
["Fankriss the Unyielding"] = "Fankriss el Implacable", |
["Lord Kri"] = "Lord Kri", |
["Ouro"] = "Ouro", |
["Princess Huhuran"] = "Princesa Huhuran", |
["Princess Yauj"] = "Princesa Yauj", |
["The Bug Family"] = "La Familia Insecto", -- check |
["The Prophet Skeram"] = "El profeta Skeram", |
["The Twin Emperors"] = "Los Emperadores Gemelos", -- check |
["Vem"] = "Vem", |
["Viscidus"] = "Viscidus", |
--Auchindoun |
--Auchenai Crypts |
["Exarch Maladaar"] = "Exarca Maladaar", |
["Shirrak the Dead Watcher"] = "Shirrak el Vig\195\173a de los Muertos", |
--Mana-Tombs |
["Nexus-Prince Shaffar"] = "Pr\195\173ncipe-nexo Shaffar", |
["Pandemonius"] = "Pandemonius", |
["Tavarok"] = "Tavarok", |
--Shadow Labyrinth |
["Ambassador Hellmaw"] = "Embajador Faucinferno", |
["Blackheart the Inciter"] = "Negrozón el Incitador", |
["Grandmaster Vorpil"] = "Maestro mayor Vorpil", |
["Murmur"] = "Murmur", |
--Sethekk Halls |
["Anzu"] = "Anzu", |
["Darkweaver Syth"] = "Tejeoscuro Syth", |
["Talon King Ikiss"] = "Rey Garra Ikiss", |
--Blackfathom Deeps |
["Aku'mai"] = "Aku'mai", |
["Baron Aquanis"] = "Bar\195\179n Aquanis", |
["Gelihast"] = "Gelihast", |
["Ghamoo-ra"] = "Ghamoo-ra", |
["Lady Sarevess"] = "Lady Sarevess", |
["Old Serra'kis"] = "Viejo Serra'kis", |
["Twilight Lord Kelris"] = "Se\195\177or Crepuscular Kelris", |
--Blackrock Depths |
["Ambassador Flamelash"] = "Embajador Latifuego", |
["Anger'rel"] = "Anger'rel", |
["Anub'shiah"] = "Anub'shiah", |
["Bael'Gar"] = "Bael'Gar", |
["Chest of The Seven"] = "Tesoro de los Siete", |
["Doom'rel"] = "Doom'rel", |
["Dope'rel"] = "Dope'rel", |
["Emperor Dagran Thaurissan"] = "Emperador Dagran Thaurissan", |
["Eviscerator"] = "Eviscerador", |
["Fineous Darkvire"] = "Finoso Virunegro", |
["General Angerforge"] = "General Forjira", |
["Gloom'rel"] = "Gloom'rel", |
["Golem Lord Argelmach"] = "Se\195\177or G\195\179lem Argelmach", |
["Gorosh the Dervish"] = "Gorosh el Endemoniado", |
["Grizzle"] = " Grisez", |
["Hate'rel"] = "Odio'rel", |
["Hedrum the Creeper"] = "Hedrum el Trepador", |
["High Interrogator Gerstahn"] = "Alto Interrogador Gerstahn", |
["High Priestess of Thaurissan"] = "Alta Sacerdotisa de Thaurissan", -- check |
["Houndmaster Grebmar"] = "Maestro de canes Grebmar", |
["Hurley Blackbreath"] = "Hurley Negr\195\161lito", |
["Lord Incendius"] = "Lord Incendius", |
["Lord Roccor"] = "Lord Roccor", |
["Magmus"] = "Magmus", |
["Ok'thor the Breaker"] = "Ok'thor el Rompedor", |
["Panzor the Invincible"] = "Panzor el Invencible", |
["Phalanx"] = "Falange", |
["Plugger Spazzring"] = "Plugger Aropatoso", |
["Princess Moira Bronzebeard"] = "Princesa Moira Barbabronce", |
["Pyromancer Loregrain"] = "Pirom\195\161ntico Cultugrano", |
["Ribbly Screwspigot"] = "Ribbly Llavenrosca", |
["Seeth'rel"] = "Seeth'rel", |
["The Seven Dwarves"] = "Los Siete Enanos", -- check |
["Verek"] = "Verek", |
["Vile'rel"] = "Vil'rel", |
["Warder Stilgiss"] = "Guarda Stilgiss", |
--Blackrock Spire |
--Lower |
["Bannok Grimaxe"] = "Bannok Hachamacabra", |
["Burning Felguard"] = "Guarda vil ardiente", |
["Crystal Fang"] = "Colmillor de cristal", |
["Ghok Bashguud"] = "Ghok Bashguud", |
["Gizrul the Slavener"] = "Gizrul el Esclavista", |
["Halycon"] = "Halycon", |
["Highlord Omokk"] = "Alto Se\195\177or Omokk", |
["Mor Grayhoof"] = "Mor Grayhoof", -- fix |
["Mother Smolderweb"] = "Madre Telabrasada", |
["Overlord Wyrmthalak"] = "Se\195\177or Supremo Vermiothalak", |
["Quartermaster Zigris"] = "Intendente Zigris", |
["Shadow Hunter Vosh'gajin"] = "Cazador de las Sombras Vosh'gajin", |
["Spirestone Battle Lord"] = "Se\195\177or de batalla Cumbrerroca", |
["Spirestone Butcher"] = "Carnicero Cumbrerroca", |
["Spirestone Lord Magus"] = "Se\195\177or Magus Cumbrerroca", |
["Urok Doomhowl"] = "Urok Aullapocalipsis", |
["War Master Voone"] = "Maestro de guerra Voone", |
--Upper |
["General Drakkisath"] = "General Drakkisath", |
["Goraluk Anvilcrack"] = "Goraluk Yunquegrieta", |
["Gyth"] = "Gyth", |
["Jed Runewatcher"] = "Jed vig\195\173a de las runas", |
["Lord Valthalak"] = "Lord Valthalak", |
["Pyroguard Emberseer"] = "Piroguardi\195\161n Brasadivino", |
["Solakar Flamewreath"] = "Solakar Corona de Fuego", |
["The Beast"] = "La Bestia", |
["Warchief Rend Blackhand"] = "Jefe de Guerra Desgarro Pu\195\177o Negro", |
--Blackwing Lair |
["Broodlord Lashlayer"] = "Se\195\177or de prole Capazote", |
["Chromaggus"] = "Chromaggus", |
["Ebonroc"] = "Ebonroc", |
["Firemaw"] = "Faucefogo", |
["Flamegor"] = "Flamagor", |
["Grethok the Controller"] = "Grethok el Controlador", |
["Lord Victor Nefarius"] = "Lord V\195\173ctor Nefarius", |
["Nefarian"] = "Nefarian", |
["Razorgore the Untamed"] = "Sangrevaja el Indomable", |
["Vaelastrasz the Corrupt"] = "Vaelastrasz el Corrupto", |
--Black Temple |
["Essence of Anger"] = "Esencia de C\195\179lera", |
["Essence of Desire"] = "Esencia de Deseo", |
["Essence of Suffering"] = "Esencia de Sufrimiento", |
["Gathios the Shatterer"] = "Gathios the Shatterer", |
["Gurtogg Bloodboil"] = "Gurtogg Sangre Hirviente", |
["High Nethermancer Zerevor"] = "High Nethermancer Zerevor", |
["High Warlord Naj'entus"] = "Gran Se\195\177or de la Guerra Naj'entus", |
["Illidan Stormrage"] = "Lord Illidan Tempestira", -- check |
["Illidari Council"] = "Concilio Illidari", |
["Lady Malande"] = "Lady Malande", |
["Mother Shahraz"] = "Madre Shahraz", |
["Reliquary of Souls"] = "Relicario de Almas", |
["Shade of Akama"] = "Sombra de Akama", |
["Supremus"] = "Supremus", |
["Teron Gorefiend"] = "Teron Sanguino", |
["The Illidari Council"] = "El concilio Illidari", |
["Veras Darkshadow"] = "Veras Darkshadow", |
--Caverns of Time |
--Old Hillsbrad Foothills |
["Captain Skarloc"] = "Capitán Skarloc", |
["Epoch Hunter"] = "Cazador de eras", |
["Lieutenant Drake"] = "Teniente Draco", |
--The Black Morass |
["Aeonus"] = "Aeonus", |
["Chrono Lord Deja"] = "Cronolord Deja", |
["Medivh"] = "Medivh", |
["Temporus"] = "Temporus", |
--Coilfang Reservoir |
--Serpentshrine Cavern |
["Coilfang Elite"] = "Elite Colimillo Torcido", |
["Coilfang Strider"] = "Coilfang Strider", -- fix |
["Fathom-Lord Karathress"] = "Se\195\177or de la profundidades Karathress", |
["Hydross the Unstable"] = "Hydross el Inestable", |
["Lady Vashj"] = "Lady Vashj", -- fix |
["Leotheras the Blind"] = "Leotheras el Ciego", |
["Morogrim Tidewalker"] = "Morogrim Levantamareas", |
["Pure Spawn of Hydross"] = "Pure Spawn of Hydross", -- fix |
["Shadow of Leotheras"] = "Sombra de Leotheras", |
["Tainted Spawn of Hydross"] = "Tainted Spawn of Hydross", -- fix |
["The Lurker Below"] = "El Rondador de abajo", |
["Tidewalker Lurker"] = "Tidewalker Lurker", -- fix |
--The Slave Pens |
["Mennu the Betrayer"] = "Mennu el Traidor", |
["Quagmirran"] = "Quagmirran", |
["Rokmar the Crackler"] = "Rokmar el Crujidor", |
--The Steamvault |
["Hydromancer Thespia"] = "Hidrom\195\161ntico Thespia", |
["Mekgineer Steamrigger"] = "Mekigeniero Vaporino", |
["Warlord Kalithresh"] = "Se\195\177or de la Guerra Kalithresh", |
--The Underbog |
["Claw"] = "Zarpa", |
["Ghaz'an"] = "Ghaz'an", |
["Hungarfen"] = "Panthambre", |
["Overseer Tidewrath"] = "Avizor Aleta de Cólera", |
["Swamplord Musel'ek"] = "Se\195\177or del pantano Musel'ek", |
["The Black Stalker"] = "La acechadora negra", |
--Dire Maul |
--Arena |
["Mushgog"] = "Mushgog", |
["Skarr the Unbreakable"] = "Skarr el Inquebrantable", |
["The Razza"] = "El Razza", |
--East |
["Alzzin the Wildshaper"] = "Alzzin el Formaferal", |
["Hydrospawn"] = "Hidromilecio", |
["Isalien"] = "Isalien", |
["Lethtendris"] = "Lethtendris", |
["Pimgib"] = "Pimgib", |
["Pusillin"] = "Pusill\195\173n", |
["Zevrim Thornhoof"] = "Zevrim Pezu\195\177ahendida", |
--North |
["Captain Kromcrush"] = "Capit\195\161n Kromcrush", |
["Cho'Rush the Observer"] = "Cho'Rush el Observador", |
["Guard Fengus"] = "Guardia Fengus", |
["Guard Mol'dar"] = " Guardia Mol'dar", |
["Guard Slip'kik"] = "Guardia Slip'kik", |
["King Gordok"] = "Rey Gordok", |
["Knot Thimblejack's Cache"] = "Carretilla de Knot Llavededo", |
["Stomper Kreeg"] = "Vapuleador Kreeg", |
--West |
["Illyanna Ravenoak"] = "Illyanna Roblecuervo", |
["Immol'thar"] = "Immol'thar", |
["Lord Hel'nurath"] = "Lord Hel'nurath", -- check |
["Magister Kalendris"] = "Magister Kalendris", |
["Prince Tortheldrin"] = "Pr\195\173ncipe Tortheldrin", |
["Tendris Warpwood"] = "Tendris Madeguerra", |
["Tsu'zee"] = "Tsu'zee", |
--Gnomeregan |
["Crowd Pummeler 9-60"] = "Gopleamasa 9-60", |
["Dark Iron Ambassador"] = "Embajador Hierro Negro", |
["Electrocutioner 6000"] = "Electrocutor 6000", |
["Grubbis"] = "Grubbis", |
["Mekgineer Thermaplugg"] = "Mekigeniero Termochufe", |
["Techbot"] = "Tecnobot", |
["Viscous Fallout"] = "Radiactivo viscoso", |
--Gruul's Lair |
["Blindeye the Seer"] = "Ciego el Vidente", |
["Gruul the Dragonkiller"] = "Gruul el Asesino de Dragones", |
["High King Maulgar"] = "Su majestad Maulgar", |
["Kiggler the Crazed"] = "Kiggler el Enloquecido", |
["Krosh Firehand"] = "Krosh Manofuego", |
["Olm the Summoner"] = "Olm el Invocador", |
--Hellfire Citadel |
--Hellfire Ramparts |
["Nazan"] = "Nazan", |
["Omor the Unscarred"] = "Omor el Sinmarcas", |
["Vazruden the Herald"] = "Vazruden el Heraldo", |
["Vazruden"] = "Vazruden", |
["Watchkeeper Gargolmar"] = "Guardi\195\161n vig\195\173a Gargolmar", |
--Magtheridon's Lair |
["Hellfire Channeler"] = "Canalizador Fuego Infernal", |
["Magtheridon"] = "Magtheridon", |
--The Blood Furnace |
["Broggok"] = "Broggok", |
["Keli'dan the Breaker"] = "Keli'dan el Ultrajador", |
["The Maker"] = "El Hacedor", |
--The Shattered Halls |
["Blood Guard Porung"] = "Guardia de sangre Porung", -- check |
["Grand Warlock Nethekurse"] = "Brujo supremo Malbisal", |
["Warbringer O'mrogg"] = "Belisario O'mrogg", |
["Warchief Kargath Bladefist"] = "Jefe de Guerra Garrafilada", -- check |
--Hyjal Summit |
["Anetheron"] = "Anetheron", |
["Archimonde"] = "Archimonde", |
["Azgalor"] = "Azgalor", |
["Kaz'rogal"] = "Kaz'rogal", |
["Rage Winterchill"] = "Ira Fr\195\173oinvierno", |
--Karazhan |
["Arcane Watchman"] = "Vigilante Arcano", |
["Attumen the Huntsman"] = "Attumen el Montero", |
["Chess Event"] = "Evento de ajedrez", -- check |
["Dorothee"] = "Dorothea", |
-- ["Dust Covered Chest"] = true, |
["Grandmother"] = "Abuela", |
["Hyakiss the Lurker"] = "Hyakiss el Rondador", |
["Julianne"] = "Julianne", |
["Kil'rek"] = "Kil'rek", |
["King Llane Piece"] = "Rey Llane", -- check - Pieza de... |
["Maiden of Virtue"] = "Doncella de Virtud", |
["Midnight"] = "Medianoche", |
["Moroes"] = "Moroes", |
["Netherspite"] = "Rencor abisal", -- check |
["Nightbane"] = "Nocturno", -- check |
["Prince Malchezaar"] = "Pr\195\173ncipe Malchezaar", |
["Restless Skeleton"] = "Esqueleto inquieto", -- check |
["Roar"] = "Rugido", |
["Rokad the Ravager"] = "Rokad el Devastador", |
["Romulo & Julianne"] = "Romulo y Julianne", -- check |
["Romulo"] = "Romulo", |
["Shade of Aran"] = "Sombra de Aran", |
["Shadikith the Glider"] = "Shadikith the Glider", -- fix |
["Strawman"] = "Espantapájaros", |
["Terestian Illhoof"] = "Terestian Pezuña Enferma", |
["The Big Bad Wolf"] = "El Gran Lobo Malvado", |
["The Crone"] = "La Vieja Bruja", -- check |
["The Curator"] = "Curator", |
["Tinhead"] = "Cabezalata", |
["Tito"] = "Tito", |
["Warchief Blackhand Piece"] = "Jefe de Guerra Mano Negra", -- check - Pieza de... |
-- Magisters' Terrace |
--["Kael'thas Sunstrider"] = true, |
["Priestess Delrissa"] = "Priestess Delrissa", -- translate me |
["Selin Fireheart"] = "Selin Fireheart", -- translate me |
["Vexallus"] = "Vexallus", -- translate me |
--Maraudon |
["Celebras the Cursed"] = "Celebras el Maldito", |
["Gelk"] = "Gelk", |
["Kolk"] = "Kolk", |
["Landslide"] = "Derrumblo", |
["Lord Vyletongue"] = "Lord Lenguavil", |
["Magra"] = "Magra", |
["Maraudos"] = "Maraudos", |
["Meshlok the Harvester"] = "Meshlok el Cosechador", |
["Noxxion"] = "Noxxion", |
["Princess Theradras"] = "Princesa Theradras", |
["Razorlash"] = "Lativaja", |
["Rotgrip"] = "Escamapodrida", |
["Tinkerer Gizlock"] = "Manitas Gizlock", |
["Veng"] = "Veng", |
--Molten Core |
["Baron Geddon"] = "Bar\195\179n Geddon", |
-- ["Cache of the Firelord"] = true, |
["Garr"] = "Garr", |
["Gehennas"] = "Gehennas", |
["Golemagg the Incinerator"] = "Golemagg el Incinerador", |
["Lucifron"] = "Lucifron", |
["Magmadar"] = "Magmadar", |
["Majordomo Executus"] = "Mayordomo Executus", |
["Ragnaros"] = "Ragnaros", |
["Shazzrah"] = "Shazzrah", |
["Sulfuron Harbinger"] = "Sulfuron Presagista", |
--Naxxramas |
["Anub'Rekhan"] = "Anub'Rekhan", |
["Deathknight Understudy"] = "Suplente Caballero de la Muerte", |
["Feugen"] = "Feugen", |
-- ["Four Horsemen Chest"] = true, |
["Gluth"] = "Gluth", |
["Gothik the Harvester"] = "Gothik el Cosechador", |
["Grand Widow Faerlina"] = "Gran Viuda Faerlina", |
["Grobbulus"] = "Grobbulus", |
["Heigan the Unclean"] = "Heigan el Impuro", |
["Highlord Mograine"] = "Alto Se\195\177or Mograine", |
["Instructor Razuvious"] = "Instructor Razuvious", |
["Kel'Thuzad"] = "Kel'Thuzad", |
["Lady Blaumeux"] = "Lady Blaumeux", |
["Loatheb"] = "Loatheb", |
["Maexxna"] = "Maexxna", |
["Noth the Plaguebringer"] = "Noth el Pesteador", |
["Patchwerk"] = "Remendejo", |
["Sapphiron"] = "Sapphiron", |
["Sir Zeliek"] = "Sir Zeliek", |
["Stalagg"] = "Stalagg", |
["Thaddius"] = "Thaddius", |
["Thane Korth'azz"] = "Thane Korth'azz", |
["The Four Horsemen"] = "Los Cuatro Jinetes", -- check |
--Onyxia's Lair |
["Onyxia"] = "Onyxia", |
--Ragefire Chasm |
["Bazzalan"] = "Bazzalan", |
["Jergosh the Invoker"] = "Jergosh el Convocador", |
["Maur Grimtotem"] = "Maur T\195\179tem Siniestro", |
["Taragaman the Hungerer"] = "Taragaman el Hambriento", |
--Razorfen Downs |
["Amnennar the Coldbringer"] = "Amnennar el G\195\169lido", |
["Glutton"] = "Glot\195\179n", |
["Mordresh Fire Eye"] = "Mordresh Ojo de Fuego", |
["Plaguemaw the Rotting"] = "Fauzpeste el Putrefacto", |
["Ragglesnout"] = "Morrandrajos", |
["Tuten'kash"] = "Tuten'kash", |
--Razorfen Kraul |
["Agathelos the Raging"] = "Agathelos el Furioso", |
["Blind Hunter"] = "Cazador ciego", |
["Charlga Razorflank"] = "Charlga Filonavaja", |
["Death Speaker Jargba"] = "M\195\169dium Jargba", |
["Earthcaller Halmgar"] = "Clamor de Tierra Halmgar", |
["Overlord Ramtusk"] = "Se\195\177or Supremo Colmicarnero", |
--Ruins of Ahn'Qiraj |
["Anubisath Guardian"] = "Guardi\195\161n Anubisath", |
["Ayamiss the Hunter"] = "Ayamiss el Cazador", |
["Buru the Gorger"] = "Buru el Manducador", |
["General Rajaxx"] = "General Rajaxx", |
["Kurinnaxx"] = "Kurinnaxx", |
["Lieutenant General Andorov"] = "Teniente General Andorov", |
["Moam"] = "Moam", |
["Ossirian the Unscarred"] = "Osirio el Sinmarcas", |
--Scarlet Monastery |
--Armory |
["Herod"] = "Herod", |
--Cathedral |
["High Inquisitor Fairbanks"] = "Alto Inquisidor Ribalimpia", |
["High Inquisitor Whitemane"] = "Alta Inquisidora Melenablanca", |
["Scarlet Commander Mograine"] = "Comandante Escarlata Mograine", |
--Graveyard |
["Azshir the Sleepless"] = "Azshir el Insomne", |
["Bloodmage Thalnos"] = "Mago sangriento Thalnos", |
["Fallen Champion"] = "Campe\195\179n ca\195\173do", |
["Interrogator Vishas"] = "Interrogador Vishas", |
["Ironspine"] = "Dorsacerado", |
--Library |
["Arcanist Doan"] = "Arcanista Doan", |
["Houndmaster Loksey"] = "Maestro de canes Loksey", |
--Scholomance |
["Blood Steward of Kirtonos"] = "Administrador de sangre de Kirtonos", |
["Darkmaster Gandling"] = "Maestro oscuro Gandling", |
["Death Knight Darkreaver"] = "Caballero de la Muerte Atracoscuro", |
["Doctor Theolen Krastinov"] = "Doctor Theolen Krastinov", |
["Instructor Malicia"] = "Instructor Malicia", |
["Jandice Barov"] = "Jandice Barov", |
["Kirtonos the Herald"] = "Kirtonos el Heraldo", |
["Kormok"] = "Kormok", |
["Lady Illucia Barov"] = "Lady Illucia Barov", |
["Lord Alexei Barov"] = "Lord Alexei Barov", |
["Lorekeeper Polkelt"] = "Tradicionalista Polkelt", |
["Marduk Blackpool"] = "Marduz Pozonegro", |
["Ras Frostwhisper"] = "Ras Levescarcha", |
["Rattlegore"] = "Traquesangre", |
["The Ravenian"] = "El Devorador", |
["Vectus"] = "Vectus", |
--Shadowfang Keep |
["Archmage Arugal"] = "Archimago Arugal", |
["Arugal's Voidwalker"] = "Abisario de Arugal", -- "Arugal's Voidwalker" |
["Baron Silverlaine"] = "Bar\195\179n Filargenta", |
["Commander Springvale"] = "Comandante Vallefont", |
["Deathsworn Captain"] = "Capit\195\161n Juramorte", |
["Fenrus the Devourer"] = "Fenrus el Devorador", |
["Odo the Blindwatcher"] = "Odo el vig\195\173a ciego", |
["Razorclaw the Butcher"] = "Zarpador el Carnicero", |
["Wolf Master Nandos"] = "Maestro de lobos Nandos", |
--Stratholme |
["Archivist Galford"] = "Archivista Galford", |
["Balnazzar"] = "Balnazzar", |
["Baron Rivendare"] = "Bar\195\179n Rivendare", |
["Baroness Anastari"] = "Baronesa Anastari", |
["Black Guard Swordsmith"] = "Armero Guardia Negra", |
["Cannon Master Willey"] = "Ca\195\177onero Jefe Willey", |
["Crimson Hammersmith"] = "Forjamartillos Carmes\195\173", |
["Fras Siabi"] = "Fras Siabi", |
["Hearthsinger Forresten"] = "Escupezones Foreste", |
["Magistrate Barthilas"] = "Magistrado Barthilas", |
["Maleki the Pallid"] = "Maleki el P\195\161lido", |
["Nerub'enkan"] = "Nerub'enkan", |
["Postmaster Malown"] = "Jefe de correos Malown", -- check |
["Ramstein the Gorger"] = "Ramstein el Empachador", |
["Skul"] = "Skul", |
["Stonespine"] = "Pidrespina", |
["The Unforgiven"] = "El Imperdonable", |
["Timmy the Cruel"] = "Timmy el Cruel", |
--Sunwell Plateau |
["Kalecgos"] = "Kalecgos", |
["Sathrovarr the Corruptor"] = "Sathrovarr the Corruptor", |
["Brutallus"] = "Brutallus", |
["Felmyst"] = "Felmyst", |
["Kil'jaeden"] = "Kil'jaeden", |
["M'uru"] = "M'uru", |
["The Eredar Twins"] = "The Eredar Twins", |
["Lady Sacrolash"] = "Lady Sacrolash", |
["Grand Warlock Alythess"] = "Grand Warlock Alythess", |
--Tempest Keep |
--The Arcatraz |
["Dalliah the Doomsayer"] = "Dalliah la Decidora del Destino", |
["Harbinger Skyriss"] = "Presagista Cieloriss", |
["Warden Mellichar"] = "Celador Mellichar", |
["Wrath-Scryer Soccothrates"] = "Ar\195\186spice de c\195\179lera Soccothrates", |
["Zereketh the Unbound"] = "Zereketh el Desatado", |
--The Botanica |
["Commander Sarannis"] = "Comandante Sarannis", |
["High Botanist Freywinn"] = "Gran botánico Freywinn", |
["Laj"] = "Laj", |
["Thorngrin the Tender"] = "Thorngrin el Tierno", |
["Warp Splinter"] = "Deshecho de distorsión", -- check |
--The Eye |
["Al'ar"] = "Al'ar", |
["Cosmic Infuser"] = "Infusor cósmico", |
["Devastation"] = "Devastación", |
["Grand Astromancer Capernian"] = "Gran Astromante Capernian", |
["High Astromancer Solarian"] = "Gran astrom\195\161ntico Solarian", |
["Infinity Blades"] = "Infinity Blades", -- fix |
["Kael'thas Sunstrider"] = "Kael'thas Caminante del Sol", |
["Lord Sanguinar"] = "Lord Sanguinar", |
["Master Engineer Telonicus"] = "Maestro Ingeriero Telonicus", |
["Netherstrand Longbow"] = "Arco largo de fibra abisal", |
["Phaseshift Bulwark"] = "Baluarte de cambio de fase", |
["Solarium Agent"] = "Solarium Agent", -- fix |
["Solarium Priest"] = "Solarium Priest", -- fix |
["Staff of Disintegration"] = "Bast\195\179n de desintegraci\195\179n", |
["Thaladred the Darkener"] = "Thaladred el Oscurecedor", |
["Void Reaver"] = "Atracador del Vac\195\173o", |
["Warp Slicer"] = "Cercenadora de distorsi\195\179n", |
--The Mechanar |
["Gatewatcher Gyro-Kill"] = "VÃgia de las puertas Giromata", |
["Gatewatcher Iron-Hand"] = "VigÃa de las puertas Manoyerro", |
["Mechano-Lord Capacitus"] = "Lord-mecano Capacitus", |
["Nethermancer Sepethrea"] = "Abisálico Sepethrea", |
["Pathaleon the Calculator"] = "Panthaleon el Calculador", |
--The Deadmines |
["Brainwashed Noble"] = "Noble aducido", |
["Captain Greenskin"] = "Capit\195\161n Verdepel", |
["Cookie"] = "El Chef", |
["Edwin VanCleef"] = "Edwin VanCleef", |
["Foreman Thistlenettle"] = "Supervisor Cardortiga", |
["Gilnid"] = "Gilnid", |
["Marisa du'Paige"] = "Marisa du'Paige", |
["Miner Johnson"] = "Minero Johnson", |
["Mr. Smite"] = "Sr. Golpin", |
["Rhahk'Zor"] = "Rhahk'Zor", |
["Sneed"] = "Sneed", |
["Sneed's Shredder"] = "Machacador de Sneed", |
--The Stockade |
["Bazil Thredd"] = "Bazil Thredd", |
["Bruegal Ironknuckle"] = "Bruegal Nudoferro", |
["Dextren Ward"] = "Dextren Tutor", |
["Hamhock"] = "Hamhock", |
["Kam Deepfury"] = "Kam Furiahonda", |
["Targorr the Dread"] = "Targor el Pavoroso", |
--The Temple of Atal'Hakkar |
["Atal'alarion"] = "Atal'alarion", |
["Avatar of Hakkar"] = "Avatar de Hakkar", |
["Dreamscythe"] = "Guada\195\177asue\195\177os", |
["Gasher"] = "Gasher", |
["Hazzas"] = "Hazzas", |
["Hukku"] = "Hukku", |
-- ["Jade"] = true, |
["Jammal'an the Prophet"] = "Jammal'an el Profeta", |
["Kazkaz the Unholy"] = "Kazkaz el Blasfemo", |
["Loro"] = "Loro", |
["Mijan"] = "Mijar", |
["Morphaz"] = "Morphaz", |
["Ogom the Wretched"] = "Ogom el Desdichado", |
["Shade of Eranikus"] = "Sombra de Eranikus", |
["Veyzhak the Cannibal"] = "Veyzhak el Can\195\173bal", |
["Weaver"] = "Sastr\195\179n", |
["Zekkis"] = "Zekkis", |
["Zolo"] = "Zolo", |
["Zul'Lor"] = "Zul'Lor", |
--Uldaman |
["Ancient Stone Keeper"] = "Vigilante p\195\169treo anciano", |
["Archaedas"] = "Archaedas", |
["Baelog"] = "Baelog", |
["Digmaster Shovelphlange"] = "Maestro de excavación Palatiro", |
["Galgann Firehammer"] = "Galgann Flamartillo", |
["Grimlok"] = "Grimlok", |
["Ironaya"] = "Hierraya", |
["Obsidian Sentinel"] = "Centinela Obsidiano", |
["Revelosh"] = "Revelosh", |
--Wailing Caverns |
["Boahn"] = "Boahn", |
["Deviate Faerie Dragon"] = "Drag\195\179n f\195\169rico descarriado", |
["Kresh"] = "Kresh", |
["Lady Anacondra"] = "Lady Anacondra", |
["Lord Cobrahn"] = "Lord Cobrahn", |
["Lord Pythas"] = "Lord Pythas", |
["Lord Serpentis"] = "Lord Serpentis", |
["Mad Magglish"] = "Magglish el Loco", |
["Mutanus the Devourer"] = "Mutanus el Devorador", |
["Skum"] = "Skum", |
["Trigore the Lasher"] = "Trigore el Azotador", |
["Verdan the Everliving"] = "Verdan el Eterno", |
--World Bosses |
["Avalanchion"] = "Avalanchion", |
["Azuregos"] = "Azuregos", |
["Baron Charr"] = "Bar\195\179n Charr", |
["Baron Kazum"] = "Bar\195\179n Kazum", |
["Doom Lord Kazzak"] = "Señor ApocalÃptico Kazzak", |
["Doomwalker"] = "Caminante del Destino", -- check |
["Emeriss"] = "Emeriss", |
["High Marshal Whirlaxis"] = "High Marshal Whirlaxis", |
["Lethon"] = "Lethon", |
["Lord Skwol"] = "Lord Skwol", |
["Prince Skaldrenox"] = "Pr\195\173ncipe Skaldrenox", |
["Princess Tempestria"] = "Princesa Tempestria", |
["Taerar"] = "Taerar", |
["The Windreaver"] = "El Atracavientos", |
["Ysondre"] = "Ysondre", |
--Zul'Aman |
["Akil'zon"] = "Akil'zon", |
["Halazzi"] = "Halazzi", |
["Jan'alai"] = "Jan'alai", |
["Malacrass"] = "Malacrass", |
["Nalorakk"] = "Nalorakk", |
["Zul'jin"] = "Zul'jin", |
["Hex Lord Malacrass"] = "Hex Lord Malacrass", |
--Zul'Farrak |
["Antu'sul"] = "Antu'sul", |
["Chief Ukorz Sandscalp"] = "Jefe Ukorz Cabellarena", |
["Dustwraith"] = "ÃÂnima de polvo", |
["Gahz'rilla"] = "Gahz'rilla", |
["Hydromancer Velratha"] = "Hidrom\195\161ntica Velratha", |
["Murta Grimgut"] = "Murta Tripuriosa", |
["Nekrum Gutchewer"] = "Nekrum Cometripas", |
["Oro Eyegouge"] = "Oro Bocojo ", |
["Ruuzlu"] = "Ruuzlu", |
["Sandarr Dunereaver"] = "Sandarr Asaltadunas", |
["Sandfury Executioner"] = "Ejecutor Furiarena", |
["Sergeant Bly"] = "Sargento Bly", |
["Shadowpriest Sezz'ziz"] = "Sacerdote oscuro Sezz'ziz", |
["Theka the Martyr"] = "Theka la M\195\161rtir", |
["Witch Doctor Zum'rah"] = "M\195\169dico brujo Zum'rah", |
["Zerillis"] = "Zerillis", |
["Zul'Farrak Dead Hero"] = "H\195\169roe muerto Zul'Farrak", |
--Zul'Gurub |
["Bloodlord Mandokir"] = "Se\195\177or sangriento Mandokir", |
["Gahz'ranka"] = "Gahz'ranka", |
["Gri'lek"] = "Gri'lek", |
["Hakkar"] = "Hakkar", |
["Hazza'rah"] = "Hazza'rah", |
["High Priest Thekal"] = "Sumo Sacerdote Thekal", |
["High Priest Venoxis"] = "Sumo Sacerdote Venoxis", |
["High Priestess Arlokk"] = "Suma Sacerdotisa Arlokk", |
["High Priestess Jeklik"] = "Suma Sacerdotisa Jeklik", |
["High Priestess Mar'li"] = "Suma Sacerdotisa Mar'li", |
["Jin'do the Hexxer"] = "Jin'do el Aojador", |
["Renataki"] = "Renataki", |
["Wushoolay"] = "Wushoolay", |
--Ring of Blood (where? an instnace? should be in other file?) |
["Brokentoe"] = "Dedorroto", |
["Mogor"] = "Mogor", |
["Murkblood Twin"] = "Gemelo Sangreoscura", |
["Murkblood Twins"] = "Gemelos Sangreoscura", |
["Rokdar the Sundered Lord"] = "Rokdar el Señor Hendido", |
["Skra'gath"] = "Skra'gath", |
["The Blue Brothers"] = "Los Hermanos Azules", |
["Warmaul Champion"] = "Campeón Mazo de Guerra", |
} |
else |
error(("%s: Locale %q not supported"):format(MAJOR_VERSION, GAME_LOCALE)) |
end |
## Interface: 20400 |
## LoadOnDemand: 1 |
## Title: Lib: Babble-Boss-3.0 |
## Notes: A library to help with localization of bosses. |
## Notes-zhCN: 为æ¬å°åæå¡çæ¯æåº[é¦é¢å称] |
## Notes-zhTW: çºæ¬å°åæåçå½å¼åº«[é¦é å稱] |
## Notes-deDE: BabbleLib ist eine Bibliothek, die bei der Lokalisierung helfen soll. |
## Notes-frFR: Une bibliothèque d'aide à la localisation. |
## Notes-esES: Una biblioteca para ayudar con las localizaciones. |
## Author: ckknight |
## X-eMail: ckknight@gmail.com |
## X-Category: Library |
## X-License: MIT |
LibStub\LibStub.lua |
lib.xml |
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info |
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke |
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! |
local LibStub = _G[LIBSTUB_MAJOR] |
if not LibStub or LibStub.minor < LIBSTUB_MINOR then |
LibStub = LibStub or {libs = {}, minors = {} } |
_G[LIBSTUB_MAJOR] = LibStub |
LibStub.minor = LIBSTUB_MINOR |
function LibStub:NewLibrary(major, minor) |
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") |
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") |
local oldminor = self.minors[major] |
if oldminor and oldminor >= minor then return nil end |
self.minors[major], self.libs[major] = minor, self.libs[major] or {} |
return self.libs[major], oldminor |
end |
function LibStub:GetLibrary(major, silent) |
if not self.libs[major] and not silent then |
error(("Cannot find a library instance of %q."):format(tostring(major)), 2) |
end |
return self.libs[major], self.minors[major] |
end |
function LibStub:IterateLibraries() return pairs(self.libs) end |
setmetatable(LibStub, { __call = LibStub.GetLibrary }) |
end |
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ |
..\FrameXML\UI.xsd"> |
<Script file="LibBabble-Boss-3.0.lua" /> |
</Ui> |
## Interface: 20400 |
## Title: Lib: AceComm-2.0 |
## Notes: AddOn development framework |
## Author: Ace Development Team |
## LoadOnDemand: 1 |
## X-Website: http://www.wowace.com |
## X-Category: Library |
## X-License: LGPL v2.1 + MIT for AceOO-2.0 |
## Dependencies: AceLibrary, AceEvent-2.0, AceOO-2.0 |
AceComm-2.0.lua |
--[[ |
Name: AceComm-2.0 |
Revision: $Rev$ |
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) |
Inspired By: Ace 1.x by Turan (turan@gryphon.com) |
Website: http://www.wowace.com/ |
Documentation: http://www.wowace.com/index.php/AceComm-2.0 |
SVN: http://svn.wowace.com/wowace/trunk/Ace2/AceComm-2.0 |
Description: Mixin to allow for inter-player addon communications. |
Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0, |
ChatThrottleLib by Mikk (included) |
License: LGPL v2.1 |
]] |
local MAJOR_VERSION = "AceComm-2.0" |
local MINOR_VERSION = "$Revision$" |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end |
local AceOO = AceLibrary("AceOO-2.0") |
local AceComm = AceOO.Mixin { |
"SendCommMessage", |
"SendPrioritizedCommMessage", |
"RegisterComm", |
"UnregisterComm", |
"UnregisterAllComms", |
"IsCommRegistered", |
"SetDefaultCommPriority", |
"SetCommPrefix", |
"RegisterMemoizations", |
"IsUserInChannel", |
} |
AceComm.hooks = {} |
local AceEvent |
local byte_a = ("a"):byte() |
local byte_z = ("z"):byte() |
local byte_A = ("A"):byte() |
local byte_Z = ("Z"):byte() |
local byte_deg = ("\176"):byte() |
local byte_b = ("b"):byte() |
local byte_B = ("B"):byte() |
local byte_nil = ("/"):byte() |
local byte_plus = ("+"):byte() |
local byte_minus = ("-"):byte() |
local byte_d = ("d"):byte() |
local byte_D = ("D"):byte() |
local byte_e = ("e"):byte() |
local byte_E = ("E"):byte() |
local byte_m = ("m"):byte() |
local byte_s = ("s"):byte() |
local byte_S = ("S"):byte() |
local byte_o = ("o"):byte() |
local byte_O = ("O"):byte() |
local byte_t = ("t"):byte() |
local byte_T = ("T"):byte() |
local byte_u = ("u"):byte() |
local byte_U = ("U"):byte() |
local byte_v = ("v"):byte() |
local byte_V = ("V"):byte() |
local byte_i = ("i"):byte() |
local byte_I = ("I"):byte() |
local byte_inf = ("@"):byte() |
local byte_ninf = ("$"):byte() |
local byte_nan = ("!"):byte() |
local fake_nil = {} |
local inf = 1/0 |
local nan = 0/0 |
local _G = getfenv(0) |
local ChatThrottleLib = _G.ChatThrottleLib |
local math_floor = _G.math.floor |
local string_char = _G.string.char |
local math_min = _G.math.min |
local table_concat = _G.table.concat |
local type = _G.type |
local unpack = _G.unpack |
local pairs = _G.pairs |
local next = _G.next |
local select = _G.select |
local setmetatable = _G.setmetatable |
local GetTime = _G.GetTime |
local AceLibrary = _G.AceLibrary |
local GetChannelName = _G.GetChannelName |
local LeaveChannelByName = _G.LeaveChannelByName |
local JoinChannelByName = _G.JoinChannelByName |
local GetRealZoneText = _G.GetRealZoneText |
local GetChannelList = _G.GetChannelList |
local tostring = _G.tostring |
local ListChannelByName = _G.ListChannelByName |
local tonumber = _G.tonumber |
local math_frexp = _G.math.frexp |
local math_ldexp = _G.math.ldexp |
local GetItemInfo = _G.GetItemInfo |
local error = _G.error |
local pcall = _G.pcall |
local GetNumRaidMembers = _G.GetNumRaidMembers |
local GetNumPartyMembers = _G.GetNumPartyMembers |
local UnitInRaid = _G.UnitInRaid |
local IsInGuild = _G.IsInGuild |
local GetCVar = _G.GetCVar |
local SetCVar = _G.SetCVar |
local IsResting = _G.IsResting |
local rawget = _G.rawget |
local GetAddOnMetadata = _G.GetAddOnMetadata |
local IsAddOnLoaded = _G.IsAddOnLoaded |
local geterrorhandler = _G.geterrorhandler |
local hooksecurefunc = _G.hooksecurefunc |
local GetFramerate = _G.GetFramerate |
local IsInInstance = _G.IsInInstance |
local player = UnitName("player") |
local new, del |
do |
local list = setmetatable({},{__mode='k'}) |
function new(...) |
local t = next(list) |
if t then |
list[t] = nil |
for i = 1, select('#', ...) do |
t[i] = select(i, ...) |
end |
return t |
else |
return {...} |
end |
end |
function del(t) |
for k in pairs(t) do |
t[k] = nil |
end |
t[''] = true |
t[''] = nil |
list[t] = true |
return nil |
end |
end |
local NumericCheckSum, HexCheckSum |
local TailoredNumericCheckSum, TailoredBinaryCheckSum |
do |
function NumericCheckSum(text) |
local counter = 1 |
local len = text:len() |
for i = 1, len, 3 do |
counter = (counter*8257 % 16777259) + |
(text:byte(i)) + |
((text:byte(i+1) or 1)*127) + |
((text:byte(i+2) or 2)*16383) |
end |
return counter % 16777213 |
end |
function HexCheckSum(text) |
return ("%06x"):format(NumericCheckSum(text)) |
end |
function TailoredNumericCheckSum(text) |
local hash = NumericCheckSum(text) |
local a = math_floor(hash / 256^2) |
local b = math_floor(hash / 256) % 256 |
local c = hash % 256 |
-- \000, \n, |, \176, s, S, \015, \020 |
if a == 0 or a == 10 or a == 124 or a == 176 or a == 115 or a == 83 or a == 15 or a == 20 or a == 37 then |
a = a + 1 |
-- \t, \255 |
elseif a == 9 or a == 255 then |
a = a - 1 |
end |
if b == 0 or b == 10 or b == 124 or b == 176 or b == 115 or b == 83 or b == 15 or b == 20 or b == 37 then |
b = b + 1 |
elseif b == 9 or b == 255 then |
b = b - 1 |
end |
if c == 0 or c == 10 or c == 124 or c == 176 or c == 115 or c == 83 or c == 15 or c == 20 or c == 37 then |
c = c + 1 |
elseif c == 9 or c == 255 then |
c = c - 1 |
end |
return a * 256^2 + b * 256 + c |
end |
function TailoredBinaryCheckSum(text) |
local num = TailoredNumericCheckSum(text) |
return string_char(math_floor(num / 256^2), math_floor(num / 256) % 256, num % 256) |
end |
end |
local function IsInChannel(chan) |
return GetChannelName(chan) ~= 0 |
end |
local Encode, EncodeByte, EncodeBytes |
do |
local drunkHelper_t = { |
[29] = "\029\030", |
[31] = "\029\032", |
[20] = "\029\021", |
[15] = "\029\016", |
[("S"):byte()] = "\020", -- change S and s to a different set of character bytes. |
[("s"):byte()] = "\015", |
[127] = "\029\126", -- \127 (this is here because \000 is more common) |
[0] = "\127", -- \000 |
[10] = "\029\011", -- \n |
[124] = "\029\125", -- | |
[("%"):byte()] = "\029\038", -- % |
} |
for c = 128, 255 do |
local num = c |
num = num - 127 |
if num >= 9 then |
num = num + 2 |
end |
if num >= 29 then |
num = num + 2 |
end |
if num >= 128 then |
drunkHelper_t[c] = string_char(29, num - 127) -- 1, 2, 3, 4, 5 |
else |
drunkHelper_t[c] = string_char(31, num) |
end |
end |
local function drunkHelper(char) |
return drunkHelper_t[char:byte()] |
end |
local soberHelper_t = { |
[176] = "\176\177", |
[255] = "\176\254", -- \255 (this is here because \000 is more common) |
[0] = "\255", -- \000 |
[10] = "\176\011", -- \n |
[124] = "\176\125", -- | |
[("%"):byte()] = "\176\038", -- % |
} |
local function soberHelper(char) |
return soberHelper_t[char:byte()] |
end |
-- Package a message for transmission |
function Encode(text, drunk) |
if drunk then |
return text:gsub("([\010\015\020\029%%\031Ss\124\127-\255])", drunkHelper) |
else |
if not text then |
DEFAULT_CHAT_FRAME:AddMessage(debugstack()) |
end |
return text:gsub("([\176\255%z\010\124%%])", soberHelper) |
end |
end |
function EncodeByte(num, drunk) |
local t |
if drunk then |
t = drunkHelper_t |
else |
t = soberHelper_t |
end |
local value = t[num] |
if value then |
return value |
else |
return string_char(num) |
end |
end |
local function EncodeBytes_helper(drunk, ...) |
local n = select('#', ...) |
if n == 0 then |
return |
end |
local t |
if drunk then |
t = drunkHelper_t |
else |
t = soberHelper_t |
end |
local num = (...) |
local value = t[num] |
if not value then |
return num, EncodeBytes_helper(drunk, select(2, ...)) |
else |
local len = #value |
if len == 1 then |
return value:byte(1), EncodeBytes_helper(drunk, select(2, ...)) |
else -- 2 |
local a, b = value:byte(1, 2) |
return a, b, EncodeBytes_helper(drunk, select(2, ...)) |
end |
end |
end |
function EncodeBytes(drunk, ...) |
return string_char(EncodeBytes_helper(drunk, ...)) |
end |
end |
local Decode |
do |
local t = { |
["\177"] = "\176", |
["\254"] = "\255", |
["\011"] = "\010", |
["\125"] = "\124", |
["\038"] = "\037", |
} |
local function soberHelper(text) |
return t[text] |
end |
local t = { |
["\127"] = "\000", |
["\015"] = "s", |
["\020"] = "S", |
} |
local function drunkHelper1(text) |
return t[text] |
end |
local t = setmetatable({}, {__index=function(self, c) |
local num = c:byte() |
if num >= 29 then |
num = num - 2 |
end |
if num >= 9 then |
num = num - 2 |
end |
num = num + 127 |
self[c] = string_char(num) |
return self[c] |
end}) |
local function drunkHelper2(text) |
return t[text] |
end |
local t = { |
["\038"] = "%", |
["\125"] = "\124", |
["\011"] = "\010", |
["\126"] = "\127", |
["\016"] = "\015", |
["\021"] = "\020", |
["\001"] = "\251", |
["\002"] = "\252", |
["\003"] = "\253", |
["\004"] = "\254", |
["\005"] = "\255", |
["\032"] = "\031", |
["\030"] = "\029", |
} |
local function drunkHelper3(text) |
return t[text] |
end |
-- Clean a received message |
function Decode(text, drunk) |
if drunk then |
text = text:gsub("^(.*)\029.-$", "%1") |
-- get rid of " ...hic!" |
text = text:gsub("([\127\015\020])", drunkHelper1) |
text = text:gsub("\031(.)", drunkHelper2) |
text = text:gsub("\029([\038\125\011\126\016\021\001\002\003\004\005\032\030])", drunkHelper3) |
else |
text = text:gsub("\255", "\000") |
text = text:gsub("\176([\177\254\011\125\038])", soberHelper) |
end |
-- remove the hidden character and refix the prohibited characters. |
return text |
end |
end |
local lastChannelJoined |
function AceComm.hooks:JoinChannelByName(orig, channel, ...) |
lastChannelJoined = channel |
return orig(channel, ...) |
end |
local function JoinChannel(channel) |
if not IsInChannel(channel) then |
LeaveChannelByName(channel) |
AceComm:ScheduleEvent("AceComm-JoinChannelByName-" .. channel, JoinChannelByName, 0, channel) |
end |
end |
local function LeaveChannel(channel) |
if IsInChannel(channel) then |
LeaveChannelByName(channel) |
end |
end |
local switches = {} |
local function SwitchChannel(former, latter) |
if IsInChannel(former) then |
LeaveChannelByName(former) |
local t = new() |
t.former = former |
t.latter = latter |
switches[t] = true |
return |
end |
if not IsInChannel(latter) then |
JoinChannelByName(latter) |
end |
end |
local shutdown = false |
local zoneCache |
local function GetCurrentZoneChannel() |
if not zoneCache then |
zoneCache = "AceCommZone" .. HexCheckSum(GetRealZoneText()) |
end |
return zoneCache |
end |
local AceComm_registry |
local function SupposedToBeInChannel(chan) |
if not chan:find("^AceComm") then |
return true |
elseif shutdown or not AceEvent:IsFullyInitialized() then |
return false |
end |
if chan == "AceComm" then |
return AceComm_registry.GLOBAL and next(AceComm_registry.GLOBAL) and true or false |
elseif chan:find("^AceCommZone%x%x%x%x%x%x$") then |
if chan == GetCurrentZoneChannel() then |
return AceComm_registry.ZONE and next(AceComm_registry.ZONE) and true or false |
else |
return false |
end |
else |
return AceComm_registry.CUSTOM and AceComm_registry.CUSTOM[chan] and next(AceComm_registry.CUSTOM[chan]) and true or false |
end |
end |
local function checkChannelList(...) |
for i = 2, select("#", ...), 2 do |
local c = select(i, ...) |
if c and not SupposedToBeInChannel(c) then |
LeaveChannelByName(c) |
end |
end |
end |
local function LeaveAceCommChannels(noShutdown) |
if not noShutdown then |
shutdown = true |
end |
checkChannelList(GetChannelList()) |
end |
local lastRefix = 0 |
local function RefixAceCommChannelsAndEvents() |
if GetTime() - lastRefix <= 5 then |
AceComm:ScheduleEvent("AceComm-RefixAceCommChannelsAndEvents", RefixAceCommChannelsAndEvents, GetTime() - lastRefix) |
return |
end |
lastRefix = GetTime() |
LeaveAceCommChannels(true) |
local channel = false |
if SupposedToBeInChannel("AceComm") then |
JoinChannel("AceComm") |
channel = true |
end |
if SupposedToBeInChannel(GetCurrentZoneChannel()) then |
JoinChannel(GetCurrentZoneChannel()) |
channel = true |
end |
if AceComm_registry.CUSTOM then |
for k,v in pairs(AceComm_registry.CUSTOM) do |
if next(v) and SupposedToBeInChannel(k) then |
JoinChannel(k) |
channel = true |
end |
end |
end |
if AceComm_registry.WHISPER or AceComm_registry.GROUP or AceComm_registry.PARTY or AceComm_registry.RAID or AceComm_registry.BATTLEGROUND or AceComm_registry.GUILD then |
if not AceComm:IsEventRegistered("CHAT_MSG_ADDON") then |
AceComm:RegisterEvent("CHAT_MSG_ADDON") |
end |
else |
if AceComm:IsEventRegistered("CHAT_MSG_ADDON") then |
AceComm:UnregisterEvent("CHAT_MSG_ADDON") |
end |
end |
if channel then |
if not AceComm:IsEventRegistered("CHAT_MSG_CHANNEL") then |
AceComm:RegisterEvent("CHAT_MSG_CHANNEL") |
end |
if not AceComm:IsEventRegistered("CHAT_MSG_CHANNEL_LIST") then |
AceComm:RegisterEvent("CHAT_MSG_CHANNEL_LIST") |
end |
if not AceComm:IsEventRegistered("CHAT_MSG_CHANNEL_JOIN") then |
AceComm:RegisterEvent("CHAT_MSG_CHANNEL_JOIN") |
end |
if not AceComm:IsEventRegistered("CHAT_MSG_CHANNEL_LEAVE") then |
AceComm:RegisterEvent("CHAT_MSG_CHANNEL_LEAVE") |
end |
else |
if AceComm:IsEventRegistered("CHAT_MSG_CHANNEL") then |
AceComm:UnregisterEvent("CHAT_MSG_CHANNEL") |
end |
if AceComm:IsEventRegistered("CHAT_MSG_CHANNEL_LIST") then |
AceComm:UnregisterEvent("CHAT_MSG_CHANNEL_LIST") |
end |
if AceComm:IsEventRegistered("CHAT_MSG_CHANNEL_JOIN") then |
AceComm:UnregisterEvent("CHAT_MSG_CHANNEL_JOIN") |
end |
if AceComm:IsEventRegistered("CHAT_MSG_CHANNEL_LEAVE") then |
AceComm:UnregisterEvent("CHAT_MSG_CHANNEL_LEAVE") |
end |
end |
end |
do |
local myFunc = function(k) |
if not IsInChannel(k.latter) then |
JoinChannelByName(k.latter) |
end |
switches[k] = del(k) |
end |
function AceComm:CHAT_MSG_CHANNEL_NOTICE(kind, _, _, deadName, _, _, _, num, channel) |
if kind == "YOU_LEFT" then |
if not channel:find("^AceComm") then |
return |
end |
for k in pairs(switches) do |
if k.former == channel then |
self:ScheduleEvent("AceComm-Join-" .. k.latter, myFunc, 0, k) |
end |
end |
if channel == "AceComm" then |
self:TriggerEvent("AceComm_LeftChannel", "GLOBAL") |
elseif channel == GetCurrentZoneChannel() then |
self:TriggerEvent("AceComm_LeftChannel", "ZONE") |
else |
self:TriggerEvent("AceComm_LeftChannel", "CUSTOM", channel:sub(8)) |
end |
if SupposedToBeInChannel(channel) then |
self:ScheduleEvent("AceComm-JoinChannel-" .. channel, JoinChannel, 0, channel) |
end |
if self.userRegistry[channel] then |
self.userRegistry[channel] = del(self.userRegistry[channel]) |
end |
elseif kind == "YOU_JOINED" then |
if not (num == 0 and deadName or channel):find("^AceComm") then |
return |
end |
if num == 0 then |
self:ScheduleEvent("AceComm-LeaveChannelByName-" .. deadName, LeaveChannelByName, 0, deadName) |
local t = new() |
t.former = deadName |
t.latter = deadName |
switches[t] = true |
elseif channel == "AceComm" then |
self:TriggerEvent("AceComm_JoinedChannel", "GLOBAL") |
elseif channel == GetCurrentZoneChannel() then |
self:TriggerEvent("AceComm_JoinedChannel", "ZONE") |
else |
self:TriggerEvent("AceComm_JoinedChannel", "CUSTOM", channel:sub(8)) |
end |
if num ~= 0 then |
if not SupposedToBeInChannel(channel) then |
LeaveChannel(channel) |
else |
ListChannelByName(channel) |
end |
end |
end |
end |
end |
local SerializeAndEncode |
do |
local recurse = {} |
local function _Serialize(v, textToHash, sb, drunk) |
local kind = type(v) |
-- Note that the ordering of these if/elseif's matters, don't |
-- change it unless you know what you're doing. |
if kind == "boolean" then |
if v then |
sb[#sb+1] = "B" -- true |
return 1 |
else |
sb[#sb+1] = "b" -- false |
return 1 |
end |
elseif not v or v == fake_nil then |
sb[#sb+1] = "/" -- nil |
return 1 |
elseif kind == "number" then |
-- v == math_floor(v) will also return true if |
-- v is 1/0 or -1/0, so we need to check that first. |
-- Thanks to Xinhuan for finding the problem. |
if v == inf then |
sb[#sb+1] = "@" |
return 1 |
elseif v == -inf then |
sb[#sb+1] = "$" |
return 1 |
elseif v == math_floor(v) then |
if v <= 2^7-1 and v >= -2^7 then |
if v < 0 then |
v = v + 256 |
end |
sb[#sb+1] = "d" |
sb[#sb+1] = EncodeByte(v, drunk) |
return 2 |
elseif v <= 2^15-1 and v >= -2^15 then |
if v < 0 then |
v = v + 256^2 |
end |
sb[#sb+1] = "D" |
sb[#sb+1] = EncodeBytes(drunk, math_floor(v / 256), v % 256) |
return 3 |
elseif v <= 2^31-1 and v >= -2^31 then |
if v < 0 then |
v = v + 256^4 |
end |
sb[#sb+1] = "e" |
sb[#sb+1] = EncodeBytes(drunk, math_floor(v / 256^3), math_floor(v / 256^2) % 256, math_floor(v / 256) % 256, v % 256) |
return 5 |
elseif v <= 2^63-1 and v >= -2^63 then |
if v < 0 then |
v = v + 256^8 |
end |
sb[#sb+1] = "E" |
sb[#sb+1] = EncodeBytes(drunk, math_floor(v / 256^7), math_floor(v / 256^6) % 256, math_floor(v / 256^5) % 256, math_floor(v / 256^4) % 256, math_floor(v / 256^3) % 256, math_floor(v / 256^2) % 256, math_floor(v / 256) % 256, v % 256) |
return 9 |
end |
elseif v ~= v then -- not a number |
sb[#sb+1] = "!" |
return 1 |
end |
local sign = v < 0 or v == 0 and tostring(v) == "-0" |
if sign then |
v = -v |
end |
local m, exp = math_frexp(v) |
m = m * 2^53 |
local x = exp + 1023 |
local b = m % 256 |
local c = math_floor(m / 256) % 256 |
m = math_floor(m / 256^2) |
m = m + x * 2^37 |
sb[#sb+1] = sign and "-" or "+" |
sb[#sb+1] = EncodeBytes(drunk, math_floor(m / 256^5) % 256, math_floor(m / 256^4) % 256, math_floor(m / 256^3) % 256, math_floor(m / 256^2) % 256, math_floor(m / 256) % 256, m % 256, c, b) |
return 9 |
elseif kind == "string" then |
local hash = textToHash and textToHash[v] |
if hash then |
sb[#sb+1] = "m" |
sb[#sb+1] = EncodeBytes(drunk, math_floor(hash / 256^2), math_floor(hash / 256) % 256, hash % 256) |
return 4 |
end |
local r,g,b,A,B,C,D,E,F,G,H,name = v:match("^|cff(%x%x)(%x%x)(%x%x)|Hitem:(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(%-?%d+):(%d+)|h%[(.+)%]|h|r$") |
if A then |
-- item link |
A = A+0 -- convert to number |
B = B+0 |
C = C+0 |
D = D+0 |
E = E+0 |
F = F+0 |
G = G+0 |
H = H+0 |
r = tonumber(r, 16) |
g = tonumber(g, 16) |
b = tonumber(b, 16) |
-- (1-35000):(1-3093):(1-3093):(1-3093):(1-3093):(?):(-57 to 2164):(0-4294967295) |
F = nil -- don't care |
if G < 0 then |
G = G + 256^2 -- handle negatives |
end |
H = H % 256^2 -- only lower 16 bits matter |
sb[#sb+1] = "I" |
sb[#sb+1] = EncodeBytes(drunk, r, g, b, math_floor(A / 256) % 256, A % 256, math_floor(B / 256) % 256, B % 256, math_floor(C / 256) % 256, C % 256, math_floor(D / 256) % 256, D % 256, math_floor(E / 256) % 256, E % 256, math_floor(G / 256) % 256, G % 256, math_floor(H / 256) % 256, H % 256, math_min(name:len(), 255)) |
sb[#sb+1] = Encode(name:sub(1, 255), drunk) |
return 19 + math_min(name:len(), 255) |
else |
-- normal string |
local len = v:len() |
if len <= 255 then |
sb[#sb+1] = "s" |
sb[#sb+1] = EncodeByte(len, drunk) |
sb[#sb+1] = Encode(v, drunk) |
return 2 + len |
else |
sb[#sb+1] = "S" |
sb[#sb+1] = EncodeBytes(drunk, math_floor(len / 256), len % 256) |
sb[#sb+1] = Encode(v, drunk) |
return 3 + len |
end |
end |
elseif kind == "function" then |
AceComm:error("Cannot serialize a function") |
elseif kind == "table" then |
if recurse[v] then |
for k in pairs(recurse) do |
recurse[k] = nil |
end |
AceComm:error("Cannot serialize a recursive table") |
return 0 |
end |
recurse[v] = true |
if AceOO.inherits(v, AceOO.Class) then |
if not v.class then |
AceComm:error("Cannot serialize an AceOO class, can only serialize objects") |
elseif type(v.Serialize) ~= "function" then |
AceComm:error("Cannot serialize an AceOO object without the `Serialize' method.") |
elseif type(v.class.Deserialize) ~= "function" then |
AceComm:error("Cannot serialize an AceOO object without the `Deserialize' static method.") |
elseif type(v.class.GetLibraryVersion) ~= "function" or not AceLibrary:HasInstance(v.class:GetLibraryVersion()) then |
AceComm:error("Cannot serialize an AceOO object if the class is not registered with AceLibrary.") |
end |
local classHash = TailoredBinaryCheckSum(v.class:GetLibraryVersion()) |
local t = new(classHash, v:Serialize()) |
local sb_id = #sb+1 |
sb[#sb+1] = "" -- dummy |
sb[#sb+1] = "" -- dummy |
local len = 0 |
local num = 0 |
for i = 2, #t do |
len = len + _Serialize(t[i], textToHash, sb, drunk) |
num = num + 1 |
end |
t = del(t) |
for k in pairs(recurse) do |
recurse[k] = nil |
end |
if num <= 255 then |
sb[sb_id] = "o" |
sb[sb_id+1] = EncodeByte(num, drunk) |
return 2 + len |
else |
sb[sb_id] = "O" |
sb[sb_id+1] = EncodeBytes(drunk, math_floor(num / 256), num % 256) |
return 3 + len |
end |
end |
local islist = false |
local n = #v |
if n >= 1 then |
islist = true |
for k,u in pairs(v) do |
if type(k) ~= "number" or k < 1 or k > n then |
islist = false |
break |
end |
end |
end |
local isset = true |
for k, v in pairs(v) do |
if v ~= true then |
isset = false |
break |
end |
end |
local sb_id = #sb+1 |
sb[#sb+1] = "" -- dummy |
sb[#sb+1] = "" -- dummy |
local len = 0 |
local num = 0 |
if islist then |
num = n |
for i = 1, n do |
len = len + _Serialize(v[i], textToHash, sb, drunk) |
end |
elseif isset then |
for k in pairs(v) do |
len = len + _Serialize(k, textToHash, sb, drunk) |
num = num + 1 |
end |
else |
for k,u in pairs(v) do |
len = len + _Serialize(k, textToHash, sb, drunk) |
len = len + _Serialize(u, textToHash, sb, drunk) |
num = num + 1 |
end |
end |
for k in pairs(recurse) do |
recurse[k] = nil |
end |
if islist then |
if num <= 255 then |
sb[sb_id] = "u" |
sb[sb_id+1] = EncodeByte(num, drunk) |
return 2 + len |
else |
sb[sb_id] = "U" |
sb[sb_id+1] = EncodeBytes(drunk, math_floor(num / 256), num % 256) |
return 3 + len |
end |
elseif isset then |
if num <= 255 then |
sb[sb_id] = "v" |
sb[sb_id+1] = EncodeByte(num, drunk) |
return 2 + len |
else |
sb[sb_id] = "V" |
sb[sb_id+1] = EncodeBytes(drunk, math_floor(num / 256), num % 256) |
return 3 + len |
end |
else |
if num <= 255 then |
sb[sb_id] = "t" |
sb[sb_id+1] = EncodeByte(num, drunk) |
return 2 + len |
else |
sb[sb_id] = "T" |
sb[sb_id+1] = EncodeBytes(drunk, math_floor(num / 256), num % 256) |
return 3 + len |
end |
end |
end |
end |
function SerializeAndEncode(value, textToHash, drunk) |
local sb = new() |
sb[1] = "" |
sb[2] = "" |
_Serialize(value, textToHash, sb, drunk) |
-- expect a table, chop off the initial byte. |
for i = 1, #sb do |
if #sb[i] > 0 then |
sb[i] = sb[i]:sub(2) |
break |
end |
end |
local len = 0 |
for i = 1, #sb do |
len = len + #sb[i] |
end |
for k in pairs(recurse) do |
recurse[k] = nil |
end |
return sb, len |
end |
end |
local Deserialize |
do |
local function _Deserialize(value, position, hashToText) |
if not position then |
position = 1 |
end |
local x = value:byte(position) |
if x == byte_b then |
-- false |
return false, position |
elseif x == byte_B then |
-- true |
return true, position |
elseif x == byte_nil then |
-- nil |
return nil, position |
elseif x == byte_i then |
-- 14-byte item link |
local a1, a2, b1, b2, c1, c2, d1, d2, e1, e2, g1, g2, h1, h2 = value:byte(position + 1, position + 14) |
local A = a1 * 256 + a2 |
local B = b1 * 256 + b2 |
local C = c1 * 256 + c2 |
local D = d1 * 256 + d2 |
local E = e1 * 256 + e2 |
local G = g1 * 256 + g2 |
local H = h1 * 256 + h2 |
if G >= 2^15 then |
G = G - 256^2 |
end |
local s = ("item:%d:%d:%d:%d:%d:%d:%d:%d"):format(A, B, C, D, E, 0, G, H) |
local _, link = GetItemInfo(s) |
return link, position + 14 |
elseif x == byte_I then |
-- long item link |
local r, g, b, a1, a2, b1, b2, c1, c2, d1, d2, e1, e2, g1, g2, h1, h2, len = value:byte(position + 1, position + 18) |
local A = a1 * 256 + a2 |
local B = b1 * 256 + b2 |
local C = c1 * 256 + c2 |
local D = d1 * 256 + d2 |
local E = e1 * 256 + e2 |
local G = g1 * 256 + g2 |
local H = h1 * 256 + h2 |
if G >= 2^15 then |
G = G - 256^2 |
end |
local s = ("item:%d:%d:%d:%d:%d:%d:%d:%d"):format(A, B, C, D, E, 0, G, H) |
local _, link = GetItemInfo(s) |
if not link then |
local name = value:sub(position + 19, position + 18 + len) |
link = ("|cff%02x%02x%02x|Hitem:%d:%d:%d:%d:%d:%d:%d:%d|h[%s]|h|r"):format(r, g, b, A, B, C, D, E, 0, G, H, name) |
end |
return link, position + 18 + len |
elseif x == byte_m then |
local a, b, c = value:byte(position + 1, position + 3) |
local hash = a * 256^2 + b * 256 + c |
return hashToText[hash], position + 3 |
elseif x == byte_s then |
-- 0-255-byte string |
local len = value:byte(position + 1) |
return value:sub(position + 2, position + 1 + len), position + 1 + len |
elseif x == byte_S then |
-- 256-65535-byte string |
local a, b = value:byte(position + 1, position + 2) |
local len = a * 256 + b |
return value:sub(position + 3, position + 2 + len), position + 2 + len |
elseif x == 64 --[[byte_inf]] then |
return inf, position |
elseif x == 36 --[[byte_ninf]] then |
return -inf, position |
elseif x == 33 --[[byte_nan]] then |
return nan, position |
elseif x == byte_d then |
-- 1-byte integer |
local a = value:byte(position + 1) |
if a >= 128 then |
a = a - 256 |
end |
return a, position + 1 |
elseif x == byte_D then |
-- 2-byte integer |
local a, b = value:byte(position + 1, position + 2) |
local N = a * 256 + b |
if N >= 2^15 then |
N = N - 256^2 |
end |
return N, position + 2 |
elseif x == byte_e then |
-- 4-byte integer |
local a, b, c, d = value:byte(position + 1, position + 4) |
local N = a * 256^3 + b * 256^2 + c * 256 + d |
if N >= 2^31 then |
N = N - 256^4 |
end |
return N, position + 4 |
elseif x == byte_E then |
-- 8-byte integer |
local a, b, c, d, e, f, g, h = value:byte(position + 1, position + 8) |
local N = a * 256^7 + b * 256^6 + c * 256^5 + d * 256^4 + e * 256^3 + f * 256^2 + g * 256 + h |
if N >= 2^63 then |
N = N - 2^64 |
end |
return N, position + 8 |
elseif x == byte_plus or x == byte_minus then |
local a, b, c, d, e, f, g, h = value:byte(position + 1, position + 8) |
local N = a * 256^5 + b * 256^4 + c * 256^3 + d * 256^2 + e * 256 + f |
local sign = x |
local x = math_floor(N / 2^37) |
local m = (N % 2^37) * 256^2 + g * 256 + h |
local mantissa = m / 2^53 |
local exp = x - 1023 |
local val = math_ldexp(mantissa, exp) |
if sign == byte_minus then |
return -val, position + 8 |
end |
return val, position + 8 |
elseif x == byte_u or x == byte_U then |
-- numerically-indexed table |
-- byte #2 is element-length, not byte-length |
local start |
local num |
if x == byte_u then |
num = value:byte(position + 1) |
start = position + 2 |
else |
local a, b = value:byte(position + 1, position + 2) |
num = a * 256 + b |
start = position + 3 |
end |
local t = new() |
local curr = start - 1 |
for i = 1, num do |
local v |
v, curr = _Deserialize(value, curr + 1, hashToText) |
t[i] = v |
end |
return t, curr |
elseif x == byte_v or x == byte_V then |
-- set-style table |
local start |
local num |
if x == byte_v then |
num = value:byte(position + 1) |
start = position + 2 |
else |
local a, b = value:byte(position + 1, position + 2) |
num = a * 256 + b |
start = position + 3 |
end |
local t = new() |
local curr = start - 1 |
for i = 1, num do |
local v |
v, curr = _Deserialize(value, curr + 1, hashToText) |
t[v] = true |
end |
return t, curr |
elseif x == byte_o or x == byte_O then |
-- numerically-indexed table |
-- byte #2 is element-length, not byte-length |
local start |
local num |
if x == byte_o then |
num = value:byte(position + 1) |
start = position + 2 |
else |
local a, b = value:byte(position + 1, position + 2) |
num = a * 256 + b |
start = position + 3 |
end |
local a, b, c = value:byte(start, start + 3) |
local hash = a * 256^2 + b * 256 + c |
local curr = start + 2 |
local class = AceComm.classes[hash] |
local tmp = new() |
for i = 1, num do |
local v |
v, curr = _Deserialize(value, curr + 1, hashToText) |
tmp[i] = v |
end |
local object |
if class and type(class.Deserialize) == "function" and type(class.prototype.Serialize) == "function" then |
object = class:Deserialize(unpack(tmp, 1, num)) |
end |
tmp = del(tmp) |
return object, curr+1 |
elseif x == byte_t or x == byte_T then |
-- table |
-- byte #2 is element-length, not byte-length |
local start |
local num |
if x == byte_t then |
num = value:byte(position + 1) |
start = position + 2 |
else |
local a, b = value:byte(position + 1, position + 2) |
num = a * 256 + b |
start = position + 3 |
end |
local t = new() |
local curr = start - 1 |
for i = 1, num do |
local key, val |
key, curr = _Deserialize(value, curr + 1, hashToText) |
val, curr = _Deserialize(value, curr + 1, hashToText) |
t[key] = val |
end |
return t, curr |
else |
error(("Improper serialized value provided: %s"):format(x)) |
end |
end |
function Deserialize(value, hashToText) |
-- prefix the table byte |
value = "u" .. value |
local ret,msg = pcall(_Deserialize, value, nil, hashToText) |
if ret then |
return msg |
end |
end |
end |
local function GetCurrentGroupDistribution() |
if select(2, IsInInstance()) == "pvp" then |
return "BATTLEGROUND" |
elseif UnitInRaid("player") then |
return "RAID" |
else |
return "PARTY" |
end |
end |
local function IsInDistribution(dist, customChannel) |
if dist == "GROUP" then |
return not not GetCurrentGroupDistribution() |
elseif dist == "BATTLEGROUND" then |
return select(2, IsInInstance()) == "pvp" |
elseif dist == "RAID" then |
return GetNumRaidMembers() > 0 |
elseif dist == "PARTY" then |
return GetNumPartyMembers() > 0 |
elseif dist == "GUILD" then |
return not not IsInGuild() |
elseif dist == "GLOBAL" then |
return IsInChannel("AceComm") |
elseif dist == "ZONE" then |
return IsInChannel(GetCurrentZoneChannel()) |
elseif dist == "WHISPER" then |
return true |
elseif dist == "CUSTOM" then |
return IsInChannel(customChannel) |
end |
error("unknown distribution: " .. tostring(dist), 2) |
end |
function AceComm:RegisterComm(prefix, distribution, method, a4) |
AceComm:argCheck(prefix, 2, "string") |
AceComm:argCheck(distribution, 3, "string") |
if distribution ~= "GLOBAL" and distribution ~= "WHISPER" and distribution ~= "PARTY" and distribution ~= "RAID" and distribution ~= "GUILD" and distribution ~= "BATTLEGROUND" and distribution ~= "GROUP" and distribution ~= "ZONE" and distribution ~= "CUSTOM" then |
AceComm:error('Argument #3 to `RegisterComm\' must be either "GLOBAL", "ZONE", "WHISPER", "PARTY", "RAID", "GUILD", "BATTLEGROUND", "GROUP", or "CUSTOM". %q is not appropriate', distribution) |
end |
local customChannel |
if distribution == "CUSTOM" then |
customChannel, method = method, a4 |
AceComm:argCheck(customChannel, 4, "string") |
if customChannel:len() == 0 then |
AceComm:error('Argument #4 to `RegisterComm\' must be a non-zero-length string.') |
elseif customChannel:find("%s") then |
AceComm:error('Argument #4 to `RegisterComm\' must not have spaces.') |
end |
end |
if self == AceComm then |
AceComm:argCheck(method, customChannel and 5 or 4, "function", "table") |
self = method |
else |
AceComm:argCheck(method, customChannel and 5 or 4, "string", "function", "table", "nil") |
end |
if not method then |
method = "OnCommReceive" |
end |
if type(method) == "string" and type(self[method]) ~= "function" and type(self[method]) ~= "table" then |
AceComm:error("Cannot register comm %q to method %q, it does not exist", prefix, method) |
end |
local registry = AceComm_registry |
if not registry[distribution] then |
registry[distribution] = new() |
end |
if customChannel then |
customChannel = "AceComm" .. customChannel |
if not registry[distribution][customChannel] then |
registry[distribution][customChannel] = new() |
end |
if not registry[distribution][customChannel][prefix] then |
registry[distribution][customChannel][prefix] = new() |
end |
registry[distribution][customChannel][prefix][self] = method |
else |
if not registry[distribution][prefix] then |
registry[distribution][prefix] = new() |
end |
registry[distribution][prefix][self] = method |
end |
RefixAceCommChannelsAndEvents() |
end |
function AceComm:UnregisterComm(prefix, distribution, customChannel) |
AceComm:argCheck(prefix, 2, "string") |
AceComm:argCheck(distribution, 3, "string", "nil") |
if distribution and distribution ~= "GLOBAL" and distribution ~= "WHISPER" and distribution ~= "PARTY" and distribution ~= "RAID" and distribution ~= "GUILD" and distribution ~= "BATTLEGROUND" and distribution ~= "GROUP" and distribution ~= "ZONE" and distribution ~= "CUSTOM" then |
AceComm:error('Argument #3 to `UnregisterComm\' must be either nil, "GLOBAL", "WHISPER", "PARTY", "RAID", "GUILD", "BATTLEGROUND", "GROUP", "ZONE", or "CUSTOM". %q is not appropriate', distribution) |
end |
if distribution == "CUSTOM" then |
AceComm:argCheck(customChannel, 3, "string") |
if customChannel:len() == 0 then |
AceComm:error('Argument #3 to `UnregisterComm\' must be a non-zero-length string.') |
end |
else |
AceComm:argCheck(customChannel, 3, "nil") |
end |
local registry = AceComm_registry |
if not distribution then |
for k,v in pairs(registry) do |
if k == "CUSTOM" then |
for l,u in pairs(v) do |
if u[prefix] and u[prefix][self] then |
AceComm.UnregisterComm(self, prefix, k, l:sub(8)) |
if not registry[k] then |
break |
end |
end |
end |
else |
if v[prefix] and v[prefix][self] then |
AceComm.UnregisterComm(self, prefix, k) |
end |
end |
end |
return |
end |
if self == AceComm then |
if distribution == "CUSTOM" then |
error(("Cannot unregister comm %q::%q. Improperly unregistering from AceComm-2.0."):format(distribution, customChannel), 2) |
else |
error(("Cannot unregister comm %q. Improperly unregistering from AceComm-2.0."):format(distribution), 2) |
end |
end |
if distribution == "CUSTOM" then |
customChannel = "AceComm" .. customChannel |
if not registry[distribution] or not registry[distribution][customChannel] or not registry[distribution][customChannel][prefix] or not registry[distribution][customChannel][prefix][self] then |
AceComm:error("Cannot unregister comm %q. %q is not registered with it.", distribution, self) |
end |
registry[distribution][customChannel][prefix][self] = nil |
if not next(registry[distribution][customChannel][prefix]) then |
registry[distribution][customChannel][prefix] = del(registry[distribution][customChannel][prefix]) |
end |
if not next(registry[distribution][customChannel]) then |
registry[distribution][customChannel] = del(registry[distribution][customChannel]) |
end |
else |
if not registry[distribution] or not registry[distribution][prefix] or not registry[distribution][prefix][self] then |
AceComm:error("Cannot unregister comm %q. %q is not registered with it.", distribution, self) |
end |
registry[distribution][prefix][self] = nil |
if not next(registry[distribution][prefix]) then |
registry[distribution][prefix] = del(registry[distribution][prefix]) |
end |
end |
if not next(registry[distribution]) then |
registry[distribution] = del(registry[distribution]) |
end |
RefixAceCommChannelsAndEvents() |
end |
function AceComm:UnregisterAllComms() |
local registry = AceComm_registry |
for k, distribution in pairs(registry) do |
if k == "CUSTOM" then |
for l, channel in pairs(distribution) do |
local j = next(channel) |
while j ~= nil do |
local prefix = channel[j] |
if prefix[self] then |
AceComm.UnregisterComm(self, j) |
if distribution[l] and registry[k] then |
j = next(channel) |
else |
l = nil |
k = nil |
break |
end |
else |
j = next(channel, j) |
end |
end |
if k == nil then |
break |
end |
end |
else |
local j = next(distribution) |
while j ~= nil do |
local prefix = distribution[j] |
if prefix[self] then |
AceComm.UnregisterComm(self, j) |
if registry[k] then |
j = next(distribution) |
else |
k = nil |
break |
end |
else |
j = next(distribution, j) |
end |
end |
end |
end |
end |
function AceComm:IsCommRegistered(prefix, distribution, customChannel) |
AceComm:argCheck(prefix, 2, "string") |
AceComm:argCheck(distribution, 3, "string", "nil") |
if distribution and distribution ~= "GLOBAL" and distribution ~= "WHISPER" and distribution ~= "PARTY" and distribution ~= "RAID" and distribution ~= "GUILD" and distribution ~= "BATTLEGROUND" and distribution ~= "GROUP" and distribution ~= "ZONE" and distribution ~= "CUSTOM" then |
AceComm:error('Argument #3 to `IsCommRegistered\' must be either "GLOBAL", "WHISPER", "PARTY", "RAID", "GUILD", "BATTLEGROUND", "GROUP", "ZONE", or "CUSTOM". %q is not appropriate', distribution) |
end |
if distribution == "CUSTOM" then |
AceComm:argCheck(customChannel, 4, "nil", "string") |
if customChannel == "" then |
AceComm:error('Argument #4 to `IsCommRegistered\' must be a non-zero-length string or nil.') |
end |
else |
AceComm:argCheck(customChannel, 4, "nil") |
end |
local registry = AceComm_registry |
if not distribution then |
for k,v in pairs(registry) do |
if k == "CUSTOM" then |
for l,u in pairs(v) do |
if u[prefix] and u[prefix][self] then |
return true |
end |
end |
else |
if v[prefix] and v[prefix][self] then |
return true |
end |
end |
end |
return false |
elseif distribution == "CUSTOM" and not customChannel then |
if not registry[distribution] then |
return false |
end |
for l,u in pairs(registry[distribution]) do |
if u[prefix] and u[prefix][self] then |
return true |
end |
end |
return false |
elseif distribution == "CUSTOM" then |
customChannel = "AceComm" .. customChannel |
return registry[distribution] and registry[distribution][customChannel] and registry[distribution][customChannel][prefix] and registry[distribution][customChannel][prefix][self] and true or false |
end |
return registry[distribution] and registry[distribution][prefix] and registry[distribution][prefix][self] and true or false |
end |
function AceComm:OnEmbedDisable(target) |
self.UnregisterAllComms(target) |
end |
local id = byte_Z |
local recentGuildMessage = 0 |
local firstGuildMessage = true |
local stopGuildMessages = false |
function AceComm:PLAYER_GUILD_UPDATE(arg1) |
if arg1 and arg1 ~= "player" then return end |
recentGuildMessage = 0 |
firstGuildMessage = true |
stopGuildMessages = false |
end |
local function SendMessage(prefix, priority, distribution, person, message, textToHash) |
if distribution == "CUSTOM" then |
person = "AceComm" .. person |
end |
if not IsInDistribution(distribution, person) then |
return false |
end |
if distribution == "GROUP" then |
distribution = GetCurrentGroupDistribution() |
end |
if distribution == "GUILD" and stopGuildMessages then |
return false |
end |
if id == byte_Z then |
id = byte_a |
elseif id == byte_z then |
id = byte_A |
else |
id = id + 1 |
end |
if id == byte_s or id == byte_S then |
id = id + 1 |
end |
local drunk = distribution == "GLOBAL" or distribution == "ZONE" or distribution == "CUSTOM" |
prefix = Encode(prefix, drunk) |
local sb, messageLen = SerializeAndEncode(message, textToHash, drunk) |
local headerLen = prefix:len() + 6 |
local max = math_floor(messageLen / (240 - headerLen) + 1) |
if max > 1 then |
local segment = math_floor(messageLen / max + 0.5) |
local last = 0 |
local message = table_concat(sb) |
sb = del(sb) |
for i = 1, max do |
local bit |
if i == max then |
bit = message:sub(last + 1) |
else |
local next = segment * i |
if message:byte(next) == byte_deg then |
next = next + 1 |
end |
bit = message:sub(last + 1, next) |
last = next |
end |
if distribution == "GLOBAL" or distribution == "ZONE" or distribution == "CUSTOM" then |
local channel |
if distribution == "GLOBAL" then |
channel = "AceComm" |
elseif distribution == "ZONE" then |
channel = GetCurrentZoneChannel() |
elseif distribution == "CUSTOM" then |
channel = person |
end |
local index = GetChannelName(channel) |
if index and index > 0 then |
local point |
if i == 1 then |
point = "b" |
elseif i == max then |
point = "d" |
else |
point = "c" |
end |
bit = prefix .. string_char(9 --[[\t]], id) .. point .. "-" .. bit .. "\029" |
ChatThrottleLib:SendChatMessage(priority, prefix, bit, "CHANNEL", nil, index) |
else |
return false |
end |
else |
local point |
if i == 1 then |
point = "b" |
elseif i == max then |
point = "d" |
else |
point = "c" |
end |
bit = string_char(id) .. point .. "-" .. bit |
ChatThrottleLib:SendAddonMessage(priority, prefix, bit, distribution, person) |
end |
end |
return true |
else |
if distribution == "GLOBAL" or distribution == "ZONE" or distribution == "CUSTOM" then |
local channel |
if distribution == "GLOBAL" then |
channel = "AceComm" |
elseif distribution == "ZONE" then |
channel = GetCurrentZoneChannel() |
elseif distribution == "CUSTOM" then |
channel = person |
end |
local index = GetChannelName(channel) |
if index and index > 0 then |
sb[1] = prefix |
sb[2] = string_char(9 --[[\t]], id, byte_a, byte_minus) |
sb[#sb+1] = "\029" |
local message = table_concat(sb) |
sb = del(sb) |
ChatThrottleLib:SendChatMessage(priority, prefix, message, "CHANNEL", nil, index) |
return true |
end |
sb = del(sb) |
else |
if distribution == "GUILD" and firstGuildMessage then |
firstGuildMessage = false |
if GetCVar("Sound_EnableErrorSpeech") == "1" then |
SetCVar("Sound_EnableErrorSpeech", "0") |
AceEvent:ScheduleEvent("AceComm-EnableErrorSpeech", SetCVar, 10, "Sound_EnableErrorSpeech", "1") |
end |
recentGuildMessage = GetTime() + 10 |
end |
sb[1] = string_char(id, byte_a, byte_minus) |
local message = table_concat(sb) |
sb = del(sb) |
ChatThrottleLib:SendAddonMessage(priority, prefix, message, distribution, person) |
return true |
end |
end |
return false |
end |
function AceComm:SendPrioritizedCommMessage(priority, distribution, person, ...) |
AceComm:argCheck(priority, 2, "string") |
if priority ~= "NORMAL" and priority ~= "BULK" and priority ~= "ALERT" then |
AceComm:error('Priority for `Send[Prioritized]CommMessage\' must be either "NORMAL", "BULK", or "ALERT"') |
end |
AceComm:argCheck(distribution, 3, "string") |
local includePerson = true |
if distribution == "WHISPER" or distribution == "CUSTOM" then |
includePerson = false |
AceComm:argCheck(person, 4, "string") |
if person:len() == 0 then |
AceComm:error("Person for `Send[Prioritized]CommMessage' must be a non-zero-length string") |
end |
end |
if self == AceComm then |
AceComm:error("Cannot send a comm message from AceComm directly.") |
end |
if distribution and distribution ~= "GLOBAL" and distribution ~= "WHISPER" and distribution ~= "PARTY" and distribution ~= "RAID" and distribution ~= "GUILD" and distribution ~= "BATTLEGROUND" and distribution ~= "GROUP" and distribution ~= "ZONE" and distribution ~= "CUSTOM" then |
AceComm:error('Distribution for `Send[Prioritized]CommMessage\' must be either nil, "GLOBAL", "ZONE", "WHISPER", "PARTY", "RAID", "GUILD", "BATTLEGROUND", "GROUP", or "CUSTOM". %q is not appropriate', distribution) |
end |
local prefix = AceComm.commPrefixes[self] |
if type(prefix) ~= "string" then |
AceComm:error("`SetCommPrefix' must be called before sending a message.") |
end |
local message = new() |
if includePerson then message[1] = person end |
for i = 1, select('#', ...) do |
local x = select(i, ...) |
if type(x) == "nil" then x = fake_nil end |
message[includePerson and i + 1 or i] = x |
end |
if includePerson then person = nil end |
local ret = SendMessage(AceComm.prefixTextToHash[prefix], priority, distribution, person, message, self.commMemoTextToHash) |
message = del(message) |
return ret |
end |
function AceComm:SendCommMessage(...) |
return AceComm.SendPrioritizedCommMessage(self, self.commPriority or "NORMAL", ...) |
end |
function AceComm:SetDefaultCommPriority(priority) |
AceComm:argCheck(priority, 2, "string") |
if priority ~= "NORMAL" and priority ~= "BULK" and priority ~= "ALERT" then |
AceComm:error('Argument #2 must be either "NORMAL", "BULK", or "ALERT"') |
end |
self.commPriority = priority |
end |
function AceComm:SetCommPrefix(prefix) |
AceComm:argCheck(prefix, 2, "string") |
if AceComm.commPrefixes[self] then |
AceComm:error("Cannot call `SetCommPrefix' more than once.") |
end |
if AceComm.prefixes[prefix] then |
AceComm:error("Cannot set prefix to %q, it is already in use.", prefix) |
end |
local hash |
if prefix:len() == 3 then |
hash = prefix |
else |
hash = TailoredBinaryCheckSum(prefix) |
end |
if AceComm.prefixHashToText[hash] then |
AceComm:error("Cannot set prefix to %q, its hash is used by another prefix: %q", prefix, AceComm.prefixHashToText[hash]) |
end |
AceComm.prefixes[prefix] = true |
self.commPrefix = prefix |
AceComm.commPrefixes[self] = prefix |
AceComm.prefixHashToText[hash] = prefix |
AceComm.prefixTextToHash[prefix] = hash |
end |
function AceComm:RegisterMemoizations(values, ...) |
AceComm:argCheck(values, 2, "table", "string") |
if type(values) == "string" then |
values = {values, ...} |
for i,v in ipairs(values) do |
if type(v) ~= "string" then |
AceComm:error("Bad argument #%d to `RegisterMemoizations'. Expected %q, got %q.", i+1, "string", type(v)) |
end |
end |
else |
for k,v in pairs(values) do |
if type(k) ~= "number" then |
AceComm:error("Bad argument #2 to `RegisterMemoizations'. All keys must be numbers") |
elseif type(v) ~= "string" then |
AceComm:error("Bad argument #2 to `RegisterMemoizations'. All values must be strings") |
end |
end |
end |
if self.commMemoHashToText or self.commMemoTextToHash then |
AceComm:error("You can only call `RegisterMemoizations' once.") |
elseif not AceComm.commPrefixes[self] then |
AceComm:error("You can only call `SetCommPrefix' before calling `RegisterMemoizations'.") |
elseif AceComm.prefixMemoizations[AceComm.commPrefixes[self]] then |
AceComm:error("Another addon with prefix %q has already registered memoizations.", AceComm.commPrefixes[self]) |
end |
local hashToText = new() |
local textToHash = new() |
for _,text in ipairs(values) do |
local hash = TailoredNumericCheckSum(text) |
if hashToText[hash] then |
AceComm:error("%q and %q have the same checksum. You must remove one of them for memoization to work properly", hashToText[hash], text) |
else |
textToHash[text] = hash |
hashToText[hash] = text |
end |
end |
values = nil |
self.commMemoHashToText = hashToText |
self.commMemoTextToHash = textToHash |
AceComm.prefixMemoizations[AceComm.commPrefixes[self]] = hashToText |
end |
local lastCheck = GetTime() |
local function CheckRefix() |
if GetTime() - lastCheck >= 120 then |
lastCheck = GetTime() |
RefixAceCommChannelsAndEvents() |
end |
end |
local function reallyHandleTableMessage(handlers, prefix, sender, distribution, message, custom) |
local n = #message * 4 |
if n < 40 then n = 40 end |
while message[n] == nil and n > 0 do |
n = n - 1 |
end |
for k, v in pairs(handlers) do |
local type_v = type(v) |
if type_v == "string" then |
local f = k[v] |
if type(f) == "table" then |
local i = 1 |
local g = f[message[i]] |
while g do |
if type(g) ~= "table" then -- function |
if custom then |
g(k, prefix, sender, distribution, custom, unpack(message, i+1, n)) |
else |
g(k, prefix, sender, distribution, unpack(message, i+1, n)) |
end |
break |
else |
i = i + 1 |
g = g[message[i]] |
end |
end |
else -- function |
if custom then |
f(k, prefix, sender, distribution, custom, unpack(message, 1, n)) |
else |
f(k, prefix, sender, distribution, unpack(message, 1, n)) |
end |
end |
elseif type_v == "table" then |
local i = 1 |
local g = v[message[i]] |
while g do |
if type(g) ~= "table" then -- function |
if custom then |
g(prefix, sender, distribution, custom, unpack(message, i+1, n)) |
else |
g(prefix, sender, distribution, unpack(message, i+1, n)) |
end |
break |
else |
i = i + 1 |
g = g[message[i]] |
end |
end |
else -- function |
if custom then |
v(prefix, sender, distribution, custom, unpack(message, 1, n)) |
else |
v(prefix, sender, distribution, unpack(message, 1, n)) |
end |
end |
end |
end |
local function reallyHandleNonTableMessage(handlers, prefix, sender, distribution, message, custom) |
for k, v in pairs(handlers) do |
local type_v = type(v) |
if type_v == "string" then |
local f = k[v] |
if type(f) == "table" then |
local g = f[message] |
if g and type(g) == "function" then |
if custom then |
g(k, prefix, sender, distribution, custom) |
else |
g(k, prefix, sender, distribution) |
end |
end |
else -- function |
if custom then |
f(k, prefix, sender, distribution, custom, message) |
else |
f(k, prefix, sender, distribution, message) |
end |
end |
elseif type_v == "table" then |
local g = v[message] |
if g and type(g) == "function" then |
if custom then |
g(k, prefix, sender, distribution, custom) |
else |
g(k, prefix, sender, distribution) |
end |
end |
else -- function |
if custom then |
v(prefix, sender, distribution, custom, message) |
else |
v(prefix, sender, distribution, message) |
end |
end |
end |
end |
local function HandleMessage(prefix, message, distribution, sender, customChannel) |
local isGroup = GetCurrentGroupDistribution() == distribution |
local isCustom = distribution == "CUSTOM" |
if (not AceComm_registry[distribution] and (not isGroup or not AceComm_registry.GROUP)) or (isCustom and not AceComm_registry.CUSTOM[customChannel]) then |
return CheckRefix() |
end |
local id, point |
if not message then |
local tmpPrefix |
tmpPrefix, id, point, message = prefix:match("^(...)\t(.)(.)%-(.*)$") |
if not tmpPrefix then |
local current, max |
tmpPrefix, id, current, max, message = prefix:match("^(...)\t(.)(.)(.)\t(.*)$") |
if not tmpPrefix then |
return |
end |
if current == max then |
if current == "\001" then |
point = 'a' |
else |
point = 'd' |
end |
elseif current == "\001" then |
point = 'b' |
else |
point = 'c' |
end |
end |
prefix = AceComm.prefixHashToText[tmpPrefix] |
if not prefix then |
return CheckRefix() |
end |
if isCustom then |
if not AceComm_registry.CUSTOM[customChannel][prefix] then |
return CheckRefix() |
end |
else |
if (not AceComm_registry[distribution] or not AceComm_registry[distribution][prefix]) and (not isGroup or not AceComm_registry.GROUP or not AceComm_registry.GROUP[prefix]) then |
return CheckRefix() |
end |
end |
else |
local tmpMessage |
id, point, tmpMessage = message:match("^(.)(.)%-(.*)$") |
if not id then |
local current, max |
id, current, max, tmpMessage = message:match("^(.)(.)(.)\t(.*)$") |
if not id then |
return |
end |
if current == max then |
if current == "\001" then |
point = 'a' |
else |
point = 'd' |
end |
elseif current == "\001" then |
point = 'b' |
else |
point = 'c' |
end |
end |
message = tmpMessage |
end |
if not message then |
return |
end |
if point ~= 'a' then |
local queue = AceComm.recvQueue |
local x |
if distribution == "CUSTOM" then |
x = prefix .. ":" .. sender .. distribution .. customChannel .. id |
else |
x = prefix .. ":" .. sender .. distribution .. id |
end |
if not queue[x] then |
if point ~= 'b' then |
return |
end |
queue[x] = new() |
end |
local chunk = queue[x] |
chunk.time = GetTime() |
chunk[#chunk+1] = message |
if point == 'd' then |
local success |
success, message = pcall(table_concat, chunk) |
if not success then |
return |
end |
queue[x] = del(queue[x]) |
else |
return |
end |
end |
message = Deserialize(message, AceComm.prefixMemoizations[prefix]) |
local isTable = type(message) == "table" |
local f = isTable and reallyHandleTableMessage or reallyHandleNonTableMessage |
if AceComm_registry[distribution] then |
if isCustom and AceComm_registry.CUSTOM[customChannel][prefix] then |
f(AceComm_registry.CUSTOM[customChannel][prefix], prefix, sender, distribution, message, customChannel and customChannel:sub(8)) |
elseif not isCustom and AceComm_registry[distribution][prefix] then |
f(AceComm_registry[distribution][prefix], prefix, sender, distribution, message) |
end |
end |
if isGroup and AceComm_registry.GROUP and AceComm_registry.GROUP[prefix] then |
f(AceComm_registry.GROUP[prefix], prefix, sender, "GROUP", message) |
end |
if isTable then |
message = del(message) |
end |
end |
function AceComm:CHAT_MSG_ADDON(prefix, message, distribution, sender) |
if sender == player and not self.enableLoopback and distribution ~= "WHISPER" then |
return |
end |
if message == "" then |
return |
end |
prefix = self.prefixHashToText[prefix] |
if not prefix then |
return CheckRefix() |
end |
local isGroup = GetCurrentGroupDistribution() == distribution |
if not AceComm_registry[distribution] and (not isGroup or not AceComm_registry.GROUP) then |
return CheckRefix() |
end |
prefix = Decode(prefix) |
if (not AceComm_registry[distribution] or not AceComm_registry[distribution][prefix]) and (not isGroup or not AceComm_registry.GROUP or not AceComm_registry.GROUP[prefix]) then |
return CheckRefix() |
end |
message = Decode(message) |
return HandleMessage(prefix, message, distribution, sender) |
end |
function AceComm:CHAT_MSG_CHANNEL(text, sender, _, _, _, _, _, _, channel) |
if text == "" or sender == player or not channel:find("^AceComm") then |
return |
end |
text = Decode(text, true) |
local distribution |
local customChannel |
if channel == "AceComm" then |
distribution = "GLOBAL" |
elseif channel == GetCurrentZoneChannel() then |
distribution = "ZONE" |
else |
distribution = "CUSTOM" |
customChannel = channel |
end |
return HandleMessage(text, nil, distribution, sender, customChannel) |
end |
function AceComm:IsUserInChannel(userName, distribution, customChannel) |
AceComm:argCheck(userName, 2, "string", "nil") |
if not userName then |
userName = player |
end |
AceComm:argCheck(distribution, 3, "string") |
local channel |
if distribution == "GLOBAL" then |
channel = "AceComm" |
elseif distribution == "ZONE" then |
channel = GetCurrentZoneChannel() |
elseif distribution == "CUSTOM" then |
AceComm:argCheck(customChannel, 4, "string") |
channel = "AceComm" .. customChannel |
else |
AceComm:error('Argument #3 to `IsUserInChannel\' must be "GLOBAL", "CUSTOM", or "ZONE"') |
end |
return AceComm.userRegistry[channel] and AceComm.userRegistry[channel][userName] or false |
end |
function AceComm:CHAT_MSG_CHANNEL_LIST(text, _, _, _, _, _, _, _, channel) |
if not channel:find("^AceComm") then |
return |
end |
if not self.userRegistry[channel] then |
self.userRegistry[channel] = new() |
end |
local t = self.userRegistry[channel] |
for k in text:gmatch("[^, @%*#]+") do |
t[k] = true |
end |
end |
function AceComm:CHAT_MSG_CHANNEL_JOIN(_, user, _, _, _, _, _, _, channel) |
if not channel:find("^AceComm") then |
return |
end |
if not self.userRegistry[channel] then |
self.userRegistry[channel] = new() |
end |
local t = self.userRegistry[channel] |
t[user] = true |
end |
function AceComm:CHAT_MSG_CHANNEL_LEAVE(_, user, _, _, _, _, _, _, channel) |
if not channel:find("^AceComm") then |
return |
end |
if not self.userRegistry[channel] then |
self.userRegistry[channel] = new() |
end |
local t = self.userRegistry[channel] |
if t[user] then |
t[user] = nil |
end |
end |
function AceComm:ZONE_CHANGED_NEW_AREA() |
local lastZone = zoneCache |
zoneCache = nil |
local newZone = GetCurrentZoneChannel() |
if self.registry.ZONE and next(self.registry.ZONE) then |
if lastZone then |
SwitchChannel(lastZone, newZone) |
else |
JoinChannel(newZone) |
end |
end |
end |
function AceComm:embed(target) |
self.super.embed(self, target) |
if not AceEvent then |
AceComm:error(MAJOR_VERSION .. " requires AceEvent-2.0") |
end |
end |
local recentNotSeen = {} |
local notSeenString = '^' .. _G.ERR_CHAT_PLAYER_NOT_FOUND_S:gsub("%%s", "(.-)"):gsub("%%1%$s", "(.-)") .. '$' |
local ambiguousString = '^' .. _G.ERR_CHAT_PLAYER_AMBIGUOUS_S:gsub("%%s", "(.-)"):gsub("%%1%$s", "(.-)") .. '$' |
local ERR_GUILD_PERMISSIONS = _G.ERR_GUILD_PERMISSIONS |
function AceComm.hooks:ChatFrame_MessageEventHandler(orig, event) |
if (event == "CHAT_MSG_CHANNEL" or event == "CHAT_MSG_CHANNEL_LIST") and _G.arg9:find("^AceComm") then |
return |
elseif event == "CHAT_MSG_SYSTEM" then |
local arg1 = _G.arg1 |
if arg1 == ERR_GUILD_PERMISSIONS then |
if recentGuildMessage > GetTime() then |
stopGuildMessages = true |
return |
end |
else |
local player = arg1:match(notSeenString) or arg1:match(ambiguousString) |
if player then |
local t = GetTime() |
if recentNotSeen[player] and recentNotSeen[player] > t then |
recentNotSeen[player] = t + 10 |
return |
else |
recentNotSeen[player] = t + 10 |
end |
end |
end |
end |
return orig(event) |
end |
function AceComm.hooks:Logout(orig) |
if IsResting() then |
LeaveAceCommChannels() |
else |
self:ScheduleEvent("AceComm-LeaveAceCommChannels", LeaveAceCommChannels, 15) |
end |
return orig() |
end |
function AceComm.hooks:CancelLogout(orig) |
shutdown = false |
self:CancelScheduledEvent("AceComm-LeaveAceCommChannels") |
RefixAceCommChannelsAndEvents() |
return orig() |
end |
function AceComm.hooks:Quit(orig) |
if IsResting() then |
LeaveAceCommChannels() |
else |
self:ScheduleEvent("AceComm-LeaveAceCommChannels", LeaveAceCommChannels, 15) |
end |
return orig() |
end |
local function filterAceComm(k, v, ...) |
if not k or not v then |
return |
end |
if v:find("^AceComm") then |
return filterAceComm(...) |
else |
return k, v, filterAceComm(...) |
end |
end |
function AceComm.hooks:FCFDropDown_LoadChannels(orig, ...) |
return orig(filterAceComm(...)) |
end |
function AceComm:CHAT_MSG_SYSTEM(text) |
if text ~= _G.ERR_TOO_MANY_CHAT_CHANNELS then |
return |
end |
if not lastChannelJoined or not lastChannelJoined:find("^AceComm") then |
return |
end |
local text |
if lastChannelJoined == "AceComm" then |
local addon = AceComm_registry.GLOBAL and next(AceComm_registry.GLOBAL) |
if not addon then |
return |
end |
addon = tostring(addon) |
text = ("%s has tried to join the AceComm global channel, but there are not enough channels available. %s may not work because of this."):format(addon, addon) |
elseif lastChannelJoined == GetCurrentZoneChannel() then |
local addon = AceComm_registry.ZONE and next(AceComm_registry.ZONE) |
if not addon then |
return |
end |
addon = tostring(addon) |
text = ("%s has tried to join the AceComm zone channel, but there are not enough channels available. %s may not work because of this."):format(addon, addon) |
else |
local addon = AceComm_registry.CUSTOM and AceComm_registry.CUSTOM[lastChannelJoined] and next(AceComm_registry.CUSTOM[lastChannelJoined]) |
if not addon then |
return |
end |
addon = tostring(addon) |
text = ("%s has tried to join the AceComm custom channel %s, but there are not enough channels available. %s may not work because of this."):format(addon, lastChannelJoined, addon) |
end |
_G.StaticPopupDialogs["ACECOMM_TOO_MANY_CHANNELS"] = { |
text = text, |
button1 = _G.CLOSE, |
timeout = 0, |
whileDead = 1, |
hideOnEscape = 1, |
} |
_G.StaticPopup_Show("ACECOMM_TOO_MANY_CHANNELS") |
end |
function AceComm:QueryAddonVersion(addon, distribution, player) |
AceComm:argCheck(addon, 2, "string") |
AceComm:argCheck(distribution, 3, "string") |
if distribution ~= "WHISPER" and distribution ~= "PARTY" and distribution ~= "RAID" and distribution ~= "GUILD" and distribution ~= "BATTLEGROUND" and distribution ~= "GROUP" then |
AceComm:error('Argument #3 to `QueryAddonVersion\' must be either "WHISPER", "PARTY", "RAID", "GUILD", "BATTLEGROUND", or "GROUP". %q is not appropriate', distribution) |
end |
if distribution == "WHISPER" then |
AceComm:argCheck(player, 4, "string") |
elseif distribution == "GROUP" then |
distribution = GetCurrentGroupDistribution() |
end |
if not IsInDistribution(distribution) then |
return |
end |
if distribution == "WHISPER" then |
self.addonVersionPinger:SendCommMessage("WHISPER", player, "PING", addon) |
else |
self.addonVersionPinger:SendCommMessage(distribution, "PING", addon) |
end |
end |
function AceComm:RegisterAddonVersionReceptor(obj, method) |
self:argCheck(obj, 2, "function", "table") |
if type(obj) == "function" then |
method = true |
else |
self:argCheck(method, 3, "string") |
if type(obj[method]) ~= "function" then |
self:error("Handler provided to `RegisterAddonVersionReceptor', %q, not a function", method) |
end |
end |
self.addonVersionPinger.receptors[obj] = method |
end |
local function activate(self, oldLib, oldDeactivate) |
AceComm = self |
if not oldLib or not oldLib.hooks or not oldLib.hooks.ChatFrame_MessageEventHandler then |
local old_ChatFrame_MessageEventHandler = _G.ChatFrame_MessageEventHandler |
function _G.ChatFrame_MessageEventHandler(event) |
if self.hooks.ChatFrame_MessageEventHandler then |
return self.hooks.ChatFrame_MessageEventHandler(self, old_ChatFrame_MessageEventHandler, event) |
else |
return old_ChatFrame_MessageEventHandler(event) |
end |
end |
end |
if not oldLib or not oldLib.hooks or not oldLib.hooks.Logout then |
local old_Logout = _G.Logout |
function _G.Logout() |
if self.hooks.Logout then |
return self.hooks.Logout(self, old_Logout) |
else |
return old_Logout() |
end |
end |
end |
if not oldLib or not oldLib.hooks or not oldLib.hooks.CancelLogout then |
local old_CancelLogout = _G.CancelLogout |
function _G.CancelLogout() |
if self.hooks.CancelLogout then |
return self.hooks.CancelLogout(self, old_CancelLogout) |
else |
return old_CancelLogout() |
end |
end |
end |
if not oldLib or not oldLib.hooks or not oldLib.hooks.Quit then |
local old_Quit = _G.Quit |
function _G.Quit() |
if self.hooks.Quit then |
return self.hooks.Quit(self, old_Quit) |
else |
return old_Quit() |
end |
end |
end |
if not oldLib or not oldLib.hooks or not oldLib.hooks.FCFDropDown_LoadChannels then |
local old_FCFDropDown_LoadChannels = _G.FCFDropDown_LoadChannels |
function _G.FCFDropDown_LoadChannels(...) |
if self.hooks.FCFDropDown_LoadChannels then |
return self.hooks.FCFDropDown_LoadChannels(self, old_FCFDropDown_LoadChannels, ...) |
else |
return old_FCFDropDown_LoadChannels(...) |
end |
end |
end |
if not oldLib or not oldLib.hooks or not oldLib.hooks.JoinChannelByName then |
local old_JoinChannelByName = _G.JoinChannelByName |
function _G.JoinChannelByName(...) |
if self.hooks.JoinChannelByName then |
return self.hooks.JoinChannelByName(self, old_JoinChannelByName, ...) |
else |
return old_JoinChannelByName(...) |
end |
end |
end |
self.recvQueue = oldLib and oldLib.recvQueue or {} |
self.registry = oldLib and oldLib.registry or {} |
self.channels = oldLib and oldLib.channels or {} |
self.prefixes = oldLib and oldLib.prefixes or {} |
self.classes = oldLib and oldLib.classes or {} |
self.prefixMemoizations = oldLib and oldLib.prefixMemoizations or {} |
self.prefixHashToText = oldLib and oldLib.prefixHashToText or {} |
self.prefixTextToHash = oldLib and oldLib.prefixTextToHash or {} |
self.userRegistry = oldLib and oldLib.userRegistry or {} |
self.commPrefixes = oldLib and oldLib.commPrefixes or {} |
self.addonVersionPinger = oldLib and oldLib.addonVersionPinger |
AceComm_registry = self.registry |
for k in pairs(self.classes) do |
self.classes[k] = nil |
end |
self:activate(oldLib, oldDeactivate) |
if oldLib and not oldLib.commPrefixes then |
for t in pairs(self.embedList) do |
if t.commPrefix and not self.commPrefixes[t] then |
self.commPrefixes[t] = t.commPrefix |
end |
end |
end |
if oldDeactivate then |
oldDeactivate(oldLib) |
end |
end |
local function external(self, major, instance) |
if major == "AceEvent-2.0" then |
AceEvent = instance |
AceEvent:embed(self) |
self:UnregisterAllEvents() |
self:CancelAllScheduledEvents() |
if AceEvent:IsFullyInitialized() then |
RefixAceCommChannelsAndEvents() |
else |
self:RegisterEvent("AceEvent_FullyInitialized", RefixAceCommChannelsAndEvents, true) |
end |
self:RegisterEvent("PLAYER_LOGOUT", LeaveAceCommChannels) |
self:RegisterEvent("ZONE_CHANGED_NEW_AREA") |
self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE") |
self:RegisterEvent("CHAT_MSG_SYSTEM") |
self:RegisterEvent("PLAYER_GUILD_UPDATE") |
if not self.addonVersionPinger then |
self.addonVersionPinger = {} |
self:embed(self.addonVersionPinger) |
self.addonVersionPinger:SetCommPrefix("Version") |
self.addonVersionPinger.receptors = {} |
else |
self.addonVersionPinger:UnregisterAllComms() |
end |
self.addonVersionPinger.OnCommReceive = { |
PING = function(self, prefix, sender, distribution, addon) |
local version = "" |
if AceLibrary:HasInstance(addon, false) then |
local lib = AceLibrary(addon) |
if lib.GetLibraryVersion then |
local revision |
version, revision = lib:GetLibraryVersion() |
version = version .. "-" .. revision |
end |
elseif LibStub(addon, true) then |
local _, revision = LibStub(addon, true) |
version = addon .. "-" .. revision |
else |
local revision |
local _G_addon = _G[addon] |
if not _G_addon then |
_G_addon = _G[addon:match("^[^_]+_(.*)$")] |
end |
if type(_G_addon) == "table" then |
if rawget(_G_addon, "version") then version = _G_addon.version |
elseif rawget(_G_addon, "Version") then version = _G_addon.Version |
elseif rawget(_G_addon, "VERSION") then version = _G_addon.VERSION |
end |
if type(version) == "function" then version = tostring(select(2, pcall(version()))) end |
local revision = nil |
if rawget(_G_addon, "revision") then revision = _G_addon.revision |
elseif rawget(_G_addon, "Revision") then revision = _G_addon.Revision |
elseif rawget(_G_addon, "REVISION") then revision = _G_addon.REVISION |
elseif rawget(_G_addon, "rev") then revision = _G_addon.rev |
elseif rawget(_G_addon, "Rev") then revision = _G_addon.Rev |
elseif rawget(_G_addon, "REV") then revision = _G_addon.REV |
end |
if type(revision) == "function" then revision = tostring(select(2, pcall(revision()))) end |
if version then version = tostring(version) end |
if revision then revision = tostring(revision) end |
if type(revision) == "string" and type(version) == "string" and version:len() > 0 and not version:find(revision) then |
version = version .. "." .. revision |
end |
if not version and revision then version = revision end |
end |
if _G[addon:upper().."_VERSION"] then |
version = _G[addon:upper() .. "_VERSION"] |
end |
if _G[addon:upper().."_REVISION"] or _G[addon:upper().."_REV"] then |
local revision = _G[addon:upper() .. "_REVISION"] or _G[addon:upper().."_REV"] |
if type(revision) == "string" and type(version) == "string" and version:len() > 0 and not version:find(revision) then |
version = version .. "." .. revision |
end |
if (not version or version == "") and revision then version = revision end |
end |
if not version or version == "" then |
version = GetAddOnMetadata(addon, "Version") |
if version and version ~= "" and not IsAddOnLoaded(addon) then |
local enabled, loadable = select(4, GetAddOnInfo(addon)) |
version = enabled and loadable and version .. " (LoD)" or version .. " (Off)" |
end |
end |
if not version or version == "" then |
local enabled, loadable = select(4, GetAddOnInfo(addon)) |
version = IsAddOnLoaded(addon) and true or enabled and loadable and "(LoD)" or false |
end |
end |
self:SendCommMessage("WHISPER", sender, "PONG", addon, version) |
end, |
PONG = function(self, prefix, sender, distribution, addon, version) |
for obj, method in pairs(self.receptors) do |
if type(obj) == "function" then |
local success, err = pcall(obj, sender, addon, version) |
if not success then |
geterrorhandler()(err) |
end |
else |
local obj_method = obj[method] |
local success, err = pcall(obj_method, obj, sender, addon, version) |
if not success then |
geterrorhandler()(err) |
end |
end |
end |
end |
} |
self.addonVersionPinger:RegisterComm("Version", "WHISPER") |
self.addonVersionPinger:RegisterComm("Version", "GUILD") |
self.addonVersionPinger:RegisterComm("Version", "RAID") |
self.addonVersionPinger:RegisterComm("Version", "PARTY") |
self.addonVersionPinger:RegisterComm("Version", "BATTLEGROUND") |
elseif AceOO.inherits(instance, AceOO.Class) and not instance.class then |
self.classes[TailoredNumericCheckSum(major)] = instance |
end |
end |
AceLibrary:Register(AceComm, MAJOR_VERSION, MINOR_VERSION, activate, nil, external) |
-- |
-- ChatThrottleLib by Mikk |
-- |
-- Manages AddOn chat output to keep player from getting kicked off. |
-- |
-- ChatThrottleLib.SendChatMessage/.SendAddonMessage functions that accept |
-- a Priority ("BULK", "NORMAL", "ALERT") as well as prefix for SendChatMessage. |
-- |
-- Priorities get an equal share of available bandwidth when fully loaded. |
-- Communication channels are separated on extension+chattype+destination and |
-- get round-robinned. (Destination only matters for whispers and channels, |
-- obviously) |
-- |
-- Will install hooks for SendChatMessage and SendAdd[Oo]nMessage to measure |
-- bandwidth bypassing the library and use less bandwidth itself. |
-- |
-- |
-- Fully embeddable library. Just copy this file into your addon directory, |
-- add it to the .toc, and it's done. |
-- |
-- Can run as a standalone addon also, but, really, just embed it! :-) |
-- |
local CTL_VERSION = 19 |
if _G.ChatThrottleLib and _G.ChatThrottleLib.version >= CTL_VERSION then |
-- There's already a newer (or same) version loaded. Buh-bye. |
return |
end |
if not _G.ChatThrottleLib then |
_G.ChatThrottleLib = {} |
end |
ChatThrottleLib = _G.ChatThrottleLib -- in case some addon does "local ChatThrottleLib" above use and we're copypasted (AceComm, sigh) |
local ChatThrottleLib = _G.ChatThrottleLib |
------------------ TWEAKABLES ----------------- |
ChatThrottleLib.MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800. |
ChatThrottleLib.MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff |
ChatThrottleLib.BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now. |
ChatThrottleLib.MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value |
local setmetatable = setmetatable |
local table_remove = table.remove |
local tostring = tostring |
local GetTime = GetTime |
local math_min = math.min |
local math_max = math.max |
local next = next |
local strlen = string.len |
ChatThrottleLib.version = CTL_VERSION |
----------------------------------------------------------------------- |
-- Double-linked ring implementation |
local Ring = {} |
local RingMeta = { __index = Ring } |
function Ring:New() |
local ret = {} |
setmetatable(ret, RingMeta) |
return ret |
end |
function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position) |
if self.pos then |
obj.prev = self.pos.prev |
obj.prev.next = obj |
obj.next = self.pos |
obj.next.prev = obj |
else |
obj.next = obj |
obj.prev = obj |
self.pos = obj |
end |
end |
function Ring:Remove(obj) |
obj.next.prev = obj.prev |
obj.prev.next = obj.next |
if self.pos == obj then |
self.pos = obj.next |
if self.pos == obj then |
self.pos = nil |
end |
end |
end |
----------------------------------------------------------------------- |
-- Recycling bin for pipes |
-- A pipe is a plain integer-indexed queue, which also happens to be a ring member |
ChatThrottleLib.PipeBin = nil -- pre-v19, drastically different |
local PipeBin = setmetatable({}, {__mode="k"}) |
local function DelPipe(pipe) |
for i = #pipe, 1, -1 do |
pipe[i] = nil |
end |
pipe.prev = nil |
pipe.next = nil |
PipeBin[pipe] = true |
end |
local function NewPipe() |
local pipe = next(PipeBin) |
if pipe then |
PipeBin[pipe] = nil |
return pipe |
end |
return {} |
end |
----------------------------------------------------------------------- |
-- Recycling bin for messages |
ChatThrottleLib.MsgBin = nil -- pre-v19, drastically different |
local MsgBin = setmetatable({}, {__mode="k"}) |
local function DelMsg(msg) |
msg[1] = nil |
-- there's more parameters, but they're very repetetive so the string pool doesn't suffer really, and it's faster to just not delete them. |
MsgBin[msg] = true |
end |
local function NewMsg() |
local msg = next(MsgBin) |
if msg then |
MsgBin[msg] = nil |
return msg |
end |
return {} |
end |
----------------------------------------------------------------------- |
-- ChatThrottleLib:Init |
-- Initialize queues, set up frame for OnUpdate, etc |
function ChatThrottleLib:Init() |
-- Set up queues |
if not self.Prio then |
self.Prio = {} |
self.Prio["ALERT"] = { ByName = {}, Ring = Ring:New(), avail = 0 } |
self.Prio["NORMAL"] = { ByName = {}, Ring = Ring:New(), avail = 0 } |
self.Prio["BULK"] = { ByName = {}, Ring = Ring:New(), avail = 0 } |
end |
-- v4: total send counters per priority |
for _, Prio in pairs(self.Prio) do |
Prio.nTotalSent = Prio.nTotalSent or 0 |
end |
if not self.avail then |
self.avail = 0 -- v5 |
end |
if not self.nTotalSent then |
self.nTotalSent = 0 -- v5 |
end |
-- Set up a frame to get OnUpdate events |
if not self.Frame then |
self.Frame = CreateFrame("Frame") |
self.Frame:Hide() |
end |
self.Frame:SetScript("OnUpdate", self.OnUpdate) |
self.Frame:SetScript("OnEvent", self.OnEvent) -- v11: Monitor P_E_W so we can throttle hard for a few seconds |
self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD") |
self.OnUpdateDelay = 0 |
self.LastAvailUpdate = GetTime() |
self.HardThrottlingBeginTime = GetTime() -- v11: Throttle hard for a few seconds after startup |
-- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7) |
if not self.ORIG_SendChatMessage then |
-- use secure hooks instead of insecure hooks (v16) |
self.securelyHooked = true |
--SendChatMessage |
self.ORIG_SendChatMessage = SendChatMessage |
hooksecurefunc("SendChatMessage", function(...) |
return ChatThrottleLib.Hook_SendChatMessage(...) |
end) |
self.ORIG_SendAddonMessage = SendAddonMessage |
--SendAddonMessage |
hooksecurefunc("SendAddonMessage", function(...) |
return ChatThrottleLib.Hook_SendAddonMessage(...) |
end) |
end |
self.nBypass = 0 |
end |
----------------------------------------------------------------------- |
-- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage |
function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination, ...) |
local self = ChatThrottleLib |
local size = strlen(tostring(text or "")) + strlen(tostring(destination or "")) + self.MSG_OVERHEAD |
self.avail = self.avail - size |
self.nBypass = self.nBypass + size -- just a statistic |
if not self.securelyHooked then |
self.ORIG_SendChatMessage(text, chattype, language, destination, ...) |
end |
end |
function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination, ...) |
local self = ChatThrottleLib |
local size = tostring(text or ""):len() + tostring(prefix or ""):len(); |
size = size + tostring(destination or ""):len() + self.MSG_OVERHEAD |
self.avail = self.avail - size |
self.nBypass = self.nBypass + size -- just a statistic |
if not self.securelyHooked then |
self.ORIG_SendAddonMessage(prefix, text, chattype, destination, ...) |
end |
end |
----------------------------------------------------------------------- |
-- ChatThrottleLib:UpdateAvail |
-- Update self.avail with how much bandwidth is currently available |
function ChatThrottleLib:UpdateAvail() |
local now = GetTime() |
local MAX_CPS = self.MAX_CPS; |
local newavail = MAX_CPS * (now - self.LastAvailUpdate) |
local avail = self.avail |
if now - self.HardThrottlingBeginTime < 5 then |
-- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then |
avail = math_min(avail + (newavail*0.1), MAX_CPS*0.5) |
self.bChoking = true |
elseif GetFramerate() < self.MIN_FPS then -- GetFrameRate call takes ~0.002 secs |
avail = math_min(MAX_CPS, avail + newavail*0.5) |
self.bChoking = true -- just a statistic |
else |
avail = math_min(self.BURST, avail + newavail) |
self.bChoking = false |
end |
avail = math_max(avail, 0-(MAX_CPS*2)) -- Can go negative when someone is eating bandwidth past the lib. but we refuse to stay silent for more than 2 seconds; if they can do it, we can. |
self.avail = avail |
self.LastAvailUpdate = now |
return avail |
end |
----------------------------------------------------------------------- |
-- Despooling logic |
function ChatThrottleLib:Despool(Prio) |
local ring = Prio.Ring |
while ring.pos and Prio.avail > ring.pos[1].nSize do |
local msg = table_remove(Prio.Ring.pos, 1) |
if not Prio.Ring.pos[1] then |
local pipe = Prio.Ring.pos |
Prio.Ring:Remove(pipe) |
Prio.ByName[pipe.name] = nil |
DelPipe(pipe) |
else |
Prio.Ring.pos = Prio.Ring.pos.next |
end |
Prio.avail = Prio.avail - msg.nSize |
msg.f(unpack(msg, 1, msg.n)) |
Prio.nTotalSent = Prio.nTotalSent + msg.nSize |
DelMsg(msg) |
end |
end |
function ChatThrottleLib.OnEvent(this,event) |
-- v11: We know that the rate limiter is touchy after login. Assume that it's touch after zoning, too. |
local self = ChatThrottleLib |
if event == "PLAYER_ENTERING_WORLD" then |
self.HardThrottlingBeginTime = GetTime() -- Throttle hard for a few seconds after zoning |
self.avail = 0 |
end |
end |
function ChatThrottleLib.OnUpdate(this,delay) |
local self = ChatThrottleLib |
self.OnUpdateDelay = self.OnUpdateDelay + delay |
if self.OnUpdateDelay < 0.08 then |
return |
end |
self.OnUpdateDelay = 0 |
self:UpdateAvail() |
if self.avail < 0 then |
return -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu. |
end |
-- See how many of our priorities have queued messages |
local n = 0 |
for prioname,Prio in pairs(self.Prio) do |
if Prio.Ring.pos or Prio.avail < 0 then |
n = n + 1 |
end |
end |
-- Anything queued still? |
if n<1 then |
-- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing |
for prioname, Prio in pairs(self.Prio) do |
self.avail = self.avail + Prio.avail |
Prio.avail = 0 |
end |
self.bQueueing = false |
self.Frame:Hide() |
return |
end |
-- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues |
local avail = self.avail/n |
self.avail = 0 |
for prioname, Prio in pairs(self.Prio) do |
if Prio.Ring.pos or Prio.avail < 0 then |
Prio.avail = Prio.avail + avail |
if Prio.Ring.pos and Prio.avail > Prio.Ring.pos[1].nSize then |
self:Despool(Prio) |
end |
end |
end |
end |
----------------------------------------------------------------------- |
-- Spooling logic |
function ChatThrottleLib:Enqueue(prioname, pipename, msg) |
local Prio = self.Prio[prioname] |
local pipe = Prio.ByName[pipename] |
if not pipe then |
self.Frame:Show() |
pipe = NewPipe() |
pipe.name = pipename |
Prio.ByName[pipename] = pipe |
Prio.Ring:Add(pipe) |
end |
pipe[#pipe + 1] = msg |
self.bQueueing = true |
end |
function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName) |
if not self or not prio or not text or not self.Prio[prio] then |
error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix" or nil, "text"[, "chattype"[, "language"[, "destination"]]]', 2) |
end |
prefix = prefix or tostring(this) -- each frame gets its own queue if prefix is not given |
local nSize = text:len() |
assert(nSize<=255, "text length cannot exceed 255 bytes"); |
nSize = nSize + self.MSG_OVERHEAD |
-- Check if there's room in the global available bandwidth gauge to send directly |
if not self.bQueueing and nSize < self:UpdateAvail() then |
self.avail = self.avail - nSize |
self.ORIG_SendChatMessage(text, chattype, language, destination) |
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize |
return |
end |
-- Message needs to be queued |
local msg = NewMsg() |
msg.f = self.ORIG_SendChatMessage |
msg[1] = text |
msg[2] = chattype or "SAY" |
msg[3] = language |
msg[4] = destination |
msg.n = 4 |
msg.nSize = nSize |
self:Enqueue(prio, queueName or (prefix..(chattype or "SAY")..(destination or "")), msg) |
end |
function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target, queueName) |
if not self or not prio or not prefix or not text or not chattype or not self.Prio[prio] then |
error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype"[, "target"])', 0) |
end |
local nSize = prefix:len() + 1 + text:len(); |
assert(nSize<=255, "prefix + text length cannot exceed 254 bytes"); |
nSize = nSize + self.MSG_OVERHEAD; |
-- Check if there's room in the global available bandwidth gauge to send directly |
if not self.bQueueing and nSize < self:UpdateAvail() then |
self.avail = self.avail - nSize |
self.ORIG_SendAddonMessage(prefix, text, chattype, target) |
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize |
return |
end |
-- Message needs to be queued |
local msg = NewMsg() |
msg.f = self.ORIG_SendAddonMessage |
msg[1] = prefix |
msg[2] = text |
msg[3] = chattype |
msg[4] = target |
msg.n = (target~=nil) and 4 or 3; |
msg.nSize = nSize |
self:Enqueue(prio, queueName or (prefix..chattype..(target or "")), msg) |
end |
----------------------------------------------------------------------- |
-- Get the ball rolling! |
ChatThrottleLib:Init() |
--[[ WoWBench debugging snippet |
if(WOWB_VER) then |
local function SayTimer() |
print("SAY: "..GetTime().." "..arg1) |
end |
ChatThrottleLib.Frame:SetScript("OnEvent", SayTimer) |
ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY") |
end |
]] |
--[[ |
Name: Dewdrop-2.0 |
Revision: $Rev$ |
Author(s): ckknight (ckknight@gmail.com) |
Website: http://ckknight.wowinterface.com/ |
Documentation: http://wiki.wowace.com/index.php/Dewdrop-2.0 |
SVN: http://svn.wowace.com/root/trunk/DewdropLib/Dewdrop-2.0 |
Description: A library to provide a clean dropdown menu interface. |
Dependencies: AceLibrary |
License: LGPL v2.1 |
]] |
local MAJOR_VERSION = "Dewdrop-2.0" |
local MINOR_VERSION = "$Revision$" |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
local Dewdrop = {} |
local SharedMedia |
local CLOSE = "Close" |
local CLOSE_DESC = "Close the menu." |
local VALIDATION_ERROR = "Validation error." |
local USAGE_TOOLTIP = "Usage: %s." |
local RANGE_TOOLTIP = "Note that you can scroll your mouse wheel while over the slider to step by one." |
local RESET_KEYBINDING_DESC = "Hit escape to clear the keybinding." |
local KEY_BUTTON1 = "Left Mouse" |
local KEY_BUTTON2 = "Right Mouse" |
local DISABLED = "Disabled" |
local DEFAULT_CONFIRM_MESSAGE = "Are you sure you want to perform `%s'?" |
if GetLocale() == "deDE" then |
CLOSE = "Schlie\195\159en" |
CLOSE_DESC = "Men\195\188 schlie\195\159en." |
VALIDATION_ERROR = "Validierungsfehler." |
USAGE_TOOLTIP = "Benutzung: %s." |
RANGE_TOOLTIP = "Beachte das du mit dem Mausrad scrollen kannst solange du mit dem Mauszeiger \195\188ber dem Schieberegler bist, um feinere Spr\195\188nge zu machen." |
RESET_KEYBINDING_DESC = "Escape dr\195\188cken, um die Tastenbelegung zu l\195\182schen." |
KEY_BUTTON1 = "Linke Maustaste" |
KEY_BUTTON2 = "Rechte Maustaste" |
DISABLED = "Deaktiviert" |
DEFAULT_CONFIRM_MESSAGE = "Bist du sicher das du `%s' machen willst?" |
elseif GetLocale() == "koKR" then |
CLOSE = "ë«ê¸°" |
CLOSE_DESC = "ë©ë´ë¥¼ ë«ìµëë¤." |
VALIDATION_ERROR = "ì¤ë¥ íì¸." |
USAGE_TOOLTIP = "ì¬ì©ë²: %s." |
RANGE_TOOLTIP = "ì림 : ì¬ë¼ì´ë ììì ë§ì°ì¤ í ì ì¬ì©íë©´ íë¨ê³ì© ì¡°ì í ì ììµëë¤." |
RESET_KEYBINDING_DESC = "ë¨ì¶í¤ë¥¼ í´ì íë ¤ë©´ ESCí¤ë¥¼ ë르ì¸ì." |
KEY_BUTTON1 = "ì¼ìª½ ë§ì°ì¤" |
KEY_BUTTON2 = "ì¤ë¥¸ìª½ ë§ì°ì¤" |
DISABLED = "ë¹íì±íë¨" |
DEFAULT_CONFIRM_MESSAGE = "ì ë§ë¡ `%s' ì¤íì íìê² ìµëê¹ ?" |
elseif GetLocale() == "frFR" then |
CLOSE = "Fermer" |
CLOSE_DESC = "Ferme le menu." |
VALIDATION_ERROR = "Erreur de validation." |
USAGE_TOOLTIP = "Utilisation : %s." |
RANGE_TOOLTIP = "Vous pouvez aussi utiliser la molette de la souris pour pour modifier progressivement." |
RESET_KEYBINDING_DESC = "Appuyez sur la touche Echappement pour effacer le raccourci." |
KEY_BUTTON1 = "Clic gauche" |
KEY_BUTTON2 = "Clic droit" |
DISABLED = "D\195\169sactiv\195\169" |
DEFAULT_CONFIRM_MESSAGE = "\195\138tes-vous s\195\187r de vouloir effectuer '%s' ?" |
elseif GetLocale() == "esES" then |
CLOSE = "Cerrar" |
CLOSE_DESC = "Cierra el menú." |
VALIDATION_ERROR = "Error de validación." |
USAGE_TOOLTIP = "Uso: %s." |
RANGE_TOOLTIP = "Puedes desplazarte verticalmente con la rueda del ratón sobre el desplazador." |
RESET_KEYBINDING_DESC = "Pulsa Escape para borrar la asignación de tecla." |
KEY_BUTTON1 = "Clic Izquierdo" |
KEY_BUTTON2 = "Clic Derecho" |
DISABLED = "Desactivado" |
DEFAULT_CONFIRM_MESSAGE = "¿Estás seguro de querer realizar `%s'?" |
elseif GetLocale() == "zhTW" then |
CLOSE = "éé" |
CLOSE_DESC = "ééé¸å®ã" |
VALIDATION_ERROR = "é©èé¯èª¤ã" |
USAGE_TOOLTIP = "ç¨æ³: %sã" |
RANGE_TOOLTIP = "ä½ å¯ä»¥å¨æ²åæ¢ä¸ä½¿ç¨æ»é¼ 滾輪ä¾æ²åã" |
RESET_KEYBINDING_DESC = "æEscéµæ¸ é¤å¿«æ·éµã" |
KEY_BUTTON1 = "æ»é¼ å·¦éµ" |
KEY_BUTTON2 = "æ»é¼ å³éµ" |
DISABLED = "åç¨" |
DEFAULT_CONFIRM_MESSAGE = "æ¯å¦å·è¡ã%sã?" |
elseif GetLocale() == "zhCN" then |
CLOSE = "å ³é" |
CLOSE_DESC = "å ³éèå" |
VALIDATION_ERROR = "éªè¯é误." |
USAGE_TOOLTIP = "ç¨æ³: %s." |
RANGE_TOOLTIP = "ä½ å¯ä»¥å¨æ»å¨æ¡ä¸ä½¿ç¨é¼ æ æ»è½®æ¥ç¿»é¡µ." |
RESET_KEYBINDING_DESC = "æESCé®æ¸ é¤æé®ç»å®" |
KEY_BUTTON1 = "é¼ æ å·¦é®" |
KEY_BUTTON2 = "é¼ æ å³é®" |
DISABLED = "ç¦ç¨" |
DEFAULT_CONFIRM_MESSAGE = "æ¯å¦æ§è¡'%s'?" |
end |
Dewdrop.KEY_BUTTON1 = KEY_BUTTON1 |
Dewdrop.KEY_BUTTON2 = KEY_BUTTON2 |
local function new(...) |
local t = {} |
for i = 1, select('#', ...), 2 do |
local k = select(i, ...) |
if k then |
t[k] = select(i+1, ...) |
else |
break |
end |
end |
return t |
end |
local tmp |
do |
local t = {} |
function tmp(...) |
for k in pairs(t) do |
t[k] = nil |
end |
for i = 1, select('#', ...), 2 do |
local k = select(i, ...) |
if k then |
t[k] = select(i+1, ...) |
else |
break |
end |
end |
return t |
end |
end |
local tmp2 |
do |
local t = {} |
function tmp2(...) |
for k in pairs(t) do |
t[k] = nil |
end |
for i = 1, select('#', ...), 2 do |
local k = select(i, ...) |
if k then |
t[k] = select(i+1, ...) |
else |
break |
end |
end |
return t |
end |
end |
local levels |
local buttons |
-- Secure frame handling: |
-- Rather than using secure buttons in the menu (has problems), we have one |
-- master secureframe that we pop onto menu items on mouseover. This requires |
-- some dark magic with OnLeave etc, but it's not too bad. |
local secureFrame = CreateFrame("Button", nil, nil, "SecureActionButtonTemplate") |
secureFrame:Hide() |
local function secureFrame_Show(self) |
local owner = self.owner |
if self.secure then -- Leftovers from previos owner, clean up! ("Shouldn't" happen but does..) |
for k,v in pairs(self.secure) do |
self:SetAttribute(k, nil) |
end |
end |
self.secure = owner.secure; -- Grab hold of new secure data |
local scale = owner:GetEffectiveScale() |
self:SetPoint("TOPLEFT", nil, "BOTTOMLEFT", owner:GetLeft() * scale, owner:GetTop() * scale) |
self:SetPoint("BOTTOMRIGHT", nil, "BOTTOMLEFT", owner:GetRight() * scale, owner:GetBottom() * scale) |
self:EnableMouse(true) |
for k,v in pairs(self.secure) do |
self:SetAttribute(k, v) |
end |
secureFrame:SetFrameStrata(owner:GetFrameStrata()) |
secureFrame:SetFrameLevel(owner:GetFrameLevel()+1) |
self:Show() |
end |
local function secureFrame_Hide(self) |
self:Hide() |
if self.secure then |
for k,v in pairs(self.secure) do |
self:SetAttribute(k, nil) |
end |
end |
self.secure = nil |
end |
secureFrame:SetScript("OnEvent", |
function() |
if event=="PLAYER_REGEN_ENABLED" then |
this.combat = false |
if not this:IsShown() and this.owner then |
secureFrame_Show(this) |
end |
elseif event=="PLAYER_REGEN_DISABLED" then |
this.combat = true |
if this:IsShown() then |
secureFrame_Hide(this) |
end |
end |
end |
) |
secureFrame:RegisterEvent("PLAYER_REGEN_ENABLED") |
secureFrame:RegisterEvent("PLAYER_REGEN_DISABLED") |
secureFrame:SetScript("OnLeave", |
function() |
local owner=this.owner |
this:Deactivate() |
owner:GetScript("OnLeave")() |
end |
) |
secureFrame:HookScript("OnClick", |
function() |
local realthis = this |
this = this.owner |
this:GetScript("OnClick")() |
end |
) |
function secureFrame:IsOwnedBy(frame) |
return self.owner == frame |
end |
function secureFrame:Activate(owner) |
if self.owner then -- "Shouldn't" happen but apparently it does and I cba to troubleshoot... |
if not self.combat then |
secureFrame_Hide(self) |
end |
end |
self.owner = owner |
if not self.combat then |
secureFrame_Show(self) |
end |
end |
function secureFrame:Deactivate() |
if not self.combat then |
secureFrame_Hide(self) |
end |
self.owner = nil |
end |
-- END secure frame utilities |
-- Underline on mouseover - use a single global underline that we move around, no point in creating lots of copies |
local underlineFrame = CreateFrame("Frame", nil) |
underlineFrame.tx = underlineFrame:CreateTexture() |
underlineFrame.tx:SetTexture(1,1,0.5,0.75) |
underlineFrame:SetScript("OnHide", function(this) this:Hide(); end) |
underlineFrame:SetScript("OnShow", function(this) -- change sizing on the fly to catch runtime uiscale changes |
underlineFrame.tx:SetPoint("TOPLEFT", -1, -2/this:GetEffectiveScale()) |
underlineFrame.tx:SetPoint("RIGHT", 1,0) |
underlineFrame.tx:SetHeight(0.6 / this:GetEffectiveScale()); |
end) |
underlineFrame:SetHeight(1) |
-- END underline on mouseover |
local function GetScaledCursorPosition() |
local x, y = GetCursorPosition() |
local scale = UIParent:GetEffectiveScale() |
return x / scale, y / scale |
end |
local function StartCounting(self, level) |
for i = level, 1, -1 do |
if levels[i] then |
levels[i].count = 3 |
end |
end |
end |
local function StopCounting(self, level) |
for i = level, 1, -1 do |
if levels[i] then |
levels[i].count = nil |
end |
end |
end |
local function OnUpdate(self, elapsed) |
for _,level in ipairs(levels) do |
local count = level.count |
if count then |
count = count - elapsed |
if count < 0 then |
level.count = nil |
self:Close(level.num) |
else |
level.count = count |
end |
end |
end |
end |
local function CheckDualMonitor(self, frame) |
local ratio = GetScreenWidth() / GetScreenHeight() |
if ratio >= 2.4 and frame:GetRight() > GetScreenWidth() / 2 and frame:GetLeft() < GetScreenWidth() / 2 then |
local offsetx |
if GetCursorPosition() / GetScreenHeight() * 768 < GetScreenWidth() / 2 then |
offsetx = GetScreenWidth() / 2 - frame:GetRight() |
else |
offsetx = GetScreenWidth() / 2 - frame:GetLeft() |
end |
local point, parent, relativePoint, x, y = frame:GetPoint(1) |
frame:SetPoint(point, parent, relativePoint, (x or 0) + offsetx, y or 0) |
end |
end |
local function CheckSize(self, level) |
if not level.buttons then |
return |
end |
local height = 20 |
for _, button in ipairs(level.buttons) do |
height = height + button:GetHeight() |
end |
level:SetHeight(height) |
local width = 160 |
for _, button in ipairs(level.buttons) do |
local extra = 1 |
if button.hasArrow or button.hasColorSwatch then |
extra = extra + 16 |
end |
if not button.notCheckable then |
extra = extra + 24 |
end |
button.text:SetFont(STANDARD_TEXT_FONT, button.textHeight) |
if button.text:GetWidth() + extra > width then |
width = button.text:GetWidth() + extra |
end |
end |
level:SetWidth(width + 20) |
if level:GetLeft() and level:GetRight() and level:GetTop() and level:GetBottom() and (level:GetLeft() < 0 or level:GetRight() > GetScreenWidth() or level:GetTop() > GetScreenHeight() or level:GetBottom() < 0) then |
level:ClearAllPoints() |
local parent = level.parent or level:GetParent() |
if type(parent) ~= "table" then |
parent = UIParent |
end |
if level.lastDirection == "RIGHT" then |
if level.lastVDirection == "DOWN" then |
level:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) |
else |
level:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) |
end |
else |
if level.lastVDirection == "DOWN" then |
level:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) |
else |
level:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) |
end |
end |
end |
local dirty = false |
if not level:GetRight() then |
self:Close() |
return |
end |
if level:GetRight() > GetScreenWidth() and level.lastDirection == "RIGHT" then |
level.lastDirection = "LEFT" |
dirty = true |
elseif level:GetLeft() < 0 and level.lastDirection == "LEFT" then |
level.lastDirection = "RIGHT" |
dirty = true |
end |
if level:GetTop() > GetScreenHeight() and level.lastVDirection == "UP" then |
level.lastVDirection = "DOWN" |
dirty = true |
elseif level:GetBottom() < 0 and level.lastVDirection == "DOWN" then |
level.lastVDirection = "UP" |
dirty = true |
end |
if dirty then |
level:ClearAllPoints() |
local parent = level.parent or level:GetParent() |
if type(parent) ~= "table" then |
parent = UIParent |
end |
if level.lastDirection == "RIGHT" then |
if level.lastVDirection == "DOWN" then |
level:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) |
else |
level:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) |
end |
else |
if level.lastVDirection == "DOWN" then |
level:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) |
else |
level:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) |
end |
end |
end |
if level:GetTop() > GetScreenHeight() then |
local top = level:GetTop() |
local point, parent, relativePoint, x, y = level:GetPoint(1) |
level:ClearAllPoints() |
level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) + GetScreenHeight() - top) |
elseif level:GetBottom() < 0 then |
local bottom = level:GetBottom() |
local point, parent, relativePoint, x, y = level:GetPoint(1) |
level:ClearAllPoints() |
level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) - bottom) |
end |
CheckDualMonitor(self, level) |
if mod(level.num, 5) == 0 then |
local left, bottom = level:GetLeft(), level:GetBottom() |
level:ClearAllPoints() |
level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) |
end |
end |
local Open |
local OpenSlider |
local OpenEditBox |
local Refresh |
local Clear |
local function ReleaseButton(self, level, index) |
if not level.buttons then |
return |
end |
if not level.buttons[index] then |
return |
end |
local button = level.buttons[index] |
button:Hide() |
if button.highlight then |
button.highlight:Hide() |
end |
-- button.arrow:SetVertexColor(1, 1, 1) |
-- button.arrow:SetHeight(16) |
-- button.arrow:SetWidth(16) |
table.remove(level.buttons, index) |
table.insert(buttons, button) |
for k in pairs(button) do |
if k ~= 0 and k ~= "text" and k ~= "check" and k ~= "arrow" and k ~= "colorSwatch" and k ~= "highlight" and k ~= "radioHighlight" then |
button[k] = nil |
end |
end |
return true |
end |
local function Scroll(self, level, down) |
if down then |
if level:GetBottom() < 0 then |
local point, parent, relativePoint, x, y = level:GetPoint(1) |
level:SetPoint(point, parent, relativePoint, x, y + 50) |
if level:GetBottom() > 0 then |
level:SetPoint(point, parent, relativePoint, x, y + 50 - level:GetBottom()) |
end |
end |
else |
if level:GetTop() > GetScreenHeight() then |
local point, parent, relativePoint, x, y = level:GetPoint(1) |
level:SetPoint(point, parent, relativePoint, x, y - 50) |
if level:GetTop() < GetScreenHeight() then |
level:SetPoint(point, parent, relativePoint, x, y - 50 + GetScreenHeight() - level:GetTop()) |
end |
end |
end |
end |
local function getArgs(t, str, num, ...) |
local x = t[str .. num] |
if x == nil then |
return ... |
else |
return x, getArgs(t, str, num + 1, ...) |
end |
end |
local sliderFrame |
local editBoxFrame |
local normalFont |
local lastSetFont |
local justSetFont = false |
local regionTmp = {} |
local function fillRegionTmp(...) |
for i = 1, select('#', ...) do |
regionTmp[i] = select(i, ...) |
end |
end |
local function showGameTooltip(this) |
if this.tooltipTitle or this.tooltipText then |
GameTooltip_SetDefaultAnchor(GameTooltip, this) |
local disabled = not this.isTitle and this.disabled |
local font |
if this.tooltipTitle then |
if SharedMedia and SharedMedia:IsValid("font", this.tooltipTitle) then |
font = SharedMedia:Fetch("font", this.tooltipTitle) |
end |
if disabled then |
GameTooltip:SetText(this.tooltipTitle, 0.5, 0.5, 0.5, 1) |
else |
GameTooltip:SetText(this.tooltipTitle, 1, 1, 1, 1) |
end |
if this.tooltipText then |
if not font and SharedMedia and SharedMedia:IsValid("font", this.tooltipText) then |
font = SharedMedia:Fetch("font", this.tooltipText) |
end |
if disabled then |
GameTooltip:AddLine(this.tooltipText, (NORMAL_FONT_COLOR.r + 0.5) / 2, (NORMAL_FONT_COLOR.g + 0.5) / 2, (NORMAL_FONT_COLOR.b + 0.5) / 2, 1) |
else |
GameTooltip:AddLine(this.tooltipText, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) |
end |
end |
else |
if SharedMedia and SharedMedia:IsValid("font", this.tooltipText) then |
font = SharedMedia:Fetch("font", this.tooltipText) |
end |
if disabled then |
GameTooltip:SetText(this.tooltipText, 0.5, 0.5, 0.5, 1) |
else |
GameTooltip:SetText(this.tooltipText, 1, 1, 1, 1) |
end |
end |
if font then |
fillRegionTmp(GameTooltip:GetRegions()) |
lastSetFont = font |
justSetFont = true |
for i,v in ipairs(regionTmp) do |
if v.SetFont then |
local norm,size,outline = v:GetFont() |
v:SetFont(font, size, outline) |
if not normalFont then |
normalFont = norm |
end |
end |
regionTmp[i] = nil |
end |
elseif not normalFont then |
fillRegionTmp(GameTooltip:GetRegions()) |
for i,v in ipairs(regionTmp) do |
if v.GetFont and not normalFont then |
normalFont = v:GetFont() |
end |
regionTmp[i] = nil |
end |
end |
GameTooltip:Show() |
end |
if this.tooltipFunc then |
GameTooltip:SetOwner(this, "ANCHOR_NONE") |
GameTooltip:SetPoint("TOPLEFT", this, "TOPRIGHT", 5, 0) |
this.tooltipFunc(getArgs(this, 'tooltipArg', 1)) |
GameTooltip:Show() |
end |
end |
local tmpt = setmetatable({}, {mode='v'}) |
local numButtons = 0 |
local function AcquireButton(self, level) |
if not levels[level] then |
return |
end |
level = levels[level] |
if not level.buttons then |
level.buttons = {} |
end |
local button |
if #buttons == 0 then |
numButtons = numButtons + 1 |
button = CreateFrame("Button", "Dewdrop20Button" .. numButtons, nil) |
button:SetFrameStrata("FULLSCREEN_DIALOG") |
button:SetHeight(16) |
local highlight = button:CreateTexture(nil, "BACKGROUND") |
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") |
button.highlight = highlight |
highlight:SetBlendMode("ADD") |
highlight:SetAllPoints(button) |
highlight:Hide() |
local check = button:CreateTexture(nil, "ARTWORK") |
button.check = check |
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") |
check:SetPoint("CENTER", button, "LEFT", 12, 0) |
check:SetWidth(24) |
check:SetHeight(24) |
local radioHighlight = button:CreateTexture(nil, "ARTWORK") |
button.radioHighlight = radioHighlight |
radioHighlight:SetTexture("Interface\\Buttons\\UI-RadioButton") |
radioHighlight:SetAllPoints(check) |
radioHighlight:SetBlendMode("ADD") |
radioHighlight:SetTexCoord(0.5, 0.75, 0, 1) |
radioHighlight:Hide() |
button:SetScript("OnEnter", function() |
if (sliderFrame and sliderFrame:IsShown() and sliderFrame.mouseDown and sliderFrame.level == this.level.num + 1) or (editBoxFrame and editBoxFrame:IsShown() and editBoxFrame.mouseDown and editBoxFrame.level == this.level.num + 1) then |
for i = 1, this.level.num do |
Refresh(self, levels[i]) |
end |
return |
end |
self:Close(this.level.num + 1) |
if not this.disabled then |
if this.secure then |
secureFrame:Activate(this) |
elseif this.hasSlider then |
OpenSlider(self, this) |
elseif this.hasEditBox then |
OpenEditBox(self, this) |
elseif this.hasArrow then |
Open(self, this, nil, this.level.num + 1, this.value) |
end |
end |
if not this.level then -- button reclaimed |
return |
end |
StopCounting(self, this.level.num + 1) |
if not this.disabled then |
highlight:Show() |
if this.isRadio then |
button.radioHighlight:Show() |
end |
if this.mouseoverUnderline then |
underlineFrame:SetParent(this) |
underlineFrame:SetPoint("BOTTOMLEFT",this.text,0,0) |
underlineFrame:SetWidth(this.text:GetWidth()) |
underlineFrame:Show() |
end |
end |
showGameTooltip(this) |
end) |
button:SetScript("OnHide", function() |
if this.secure and secureFrame:IsOwnedBy(this) then |
secureFrame:Deactivate() |
end |
end) |
button:SetScript("OnLeave", function() |
if this.secure and secureFrame:IsShown() then |
return; -- it's ok, we didn't actually mouse out of the button, only onto the secure frame on top of it |
end |
underlineFrame:Hide() |
if not this.selected then |
highlight:Hide() |
end |
button.radioHighlight:Hide() |
if this.level then |
StartCounting(self, this.level.num) |
end |
GameTooltip:Hide() |
end) |
local first = true |
button:SetScript("OnClick", function() |
if not this.disabled then |
if this.hasColorSwatch then |
local func = button.colorFunc |
local hasOpacity = this.hasOpacity |
local this = this |
for k in pairs(tmpt) do |
tmpt[k] = nil |
end |
for i = 1, 1000 do |
local x = this['colorArg'..i] |
if x == nil then |
break |
else |
tmpt[i] = x |
end |
end |
ColorPickerFrame.func = function() |
if func then |
local r,g,b = ColorPickerFrame:GetColorRGB() |
local a = hasOpacity and 1 - OpacitySliderFrame:GetValue() or nil |
local n = #tmpt |
tmpt[n+1] = r |
tmpt[n+2] = g |
tmpt[n+3] = b |
tmpt[n+4] = a |
func(unpack(tmpt)) |
tmpt[n+1] = nil |
tmpt[n+2] = nil |
tmpt[n+3] = nil |
tmpt[n+4] = nil |
end |
end |
ColorPickerFrame.hasOpacity = this.hasOpacity |
ColorPickerFrame.opacityFunc = ColorPickerFrame.func |
ColorPickerFrame.opacity = 1 - this.opacity |
ColorPickerFrame:SetColorRGB(this.r, this.g, this.b) |
local r, g, b, a = this.r, this.g, this.b, this.opacity |
ColorPickerFrame.cancelFunc = function() |
if func then |
local n = #tmpt |
tmpt[n+1] = r |
tmpt[n+2] = g |
tmpt[n+3] = b |
tmpt[n+4] = a |
func(unpack(tmpt)) |
for i = 1, n+4 do |
tmpt[i] = nil |
end |
end |
end |
self:Close(1) |
ShowUIPanel(ColorPickerFrame) |
elseif this.func then |
local level = this.level |
if type(this.func) == "string" then |
if type(this.arg1[this.func]) ~= "function" then |
self:error("Cannot call method %q", this.func) |
end |
this.arg1[this.func](this.arg1, getArgs(this, 'arg', 2)) |
else |
this.func(getArgs(this, 'arg', 1)) |
end |
if this.closeWhenClicked then |
self:Close() |
elseif level:IsShown() then |
for i = 1, level.num do |
Refresh(self, levels[i]) |
end |
local value = levels[level.num].value |
for i = level.num-1, 1, -1 do |
local level = levels[i] |
local good = false |
for _,button in ipairs(level.buttons) do |
if button.value == value then |
good = true |
break |
end |
end |
if not good then |
Dewdrop:Close(i+1) |
end |
value = levels[i].value |
end |
end |
elseif this.closeWhenClicked then |
self:Close() |
end |
end |
end) |
local text = button:CreateFontString(nil, "ARTWORK") |
button.text = text |
text:SetFontObject(GameFontHighlightSmall) |
button.text:SetFont(STANDARD_TEXT_FONT, UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT) |
button:SetScript("OnMouseDown", function() |
if not this.disabled and (this.func or this.colorFunc or this.closeWhenClicked) then |
text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 1 or 25, -1) |
end |
end) |
button:SetScript("OnMouseUp", function() |
if not this.disabled and (this.func or this.colorFunc or this.closeWhenClicked) then |
text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 0 or 24, 0) |
end |
end) |
local arrow = button:CreateTexture(nil, "ARTWORK") |
button.arrow = arrow |
arrow:SetPoint("LEFT", button, "RIGHT", -16, 0) |
arrow:SetWidth(16) |
arrow:SetHeight(16) |
arrow:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow") |
local colorSwatch = button:CreateTexture(nil, "ARTWORK") |
button.colorSwatch = colorSwatch |
colorSwatch:SetWidth(20) |
colorSwatch:SetHeight(20) |
colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch") |
local texture = button:CreateTexture(nil, "OVERLAY") |
colorSwatch.texture = texture |
texture:SetTexture("Interface\\Buttons\\WHITE8X8") |
texture:SetWidth(11.5) |
texture:SetHeight(11.5) |
texture:Show() |
texture:SetPoint("CENTER", colorSwatch, "CENTER") |
colorSwatch:SetPoint("RIGHT", button, "RIGHT", 0, 0) |
else |
button = table.remove(buttons) |
end |
button:ClearAllPoints() |
button:SetParent(level) |
button:SetFrameStrata(level:GetFrameStrata()) |
button:SetFrameLevel(level:GetFrameLevel() + 1) |
button:SetPoint("LEFT", level, "LEFT", 10, 0) |
button:SetPoint("RIGHT", level, "RIGHT", -10, 0) |
if #level.buttons == 0 then |
button:SetPoint("TOP", level, "TOP", 0, -10) |
else |
button:SetPoint("TOP", level.buttons[#level.buttons], "BOTTOM", 0, 0) |
end |
button.text:SetPoint("LEFT", button, "LEFT", 24, 0) |
button:Show() |
button.level = level |
table.insert(level.buttons, button) |
if not level.parented then |
level.parented = true |
level:ClearAllPoints() |
if level.num == 1 then |
if level.parent ~= UIParent and type(level.parent) == "table" then |
level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT") |
else |
level:SetPoint("CENTER", UIParent, "CENTER") |
end |
else |
if level.lastDirection == "RIGHT" then |
if level.lastVDirection == "DOWN" then |
level:SetPoint("TOPLEFT", level.parent, "TOPRIGHT", 5, 10) |
else |
level:SetPoint("BOTTOMLEFT", level.parent, "BOTTOMRIGHT", 5, -10) |
end |
else |
if level.lastVDirection == "DOWN" then |
level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT", -5, 10) |
else |
level:SetPoint("BOTTOMRIGHT", level.parent, "BOTTOMLEFT", -5, -10) |
end |
end |
end |
level:SetFrameStrata("FULLSCREEN_DIALOG") |
end |
button:SetAlpha(1) |
return button |
end |
local numLevels = 0 |
local function AcquireLevel(self, level) |
if not levels[level] then |
for i = #levels + 1, level, -1 do |
local i = i |
numLevels = numLevels + 1 |
local frame = CreateFrame("Button", "Dewdrop20Level" .. numLevels, nil) |
if i == 1 then |
local old_CloseSpecialWindows = CloseSpecialWindows |
function CloseSpecialWindows() |
local found = old_CloseSpecialWindows() |
if levels[1]:IsShown() then |
self:Close() |
return 1 |
end |
return found |
end |
end |
levels[i] = frame |
frame.num = i |
frame:SetParent(UIParent) |
frame:SetFrameStrata("FULLSCREEN_DIALOG") |
frame:Hide() |
frame:SetWidth(180) |
frame:SetHeight(10) |
frame:SetFrameLevel(i * 3) |
frame:SetScript("OnHide", function() |
self:Close(level + 1) |
end) |
if frame.SetTopLevel then |
frame:SetTopLevel(true) |
end |
frame:EnableMouse(true) |
frame:EnableMouseWheel(true) |
local backdrop = CreateFrame("Frame", nil, frame) |
backdrop:SetAllPoints(frame) |
backdrop:SetBackdrop(tmp( |
'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", |
'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", |
'tile', true, |
'insets', tmp2( |
'left', 5, |
'right', 5, |
'top', 5, |
'bottom', 5 |
), |
'tileSize', 16, |
'edgeSize', 16 |
)) |
backdrop:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) |
backdrop:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) |
frame:SetScript("OnClick", function() |
self:Close(i) |
end) |
frame:SetScript("OnEnter", function() |
StopCounting(self, i) |
end) |
frame:SetScript("OnLeave", function() |
StartCounting(self, i) |
end) |
frame:SetScript("OnMouseWheel", function() |
Scroll(self, frame, arg1 < 0) |
end) |
if i == 1 then |
frame:SetScript("OnUpdate", function(this, arg1) |
OnUpdate(self, arg1) |
end) |
levels[1].lastDirection = "RIGHT" |
levels[1].lastVDirection = "DOWN" |
else |
levels[i].lastDirection = levels[i - 1].lastDirection |
levels[i].lastVDirection = levels[i - 1].lastVDirection |
end |
end |
end |
local fullscreenFrame = GetUIPanel("fullscreen") |
local l = levels[level] |
local strata, framelevel = l:GetFrameStrata(), l:GetFrameLevel() |
if fullscreenFrame then |
l:SetParent(fullscreenFrame) |
else |
l:SetParent(UIParent) |
end |
l:SetFrameStrata(strata) |
l:SetFrameLevel(framelevel) |
l:SetAlpha(1) |
return l |
end |
local function validateOptions(options, position, baseOptions, fromPass) |
if not baseOptions then |
baseOptions = options |
end |
if type(options) ~= "table" then |
return "Options must be a table.", position |
end |
local kind = options.type |
if type(kind) ~= "string" then |
return '"type" must be a string.', position |
elseif kind ~= "group" and kind ~= "range" and kind ~= "text" and kind ~= "execute" and kind ~= "toggle" and kind ~= "color" and kind ~= "dragLink" and kind ~= "header" then |
return '"type" must either be "range", "text", "group", "toggle", "execute", "color", "dragLink", or "header".', position |
end |
if options.aliases then |
if type(options.aliases) ~= "table" and type(options.aliases) ~= "string" then |
return '"alias" must be a table or string', position |
end |
end |
if not fromPass then |
if kind == "execute" then |
if type(options.func) ~= "string" and type(options.func) ~= "function" then |
return '"func" must be a string or function', position |
end |
elseif kind == "range" or kind == "text" or kind == "toggle" then |
if type(options.set) ~= "string" and type(options.set) ~= "function" then |
return '"set" must be a string or function', position |
end |
if kind == "text" and options.get == false then |
elseif type(options.get) ~= "string" and type(options.get) ~= "function" then |
return '"get" must be a string or function', position |
end |
elseif kind == "group" and options.pass then |
if options.pass ~= true then |
return '"pass" must be either nil, true, or false', position |
end |
if not options.func then |
if type(options.set) ~= "string" and type(options.set) ~= "function" then |
return '"set" must be a string or function', position |
end |
if type(options.get) ~= "string" and type(options.get) ~= "function" then |
return '"get" must be a string or function', position |
end |
elseif type(options.func) ~= "string" and type(options.func) ~= "function" then |
return '"func" must be a string or function', position |
end |
end |
end |
if options ~= baseOptions then |
if kind == "header" then |
elseif type(options.desc) ~= "string" then |
return '"desc" must be a string', position |
elseif options.desc:len() == 0 then |
return '"desc" cannot be a 0-length string', position |
end |
end |
if options ~= baseOptions or kind == "range" or kind == "text" or kind == "toggle" or kind == "color" then |
if options.type == "header" and not options.cmdName and not options.name then |
elseif options.cmdName then |
if type(options.cmdName) ~= "string" then |
return '"cmdName" must be a string or nil', position |
elseif options.cmdName:len() == 0 then |
return '"cmdName" cannot be a 0-length string', position |
end |
if type(options.guiName) ~= "string" then |
if not options.guiNameIsMap then |
return '"guiName" must be a string or nil', position |
end |
elseif options.guiName:len() == 0 then |
return '"guiName" cannot be a 0-length string', position |
end |
else |
if type(options.name) ~= "string" then |
return '"name" must be a string', position |
elseif options.name:len() == 0 then |
return '"name" cannot be a 0-length string', position |
end |
end |
end |
if options.guiNameIsMap then |
if type(options.guiNameIsMap) ~= "boolean" then |
return '"guiNameIsMap" must be a boolean or nil', position |
elseif options.type ~= "toggle" then |
return 'if "guiNameIsMap" is true, then "type" must be set to \'toggle\'', position |
elseif type(options.map) ~= "table" then |
return '"map" must be a table', position |
end |
end |
if options.message and type(options.message) ~= "string" then |
return '"message" must be a string or nil', position |
end |
if options.error and type(options.error) ~= "string" then |
return '"error" must be a string or nil', position |
end |
if options.current and type(options.current) ~= "string" then |
return '"current" must be a string or nil', position |
end |
if options.order then |
if type(options.order) ~= "number" or (-1 < options.order and options.order < 0.999) then |
return '"order" must be a non-zero number or nil', position |
end |
end |
if options.disabled then |
if type(options.disabled) ~= "function" and type(options.disabled) ~= "string" and options.disabled ~= true then |
return '"disabled" must be a function, string, or boolean', position |
end |
end |
if options.cmdHidden then |
if type(options.cmdHidden) ~= "function" and type(options.cmdHidden) ~= "string" and options.cmdHidden ~= true then |
return '"cmdHidden" must be a function, string, or boolean', position |
end |
end |
if options.guiHidden then |
if type(options.guiHidden) ~= "function" and type(options.guiHidden) ~= "string" and options.guiHidden ~= true then |
return '"guiHidden" must be a function, string, or boolean', position |
end |
end |
if options.hidden then |
if type(options.hidden) ~= "function" and type(options.hidden) ~= "string" and options.hidden ~= true then |
return '"hidden" must be a function, string, or boolean', position |
end |
end |
if kind == "text" then |
if type(options.validate) == "table" then |
local t = options.validate |
local iTable = nil |
for k,v in pairs(t) do |
if type(k) == "number" then |
if iTable == nil then |
iTable = true |
elseif not iTable then |
return '"validate" must either have all keys be indexed numbers or strings', position |
elseif k < 1 or k > #t then |
return '"validate" numeric keys must be indexed properly. >= 1 and <= #t', position |
end |
else |
if iTable == nil then |
iTable = false |
elseif iTable then |
return '"validate" must either have all keys be indexed numbers or strings', position |
end |
end |
if type(v) ~= "string" then |
return '"validate" values must all be strings', position |
end |
end |
if options.multiToggle and options.multiToggle ~= true then |
return '"multiToggle" must be a boolean or nil if "validate" is a table', position |
end |
elseif options.validate == "keybinding" then |
-- no other checks |
else |
if type(options.usage) ~= "string" then |
return '"usage" must be a string', position |
elseif options.validate and type(options.validate) ~= "string" and type(options.validate) ~= "function" then |
return '"validate" must be a string, function, or table', position |
end |
end |
if options.multiToggle and type(options.validate) ~= "table" then |
return '"validate" must be a table if "multiToggle" is true', position |
end |
elseif kind == "range" then |
if options.min or options.max then |
if type(options.min) ~= "number" then |
return '"min" must be a number', position |
elseif type(options.max) ~= "number" then |
return '"max" must be a number', position |
elseif options.min >= options.max then |
return '"min" must be less than "max"', position |
end |
end |
if options.step then |
if type(options.step) ~= "number" then |
return '"step" must be a number', position |
elseif options.step < 0 then |
return '"step" must be nonnegative', position |
end |
end |
if options.bigStep then |
if type(options.bigStep) ~= "number" then |
return '"bigStep" must be a number', position |
elseif options.bigStep < 0 then |
return '"bigStep" must be nonnegative', position |
end |
end |
if options.isPercent and options.isPercent ~= true then |
return '"isPercent" must either be nil, true, or false', position |
end |
elseif kind == "toggle" then |
if options.map then |
if type(options.map) ~= "table" then |
return '"map" must be a table', position |
elseif type(options.map[true]) ~= "string" then |
return '"map[true]" must be a string', position |
elseif type(options.map[false]) ~= "string" then |
return '"map[false]" must be a string', position |
end |
end |
elseif kind == "color" then |
if options.hasAlpha and options.hasAlpha ~= true then |
return '"hasAlpha" must be nil, true, or false', position |
end |
elseif kind == "group" then |
if options.pass and options.pass ~= true then |
return '"pass" must be nil, true, or false', position |
end |
if type(options.args) ~= "table" then |
return '"args" must be a table', position |
end |
for k,v in pairs(options.args) do |
if type(k) ~= "number" then |
if type(k) ~= "string" then |
return '"args" keys must be strings or numbers', position |
elseif k:len() == 0 then |
return '"args" keys must not be 0-length strings.', position |
end |
end |
if type(v) ~= "table" then |
return '"args" values must be tables', position and position .. "." .. k or k |
end |
local newposition |
if position then |
newposition = position .. ".args." .. k |
else |
newposition = "args." .. k |
end |
local err, pos = validateOptions(v, newposition, baseOptions, options.pass) |
if err then |
return err, pos |
end |
end |
elseif kind == "execute" then |
if type(options.confirm) ~= "string" and type(options.confirm) ~= "boolean" and type(options.confirm) ~= "nil" then |
return '"confirm" must be a string, boolean, or nil', position |
end |
end |
if options.icon and type(options.icon) ~= "string" then |
return'"icon" must be a string', position |
end |
if options.iconWidth or options.iconHeight then |
if type(options.iconWidth) ~= "number" or type(options.iconHeight) ~= "number" then |
return '"iconHeight" and "iconWidth" must be numbers', position |
end |
end |
if options.iconCoordLeft or options.iconCoordRight or options.iconCoordTop or options.iconCoordBottom then |
if type(options.iconCoordLeft) ~= "number" or type(options.iconCoordRight) ~= "number" or type(options.iconCoordTop) ~= "number" or type(options.iconCoordBottom) ~= "number" then |
return '"iconCoordLeft", "iconCoordRight", "iconCoordTop", and "iconCoordBottom" must be numbers', position |
end |
end |
end |
local validatedOptions |
local values |
local mysort_args |
local mysort |
local othersort |
local othersort_validate |
local baseFunc, currentLevel |
local function confirmPopup(message, func, ...) |
if not StaticPopupDialogs["DEWDROP20_CONFIRM_DIALOG"] then |
StaticPopupDialogs["DEWDROP20_CONFIRM_DIALOG"] = {} |
end |
local t = StaticPopupDialogs["DEWDROP20_CONFIRM_DIALOG"] |
for k in pairs(t) do |
t[k] = nil |
end |
t.text = message |
t.button1 = ACCEPT or "Accept" |
t.button2 = CANCEL or "Cancel" |
t.OnAccept = function() |
func(unpack(t)) |
end |
for i = 1, select('#', ...) do |
t[i] = select(i, ...) |
end |
t.timeout = 0 |
t.whileDead = 1 |
t.hideOnEscape = 1 |
Dewdrop:Close() |
StaticPopup_Show("DEWDROP20_CONFIRM_DIALOG") |
end |
local function getMethod(settingname, handler, v, methodName, ...) -- "..." is simply returned straight out cause you can't do "a,b,c = 111,f(),222" |
assert(v and type(v)=="table") |
assert(methodName and type(methodName)=="string") |
local method = v[methodName] |
if type(method)=="function" then |
return method, ... |
elseif type(method)=="string" then |
if not handler then |
Dewdrop:error("[%s] 'handler' is required if providing a method name: %q", tostring(settingname), method) |
elseif not handler[method] then |
Dewdrop:error("[%s] 'handler' method %q not defined", tostring(settingname), method) |
end |
return handler[method], handler, ... |
end |
Dewdrop:error("[%s] Missing %q directive", tostring(settingname), methodName) |
end |
local function callMethod(settingname, handler, v, methodName, ...) |
assert(v and type(v)=="table") |
assert(methodName and type(methodName)=="string") |
local method = v[methodName] |
if type(method)=="function" then |
local success, ret,ret2,ret3,ret4 = pcall(v[methodName], ...) |
if not success then |
geterrorhandler()(ret) |
return nil |
end |
return ret,ret2,ret3,ret4 |
elseif type(method)=="string" then |
local neg = method:match("^~(.-)$") |
if neg then |
method = neg |
end |
if not handler then |
Dewdrop:error("[%s] 'handler' is required if providing a method name: %q", tostring(settingname), method) |
elseif not handler[method] then |
Dewdrop:error("[%s] 'handler' (%q) method %q not defined", tostring(settingname), handler.name or "(unnamed)", method) |
end |
local success, ret,ret2,ret3,ret4 = pcall(handler[method], handler, ...) |
if not success then |
geterrorhandler()(ret) |
return nil |
end |
if neg then |
return not ret |
end |
return ret,ret2,ret3,ret4 |
elseif method == false then |
return nil |
end |
Dewdrop:error("[%s] Missing %q directive in %q", tostring(settingname), methodName, v.name or "(unnamed)") |
end |
local function skip1Nil(...) |
if select(1,...)==nil then |
return select(2,...) |
end |
return ... |
end |
function Dewdrop:FeedAceOptionsTable(options, difference) |
self:argCheck(options, 2, "table") |
self:argCheck(difference, 3, "nil", "number") |
if not currentLevel then |
self:error("Cannot call `FeedAceOptionsTable' outside of a Dewdrop declaration") |
end |
if not difference then |
difference = 0 |
end |
if not validatedOptions then |
validatedOptions = {} |
end |
if not validatedOptions[options] then |
local err, position = validateOptions(options) |
if err then |
if position then |
Dewdrop:error(position .. ": " .. err) |
else |
Dewdrop:error(err) |
end |
end |
validatedOptions[options] = true |
end |
local level = levels[currentLevel] |
if not level then |
self:error("Improper level given") |
end |
if not values then |
values = {} |
else |
for k,v in pairs(values) do |
values[k] = nil |
end |
end |
local current = level |
while current do -- this traverses from higher level numbers to lower, building "values" with leaf nodes first and trunk nodes later |
if current.num == difference + 1 then |
break |
end |
table.insert(values, current.value) |
current = levels[current.num - 1] |
end |
local realOptions = options |
local handler = options.handler |
local passTable |
local passValue |
while #values > 0 do -- This loop traverses values from the END (trunk nodes first, then onto leaf nodes) |
if options.pass then |
if options.get and options.set then |
passTable = options |
elseif not passTable then |
passTable = options |
end |
else |
passTable = nil |
end |
local value = table.remove(values) |
options = options.args and options.args[value] |
if not options then |
return |
end |
handler = options.handler or handler |
passValue = passTable and value or nil |
end |
if options.type == "group" then |
local hidden = options.hidden |
if type(hidden) == "function" or type(hidden) == "string" then |
hidden = callMethod(options.name or "(options root)", handler, options, "hidden", options.passValue) or false |
end |
if hidden then |
return |
end |
local disabled = options.disabled |
if type(disabled) == "function" or type(disabled) == "string" then |
disabled = callMethod(options.name or "(options root)", handler, options, "disabled", options.passValue) or false |
end |
if disabled then |
self:AddLine( |
'text', DISABLED, |
'disabled', true |
) |
return |
end |
for k in pairs(options.args) do |
table.insert(values, k) |
end |
if options.pass then |
if options.get and options.set then |
passTable = options |
elseif not passTable then |
passTable = options |
end |
else |
passTable = nil |
end |
if not mysort then |
mysort = function(a, b) |
local alpha, bravo = mysort_args[a], mysort_args[b] |
local alpha_order = alpha.order or 100 |
local bravo_order = bravo.order or 100 |
local alpha_name = alpha.guiName or alpha.name |
local bravo_name = bravo.guiName or bravo.name |
if alpha_order == bravo_order then |
if not alpha_name then |
return bravo_name |
elseif not bravo_name then |
return false |
else |
return alpha_name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() < bravo_name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() |
end |
else |
if alpha_order < 0 then |
if bravo_order > 0 then |
return false |
end |
else |
if bravo_order < 0 then |
return true |
end |
end |
return alpha_order < bravo_order |
end |
end |
end |
mysort_args = options.args |
table.sort(values, mysort) |
mysort_args = nil |
local hasBoth = #values >= 1 and (options.args[values[1]].order or 100) > 0 and (options.args[values[#values]].order or 100) < 0 |
local last_order = 1 |
for _,k in ipairs(values) do |
local v = options.args[k] |
local handler = v.handler or handler |
if hasBoth and last_order > 0 and (v.order or 100) < 0 then |
hasBoth = false |
self:AddLine() |
end |
local hidden, disabled = v.guiHidden or v.hidden, v.disabled |
if type(hidden) == "function" or type(hidden) == "string" then |
hidden = callMethod(k, handler, v, "hidden", v.passValue) or false |
end |
if not hidden then |
if type(disabled) == "function" or type(disabled) == "string" then |
disabled = callMethod(k, handler, v, "disabled", v.passValue) or false |
end |
local name = (v.guiIconOnly and v.icon) and "" or (v.guiName or v.name) |
local desc = v.guiDesc or v.desc |
local iconHeight = v.iconHeight or 16 |
local iconWidth = v.iconWidth or 16 |
local iconCoordLeft = v.iconCoordLeft |
local iconCoordRight = v.iconCoordRight |
local iconCoordBottom = v.iconCoordBottom |
local iconCoordTop = v.iconCoordTop |
local tooltipTitle, tooltipText |
tooltipTitle = name |
if name ~= desc then |
tooltipText = desc |
end |
if type(v.usage) == "string" and v.usage:trim():len() > 0 then |
if tooltipText then |
tooltipText = tooltipText .. "\n\n" .. USAGE_TOOLTIP:format(v.usage) |
else |
tooltipText = USAGE_TOOLTIP:format(v.usage) |
end |
end |
local v_p = passTable |
if not v_p or (v.type ~= "execute" and v.get and v.set) or (v.type == "execute" and v.func) then |
v_p = v |
end |
local passValue = v.passValue or (v_p~=v and k) or nil |
if v.type == "toggle" then |
local checked = callMethod(name, handler, v_p, "get", passValue) or false |
local checked_arg = checked |
if type(v_p.get)=="string" and v_p.get:match("^~") then |
checked_arg = not checked |
end |
local func, arg1, arg2, arg3 = getMethod(name, handler, v_p, "set", skip1Nil(passValue, not checked_arg)) |
if v.guiNameIsMap then |
checked = checked and true or false |
name = tostring(v.map and v.map[checked]):gsub("|c%x%x%x%x%x%x%x%x(.-)|r", "%1") |
tooltipTitle = name |
checked = true--nil |
end |
self:AddLine( |
'text', name, |
'checked', checked, |
'isRadio', v.isRadio, |
'func', func, |
'arg1', arg1, |
'arg2', arg2, |
'arg3', arg3, |
'disabled', disabled, |
'tooltipTitle', tooltipTitle, |
'tooltipText', tooltipText |
) |
elseif v.type == "execute" then |
local func, arg1, arg2, arg3, arg4 |
local confirm = v.confirm |
if confirm == true then |
confirm = DEFAULT_CONFIRM_MESSAGE:format(tooltipText or tooltipTitle) |
func,arg1,arg2,arg3,arg4 = confirmPopup, confirm, getMethod(name, handler, v_p, "func", passValue) |
elseif type(confirm) == "string" then |
func,arg1,arg2,arg3,arg4 = confirmPopup, confirm, getMethod(name, handler, v_p, "func", passValue) |
else |
func,arg1,arg2 = getMethod(name, handler, v_p, "func", passValue) |
end |
self:AddLine( |
'text', name, |
'checked', checked, |
'func', func, |
'arg1', arg1, |
'arg2', arg2, |
'arg3', arg3, |
'arg4', arg4, |
'disabled', disabled, |
'tooltipTitle', tooltipTitle, |
'tooltipText', tooltipText, |
'icon', v.icon, |
'iconHeight', iconHeight, |
'iconWidth', iconWidth, |
'iconCoordLeft', iconCoordLeft, |
'iconCoordRight', iconCoordRight, |
'iconCoordTop', iconCoordTop, |
'iconCoordBottom', iconCoordBottom |
) |
elseif v.type == "range" then |
local sliderValue |
sliderValue = callMethod(name, handler, v_p, "get", passValue) or 0 |
local sliderFunc, sliderArg1, sliderArg2 = getMethod(name, handler, v_p, "set", passValue) |
if tooltipText then |
tooltipText = format("%s\n\n%s", tooltipText, RANGE_TOOLTIP) |
else |
tooltipText = RANGE_TOOLTIP |
end |
self:AddLine( |
'text', name, |
'hasArrow', true, |
'hasSlider', true, |
'sliderMin', v.min or 0, |
'sliderMax', v.max or 1, |
'sliderStep', v.step or 0, |
'sliderBigStep', v.bigStep or nil, |
'sliderIsPercent', v.isPercent or false, |
'sliderValue', sliderValue, |
'sliderFunc', sliderFunc, |
'sliderArg1', sliderArg1, |
'sliderArg2', sliderArg2, |
'fromAceOptions', true, |
'disabled', disabled, |
'tooltipTitle', tooltipTitle, |
'tooltipText', tooltipText, |
'icon', v.icon, |
'iconHeight', iconHeight, |
'iconWidth', iconWidth, |
'iconCoordLeft', iconCoordLeft, |
'iconCoordRight', iconCoordRight, |
'iconCoordTop', iconCoordTop, |
'iconCoordBottom', iconCoordBottom |
) |
elseif v.type == "color" then |
local r,g,b,a = callMethod(name, handler, v_p, "get", passValue) |
if not r then |
r,g,b,a = 0,0,0,0 |
end |
local colorFunc, colorArg1, colorArg2 = getMethod(name, handler, v_p, "set", passValue) |
self:AddLine( |
'text', name, |
'hasArrow', true, |
'hasColorSwatch', true, |
'r', r, |
'g', g, |
'b', b, |
'opacity', v.hasAlpha and a or nil, |
'hasOpacity', v.hasAlpha, |
'colorFunc', colorFunc, |
'colorArg1', colorArg1, |
'colorArg2', colorArg2, |
'disabled', disabled, |
'tooltipTitle', tooltipTitle, |
'tooltipText', tooltipText |
) |
elseif v.type == "text" then |
if type(v.validate) == "table" then |
local func,arg1,arg2 |
if v.onClick then |
func,arg1,arg2 = getMethod(name, handler, v, "onClick", passValue) |
end |
local checked |
if v.isChecked then |
checked = callMethod(name, handler, v, "isChecked", passValue) or false |
end |
self:AddLine( |
'text', name, |
'hasArrow', true, |
'value', k, |
'func', func, |
'arg1', arg1, |
'arg2', arg2, |
'mouseoverUnderline', func and true or nil, |
'disabled', disabled, |
'checked', checked, |
'tooltipTitle', tooltipTitle, |
'tooltipText', tooltipText, |
'icon', v.icon, |
'iconHeight', iconHeight, |
'iconWidth', iconWidth, |
'iconCoordLeft', iconCoordLeft, |
'iconCoordRight', iconCoordRight, |
'iconCoordTop', iconCoordTop, |
'iconCoordBottom', iconCoordBottom |
) |
else |
local editBoxText |
editBoxText = callMethod(name, handler, v_p, "get", passValue) or "" |
local editBoxFunc, editBoxArg1, editBoxArg2 = getMethod(name, handler, v_p, "set", passValue) |
local editBoxValidateFunc, editBoxValidateArg1 |
if v.validate and v.validate ~= "keybinding" then |
if v.validate == "keybinding" then |
if tooltipText then |
tooltipText = format("%s\n\n%s", tooltipText, RESET_KEYBINDING_DESC) |
else |
tooltipText = RESET_KEYBINDING_DESC |
end |
else |
editBoxValidateFunc, editBoxValidateArg1 = getMethod(name, handler, v, "validate") -- no passvalue! |
end |
end |
self:AddLine( |
'text', name, |
'hasArrow', true, |
'icon', v.icon, |
'iconHeight', iconHeight, |
'iconWidth', iconWidth, |
'iconCoordLeft', iconCoordLeft, |
'iconCoordRight', iconCoordRight, |
'iconCoordTop', iconCoordTop, |
'iconCoordBottom', iconCoordBottom, |
'hasEditBox', true, |
'editBoxText', editBoxText, |
'editBoxFunc', editBoxFunc, |
'editBoxArg1', editBoxArg1, |
'editBoxArg2', editBoxArg2, |
'editBoxValidateFunc', editBoxValidateFunc, |
'editBoxValidateArg1', editBoxValidateArg1, |
'editBoxIsKeybinding', v.validate == "keybinding", |
'editBoxKeybindingOnly', v.keybindingOnly, |
'editBoxKeybindingExcept', v.keybindingExcept, |
'disabled', disabled, |
'tooltipTitle', tooltipTitle, |
'tooltipText', tooltipText |
) |
end |
elseif v.type == "group" then |
local func,arg1,arg2 |
if v.onClick then |
func,arg1,arg2 = getMethod(name, handler, v, "onClick", passValue) |
end |
local checked |
if v.isChecked then |
checked = callMethod(name, handler, v, "isChecked", passValue) or false |
end |
self:AddLine( |
'text', name, |
'hasArrow', true, |
'value', k, |
'func', func, |
'arg1', arg1, |
'arg2', arg2, |
'mouseoverUnderline', func and true or nil, |
'disabled', disabled, |
'checked', checked, |
'tooltipTitle', tooltipTitle, |
'tooltipText', tooltipText, |
'icon', v.icon, |
'iconHeight', iconHeight, |
'iconWidth', iconWidth, |
'iconCoordLeft', iconCoordLeft, |
'iconCoordRight', iconCoordRight, |
'iconCoordTop', iconCoordTop, |
'iconCoordBottom', iconCoordBottom |
) |
elseif v.type == "header" then |
if name == "" or not name then |
self:AddLine( |
'isTitle', true, |
'icon', v.icon, |
'iconHeight', iconHeight, |
'iconWidth', iconWidth, |
'iconCoordLeft', iconCoordLeft, |
'iconCoordRight', iconCoordRight, |
'iconCoordTop', iconCoordTop, |
'iconCoordBottom', iconCoordBottom |
) |
else |
self:AddLine( |
'text', name, |
'isTitle', true, |
'icon', v.icon, |
'iconHeight', iconHeight, |
'iconWidth', iconWidth, |
'iconCoordLeft', iconCoordLeft, |
'iconCoordRight', iconCoordRight, |
'iconCoordTop', iconCoordTop, |
'iconCoordBottom', iconCoordBottom |
) |
end |
end |
end |
last_order = v.order or 100 |
end |
elseif options.type == "text" and type(options.validate) == "table" then |
local current |
local options_p = passTable |
if not options_p or (options.get and options.set) then |
options_p = options |
passTable = nil |
passValue = nil |
end |
local multiToggle = options.multiToggle |
local passValue = options.passValue or passValue |
if not multiToggle then |
current = callMethod(k, handler, options_p, "get", passValue) |
end |
local indexed = true |
for k,v in pairs(options.validate) do |
if type(k) ~= "number" then |
indexed = false |
end |
table.insert(values, k) |
end |
if not indexed then |
if not othersort then |
othersort = function(alpha, bravo) |
return othersort_validate[alpha]:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() < othersort_validate[bravo]:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() |
end |
end |
othersort_validate = options.validate |
table.sort(values, othersort) |
othersort_validate = nil |
end |
for _,k in ipairs(values) do |
local v = options.validate[k] |
if type(k) == "number" then |
k = v |
end |
local func, arg1, arg2, arg3, arg4 = getMethod(k, handler, options_p, "set", skip1Nil(passValue, k)) |
local checked |
if multiToggle then |
checked = callMethod(k, handler, options_p, "get", skip1Nil(passValue, k)) or false |
if arg2 == nil then |
arg2 = not checked |
elseif arg3 == nil then |
arg3 = not checked |
else |
arg4 = not checked |
end |
else |
checked = (k == current or (type(k) == "string" and type(current) == "string" and k:lower() == current:lower())) |
if checked then |
func, arg1, arg2, arg3, arg4 = nil, nil, nil, nil, nil |
end |
end |
local tooltipTitle |
local tooltipText |
if options.validateDesc then |
tooltipTitle = v |
tooltipText = options.validateDesc[k] |
else |
tooltipTitle = options.guiName or options.name |
tooltipText = v |
end |
self:AddLine( |
'text', v, |
'func', func, |
'arg1', arg1, |
'arg2', arg2, |
'arg3', arg3, |
'arg4', arg4, |
'isRadio', not multiToggle, |
'checked', checked, |
'tooltipTitle', tooltipTitle, |
'tooltipText', tooltipText |
) |
end |
for k in pairs(values) do |
values[k] = nil |
end |
else |
return false |
end |
return true |
end |
function Dewdrop:FeedTable(s, difference) |
self:argCheck(s, 2, "table") |
self:argCheck(difference, 3, "nil", "number") |
if not currentLevel then |
self:error("Cannot call `FeedTable' outside of a Dewdrop declaration") |
end |
if not difference then |
difference = 0 |
end |
local level = levels[currentLevel] |
if not level then |
self:error("Improper level given") |
end |
if not values then |
values = {} |
else |
for k,v in pairs(values) do |
values[k] = nil |
end |
end |
local t = s.subMenu and s or {subMenu = s} |
local current = level |
while current do |
if current.num == difference + 1 then |
break |
end |
table.insert(values, current.value) |
current = levels[current.num - 1] |
end |
while #values > 0 do |
local value = table.remove(values) |
t = t.subMenu and t.subMenu[value] |
if not t then |
return |
end |
end |
if t.subMenu or current.num == 1 then |
for k in pairs(t.subMenu) do |
table.insert(values, k) |
end |
table.sort(values) |
for _,k in ipairs(values) do |
local argTable = {"value", k} |
for key, val in pairs(t.subMenu[k]) do |
table.insert(argTable, key) |
table.insert(argTable, val) |
end |
self:AddLine(unpack(argTable)) |
end |
for k in pairs(values) do |
values[k] = nil |
end |
return false |
end |
return true |
end |
function Refresh(self, level) |
if type(level) == "number" then |
level = levels[level] |
end |
if not level then |
return |
end |
if baseFunc then |
Clear(self, level) |
currentLevel = level.num |
if type(baseFunc) == "table" then |
if currentLevel == 1 then |
local handler = baseFunc.handler |
if handler then |
local name = tostring(handler) |
if not name:find('^table:') and not handler.hideMenuTitle then |
name = name:gsub("|c%x%x%x%x%x%x%x%x(.-)|r", "%1") |
self:AddLine( |
'text', name, |
'isTitle', true |
) |
end |
end |
-- elseif level.parentText then |
-- self:AddLine( |
-- 'text', level.parentText, |
-- 'tooltipTitle', level.parentTooltipTitle, |
-- 'tooltipText', level.parentTooltipText, |
-- 'tooltipFunc', level.parentTooltipFunc, |
-- 'isTitle', true |
-- ) |
end |
self:FeedAceOptionsTable(baseFunc) |
if currentLevel == 1 then |
self:AddLine( |
'text', CLOSE, |
'tooltipTitle', CLOSE, |
'tooltipText', CLOSE_DESC, |
'closeWhenClicked', true |
) |
end |
else |
-- if level.parentText then |
-- self:AddLine( |
-- 'text', level.parentText, |
-- 'tooltipTitle', level.parentTooltipTitle, |
-- 'tooltipText', level.parentTooltipText, |
-- 'tooltipFunc', level.parentTooltipFunc, |
-- 'isTitle', true |
-- ) |
-- end |
baseFunc(currentLevel, level.value, levels[level.num - 1] and levels[level.num - 1].value, levels[level.num - 2] and levels[level.num - 2].value, levels[level.num - 3] and levels[level.num - 3].value, levels[level.num - 4] and levels[level.num - 4].value) |
end |
currentLevel = nil |
CheckSize(self, level) |
end |
end |
function Dewdrop:Refresh(level) |
self:argCheck(level, 2, "number", "nil") |
if not level then |
for k,v in pairs(levels) do |
Refresh(self, v) |
end |
else |
Refresh(self, levels[level]) |
end |
end |
function OpenSlider(self, parent) |
if not sliderFrame then |
sliderFrame = CreateFrame("Frame", nil, nil) |
sliderFrame:SetWidth(100) |
sliderFrame:SetHeight(170) |
sliderFrame:SetScale(UIParent:GetScale()) |
sliderFrame:SetBackdrop(tmp( |
'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", |
'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", |
'tile', true, |
'insets', tmp2( |
'left', 5, |
'right', 5, |
'top', 5, |
'bottom', 5 |
), |
'tileSize', 16, |
'edgeSize', 16 |
)) |
sliderFrame:SetFrameStrata("FULLSCREEN_DIALOG") |
if sliderFrame.SetTopLevel then |
sliderFrame:SetTopLevel(true) |
end |
sliderFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) |
sliderFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) |
sliderFrame:EnableMouse(true) |
sliderFrame:EnableMouseWheel(true) |
sliderFrame:Hide() |
sliderFrame:SetPoint("CENTER", UIParent, "CENTER") |
local slider = CreateFrame("Slider", nil, sliderFrame) |
sliderFrame.slider = slider |
slider:SetOrientation("VERTICAL") |
slider:SetMinMaxValues(0, 1) |
slider:SetValueStep(0.000000001) |
slider:SetValue(0.5) |
slider:SetWidth(16) |
slider:SetHeight(128) |
slider:SetPoint("LEFT", sliderFrame, "LEFT", 15, 0) |
slider:SetBackdrop(tmp( |
'bgFile', "Interface\\Buttons\\UI-SliderBar-Background", |
'edgeFile', "Interface\\Buttons\\UI-SliderBar-Border", |
'tile', true, |
'edgeSize', 8, |
'tileSize', 8, |
'insets', tmp2( |
'left', 3, |
'right', 3, |
'top', 3, |
'bottom', 3 |
) |
)) |
local texture = slider:CreateTexture() |
slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical") |
local text = slider:CreateFontString(nil, "ARTWORK") |
sliderFrame.topText = text |
text:SetFontObject(GameFontGreenSmall) |
text:SetText("100%") |
text:SetPoint("BOTTOM", slider, "TOP") |
local text = slider:CreateFontString(nil, "ARTWORK") |
sliderFrame.bottomText = text |
text:SetFontObject(GameFontGreenSmall) |
text:SetText("0%") |
text:SetPoint("TOP", slider, "BOTTOM") |
local editBox = CreateFrame("EditBox", nil, sliderFrame) |
sliderFrame.currentText = editBox |
editBox:SetFontObject(ChatFontNormal) |
editBox:SetHeight(13) |
editBox:SetPoint("RIGHT", sliderFrame, "RIGHT", -16, 0) |
editBox:SetPoint("LEFT", slider, "RIGHT", 12, 0) |
editBox:SetText("50%") |
editBox:SetJustifyH("CENTER") |
local width = editBox:GetWidth()/2 + 10 |
local left = editBox:CreateTexture(nil, "BACKGROUND") |
left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left") |
left:SetTexCoord(0, width / 256, 0, 1) |
left:SetWidth(width) |
left:SetHeight(32) |
left:SetPoint("LEFT", editBox, "LEFT", -10, 0) |
local right = editBox:CreateTexture(nil, "BACKGROUND") |
right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right") |
right:SetTexCoord(1 - width / 256, 1, 0, 1) |
right:SetWidth(width) |
right:SetHeight(32) |
right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0) |
local changed = false |
local inside = false |
slider:SetScript("OnValueChanged", function() |
if sliderFrame.changing then |
return |
end |
changed = true |
local done = false |
if sliderFrame.parent and sliderFrame.parent.sliderFunc then |
local min = sliderFrame.parent.sliderMin or 0 |
local max = sliderFrame.parent.sliderMax or 1 |
local step |
if sliderFrame.fineStep then |
step = sliderFrame.parent.sliderStep or (max - min) / 100 |
else |
step = sliderFrame.parent.sliderBigStep or sliderFrame.parent.sliderStep or (max - min) / 100 |
end |
local value = (1 - slider:GetValue()) * (max - min) + min |
if step > 0 then |
value = math.floor((value - min) / step + 0.5) * step + min |
if value > max then |
value = max |
elseif value < min then |
value = min |
end |
end |
if value == sliderFrame.lastValue then |
return |
end |
sliderFrame.lastValue = value |
local text = sliderFrame.parent.sliderFunc(getArgs(sliderFrame.parent, 'sliderArg', 1, value)) |
if sliderFrame.parent.fromAceOptions then |
text = nil |
elseif type(text) == "string" or type(text) == "number" then |
sliderFrame.currentText:SetText(text) |
done = true |
end |
end |
if not done then |
local min = sliderFrame.parent.sliderMin or 0 |
local max = sliderFrame.parent.sliderMax or 1 |
local step |
if sliderFrame.fineStep then |
step = sliderFrame.parent.sliderStep or (max - min) / 100 |
else |
step = sliderFrame.parent.sliderBigStep or sliderFrame.parent.sliderStep or (max - min) / 100 |
end |
local value = (1 - slider:GetValue()) * (max - min) + min |
if step > 0 then |
value = math.floor((value - min) / step + 0.5) * step + min |
if value > max then |
value = max |
elseif value < min then |
value = min |
end |
end |
if sliderFrame.parent.sliderIsPercent then |
sliderFrame.currentText:SetText(string.format("%.0f%%", value * 100)) |
else |
if step < 0.1 then |
sliderFrame.currentText:SetText(string.format("%.2f", value)) |
elseif step < 1 then |
sliderFrame.currentText:SetText(string.format("%.1f", value)) |
else |
sliderFrame.currentText:SetText(string.format("%.0f", value)) |
end |
end |
end |
end) |
local function onEnter() |
StopCounting(self, sliderFrame.level) |
showGameTooltip(sliderFrame.parent) |
end |
local function onLeave() |
GameTooltip:Hide() |
end |
sliderFrame:SetScript("OnEnter", onEnter) |
sliderFrame:SetScript("OnLeave", function() |
GameTooltip:Hide() |
if changed then |
local parent = sliderFrame.parent |
local sliderFunc = parent.sliderFunc |
for i = 1, sliderFrame.level - 1 do |
Refresh(self, levels[i]) |
end |
local newParent |
for _,button in ipairs(levels[sliderFrame.level-1].buttons) do |
if button.sliderFunc == sliderFunc then |
newParent = button |
break |
end |
end |
if newParent then |
OpenSlider(self, newParent) |
else |
sliderFrame:Hide() |
end |
end |
end) |
editBox:SetScript("OnEnter", onEnter) |
editBox:SetScript("OnLeave", onLeave) |
slider:SetScript("OnMouseDown", function() |
sliderFrame.mouseDown = true |
GameTooltip:Hide() |
end) |
slider:SetScript("OnMouseUp", function() |
sliderFrame.mouseDown = false |
if changed--[[ and not inside]] then |
local parent = sliderFrame.parent |
local sliderFunc = parent.sliderFunc |
for i = 1, sliderFrame.level - 1 do |
Refresh(self, levels[i]) |
end |
local newParent |
for _,button in ipairs(levels[sliderFrame.level-1].buttons) do |
if button.sliderFunc == sliderFunc then |
newParent = button |
break |
end |
end |
if newParent then |
OpenSlider(self, newParent) |
else |
sliderFrame:Hide() |
end |
end |
if inside then |
showGameTooltip(sliderFrame.parent) |
end |
end) |
slider:SetScript("OnEnter", function() |
inside = true |
StopCounting(self, sliderFrame.level) |
showGameTooltip(sliderFrame.parent) |
end) |
slider:SetScript("OnLeave", function() |
inside = false |
GameTooltip:Hide() |
if changed and not sliderFrame.mouseDown then |
local parent = sliderFrame.parent |
local sliderFunc = parent.sliderFunc |
for i = 1, sliderFrame.level - 1 do |
Refresh(self, levels[i]) |
end |
local newParent |
for _,button in ipairs(levels[sliderFrame.level-1].buttons) do |
if button.sliderFunc == sliderFunc then |
newParent = button |
break |
end |
end |
if newParent then |
OpenSlider(self, newParent) |
else |
sliderFrame:Hide() |
end |
changed = false |
end |
end) |
sliderFrame:SetScript("OnMouseWheel", function(t, a1) |
local arg1 = a1 or arg1 |
local up = arg1 > 0 |
local min = sliderFrame.parent.sliderMin or 0 |
local max = sliderFrame.parent.sliderMax or 1 |
local step = sliderFrame.parent.sliderStep or (max - min) / 100 |
if step <= 0 then |
step = (max - min) / 100 |
end |
local value = (1 - slider:GetValue()) * (max - min) + min |
if up then |
value = value + step |
else |
value = value - step |
end |
if value > max then |
value = max |
elseif value < min then |
value = min |
end |
sliderFrame.fineStep = true |
if max<=min then |
slider:SetValue(0) |
else |
slider:SetValue(1 - (value - min) / (max - min)) |
end |
sliderFrame.fineStep = nil |
end) |
slider:SetScript("OnMouseWheel", sliderFrame:GetScript("OnMouseWheel")) |
editBox:SetScript("OnEnterPressed", function(t, a1) |
local value = editBox:GetNumber() |
if sliderFrame.parent.sliderIsPercent then |
value = value / 100 |
end |
local min = sliderFrame.parent.sliderMin or 0 |
local max = sliderFrame.parent.sliderMax or 1 |
if value > max then |
value = max |
elseif value < min then |
value = min |
end |
sliderFrame.fineStep = true |
if max <= min then |
slider:SetValue(0) |
else |
slider:SetValue(1 - (value - min) / (max - min)) |
end |
sliderFrame.fineStep = nil |
StartCounting(self, sliderFrame.level) |
end) |
editBox:SetScript("OnEscapePressed", function() |
self:Close(sliderFrame.level) |
StartCounting(self, sliderFrame.level) |
end) |
editBox:SetAutoFocus(false) |
end |
sliderFrame.parent = parent |
sliderFrame.level = parent.level.num + 1 |
sliderFrame.parentValue = parent.level.value |
sliderFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) |
sliderFrame.slider:SetFrameLevel(sliderFrame:GetFrameLevel() + 1) |
sliderFrame.currentText:SetFrameLevel(sliderFrame:GetFrameLevel() + 1) |
sliderFrame.currentText:ClearFocus() |
sliderFrame.changing = true |
if not parent.sliderMin or not parent.sliderMax then |
return |
end |
if parent.arrow then |
-- parent.arrow:SetVertexColor(0.2, 0.6, 0) |
-- parent.arrow:SetHeight(24) |
-- parent.arrow:SetWidth(24) |
parent.selected = true |
parent.highlight:Show() |
end |
sliderFrame:SetClampedToScreen(false) |
if not parent.sliderValue then |
parent.sliderValue = (parent.sliderMin + parent.sliderMax) / 2 |
end |
if parent.sliderMax <= parent.sliderMin then |
sliderFrame.slider:SetValue(0) |
else |
sliderFrame.slider:SetValue(1 - (parent.sliderValue - parent.sliderMin) / (parent.sliderMax - parent.sliderMin)) |
end |
sliderFrame.changing = false |
sliderFrame.bottomText:SetText(parent.sliderMinText or "0") |
sliderFrame.topText:SetText(parent.sliderMaxText or "1") |
local text |
if parent.sliderFunc and not parent.fromAceOptions then |
text = parent.sliderFunc(getArgs(parent, 'sliderArg', 1, parent.sliderValue)) |
end |
if type(text) == "number" or type(text) == "string" then |
sliderFrame.currentText:SetText(text) |
elseif parent.sliderIsPercent then |
sliderFrame.currentText:SetText(string.format("%.0f%%", parent.sliderValue * 100)) |
else |
if parent.sliderStep < 0.1 then |
sliderFrame.currentText:SetText(string.format("%.2f", parent.sliderValue)) |
elseif parent.sliderStep < 1 then |
sliderFrame.currentText:SetText(string.format("%.1f", parent.sliderValue)) |
else |
sliderFrame.currentText:SetText(string.format("%.0f", parent.sliderValue)) |
end |
end |
sliderFrame.lastValue = parent.sliderValue |
local level = parent.level |
sliderFrame:Show() |
sliderFrame:ClearAllPoints() |
if level.lastDirection == "RIGHT" then |
if level.lastVDirection == "DOWN" then |
sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) |
else |
sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) |
end |
else |
if level.lastVDirection == "DOWN" then |
sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) |
else |
sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) |
end |
end |
local dirty |
if level.lastDirection == "RIGHT" then |
if sliderFrame:GetRight() > GetScreenWidth() then |
level.lastDirection = "LEFT" |
dirty = true |
end |
elseif sliderFrame:GetLeft() < 0 then |
level.lastDirection = "RIGHT" |
dirty = true |
end |
if level.lastVDirection == "DOWN" then |
if sliderFrame:GetBottom() < 0 then |
level.lastVDirection = "UP" |
dirty = true |
end |
elseif sliderFrame:GetTop() > GetScreenWidth() then |
level.lastVDirection = "DOWN" |
dirty = true |
end |
if dirty then |
sliderFrame:ClearAllPoints() |
if level.lastDirection == "RIGHT" then |
if level.lastVDirection == "DOWN" then |
sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) |
else |
sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) |
end |
else |
if level.lastVDirection == "DOWN" then |
sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) |
else |
sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) |
end |
end |
end |
local left, bottom = sliderFrame:GetLeft(), sliderFrame:GetBottom() |
sliderFrame:ClearAllPoints() |
sliderFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) |
if mod(level.num, 5) == 0 then |
local left, bottom = level:GetLeft(), level:GetBottom() |
level:ClearAllPoints() |
level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) |
end |
sliderFrame:SetClampedToScreen(true) |
end |
function OpenEditBox(self, parent) |
if not editBoxFrame then |
editBoxFrame = CreateFrame("Frame", nil, nil) |
editBoxFrame:SetWidth(200) |
editBoxFrame:SetHeight(40) |
editBoxFrame:SetScale(UIParent:GetScale()) |
editBoxFrame:SetBackdrop(tmp( |
'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", |
'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", |
'tile', true, |
'insets', tmp2( |
'left', 5, |
'right', 5, |
'top', 5, |
'bottom', 5 |
), |
'tileSize', 16, |
'edgeSize', 16 |
)) |
editBoxFrame:SetFrameStrata("FULLSCREEN_DIALOG") |
if editBoxFrame.SetTopLevel then |
editBoxFrame:SetTopLevel(true) |
end |
editBoxFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) |
editBoxFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) |
editBoxFrame:EnableMouse(true) |
editBoxFrame:EnableMouseWheel(true) |
editBoxFrame:Hide() |
editBoxFrame:SetPoint("CENTER", UIParent, "CENTER") |
local editBox = CreateFrame("EditBox", nil, editBoxFrame) |
editBoxFrame.editBox = editBox |
editBox:SetFontObject(ChatFontNormal) |
editBox:SetWidth(160) |
editBox:SetHeight(13) |
editBox:SetPoint("CENTER", editBoxFrame, "CENTER", 0, 0) |
local left = editBox:CreateTexture(nil, "BACKGROUND") |
left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left") |
left:SetTexCoord(0, 100 / 256, 0, 1) |
left:SetWidth(100) |
left:SetHeight(32) |
left:SetPoint("LEFT", editBox, "LEFT", -10, 0) |
local right = editBox:CreateTexture(nil, "BACKGROUND") |
right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right") |
right:SetTexCoord(156/256, 1, 0, 1) |
right:SetWidth(100) |
right:SetHeight(32) |
right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0) |
editBox:SetScript("OnEnterPressed", function() |
if editBoxFrame.parent and editBoxFrame.parent.editBoxValidateFunc then |
local t = editBox.realText or editBox:GetText() or "" |
local result = editBoxFrame.parent.editBoxValidateFunc(getArgs(editBoxFrame.parent, 'editBoxValidateArg', 1, t)) |
if not result then |
UIErrorsFrame:AddMessage(VALIDATION_ERROR, 1, 0, 0) |
return |
end |
end |
if editBoxFrame.parent and editBoxFrame.parent.editBoxFunc then |
local t |
if editBox.realText ~= "NONE" then |
t = editBox.realText or editBox:GetText() or "" |
end |
editBoxFrame.parent.editBoxFunc(getArgs(editBoxFrame.parent, 'editBoxArg', 1, t)) |
end |
self:Close(editBoxFrame.level) |
for i = 1, editBoxFrame.level - 1 do |
Refresh(self, levels[i]) |
end |
StartCounting(self, editBoxFrame.level-1) |
end) |
editBox:SetScript("OnEscapePressed", function() |
self:Close(editBoxFrame.level) |
StartCounting(self, editBoxFrame.level-1) |
end) |
editBox:SetScript("OnReceiveDrag", function(this) |
if GetCursorInfo then |
local type, alpha, bravo = GetCursorInfo() |
local text |
if type == "spell" then |
text = GetSpellName(alpha, bravo) |
elseif type == "item" then |
text = bravo |
end |
if not text then |
return |
end |
ClearCursor() |
editBox:SetText(text) |
end |
end) |
local changing = false |
local skipNext = false |
function editBox:SpecialSetText(text) |
local oldText = editBox:GetText() or "" |
if not text then |
text = "" |
end |
if text ~= oldText then |
changing = true |
self:SetText(tostring(text)) |
changing = false |
skipNext = true |
end |
end |
editBox:SetScript("OnTextChanged", function() |
if skipNext then |
skipNext = false |
elseif not changing and editBoxFrame.parent and editBoxFrame.parent.editBoxChangeFunc then |
local t |
if editBox.realText ~= "NONE" then |
t = editBox.realText or editBox:GetText() or "" |
end |
local text = editBoxFrame.parent.editBoxChangeFunc(getArgs(editBoxFrame.parent, 'editBoxChangeArg', 1, t)) |
if text then |
editBox:SpecialSetText(text) |
end |
end |
end) |
editBoxFrame:SetScript("OnEnter", function() |
StopCounting(self, editBoxFrame.level) |
showGameTooltip(editBoxFrame.parent) |
end) |
editBoxFrame:SetScript("OnLeave", function() |
GameTooltip:Hide() |
end) |
editBox:SetScript("OnEnter", function() |
StopCounting(self, editBoxFrame.level) |
showGameTooltip(editBoxFrame.parent) |
end) |
editBox:SetScript("OnLeave", function() |
GameTooltip:Hide() |
end) |
editBoxFrame:SetScript("OnKeyDown", function(this, a1) |
if not editBox.keybinding then |
return |
end |
local arg1 = a1 or arg1 |
local screenshotKey = GetBindingKey("SCREENSHOT") |
if screenshotKey and arg1 == screenshotKey then |
Screenshot() |
return |
end |
if arg1 == "LeftButton" then |
arg1 = "BUTTON1" |
elseif arg1 == "RightButton" then |
arg1 = "BUTTON2" |
elseif arg1 == "MiddleButton" then |
arg1 = "BUTTON3" |
elseif arg1 == "Button4" then |
arg1 = "BUTTON4" |
elseif arg1 == "Button5" then |
arg1 = "BUTTON5" |
end |
if arg1 == "UNKNOWN" then |
return |
elseif arg1 == "SHIFT" or arg1 == "CTRL" or arg1 == "ALT" then |
return |
elseif arg1 == "ENTER" then |
if editBox.keybindingOnly and not editBox.keybindingOnly[editBox.realText] then |
return editBox:GetScript("OnEscapePressed")() |
elseif editBox.keybindingExcept and editBox.keybindingExcept[editBox.realText] then |
return editBox:GetScript("OnEscapePressed")() |
else |
return editBox:GetScript("OnEnterPressed")() |
end |
elseif arg1 == "ESCAPE" then |
if editBox.realText == "NONE" then |
return editBox:GetScript("OnEscapePressed")() |
else |
editBox:SpecialSetText(NONE or "NONE") |
editBox.realText = "NONE" |
return |
end |
elseif editBox.keybindingOnly and not editBox.keybindingOnly[arg1] then |
return |
elseif editBox.keybindingExcept and editBox.keybindingExcept[arg1] then |
return |
end |
local s = GetBindingText(arg1, "KEY_") |
if s == "BUTTON1" then |
s = KEY_BUTTON1 |
elseif s == "BUTTON2" then |
s = KEY_BUTTON2 |
end |
local real = arg1 |
if IsShiftKeyDown() then |
s = "Shift-" .. s |
real = "SHIFT-" .. real |
end |
if IsControlKeyDown() then |
s = "Ctrl-" .. s |
real = "CTRL-" .. real |
end |
if IsAltKeyDown() then |
s = "Alt-" .. s |
real = "ALT-" .. real |
end |
if editBox:GetText() ~= s then |
editBox:SpecialSetText("-") |
editBox:SpecialSetText(s) |
editBox.realText = real |
return editBox:GetScript("OnTextChanged")() |
end |
end) |
editBoxFrame:SetScript("OnMouseDown", editBoxFrame:GetScript("OnKeyDown")) |
editBox:SetScript("OnMouseDown", function(this, ...) |
if GetCursorInfo and (CursorHasItem() or CursorHasSpell()) then |
return editBox:GetScript("OnReceiveDrag")(this, ...) |
end |
return editBoxFrame:GetScript("OnKeyDown")(this, ...) |
end) |
editBoxFrame:SetScript("OnMouseWheel", function(t, a1) |
local arg1 = a1 or arg1 |
local up = arg1 > 0 |
arg1 = up and "MOUSEWHEELUP" or "MOUSEWHEELDOWN" |
return editBoxFrame:GetScript("OnKeyDown")(t or this, arg1) |
end) |
editBox:SetScript("OnMouseWheel", editBoxFrame:GetScript("OnMouseWheel")) |
end |
editBoxFrame.parent = parent |
editBoxFrame.level = parent.level.num + 1 |
editBoxFrame.parentValue = parent.level.value |
editBoxFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) |
editBoxFrame.editBox:SetFrameLevel(editBoxFrame:GetFrameLevel() + 1) |
editBoxFrame.editBox.realText = nil |
editBoxFrame:SetClampedToScreen(false) |
editBoxFrame.editBox:SpecialSetText("") |
if parent.editBoxIsKeybinding then |
local s = parent.editBoxText |
if s == "" then |
s = "NONE" |
end |
editBoxFrame.editBox.realText = s |
if s and s ~= "NONE" then |
local alpha,bravo = s:match("^(.+)%-(.+)$") |
if not bravo then |
alpha = nil |
bravo = s |
end |
bravo = GetBindingText(bravo, "KEY_") |
if alpha then |
editBoxFrame.editBox:SpecialSetText(alpha:upper() .. "-" .. bravo) |
else |
editBoxFrame.editBox:SpecialSetText(bravo) |
end |
else |
editBoxFrame.editBox:SpecialSetText(NONE or "NONE") |
end |
else |
editBoxFrame.editBox:SpecialSetText(parent.editBoxText) |
end |
editBoxFrame.editBox.keybinding = parent.editBoxIsKeybinding |
editBoxFrame.editBox.keybindingOnly = parent.editBoxKeybindingOnly |
editBoxFrame.editBox.keybindingExcept = parent.editBoxKeybindingExcept |
editBoxFrame.editBox:EnableKeyboard(not parent.editBoxIsKeybinding) |
editBoxFrame:EnableKeyboard(parent.editBoxIsKeybinding) |
if parent.arrow then |
-- parent.arrow:SetVertexColor(0.2, 0.6, 0) |
-- parent.arrow:SetHeight(24) |
-- parent.arrow:SetWidth(24) |
parent.selected = true |
parent.highlight:Show() |
end |
local level = parent.level |
editBoxFrame:Show() |
editBoxFrame:ClearAllPoints() |
if level.lastDirection == "RIGHT" then |
if level.lastVDirection == "DOWN" then |
editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) |
else |
editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) |
end |
else |
if level.lastVDirection == "DOWN" then |
editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) |
else |
editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) |
end |
end |
local dirty |
if level.lastDirection == "RIGHT" then |
if editBoxFrame:GetRight() > GetScreenWidth() then |
level.lastDirection = "LEFT" |
dirty = true |
end |
elseif editBoxFrame:GetLeft() < 0 then |
level.lastDirection = "RIGHT" |
dirty = true |
end |
if level.lastVDirection == "DOWN" then |
if editBoxFrame:GetBottom() < 0 then |
level.lastVDirection = "UP" |
dirty = true |
end |
elseif editBoxFrame:GetTop() > GetScreenWidth() then |
level.lastVDirection = "DOWN" |
dirty = true |
end |
if dirty then |
editBoxFrame:ClearAllPoints() |
if level.lastDirection == "RIGHT" then |
if level.lastVDirection == "DOWN" then |
editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) |
else |
editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) |
end |
else |
if level.lastVDirection == "DOWN" then |
editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) |
else |
editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) |
end |
end |
end |
local left, bottom = editBoxFrame:GetLeft(), editBoxFrame:GetBottom() |
editBoxFrame:ClearAllPoints() |
editBoxFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) |
if mod(level.num, 5) == 0 then |
local left, bottom = level:GetLeft(), level:GetBottom() |
level:ClearAllPoints() |
level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) |
end |
editBoxFrame:SetClampedToScreen(true) |
end |
function Dewdrop:EncodeKeybinding(text) |
if text == nil or text == "NONE" then |
return nil |
end |
text = tostring(text):upper() |
local shift, ctrl, alt |
local modifier |
while true do |
if text == "-" then |
break |
end |
modifier, text = strsplit('-', text, 2) |
if text then |
if modifier ~= "SHIFT" and modifier ~= "CTRL" and modifier ~= "ALT" then |
return false |
end |
if modifier == "SHIFT" then |
if shift then |
return false |
end |
shift = true |
end |
if modifier == "CTRL" then |
if ctrl then |
return false |
end |
ctrl = true |
end |
if modifier == "ALT" then |
if alt then |
return false |
end |
alt = true |
end |
else |
text = modifier |
break |
end |
end |
if not text:find("^F%d+$") and text ~= "CAPSLOCK" and text:len() ~= 1 and (text:len() == 0 or text:byte() < 128 or text:len() > 4) and not _G["KEY_" .. text] and text ~= "BUTTON1" and text ~= "BUTTON2" then |
return false |
end |
local s = GetBindingText(text, "KEY_") |
if s == "BUTTON1" then |
s = KEY_BUTTON1 |
elseif s == "BUTTON2" then |
s = KEY_BUTTON2 |
end |
if shift then |
s = "Shift-" .. s |
end |
if ctrl then |
s = "Ctrl-" .. s |
end |
if alt then |
s = "Alt-" .. s |
end |
return s |
end |
function Dewdrop:IsOpen(parent) |
self:argCheck(parent, 2, "table", "string", "nil") |
return levels[1] and levels[1]:IsShown() and (not parent or parent == levels[1].parent or parent == levels[1]:GetParent()) |
end |
function Dewdrop:GetOpenedParent() |
return (levels[1] and levels[1]:IsShown()) and (levels[1].parent or levels[1]:GetParent()) |
end |
function Open(self, parent, func, level, value, point, relativePoint, cursorX, cursorY) |
self:Close(level) |
if DewdropLib then |
local d = DewdropLib:GetInstance('1.0') |
local ret, val = pcall(d, IsOpen, d) |
if ret and val then |
DewdropLib:GetInstance('1.0'):Close() |
end |
end |
if type(parent) == "table" then |
parent:GetCenter() |
end |
local frame = AcquireLevel(self, level) |
if level == 1 then |
frame.lastDirection = "RIGHT" |
frame.lastVDirection = "DOWN" |
else |
frame.lastDirection = levels[level - 1].lastDirection |
frame.lastVDirection = levels[level - 1].lastVDirection |
end |
frame:SetFrameStrata("FULLSCREEN_DIALOG") |
frame:ClearAllPoints() |
frame.parent = parent |
frame:SetPoint("LEFT", UIParent, "RIGHT", 10000, 0) |
frame:Show() |
if level == 1 then |
baseFunc = func |
end |
levels[level].value = value |
-- levels[level].parentText = parent.text and parent.text:GetText() or nil |
-- levels[level].parentTooltipTitle = parent.tooltipTitle |
-- levels[level].parentTooltipText = parent.tooltipText |
-- levels[level].parentTooltipFunc = parent.tooltipFunc |
if type(parent) == "table" and parent.arrow then |
-- parent.arrow:SetVertexColor(0.2, 0.6, 0) |
-- parent.arrow:SetHeight(24) |
-- parent.arrow:SetWidth(24) |
parent.selected = true |
parent.highlight:Show() |
end |
relativePoint = relativePoint or point |
Refresh(self, levels[level]) |
if point or (cursorX and cursorY) then |
frame:ClearAllPoints() |
if cursorX and cursorY then |
local curX, curY = GetScaledCursorPosition() |
if curY < GetScreenHeight() / 2 then |
point, relativePoint = "BOTTOM", "BOTTOM" |
else |
point, relativePoint = "TOP", "TOP" |
end |
if curX < GetScreenWidth() / 2 then |
point, relativePoint = point .. "LEFT", relativePoint .. "RIGHT" |
else |
point, relativePoint = point .. "RIGHT", relativePoint .. "LEFT" |
end |
end |
frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint) |
if cursorX and cursorY then |
local left = frame:GetLeft() |
local width = frame:GetWidth() |
local bottom = frame:GetBottom() |
local height = frame:GetHeight() |
local curX, curY = GetScaledCursorPosition() |
frame:ClearAllPoints() |
relativePoint = relativePoint or point |
if point == "BOTTOM" or point == "TOP" then |
if curX < GetScreenWidth() / 2 then |
point = point .. "LEFT" |
else |
point = point .. "RIGHT" |
end |
elseif point == "CENTER" then |
if curX < GetScreenWidth() / 2 then |
point = "LEFT" |
else |
point = "RIGHT" |
end |
end |
local xOffset, yOffset = 0, 0 |
if curY > GetScreenHeight() / 2 then |
yOffset = -height |
end |
if curX > GetScreenWidth() / 2 then |
xOffset = -width |
end |
frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint, curX - left + xOffset, curY - bottom + yOffset) |
if level == 1 then |
frame.lastDirection = "RIGHT" |
end |
elseif cursorX then |
local left = frame:GetLeft() |
local width = frame:GetWidth() |
local curX, curY = GetScaledCursorPosition() |
frame:ClearAllPoints() |
relativePoint = relativePoint or point |
if point == "BOTTOM" or point == "TOP" then |
if curX < GetScreenWidth() / 2 then |
point = point .. "LEFT" |
else |
point = point .. "RIGHT" |
end |
elseif point == "CENTER" then |
if curX < GetScreenWidth() / 2 then |
point = "LEFT" |
else |
point = "RIGHT" |
end |
end |
frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint, curX - left - width / 2, 0) |
if level == 1 then |
frame.lastDirection = "RIGHT" |
end |
elseif cursorY then |
local bottom = frame:GetBottom() |
local height = frame:GetHeight() |
local curX, curY = GetScaledCursorPosition() |
frame:ClearAllPoints() |
relativePoint = relativePoint or point |
if point == "LEFT" or point == "RIGHT" then |
if curX < GetScreenHeight() / 2 then |
point = point .. "BOTTOM" |
else |
point = point .. "TOP" |
end |
elseif point == "CENTER" then |
if curX < GetScreenHeight() / 2 then |
point = "BOTTOM" |
else |
point = "TOP" |
end |
end |
frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint, 0, curY - bottom - height / 2) |
if level == 1 then |
frame.lastDirection = "DOWN" |
end |
end |
if (strsub(point, 1, 3) ~= strsub(relativePoint, 1, 3)) then |
if frame:GetBottom() < 0 then |
local point, parent, relativePoint, x, y = frame:GetPoint(1) |
local change = GetScreenHeight() - frame:GetTop() |
local otherChange = -frame:GetBottom() |
if otherChange < change then |
change = otherChange |
end |
frame:SetPoint(point, parent, relativePoint, x, y + change) |
elseif frame:GetTop() > GetScreenHeight() then |
local point, parent, relativePoint, x, y = frame:GetPoint(1) |
local change = GetScreenHeight() - frame:GetTop() |
local otherChange = -frame:GetBottom() |
if otherChange < change then |
change = otherChange |
end |
frame:SetPoint(point, parent, relativePoint, x, y + change) |
end |
end |
end |
CheckDualMonitor(self, frame) |
frame:SetClampedToScreen(true) |
frame:SetClampedToScreen(false) |
StartCounting(self, level) |
end |
function Dewdrop:IsRegistered(parent) |
self:argCheck(parent, 2, "table", "string") |
return not not self.registry[parent] |
end |
function Dewdrop:Register(parent, ...) |
self:argCheck(parent, 2, "table", "string") |
if self.registry[parent] then |
self:Unregister(parent) |
end |
local info = new(...) |
if type(info.children) == "table" then |
local err, position = validateOptions(info.children) |
if err then |
if position then |
Dewdrop:error(position .. ": " .. err) |
else |
Dewdrop:error(err) |
end |
end |
end |
self.registry[parent] = info |
if not info.dontHook and not self.onceRegistered[parent] and type(parent) == "table" then |
if parent:HasScript("OnMouseUp") then |
local script = parent:GetScript("OnMouseUp") |
parent:SetScript("OnMouseUp", function(this, ...) |
if script then |
script(this, ...) |
end |
if arg1 == "RightButton" and self.registry[parent] then |
if self:IsOpen(parent) then |
self:Close() |
else |
self:Open(parent) |
end |
end |
end) |
end |
if parent:HasScript("OnMouseDown") then |
local script = parent:GetScript("OnMouseDown") |
parent:SetScript("OnMouseDown", function(this, ...) |
if script then |
script(this, ...) |
end |
if self.registry[parent] then |
self:Close() |
end |
end) |
end |
end |
self.onceRegistered[parent] = true |
end |
function Dewdrop:Unregister(parent) |
self:argCheck(parent, 2, "table", "string") |
self.registry[parent] = nil |
end |
function Dewdrop:Open(parent, ...) |
self:argCheck(parent, 2, "table", "string") |
local info |
local k1 = ... |
if type(k1) == "table" and k1[0] and k1.IsFrameType and self.registry[k1] then |
info = tmp(select(2, ...)) |
for k,v in pairs(self.registry[k1]) do |
if info[k] == nil then |
info[k] = v |
end |
end |
else |
info = tmp(...) |
if self.registry[parent] then |
for k,v in pairs(self.registry[parent]) do |
if info[k] == nil then |
info[k] = v |
end |
end |
end |
end |
local point = info.point |
local relativePoint = info.relativePoint |
local cursorX = info.cursorX |
local cursorY = info.cursorY |
if type(point) == "function" then |
local b |
point, b = point(parent) |
if b then |
relativePoint = b |
end |
end |
if type(relativePoint) == "function" then |
relativePoint = relativePoint(parent) |
end |
Open(self, parent, info.children, 1, nil, point, relativePoint, cursorX, cursorY) |
end |
function Clear(self, level) |
if level then |
if level.buttons then |
for i = #level.buttons, 1, -1 do |
ReleaseButton(self, level, i) |
end |
end |
end |
end |
function Dewdrop:Close(level) |
if DropDownList1:IsShown() then |
DropDownList1:Hide() |
end |
if DewdropLib then |
local d = DewdropLib:GetInstance('1.0') |
local ret, val = pcall(d, IsOpen, d) |
if ret and val then |
DewdropLib:GetInstance('1.0'):Close() |
end |
end |
self:argCheck(level, 2, "number", "nil") |
if not level then |
level = 1 |
end |
if level == 1 and levels[level] then |
levels[level].parented = false |
end |
if level > 1 and levels[level-1].buttons then |
local buttons = levels[level-1].buttons |
for _,button in ipairs(buttons) do |
-- button.arrow:SetWidth(16) |
-- button.arrow:SetHeight(16) |
button.selected = nil |
button.highlight:Hide() |
-- button.arrow:SetVertexColor(1, 1, 1) |
end |
end |
if sliderFrame and sliderFrame.level >= level then |
sliderFrame:Hide() |
end |
if editBoxFrame and editBoxFrame.level >= level then |
editBoxFrame:Hide() |
end |
for i = level, #levels do |
Clear(self, levels[level]) |
levels[i]:Hide() |
levels[i]:ClearAllPoints() |
levels[i]:SetPoint("CENTER", UIParent, "CENTER") |
levels[i].value = nil |
end |
end |
function Dewdrop:AddSeparator(level) |
level = levels[level or currentLevel] |
if not level or not level.buttons then return; end |
local prevbutton = level.buttons[#level.buttons] |
if not prevbutton then return; end |
if prevbutton.disabled and prevbutton.text:GetText() == "" then |
return |
end |
self:AddLine("text", "", "disabled", true) |
end |
function Dewdrop:AddLine(...) |
local info = tmp(...) |
local level = info.level or currentLevel |
info.level = nil |
local button = AcquireButton(self, level) |
if not next(info) then |
info.disabled = true |
end |
button.disabled = info.isTitle or info.notClickable or info.disabled or (self.combat and info.secure) |
button.isTitle = info.isTitle |
button.notClickable = info.notClickable |
if button.isTitle then |
button.text:SetFontObject(GameFontNormalSmall) |
elseif button.notClickable then |
button.text:SetFontObject(GameFontHighlightSmall) |
elseif button.disabled then |
button.text:SetFontObject(GameFontDisableSmall) |
else |
button.text:SetFontObject(GameFontHighlightSmall) |
end |
if info.disabled then |
button.arrow:SetDesaturated(true) |
button.check:SetDesaturated(true) |
else |
button.arrow:SetDesaturated(false) |
button.check:SetDesaturated(false) |
end |
if info.textR and info.textG and info.textB then |
button.textR = info.textR |
button.textG = info.textG |
button.textB = info.textB |
button.text:SetTextColor(button.textR, button.textG, button.textB) |
else |
button.text:SetTextColor(button.text:GetFontObject():GetTextColor()) |
end |
button.notCheckable = info.notCheckable |
button.text:SetPoint("LEFT", button, "LEFT", button.notCheckable and 0 or 24, 0) |
button.checked = not info.notCheckable and info.checked |
button.mouseoverUnderline = info.mouseoverUnderline |
button.isRadio = not info.notCheckable and info.isRadio |
if info.isRadio then |
button.check:Show() |
button.check:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") |
if button.checked then |
button.check:SetTexCoord(0.25, 0.5, 0, 1) |
button.check:SetVertexColor(1, 1, 1, 1) |
else |
button.check:SetTexCoord(0, 0.25, 0, 1) |
button.check:SetVertexColor(1, 1, 1, 0.5) |
end |
button.radioHighlight:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") |
button.check:SetWidth(16) |
button.check:SetHeight(16) |
elseif info.icon then |
button.check:Show() |
button.check:SetTexture(info.icon) |
if info.iconWidth and info.iconHeight then |
button.check:SetWidth(info.iconWidth) |
button.check:SetHeight(info.iconHeight) |
else |
button.check:SetWidth(16) |
button.check:SetHeight(16) |
end |
if info.iconCoordLeft and info.iconCoordRight and info.iconCoordTop and info.iconCoordBottom then |
button.check:SetTexCoord(info.iconCoordLeft, info.iconCoordRight, info.iconCoordTop, info.iconCoordBottom) |
elseif info.icon:find("^Interface\\Icons\\") then |
button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95) |
else |
button.check:SetTexCoord(0, 1, 0, 1) |
end |
button.check:SetVertexColor(1, 1, 1, 1) |
else |
if button.checked then |
if info.checkIcon then |
button.check:SetWidth(16) |
button.check:SetHeight(16) |
button.check:SetTexture(info.checkIcon) |
if info.checkIcon:find("^Interface\\Icons\\") then |
button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95) |
else |
button.check:SetTexCoord(0, 1, 0, 1) |
end |
else |
button.check:SetWidth(24) |
button.check:SetHeight(24) |
button.check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") |
button.check:SetTexCoord(0, 1, 0, 1) |
end |
button.check:SetVertexColor(1, 1, 1, 1) |
else |
button.check:SetVertexColor(1, 1, 1, 0) |
end |
end |
if not button.disabled then |
button.func = info.func |
button.secure = info.secure |
end |
button.hasColorSwatch = info.hasColorSwatch |
if button.hasColorSwatch then |
button.colorSwatch:Show() |
button.colorSwatch.texture:Show() |
button.r = info.r or 1 |
button.g = info.g or 1 |
button.b = info.b or 1 |
button.colorSwatch.texture:SetVertexColor(button.r, button.g, button.b) |
button.checked = false |
button.func = nil |
button.colorFunc = info.colorFunc |
local i = 1 |
while true do |
local k = "colorArg" .. i |
local x = info[k] |
if x == nil then |
break |
end |
button[k] = x |
i = i + 1 |
end |
button.hasOpacity = info.hasOpacity |
button.opacity = info.opacity or 1 |
else |
button.colorSwatch:Hide() |
button.colorSwatch.texture:Hide() |
end |
button.hasArrow = not button.hasColorSwatch and (info.value or info.hasSlider or info.hasEditBox) and info.hasArrow |
if button.hasArrow then |
button.arrow:SetAlpha(1) |
if info.hasSlider then |
button.hasSlider = true |
button.sliderMin = info.sliderMin or 0 |
button.sliderMax = info.sliderMax or 1 |
button.sliderStep = info.sliderStep or 0 |
button.sliderBigStep = info.sliderBigStep or button.sliderStep |
if button.sliderBigStep < button.sliderStep then |
button.sliderBigStep = button.sliderStep |
end |
button.sliderIsPercent = info.sliderIsPercent and true or false |
button.sliderMinText = info.sliderMinText or button.sliderIsPercent and string.format("%.0f%%", button.sliderMin * 100) or button.sliderMin |
button.sliderMaxText = info.sliderMaxText or button.sliderIsPercent and string.format("%.0f%%", button.sliderMax * 100) or button.sliderMax |
button.sliderFunc = info.sliderFunc |
button.sliderValue = info.sliderValue |
button.fromAceOptions = info.fromAceOptions |
local i = 1 |
while true do |
local k = "sliderArg" .. i |
local x = info[k] |
if x == nil then |
break |
end |
button[k] = x |
i = i + 1 |
end |
elseif info.hasEditBox then |
button.hasEditBox = true |
button.editBoxText = info.editBoxText or "" |
button.editBoxFunc = info.editBoxFunc |
local i = 1 |
while true do |
local k = "editBoxArg" .. i |
local x = info[k] |
if x == nil then |
break |
end |
button[k] = x |
i = i + 1 |
end |
button.editBoxChangeFunc = info.editBoxChangeFunc |
local i = 1 |
while true do |
local k = "editBoxChangeArg" .. i |
local x = info[k] |
if x == nil then |
break |
end |
button[k] = x |
i = i + 1 |
end |
button.editBoxValidateFunc = info.editBoxValidateFunc |
local i = 1 |
while true do |
local k = "editBoxValidateArg" .. i |
local x = info[k] |
if x == nil then |
break |
end |
button[k] = x |
i = i + 1 |
end |
button.editBoxIsKeybinding = info.editBoxIsKeybinding |
button.editBoxKeybindingOnly = info.editBoxKeybindingOnly |
button.editBoxKeybindingExcept = info.editBoxKeybindingExcept |
else |
button.value = info.value |
local l = levels[level+1] |
if l and info.value == l.value then |
-- button.arrow:SetWidth(24) |
-- button.arrow:SetHeight(24) |
button.selected = true |
button.highlight:Show() |
end |
end |
else |
button.arrow:SetAlpha(0) |
end |
local i = 1 |
while true do |
local k = "arg" .. i |
local x = info[k] |
if x == nil then |
break |
end |
button[k] = x |
i = i + 1 |
end |
button.closeWhenClicked = info.closeWhenClicked |
button.textHeight = info.textHeight or UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT or 10 |
local font,_ = button.text:GetFont() |
button.text:SetFont(STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", button.textHeight) |
button:SetHeight(button.textHeight + 6) |
button.text:SetPoint("RIGHT", button.arrow, (button.hasColorSwatch or button.hasArrow) and "LEFT" or "RIGHT") |
button.text:SetJustifyH(info.justifyH or "LEFT") |
button.text:SetText(info.text) |
button.tooltipTitle = info.tooltipTitle |
button.tooltipText = info.tooltipText |
button.tooltipFunc = info.tooltipFunc |
local i = 1 |
while true do |
local k = "tooltipArg" .. i |
local x = info[k] |
if x == nil then |
break |
end |
button[k] = x |
i = i + 1 |
end |
if not button.tooltipTitle and not button.tooltipText and not button.tooltipFunc and not info.isTitle then |
button.tooltipTitle = info.text |
end |
if type(button.func) == "string" then |
if type(button.arg1) ~= "table" then |
self:error("Cannot call method %q on a non-table", button.func) |
end |
if type(button.arg1[button.func]) ~= "function" then |
self:error("Method %q nonexistant.", button.func) |
end |
end |
end |
function Dewdrop:InjectAceOptionsTable(handler, options) |
self:argCheck(handler, 2, "table") |
self:argCheck(options, 3, "table") |
if tostring(options.type):lower() ~= "group" then |
self:error('Cannot inject into options table argument #3 if its type is not "group"') |
end |
if options.handler ~= nil and options.handler ~= handler then |
self:error("Cannot inject into options table argument #3 if it has a different handler than argument #2") |
end |
options.handler = handler |
local class = handler.class |
if not AceLibrary:HasInstance("AceOO-2.0") or not class then |
if Rock then |
-- possible Rock object |
for mixin in Rock:IterateObjectMixins(handler) do |
if type(mixin.GetAceOptionsDataTable) == "function" then |
local t = mixin:GetAceOptionsDataTable(handler) |
for k,v in pairs(t) do |
if type(options.args) ~= "table" then |
options.args = {} |
end |
if options.args[k] == nil then |
options.args[k] = v |
end |
end |
end |
end |
end |
else |
-- Ace2 object |
while class and class ~= AceLibrary("AceOO-2.0").Class do |
if type(class.GetAceOptionsDataTable) == "function" then |
local t = class:GetAceOptionsDataTable(handler) |
for k,v in pairs(t) do |
if type(options.args) ~= "table" then |
options.args = {} |
end |
if options.args[k] == nil then |
options.args[k] = v |
end |
end |
end |
local mixins = class.mixins |
if mixins then |
for mixin in pairs(mixins) do |
if type(mixin.GetAceOptionsDataTable) == "function" then |
local t = mixin:GetAceOptionsDataTable(handler) |
for k,v in pairs(t) do |
if type(options.args) ~= "table" then |
options.args = {} |
end |
if options.args[k] == nil then |
options.args[k] = v |
end |
end |
end |
end |
end |
class = class.super |
end |
end |
return options |
end |
function Dewdrop:OnTooltipHide() |
if lastSetFont then |
if lastSetFont == normalFont then |
lastSetFont = nil |
return |
end |
fillRegionTmp(GameTooltip:GetRegions()) |
for i,v in ipairs(regionTmp) do |
if v.GetFont then |
local font,size,outline = v:GetFont() |
if font == lastSetFont then |
v:SetFont(normalFont, size, outline) |
end |
end |
regionTmp[i] = nil |
end |
lastSetFont = nil |
end |
end |
local function activate(self, oldLib, oldDeactivate) |
Dewdrop = self |
if oldLib and oldLib.registry then |
self.registry = oldLib.registry |
self.onceRegistered = oldLib.onceRegistered |
else |
self.registry = {} |
self.onceRegistered = {} |
local WorldFrame_OnMouseDown = WorldFrame:GetScript("OnMouseDown") |
local WorldFrame_OnMouseUp = WorldFrame:GetScript("OnMouseUp") |
local oldX, oldY, clickTime |
WorldFrame:SetScript("OnMouseDown", function(this, ...) |
oldX,oldY = GetCursorPosition() |
clickTime = GetTime() |
if WorldFrame_OnMouseDown then |
WorldFrame_OnMouseDown(this, ...) |
end |
end) |
WorldFrame:SetScript("OnMouseUp", function(this, ...) |
local x,y = GetCursorPosition() |
if not oldX or not oldY or not x or not y or not clickTime then |
self:Close() |
if WorldFrame_OnMouseUp then |
WorldFrame_OnMouseUp(this, ...) |
end |
return |
end |
local d = math.abs(x - oldX) + math.abs(y - oldY) |
if d <= 5 and GetTime() - clickTime < 0.5 then |
self:Close() |
end |
if WorldFrame_OnMouseUp then |
WorldFrame_OnMouseUp(this, ...) |
end |
end) |
hooksecurefunc(DropDownList1, "Show", function() |
if levels[1] and levels[1]:IsVisible() then |
self:Close() |
end |
end) |
hooksecurefunc("HideDropDownMenu", function() |
if levels[1] and levels[1]:IsVisible() then |
self:Close() |
end |
end) |
hooksecurefunc("CloseDropDownMenus", function() |
if levels[1] and levels[1]:IsVisible() then |
local stack = debugstack() |
if not stack:find("`TargetFrame_OnHide'") then |
self:Close() |
end |
end |
end) |
end |
self.frame = oldLib and oldLib.frame or CreateFrame("Frame") |
self.frame:UnregisterAllEvents() |
self.frame:RegisterEvent("PLAYER_REGEN_ENABLED") |
self.frame:RegisterEvent("PLAYER_REGEN_DISABLED") |
self.frame:Hide() |
self.frame:SetScript("OnEvent", function(this, event) |
this:Show() |
if event=="PLAYER_REGEN_ENABLED" then -- track combat state for secure frame operations |
self.combat = false |
elseif event=="PLAYER_REGEN_DISABLED" then |
self.combat = true |
end |
end) |
self.frame:SetScript("OnUpdate", function(this) |
this:Hide() |
self:Refresh(1) |
end) |
self.hookedTooltip = true |
if not oldLib or not oldLib.hookedTooltip then |
local OnTooltipHide = GameTooltip:GetScript("OnHide") |
GameTooltip:SetScript("OnHide", function(this, ...) |
if OnTooltipHide then |
OnTooltipHide(this, ...) |
end |
if type(self.OnTooltipHide) == "function" then |
self:OnTooltipHide() |
end |
end) |
end |
levels = {} |
buttons = {} |
if oldDeactivate then |
oldDeactivate(oldLib) |
end |
end |
local function external(lib, major, instance) |
if major == "SharedMedia-1.0" then |
SharedMedia = instance |
end |
end |
AceLibrary:Register(Dewdrop, MAJOR_VERSION, MINOR_VERSION, activate, nil, external) |
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info |
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke |
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! |
local LibStub = _G[LIBSTUB_MAJOR] |
if not LibStub or LibStub.minor < LIBSTUB_MINOR then |
LibStub = LibStub or {libs = {}, minors = {} } |
_G[LIBSTUB_MAJOR] = LibStub |
LibStub.minor = LIBSTUB_MINOR |
function LibStub:NewLibrary(major, minor) |
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") |
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") |
local oldminor = self.minors[major] |
if oldminor and oldminor >= minor then return nil end |
self.minors[major], self.libs[major] = minor, self.libs[major] or {} |
return self.libs[major], oldminor |
end |
function LibStub:GetLibrary(major, silent) |
if not self.libs[major] and not silent then |
error(("Cannot find a library instance of %q."):format(tostring(major)), 2) |
end |
return self.libs[major], self.minors[major] |
end |
function LibStub:IterateLibraries() return pairs(self.libs) end |
setmetatable(LibStub, { __call = LibStub.GetLibrary }) |
end |
--[[ |
Name: LibBabble-Zone-3.0 |
Revision: $Rev$ |
Author(s): ckknight (ckknight@gmail.com) |
Website: http://ckknight.wowinterface.com/ |
Description: A library to provide localizations for zones. |
Dependencies: None |
License: MIT |
]] |
local MAJOR_VERSION = "LibBabble-Zone-3.0" |
local MINOR_VERSION = "$Revision$" |
-- #AUTODOC_NAMESPACE prototype |
local GAME_LOCALE = GetLocale() |
do |
-- LibBabble-Core-3.0 is hereby placed in the Public Domain |
-- Credits: ckknight |
local LIBBABBLE_MAJOR, LIBBABBLE_MINOR = "LibBabble-3.0", 2 |
local LibBabble = LibStub:NewLibrary(LIBBABBLE_MAJOR, LIBBABBLE_MINOR) |
if LibBabble then |
local data = LibBabble.data or {} |
for k,v in pairs(LibBabble) do |
LibBabble[k] = nil |
end |
LibBabble.data = data |
local tablesToDB = {} |
for namespace, db in pairs(data) do |
for k,v in pairs(db) do |
tablesToDB[v] = db |
end |
end |
local function warn(message) |
local _, ret = pcall(error, message, 3) |
geterrorhandler()(ret) |
end |
local lookup_mt = { __index = function(self, key) |
local db = tablesToDB[self] |
local current_key = db.current[key] |
if current_key then |
self[key] = current_key |
return current_key |
end |
local base_key = db.base[key] |
local real_MAJOR_VERSION |
for k,v in pairs(data) do |
if v == db then |
real_MAJOR_VERSION = k |
break |
end |
end |
if not real_MAJOR_VERSION then |
real_MAJOR_VERSION = LIBBABBLE_MAJOR |
end |
if base_key then |
warn(("%s: Translation %q not found for locale %q"):format(real_MAJOR_VERSION, key, GAME_LOCALE)) |
rawset(self, key, base_key) |
return base_key |
end |
warn(("%s: Translation %q not found."):format(real_MAJOR_VERSION, key)) |
rawset(self, key, key) |
return key |
end } |
local function initLookup(module, lookup) |
local db = tablesToDB[module] |
for k in pairs(lookup) do |
lookup[k] = nil |
end |
setmetatable(lookup, lookup_mt) |
tablesToDB[lookup] = db |
db.lookup = lookup |
return lookup |
end |
local function initReverse(module, reverse) |
local db = tablesToDB[module] |
for k in pairs(reverse) do |
reverse[k] = nil |
end |
for k,v in pairs(db.current) do |
reverse[v] = k |
end |
tablesToDB[reverse] = db |
db.reverse = reverse |
db.reverseIterators = nil |
return reverse |
end |
local prototype = {} |
local prototype_mt = {__index = prototype} |
--[[--------------------------------------------------------------------------- |
Notes: |
* If you try to access a nonexistent key, it will warn but allow the code to pass through. |
Returns: |
A lookup table for english to localized words. |
Example: |
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want. |
local BL = B:GetLookupTable() |
assert(BL["Some english word"] == "Some localized word") |
DoSomething(BL["Some english word that doesn't exist"]) -- warning! |
-----------------------------------------------------------------------------]] |
function prototype:GetLookupTable() |
local db = tablesToDB[self] |
local lookup = db.lookup |
if lookup then |
return lookup |
end |
return initLookup(self, {}) |
end |
--[[--------------------------------------------------------------------------- |
Notes: |
* If you try to access a nonexistent key, it will return nil. |
Returns: |
A lookup table for english to localized words. |
Example: |
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want. |
local B_has = B:GetUnstrictLookupTable() |
assert(B_has["Some english word"] == "Some localized word") |
assert(B_has["Some english word that doesn't exist"] == nil) |
-----------------------------------------------------------------------------]] |
function prototype:GetUnstrictLookupTable() |
local db = tablesToDB[self] |
return db.current |
end |
--[[--------------------------------------------------------------------------- |
Notes: |
* If you try to access a nonexistent key, it will return nil. |
* This is useful for checking if the base (English) table has a key, even if the localized one does not have it registered. |
Returns: |
A lookup table for english to localized words. |
Example: |
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want. |
local B_hasBase = B:GetBaseLookupTable() |
assert(B_hasBase["Some english word"] == "Some english word") |
assert(B_hasBase["Some english word that doesn't exist"] == nil) |
-----------------------------------------------------------------------------]] |
function prototype:GetBaseLookupTable() |
local db = tablesToDB[self] |
return db.base |
end |
--[[--------------------------------------------------------------------------- |
Notes: |
* If you try to access a nonexistent key, it will return nil. |
* This will return only one English word that it maps to, if there are more than one to check, see :GetReverseIterator("word") |
Returns: |
A lookup table for localized to english words. |
Example: |
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want. |
local BR = B:GetReverseLookupTable() |
assert(BR["Some localized word"] == "Some english word") |
assert(BR["Some localized word that doesn't exist"] == nil) |
-----------------------------------------------------------------------------]] |
function prototype:GetReverseLookupTable() |
local db = tablesToDB[self] |
local reverse = db.reverse |
if reverse then |
return reverse |
end |
return initReverse(self, {}) |
end |
local blank = {} |
local weakVal = {__mode='v'} |
--[[--------------------------------------------------------------------------- |
Arguments: |
string - the localized word to chek for. |
Returns: |
An iterator to traverse all English words that map to the given key |
Example: |
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want. |
for word in B:GetReverseIterator("Some localized word") do |
DoSomething(word) |
end |
-----------------------------------------------------------------------------]] |
function prototype:GetReverseIterator(key) |
local db = tablesToDB[self] |
local reverseIterators = db.reverseIterators |
if not reverseIterators then |
reverseIterators = setmetatable({}, weakVal) |
db.reverseIterators = reverseIterators |
elseif reverseIterators[key] then |
return pairs(reverseIterators[key]) |
end |
local t |
for k,v in pairs(db.current) do |
if v == key then |
if not t then |
t = {} |
end |
t[k] = true |
end |
end |
reverseIterators[key] = t or blank |
return pairs(reverseIterators[key]) |
end |
--[[--------------------------------------------------------------------------- |
Returns: |
An iterator to traverse all translations English to localized. |
Example: |
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want. |
for english, localized in B:Iterate() do |
DoSomething(english, localized) |
end |
-----------------------------------------------------------------------------]] |
function prototype:Iterate() |
local db = tablesToDB[self] |
return pairs(db.current) |
end |
-- #NODOC |
-- modules need to call this to set the base table |
function prototype:SetBaseTranslations(base) |
local db = tablesToDB[self] |
local oldBase = db.base |
if oldBase then |
for k in pairs(oldBase) do |
oldBase[k] = nil |
end |
for k, v in pairs(base) do |
oldBase[k] = v |
end |
base = oldBase |
else |
db.base = base |
end |
for k,v in pairs(base) do |
if v == true then |
base[k] = k |
end |
end |
end |
local function init(module) |
local db = tablesToDB[module] |
if db.lookup then |
initLookup(module, db.lookup) |
end |
if db.reverse then |
initReverse(module, db.reverse) |
end |
db.reverseIterators = nil |
end |
-- #NODOC |
-- modules need to call this to set the current table. if current is true, use the base table. |
function prototype:SetCurrentTranslations(current) |
local db = tablesToDB[self] |
if current == true then |
db.current = db.base |
else |
local oldCurrent = db.current |
if oldCurrent then |
for k in pairs(oldCurrent) do |
oldCurrent[k] = nil |
end |
for k, v in pairs(current) do |
oldCurrent[k] = v |
end |
current = oldCurrent |
else |
db.current = current |
end |
end |
init(self) |
end |
for namespace, db in pairs(data) do |
setmetatable(db.module, prototype_mt) |
init(db.module) |
end |
-- #NODOC |
-- modules need to call this to create a new namespace. |
function LibBabble:New(namespace, minor) |
local module, oldminor = LibStub:NewLibrary(namespace, minor) |
if not module then |
return |
end |
if not oldminor then |
local db = { |
module = module, |
} |
data[namespace] = db |
tablesToDB[module] = db |
else |
for k,v in pairs(module) do |
module[k] = nil |
end |
end |
setmetatable(module, prototype_mt) |
return module |
end |
end |
end |
local lib = LibStub("LibBabble-3.0"):New(MAJOR_VERSION, MINOR_VERSION) |
if not lib then |
return |
end |
lib:SetBaseTranslations { |
["Azeroth"] = true, |
["Eastern Kingdoms"] = true, |
["Kalimdor"] = true, |
["Outland"] = true, |
["Cosmic map"] = true, |
["Ahn'Qiraj"] = true, |
["Alterac Mountains"] = true, |
["Alterac Valley"] = true, |
["Arathi Basin"] = true, |
["Arathi Highlands"] = true, |
["Ashenvale"] = true, |
["Auberdine"] = true, |
["Azshara"] = true, |
["Badlands"] = true, |
["The Barrens"] = true, |
["Blackfathom Deeps"] = true, |
["Blackrock Depths"] = true, |
["Blackrock Mountain"] = true, |
["Blackrock Spire"] = true, |
["Blackwing Lair"] = true, |
["Blasted Lands"] = true, |
["Booty Bay"] = true, |
["Burning Steppes"] = true, |
["Darkshore"] = true, |
["Darnassus"] = true, |
["The Deadmines"] = true, |
["Deadwind Pass"] = true, |
["Deeprun Tram"] = true, |
["Desolace"] = true, |
["Dire Maul"] = true, |
["Dire Maul (East)"] = true, |
["Dire Maul (West)"] = true, |
["Dire Maul (North)"] = true, |
["Dun Morogh"] = true, |
["Durotar"] = true, |
["Duskwood"] = true, |
["Dustwallow Marsh"] = true, |
["Eastern Plaguelands"] = true, |
["Elwynn Forest"] = true, |
["Everlook"] = true, |
["Felwood"] = true, |
["Feralas"] = true, |
["The Forbidding Sea"] = true, |
["Gadgetzan"] = true, |
["Gates of Ahn'Qiraj"] = true, |
["Gnomeregan"] = true, |
["The Great Sea"] = true, |
["Grom'gol Base Camp"] = true, |
["Hall of Legends"] = true, |
["Hillsbrad Foothills"] = true, |
["The Hinterlands"] = true, |
["Hyjal"] = true, |
["Hyjal Summit"] = true, |
["Ironforge"] = true, |
["Loch Modan"] = true, |
["Lower Blackrock Spire"] = true, |
["Maraudon"] = true, |
["Menethil Harbor"] = true, |
["Molten Core"] = true, |
["Moonglade"] = true, |
["Mulgore"] = true, |
["Naxxramas"] = true, |
["Onyxia's Lair"] = true, |
["Orgrimmar"] = true, |
["Ratchet"] = true, |
["Ragefire Chasm"] = true, |
["Razorfen Downs"] = true, |
["Razorfen Kraul"] = true, |
["Redridge Mountains"] = true, |
["Ruins of Ahn'Qiraj"] = true, |
["Scarlet Monastery"] = true, |
["Scholomance"] = true, |
["Searing Gorge"] = true, |
["Shadowfang Keep"] = true, |
["Silithus"] = true, |
["Silverpine Forest"] = true, |
["The Stockade"] = true, |
["Stonard"] = true, |
["Stonetalon Mountains"] = true, |
["Stormwind City"] = true, |
["Stormwind"] = true, |
["Stranglethorn Vale"] = true, |
["Stratholme"] = true, |
["Swamp of Sorrows"] = true, |
["Tanaris"] = true, |
["Teldrassil"] = true, |
["Temple of Ahn'Qiraj"] = true, |
["The Temple of Atal'Hakkar"] = true, |
["Theramore Isle"] = true, |
["Thousand Needles"] = true, |
["Thunder Bluff"] = true, |
["Tirisfal Glades"] = true, |
["Uldaman"] = true, |
["Un'Goro Crater"] = true, |
["Undercity"] = true, |
["Upper Blackrock Spire"] = true, |
["Wailing Caverns"] = true, |
["Warsong Gulch"] = true, |
["Western Plaguelands"] = true, |
["Westfall"] = true, |
["Wetlands"] = true, |
["Winterspring"] = true, |
["Zul'Farrak"] = true, |
["Zul'Gurub"] = true, |
["Champions' Hall"] = true, |
["Hall of Champions"] = true, |
["Blade's Edge Arena"] = true, |
["Nagrand Arena"] = true, |
["Ruins of Lordaeron"] = true, |
["Twisting Nether"] = true, |
["The Veiled Sea"] = true, |
["The North Sea"] = true, |
["Armory"] = true, |
["Library"] = true, |
["Cathedral"] = true, |
["Graveyard"] = true, |
-- Burning Crusade |
-- Subzones used for displaying instances. |
["Plaguewood"] = true, |
["Hellfire Citadel"] = true, |
["Auchindoun"] = true, |
["The Bone Wastes"] = true, -- Substitute for Auchindoun, since this is what shows on the minimap. |
["Ring of Observance"] = true, |
["Coilfang Reservoir"] = true, |
["Amani Pass"] = true, |
["Azuremyst Isle"] = true, |
["Bloodmyst Isle"] = true, |
["Eversong Woods"] = true, |
["Ghostlands"] = true, |
["The Exodar"] = true, |
["Silvermoon City"] = true, |
["Shadowmoon Valley"] = true, |
["Black Temple"] = true, |
["Terokkar Forest"] = true, |
["Auchenai Crypts"] = true, |
["Mana-Tombs"] = true, |
["Shadow Labyrinth"] = true, |
["Sethekk Halls"] = true, |
["Hellfire Peninsula"] = true, |
["The Dark Portal"] = true, |
["Hellfire Ramparts"] = true, |
["The Blood Furnace"] = true, |
["The Shattered Halls"] = true, |
["Magtheridon's Lair"] = true, |
["Nagrand"] = true, |
["Zangarmarsh"] = true, |
["The Slave Pens"] = true, |
["The Underbog"] = true, |
["The Steamvault"] = true, |
["Serpentshrine Cavern"] = true, |
["Blade's Edge Mountains"] = true, |
["Gruul's Lair"] = true, |
["Netherstorm"] = true, |
["Tempest Keep"] = true, |
["The Mechanar"] = true, |
["The Botanica"] = true, |
["The Arcatraz"] = true, |
["The Eye"] = true, |
["Eye of the Storm"] = true, |
["Shattrath City"] = true, |
["Shattrath"] = true, |
["Karazhan"] = true, |
["Caverns of Time"] = true, |
["Old Hillsbrad Foothills"] = true, |
["The Black Morass"] = true, |
["Night Elf Village"] = true, |
["Horde Encampment"] = true, |
["Alliance Base"] = true, |
["Zul'Aman"] = true, |
["Quel'thalas"] = true, |
["Isle of Quel'Danas"] = true, |
["Sunwell Plateau"] = true, |
["Magisters' Terrace"] = true, |
-- Blade's Edge Plateau |
["Forge Camp: Terror"] = true, |
["Vortex Pinnacle"] = true, |
["Rivendark's Perch"] = true, |
["Ogri'la"] = true, |
["Obsidia's Perch"] = true, |
["Skyguard Outpost"] = true, |
["Shartuul's Transporter"] = true, |
["Forge Camp: Wrath"] = true, |
["Bash'ir Landing"] = true, |
["Crystal Spine"] = true, |
["Insidion's Perch"] = true, |
["Furywing's Perch"] = true, |
["Tirisfal"] = true, |
["Sunken Temple"] = true, |
} |
if GAME_LOCALE == "enUS" then |
lib:SetCurrentTranslations(true) |
elseif GAME_LOCALE == "deDE" then |
lib:SetCurrentTranslations { |
["Azeroth"] = "Azeroth", |
["Eastern Kingdoms"] = "Ãstliche Königreiche", |
["Kalimdor"] = "Kalimdor", |
["Outland"] = "Scherbenwelt", |
["Cosmic map"] = "Kosmische Karte", |
["Ahn'Qiraj"] = "Ahn'Qiraj", |
["Alterac Mountains"] = "Alteracgebirge", |
["Alterac Valley"] = "Alteractal", |
["Arathi Basin"] = "Arathibecken", |
["Arathi Highlands"] = "Arathihochland", |
["Ashenvale"] = "Eschental", |
["Auberdine"] = "Auberdine", |
["Azshara"] = "Azshara", |
["Badlands"] = "Ãdland", |
["The Barrens"] = "Brachland", |
["Blackfathom Deeps"] = "Tiefschwarze Grotte", |
["Blackrock Depths"] = "Schwarzfelstiefen", |
["Blackrock Mountain"] = "Der Schwarzfels", |
["Blackrock Spire"] = "Schwarzfelsspitze", |
["Blackwing Lair"] = "Pechschwingenhort", |
["Blasted Lands"] = "Verwüstete Lande", |
["Booty Bay"] = "Beutebucht", |
["Burning Steppes"] = "Brennende Steppe", |
["Darkshore"] = "Dunkelküste", |
["Darnassus"] = "Darnassus", |
["The Deadmines"] = "Die Todesminen", |
["Deadwind Pass"] = "Gebirgspass der Totenwinde", |
["Deeprun Tram"] = "Die Tiefenbahn", |
["Desolace"] = "Desolace", |
["Dire Maul"] = "Düsterbruch", |
["Dire Maul (North)"] = "Düsterbruch (Nord)", |
["Dire Maul (East)"] = "Düsterbruch (Ost)", |
["Dire Maul (West)"] = "Düsterbruch (West)", |
["Dun Morogh"] = "Dun Morogh", |
["Durotar"] = "Durotar", |
["Duskwood"] = "Dämmerwald", |
["Dustwallow Marsh"] = "Düstermarschen", |
["Eastern Plaguelands"] = "Ãstliche Pestländer", |
["Elwynn Forest"] = "Wald von Elwynn", |
["Everlook"] = "Ewige Warte", |
["Felwood"] = "Teufelswald", |
["Feralas"] = "Feralas", |
["The Forbidding Sea"] = "Das verbotene Meer", |
["Gadgetzan"] = "Gadgetzan", |
["Gates of Ahn'Qiraj"] = "Tore von Ahn'Qiraj", |
["Gnomeregan"] = "Gnomeregan", |
["Grom'gol Base Camp"] = "Basislager von Grom'gol", |
["The Great Sea"] = "Das groÃe Meer", |
["Hall of Legends"] = "Halle der Legenden", |
["Hillsbrad Foothills"] = "Vorgebirge des Hügellands", |
["The Hinterlands"] = "Hinterland", |
["Hyjal"] = "Hyjal", |
["Hyjal Summit"] = "Hyjalgipfel", |
["Ironforge"] = "Eisenschmiede", |
["Loch Modan"] = "Loch Modan", |
["Lower Blackrock Spire"] = "Untere Schwarzfelsspitze", |
["Maraudon"] = "Maraudon", |
["Menethil Harbor"] = "Hafen von Menethil", |
["Molten Core"] = "Geschmolzener Kern", |
["Moonglade"] = "Mondlichtung", |
["Mulgore"] = "Mulgore", |
["Naxxramas"] = "Naxxramas", |
["Onyxia's Lair"] = "Onyxias Hort", |
["Orgrimmar"] = "Orgrimmar", |
["Ratchet"] = "Ratschet", |
["Ragefire Chasm"] = "Der Flammenschlund", |
["Razorfen Downs"] = "Hügel der Klingenhauer", |
["Razorfen Kraul"] = "Kral der Klingenhauer", |
["Redridge Mountains"] = "Rotkammgebirge", |
["Ruins of Ahn'Qiraj"] = "Ruinen von Ahn'Qiraj", |
["Scarlet Monastery"] = "Das Scharlachrote Kloster", |
["Scholomance"] = "Scholomance", |
["Searing Gorge"] = "Sengende Schlucht", |
["Shadowfang Keep"] = "Burg Schattenfang", |
["Silithus"] = "Silithus", |
["Silverpine Forest"] = "Silberwald", |
["The Stockade"] = "Das Verlies", |
["Stonard"] = "Steinard", |
["Stonetalon Mountains"] = "Steinkrallengebirge", |
["Stormwind City"] = "Sturmwind", |
["Stormwind"] = "Sturmwind", |
["Stranglethorn Vale"] = "Schlingendorntal", |
["Stratholme"] = "Stratholme", |
["Swamp of Sorrows"] = "Sümpfe des Elends", |
["Tanaris"] = "Tanaris", |
["Teldrassil"] = "Teldrassil", |
["Temple of Ahn'Qiraj"] = "Tempel von Ahn'Qiraj", |
["The Temple of Atal'Hakkar"] = "Der Tempel von Atal'Hakkar", |
["Theramore Isle"] = "Insel Theramore", |
["Thousand Needles"] = "Tausend Nadeln", |
["Thunder Bluff"] = "Donnerfels", |
["Tirisfal Glades"] = "Tirisfal", |
["Uldaman"] = "Uldaman", |
["Un'Goro Crater"] = "Krater von Un'Goro", |
["Undercity"] = "Unterstadt", |
["Upper Blackrock Spire"] = "Obere Schwarzfelsspitze", |
["Wailing Caverns"] = "Die Höhlen des Wehklagens", |
["Warsong Gulch"] = "Kriegshymnenschlucht", |
["Western Plaguelands"] = "Westliche Pestländer", |
["Westfall"] = "Westfall", |
["Wetlands"] = "Sumpfland", |
["Winterspring"] = "Winterquell", |
["Zul'Farrak"] = "Zul'Farrak", |
["Zul'Gurub"] = "Zul'Gurub", |
["Champions' Hall"] = "Halle der Champions", |
["Hall of Champions"] = "Halle der Champions", |
["Blade's Edge Arena"] = "Arena des Schergrats", |
["Nagrand Arena"] = "Arena von Nagrand", |
["Ruins of Lordaeron"] = "Ruinen von Lordaeron", |
["Twisting Nether"] = "Wirbelnder Nether", |
["The Veiled Sea"] = "Das verhüllte Meer", |
["The North Sea"] = "Das nördliche Meer", |
["Armory"] = "Waffenkammer", |
["Library"] = "Bibliothek", |
["Cathedral"] = "Kathedrale", |
["Graveyard"] = "Friedhof", |
-- Burning Crusade |
-- Subzones used for displaying instances. |
["Plaguewood"] = "Seuchenwald", |
["Hellfire Citadel"] = "Höllenfeuerzitadelle", |
["Auchindoun"] = "Auchindoun", |
["The Bone Wastes"] = "Die Knochenwüste", -- Substitute for Auchindoun, since this is what shows on the minimap. |
["Ring of Observance"] = "Ring der Beobachtung", |
["Coilfang Reservoir"] = "Der Echsenkessel", |
["Amani Pass"] = "Amanipass", |
["Azuremyst Isle"] = "Azurmythosinsel", |
["Bloodmyst Isle"] = "Blutmythosinsel", |
["Eversong Woods"] = "Immersangwald", |
["Ghostlands"] = "Geisterlande", |
["The Exodar"] = "Die Exodar", |
["Silvermoon City"] = "Silbermond", |
["Shadowmoon Valley"] = "Schattenmondtal", |
["Black Temple"] = "Der Schwarze Tempel", |
["Terokkar Forest"] = "Wälder von Terokkar", |
["Auchenai Crypts"] = "Auchenaikrypta", |
["Mana-Tombs"] = "Managruft", |
["Shadow Labyrinth"] = "Schattenlabyrinth", |
["Sethekk Halls"] = "Sethekkhallen", |
["Hellfire Peninsula"] = "Höllenfeuerhalbinsel", |
["The Dark Portal"] = "Das Dunkle Portal", |
["Hellfire Ramparts"] = "Höllenfeuerbollwerk", |
["The Blood Furnace"] = "Der Blutkessel", |
["The Shattered Halls"] = "Die zerschmetterten Hallen", |
["Magtheridon's Lair"] = "Magtheridons Kammer", |
["Nagrand"] = "Nagrand", |
["Zangarmarsh"] = "Zangarmarschen", |
["The Slave Pens"] = "Die Sklavenunterkünfte", |
["The Underbog"] = "Der Tiefensumpf", |
["The Steamvault"] = "Die Dampfkammer", |
["Serpentshrine Cavern"] = "Höhle des Schlangenschreins", |
["Blade's Edge Mountains"] = "Schergrat", |
["Gruul's Lair"] = "Gruuls Unterschlupf", |
["Netherstorm"] = "Nethersturm", |
["Tempest Keep"] = "Festung der Stürme", |
["The Mechanar"] = "Die Mechanar", |
["The Botanica"] = "Die Botanika", |
["The Arcatraz"] = "Die Arkatraz", |
["The Eye"] = "Das Auge", |
["Eye of the Storm"] = "Auge des Sturms", |
["Shattrath City"] = "Shattrath", |
["Shattrath"] = "Shattrath", |
["Karazhan"] = "Karazhan", |
["Caverns of Time"] = "Die Höhlen der Zeit", |
["Old Hillsbrad Foothills"] = "Vorgebirge des Alten Hügellands", |
["The Black Morass"] = "Der schwarze Morast", |
["Night Elf Village"] = "Nachtelfen Dorf", |
["Horde Encampment"] = "Lager der Horde", |
["Alliance Base"] = "Basis der Allianz", |
["Zul'Aman"] = "Zul'Aman", |
["Quel'thalas"] = "Quel'Thalas", |
["Isle of Quel'Danas"] = "Insel von Quel'Danas", |
["Sunwell Plateau"] = "Sonnenbrunnenplateau", |
["Magisters' Terrace"] = "Terrasse der Magister", |
-- Blade's Edge Plateau |
["Forge Camp: Terror"] = "", |
["Vortex Pinnacle"] = "", |
["Rivendark's Perch"] = "", |
["Ogri'la"] = "", |
["Obsidia's Perch"] = "", |
["Skyguard Outpost"] = "", |
["Shartuul's Transporter"] = "", |
["Forge Camp: Wrath"] = "", |
["Bash'ir Landing"] = "", |
["Crystal Spine"] = "", |
["Insidion's Perch"] = "", |
["Furywing's Perch"] = "", |
["Tirisfal"] = "Tirisfal", |
["Sunken Temple"] = "Versunkener Tempel", |
} |
elseif GAME_LOCALE == "frFR" then |
lib:SetCurrentTranslations { |
["Azeroth"] = "Azeroth", |
["Eastern Kingdoms"] = "Royaumes de l'est", |
["Kalimdor"] = "Kalimdor", |
["Outland"] = "Outreterre", |
["Cosmic map"] = "Carte cosmique", |
["Ahn'Qiraj"] = "Ahn'Qiraj", |
["Alterac Mountains"] = "Montagnes d'Alterac", |
["Alterac Valley"] = "Vallée d'Alterac", |
["Arathi Basin"] = "Bassin d'Arathi", |
["Arathi Highlands"] = "Hautes-terres d'Arathi", |
["Ashenvale"] = "Orneval", |
["Auberdine"] = "Auberdine", |
["Azshara"] = "Azshara", |
["Badlands"] = "Terres ingrates", |
["The Barrens"] = "Les Tarides", |
["Blackfathom Deeps"] = "Profondeurs de Brassenoire", |
["Blackrock Depths"] = "Profondeurs de Rochenoire", |
["Blackrock Mountain"] = "Mont Rochenoire", |
["Blackrock Spire"] = "Pic Rochenoire", |
["Blackwing Lair"] = "Repaire de l'Aile noire", |
["Blasted Lands"] = "Terres foudroyées", |
["Booty Bay"] = "Baie-du-Butin", |
["Burning Steppes"] = "Steppes ardentes", |
["Darkshore"] = "Sombrivage", |
["Darnassus"] = "Darnassus", |
["The Deadmines"] = "Les Mortemines", |
["Deadwind Pass"] = "Défilé de Deuillevent", |
["Deeprun Tram"] = "Tram des profondeurs", |
["Desolace"] = "Désolace", |
["Dire Maul"] = "Hache-tripes", |
["Dire Maul (East)"] = "Hache-tripes (Est)", |
["Dire Maul (West)"] = "Hache-tripes (Ouest)", |
["Dire Maul (North)"] = "Hache-tripes (Nord)", |
["Dun Morogh"] = "Dun Morogh", |
["Durotar"] = "Durotar", |
["Duskwood"] = "Bois de la Pénombre", |
["Dustwallow Marsh"] = "Marécage d'Ãprefange", |
["Eastern Plaguelands"] = "Maleterres de l'est", |
["Elwynn Forest"] = "Forêt d'Elwynn", |
["Everlook"] = "Long-guet", |
["Felwood"] = "Gangrebois", |
["Feralas"] = "Féralas", |
["The Forbidding Sea"] = "La Mer interdite", |
["Gadgetzan"] = "Gadgetzan", |
["Gates of Ahn'Qiraj"] = "Portes d'Ahn'Qiraj", |
["Gnomeregan"] = "Gnomeregan", |
["Grom'gol Base Camp"] = "Campement Grom'gol", |
["The Great Sea"] = "La Grande mer", |
["Hall of Legends"] = "Hall des Légendes", |
["Hillsbrad Foothills"] = "Contreforts de Hautebrande", |
["The Hinterlands"] = "Les Hinterlands", |
["Hyjal"] = "Hyjal", |
["Hyjal Summit"] = "Sommet d'Hyjal", |
["Ironforge"] = "Forgefer", |
["Loch Modan"] = "Loch Modan", |
["Lower Blackrock Spire"] = "Pic de Rochenoire inférieur", |
["Maraudon"] = "Maraudon", |
["Menethil Harbor"] = "Port de Menethil", |
["Molten Core"] = "CÅur du Magma", |
["Moonglade"] = "Reflet-de-Lune", |
["Mulgore"] = "Mulgore", |
["Onyxia's Lair"] = "Repaire d'Onyxia", |
["Naxxramas"] = "Naxxramas", |
["Orgrimmar"] = "Orgrimmar", |
["Ratchet"] = "Cabestan", |
["Ragefire Chasm"] = "Gouffre de Ragefeu", |
["Razorfen Downs"] = "Souilles de Tranchebauge", |
["Razorfen Kraul"] = "Kraal de Tranchebauge", |
["Redridge Mountains"] = "Les Carmines", |
["Ruins of Ahn'Qiraj"] = "Ruines d'Ahn'Qiraj", |
["Scarlet Monastery"] = "Monastère écarlate", |
["Scholomance"] = "Scholomance", |
["Searing Gorge"] = "Gorge des Vents brûlants", |
["Shadowfang Keep"] = "Donjon d'Ombrecroc", |
["Silithus"] = "Silithus", |
["Silverpine Forest"] = "Forêt des Pins argentés", |
["The Stockade"] = "La Prison", |
--["Stonard"] = "", |
["Stonetalon Mountains"] = "Les Serres-Rocheuses", |
["Stormwind City"] = "Hurlevent", |
["Stranglethorn Vale"] = "Vallée de Strangleronce", |
["Stratholme"] = "Stratholme", |
["Swamp of Sorrows"] = "Marais des Chagrins", |
["Tanaris"] = "Tanaris", |
["Teldrassil"] = "Teldrassil", |
["Temple of Ahn'Qiraj"] = "Le temple d'Ahn'Qiraj", |
["The Temple of Atal'Hakkar"] = "Le temple d'Atal'Hakkar", |
["Theramore Isle"] = "Ile de Theramore", |
["Thousand Needles"] = "Mille pointes", |
["Thunder Bluff"] = "Les Pitons du Tonnerre", |
["Tirisfal Glades"] = "Clairières de Tirisfal", |
["Uldaman"] = "Uldaman", |
["Un'Goro Crater"] = "Cratère d'Un'Goro", |
["Undercity"] = "Fossoyeuse", |
["Upper Blackrock Spire"] = "Pic de Rochenoire supérieur", |
["Wailing Caverns"] = "Cavernes des lamentations", |
["Warsong Gulch"] = "Goulet des Chanteguerres", |
["Western Plaguelands"] = "Maleterres de l'ouest", |
["Westfall"] = "Marche de l'Ouest", |
["Wetlands"] = "Les Paluns", |
["Winterspring"] = "Berceau-de-l'Hiver", |
["Zul'Farrak"] = "Zul'Farrak", |
["Zul'Gurub"] = "Zul'Gurub", |
["Champions' Hall"] = "Hall des Champions", |
["Blade's Edge Arena"] = "Arène des Tranchantes", |
["Nagrand Arena"] = "Arène de Nagrand", |
["Ruins of Lordaeron"] = "Ruines de Lordaeron", |
["Twisting Nether"] = "Le Néant distordu", |
["The Veiled Sea"] = "La Mer voilée", |
["The North Sea"] = "La mer Boréale", |
["Armory"] = "Armurerie", |
["Library"] = "Bibliothèque", |
["Cathedral"] = "Cathédrale", |
["Graveyard"] = "Cimetière", |
-- Burning Crusade |
-- Subzones used for displaying instances. |
["Plaguewood"] = "Pestebois", |
["Hellfire Citadel"] = "Citadelle des Flammes infernales", |
["Auchindoun"] = "Auchindoun", |
["The Bone Wastes"] = "Le désert des Ossements", -- Substitute for Auchindoun, since this is what shows on the minimap. |
["Ring of Observance"] = "Cercle d'observance", |
["Coilfang Reservoir"] = "Réservoir de Glissecroc", |
["Amani Pass"] = "Passage des Amani", |
["Azuremyst Isle"] = "Ile de Brume-azur", |
["Bloodmyst Isle"] = "Ile de Brume-sang", |
["Eversong Woods"] = "Bois des Chants éternels", |
["Ghostlands"] = "Les Terres fantômes", |
["The Exodar"] = "L'Exodar", |
["Silvermoon City"] = "Lune-d'argent", |
["Shadowmoon Valley"] = "Vallée d'Ombrelune", |
["Black Temple"] = "Temple noir", |
["Terokkar Forest"] = "Forêt de Terokkar", |
["Auchenai Crypts"] = "Cryptes Auchenaï", |
["Mana-Tombs"] = "Tombes-mana", |
["Shadow Labyrinth"] = "Labyrinthe des ombres", |
["Sethekk Halls"] = "Les salles des Sethekk", |
["Hellfire Peninsula"] = "Péninsule des Flammes infernales", |
["The Dark Portal"] = "La Porte des ténèbres", |
["Hellfire Ramparts"] = "Remparts des Flammes infernales", |
["The Blood Furnace"] = "La Fournaise du sang", |
["The Shattered Halls"] = "Les Salles brisées", |
["Magtheridon's Lair"] = "Le repaire de Magtheridon", |
["Nagrand"] = "Nagrand", |
["Zangarmarsh"] = "Marécage de Zangar", |
["The Slave Pens"] = "Les enclos aux esclaves", |
["The Underbog"] = "La Basse-tourbière", |
["The Steamvault"] = "Le Caveau de la vapeur", |
["Serpentshrine Cavern"] = "Caverne du sanctuaire du Serpent", |
["Blade's Edge Mountains"] = "Les Tranchantes", |
["Gruul's Lair"] = "Repaire de Gruul", |
["Netherstorm"] = "Raz-de-Néant", |
["Tempest Keep"] = "Donjon de la Tempête", |
["The Mechanar"] = "Le Méchanar", |
["The Botanica"] = "La Botanica", |
["The Arcatraz"] = "L'Arcatraz", |
["The Eye"] = "L'Åil", |
["Eye of the Storm"] = "L'Åil du cyclone", |
["Shattrath City"] = "Shattrath", |
["Karazhan"] = "Karazhan", |
["Caverns of Time"] = "Grottes du temps", |
["Old Hillsbrad Foothills"] = "Contreforts de Hautebrande d'antan", |
["The Black Morass"] = "Le Noir Marécage", |
["Night Elf Village"] = "Village elfe de la nuit", |
["Horde Encampment"] = "Campement de la Horde", |
["Alliance Base"] = "Base de l'Alliance", |
["Zul'Aman"] = "Zul'Aman", |
["Quel'thalas"] = "Quel'thalas", |
["Isle of Quel'Danas"] = "Ãle de Quel'Danas", |
["Sunwell Plateau"] = "Plateau du Puits de soleil", |
["Magisters' Terrace"] = "Terrasse des Magistères", |
-- Blade's Edge Plateau |
["Forge Camp: Terror"] = "", |
["Vortex Pinnacle"] = "", |
["Rivendark's Perch"] = "", |
["Ogri'la"] = "", |
["Obsidia's Perch"] = "", |
["Skyguard Outpost"] = "", |
["Shartuul's Transporter"] = "", |
["Forge Camp: Wrath"] = "", |
["Bash'ir Landing"] = "", |
["Crystal Spine"] = "", |
["Insidion's Perch"] = "", |
["Furywing's Perch"] = "", |
} |
elseif GAME_LOCALE == "zhCN" then |
lib:SetCurrentTranslations { |
["Azeroth"] = "è¾æ³½ææ¯", |
["Eastern Kingdoms"] = "ä¸é¨çå½", |
["Kalimdor"] = "å¡å©å§å¤", |
["Outland"] = "å¤å", |
["Cosmic map"] = "å ¨é¨å°å¾", |
["Ahn'Qiraj"] = "å®å ¶æ", |
["Alterac Mountains"] = "奥ç¹å °å å±±è", |
["Alterac Valley"] = "奥ç¹å °å 山谷", |
["Arathi Basin"] = "é¿æå¸çå°", |
["Arathi Highlands"] = "é¿æå¸é«å°", |
["Ashenvale"] = "ç°è°·", |
["Auberdine"] = "奥伯ä¸", |
["Azshara"] = "è¾è¨æ", |
["Badlands"] = "èèä¹å°", |
["The Barrens"] = "è´«ç ä¹å°", |
["Blackfathom Deeps"] = "é»ææ·±æ¸", |
["Blackrock Depths"] = "é»ç³æ·±æ¸", |
["Blackrock Mountain"] = "é»ç³å±±", |
["Blackrock Spire"] = "é»ç³å¡", |
["Blackwing Lair"] = "é»ç¿¼ä¹å·¢", |
["Blasted Lands"] = "è¯ åä¹å°", |
["Booty Bay"] = "èå®æµ·æ¹¾", |
["Burning Steppes"] = "çç§å¹³å", |
["Darkshore"] = "é»æµ·å²¸", |
["Darnassus"] = "达纳èæ¯", |
["The Deadmines"] = "æ»äº¡ç¿äº", |
["Deadwind Pass"] = "éé£å°å¾", |
["Deeprun Tram"] = "ç¿éå°é", |
["Desolace"] = "ååä¹å°", |
["Dire Maul"] = "åè¿ä¹æ§", |
["Dire Maul (East)"] = "åè¿ä¹æ§ (ä¸)", |
["Dire Maul (West)"] = "åè¿ä¹æ§ (西)", |
["Dire Maul (North)"] = "åè¿ä¹æ§ (å)", |
["Dun Morogh"] = "丹è«ç½", |
["Durotar"] = "æéå¡å°", |
["Duskwood"] = "æ®è²æ£®æ", |
["Dustwallow Marsh"] = "å°æ³¥æ²¼æ³½", |
["Eastern Plaguelands"] = "ä¸çç«ä¹å°", |
["Elwynn Forest"] = "è¾å°æ森æ", |
["Everlook"] = "æ°¸æé", |
["Felwood"] = "è´¹ä¼å¾·æ£®æ", |
["Feralas"] = "è²ææ¯", |
["The Forbidding Sea"] = "ç¦å¿ä¹æµ·", |
["Gadgetzan"] = "å åºæ£®", |
["Gates of Ahn'Qiraj"] = "å®å ¶æä¹é¨", |
["Gnomeregan"] = "诺è«çæ ¹", |
["The Great Sea"] = "æ å°½ä¹æµ·", |
["Grom'gol Base Camp"] = "æ ¼ç½å§é«è¥å°", |
["Hall of Legends"] = "ä¼ è¯´å¤§å ", |
["Hillsbrad Foothills"] = "å¸å°æ¯å¸è±å¾·ä¸éµ", |
["The Hinterlands"] = "è¾ç¹å °", |
["Hyjal"] = "æµ·å å°å±±", |
["Hyjal Summit"] = "æµ·å å°å³°", |
["Ironforge"] = "éçå ¡", |
["Loch Modan"] = "æ´å è«ä¸¹", |
["Lower Blackrock Spire"] = "é»ç³å¡ (ä¸å±)", |
["Maraudon"] = "çæé¡¿", |
["Menethil Harbor"] = "ç±³å¥å¸å°æ¸¯", |
["Molten Core"] = "çç«ä¹å¿", |
["Moonglade"] = "æå æå°", |
["Mulgore"] = "è«é«é·", |
["Naxxramas"] = "纳å è¨çæ¯", |
["Onyxia's Lair"] = "奥妮å å¸äºç巢穴", |
["Orgrimmar"] = "å¥¥æ ¼çç", |
["Ratchet"] = "æ£é½¿å", |
["Ragefire Chasm"] = "æç°è£è°·", |
["Razorfen Downs"] = "ååé«å°", |
["Razorfen Kraul"] = "åå沼泽", |
["Redridge Mountains"] = "赤èå±±", |
["Ruins of Ahn'Qiraj"] = "å®å ¶æåºå¢", |
["Scarlet Monastery"] = "è¡è²ä¿®éé¢", |
["Scholomance"] = "éçµå¦é¢", |
["Searing Gorge"] = "ç¼ç峡谷", |
["Shadowfang Keep"] = "å½±çåå ¡", |
["Silithus"] = "å¸å©èæ¯", |
["Silverpine Forest"] = "é¶æ¾æ£®æ", |
["The Stockade"] = "çç±", |
["Stonard"] = "æ¯é纳德", |
["Stonetalon Mountains"] = "ç³çªå±±è", |
["Stormwind City"] = "æ´é£å", |
["Stormwind"] = "æ´é£å",--TaxiNodesDBC |
["Stranglethorn Vale"] = "èæ£è°·", |
["Stratholme"] = "æ¯å¦ç´¢å§", |
["Swamp of Sorrows"] = "æ²ä¼¤æ²¼æ³½", |
["Tanaris"] = "å¡çº³å©æ¯", |
["Teldrassil"] = "æ³°è¾¾å¸å°", |
["Temple of Ahn'Qiraj"] = "å®å ¶æç¥æ®¿", |
["The Temple of Atal'Hakkar"] = "é¿å¡åå¡ç¥åº", |
["Theramore Isle"] = "å¡ææ©å²", |
["Thousand Needles"] = "åéç³æ", |
["Thunder Bluff"] = "é·éå´", |
["Tirisfal Glades"] = "æçæ¯æ³æå°", |
["Uldaman"] = "奥达æ¼", |
["Un'Goro Crater"] = "å®ææ´ç¯å½¢å±±", |
["Undercity"] = "å¹½æå", |
["Upper Blackrock Spire"] = "é»ç³å¡ (ä¸å±)", |
["Wailing Caverns"] = "ååæ´ç©´", |
["Warsong Gulch"] = "ææ峡谷", |
["Western Plaguelands"] = "西çç«ä¹å°", |
["Westfall"] = "西é¨èé", |
["Wetlands"] = "湿å°", |
["Winterspring"] = "å¬æ³è°·", |
["Zul'Farrak"] = "ç¥å°æ³æå ", |
["Zul'Gurub"] = "ç¥å°æ ¼æå¸", |
["Champions' Hall"] = "å士大å ", |
["Hall of Champions"] = "å士大å ",--WMOAreaTableDBC |
["Blade's Edge Arena"] = "åéå±±ç«æåº", |
["Nagrand Arena"] = "çº³æ ¼å °ç«æåº", |
["Ruins of Lordaeron"] = "æ´ä¸¹ä¼¦åºå¢", |
["Twisting Nether"] = "ææ²è空", |
["The Veiled Sea"] = "è¿·é¾ä¹æµ·", |
["The North Sea"] = "åæµ·", |
["Armory"] = "å械åº", |
["Library"] = "å¾ä¹¦é¦", |
["Cathedral"] = "æå ", |
["Graveyard"] = "å¢å°", |
-- Burning Crusade |
-- Subzones used for displaying instances. |
["Plaguewood"] = "ç æ¨æ", |
["Hellfire Citadel"] = "å°ç±ç«å ¡å", |
["Auchindoun"] = "奥éé¡¿", |
["The Bone Wastes"] = "ç½éª¨èé", |
["Ring of Observance"] = "仪å¼å¹¿åº", |
["Coilfang Reservoir"] = "ççæ°´åº", |
["Amani Pass"] = "é¿æ¼å°¼å°å¾", |
["Azuremyst Isle"] = "ç§èå²", |
["Bloodmyst Isle"] = "ç§è¡å²", |
["Eversong Woods"] = "æ°¸æ森æ", |
["Ghostlands"] = "å¹½éä¹å°", |
["The Exodar"] = "å索达", |
["Silvermoon City"] = "é¶æå", |
["Shadowmoon Valley"] = "å½±æè°·", |
["Black Temple"] = "é»æç¥æ®¿", |
["Terokkar Forest"] = "æ³°ç½å¡æ£®æ", |
["Auchenai Crypts"] = "奥éå°¼å°ç©´", |
["Mana-Tombs"] = "æ³åéµå¢", |
["Shadow Labyrinth"] = "æ影迷宫", |
["Sethekk Halls"] = "å¡æ³°å 大å ", |
["Hellfire Peninsula"] = "å°ç±ç«åå²", |
["The Dark Portal"] = "é»æä¹é¨", |
["Hellfire Ramparts"] = "å°ç±ç«åå¢", |
["The Blood Furnace"] = "é²è¡çç", |
["The Shattered Halls"] = "ç ´ç¢å¤§å ", |
["Magtheridon's Lair"] = "ççéé¡¿ç巢穴", |
["Nagrand"] = "çº³æ ¼å °", |
["Zangarmarsh"] = "èµå 沼泽", |
["The Slave Pens"] = "奴é¶å´æ ", |
["The Underbog"] = "å¹½æ沼泽", |
["The Steamvault"] = "è¸æ±½å°çª", |
["Serpentshrine Cavern"] = "æ¯èç¥æ®¿", |
["Blade's Edge Mountains"] = "åéå±±", |
["Gruul's Lair"] = "æ ¼é²å°ç巢穴", |
["Netherstorm"] = "è空é£æ´", |
["Tempest Keep"] = "é£æ´è¦å¡", |
["The Mechanar"] = "è½æºè°", |
["The Botanica"] = "çæè¹", |
["The Arcatraz"] = "ç¦éçç±", |
["The Eye"] = "é£æ´è¦å¡", |
["Eye of the Storm"] = "é£æ´ä¹ç¼", |
["Shattrath City"] = "æ²å¡æ¯å", |
["Shattrath"] = "æ²å¡æ¯",--TaxiNodesDBC |
["Karazhan"] = "å¡æèµ", |
["Caverns of Time"] = "æ¶å ä¹ç©´", |
["Old Hillsbrad Foothills"] = "æ§å¸å°æ¯å¸è±å¾·ä¸éµ", |
["The Black Morass"] = "é»è²æ²¼æ³½", |
["Night Elf Village"] = "æå¤ç²¾çµæåº", |
["Horde Encampment"] = "é¨è½è¥å°", |
["Alliance Base"] = "èçåºå°", |
["Zul'Aman"] = "ç¥é¿æ¼", |
["Quel'thalas"] = "å¥å°è¨ææ¯", |
["Isle of Quel'Danas"] = "å¥å°ä¸¹çº³æ¯å²", |
["Sunwell Plateau"] = "太é³ä¹äºé«å°", |
["Magisters' Terrace"] = "é导å¸å¹³å°", |
-- Blade's Edge Plateau |
["Forge Camp: Terror"] = "é¸éè¥å°ï¼ææ", |
["Vortex Pinnacle"] = "漩涡峰", |
["Rivendark's Perch"] = "é·æè¾¾å æ æ¨", |
["Ogri'la"] = "å¥¥æ ¼çæ", |
["Obsidia's Perch"] = "欧æ¯æ¯è¿ªæ æ¨", |
["Skyguard Outpost"] = "天空å«éå¨ç«", |
["Shartuul's Transporter"] = "æ²å¾å°çä¼ éå¨", |
["Forge Camp: Wrath"] = "é¸éè¥å°ï¼å¤©ç½", |
["Bash'ir Landing"] = "å·´ä»ä¼å°ç 头", |
["Crystal Spine"] = "æ°´æ¶ä¹è", |
["Insidion's Perch"] = "å æ¯è¿ªå®æ æ¨", |
["Furywing's Perch"] = "å¼é·ææ æ¨", |
["Tirisfal"] = "æéæ¯æ³æå°",--TaxiNodesDBC |
["Sunken Temple"] = "æ²æ²¡çç¥åº",--AreaTableDBC |
} |
elseif GAME_LOCALE == "zhTW" then |
lib:SetCurrentTranslations { |
["Azeroth"] = "è¾æ¾¤ææ¯", |
["Eastern Kingdoms"] = "æ±é¨çå", |
["Kalimdor"] = "å¡æå¤", |
["Outland"] = "å¤å", |
["Cosmic map"] = "å®å®å°å", |
["Ahn'Qiraj"] = "å®å ¶æ", |
["Alterac Mountains"] = "奧ç¹èå å±±è", |
["Alterac Valley"] = "奧ç¹èå 山谷", |
["Arathi Basin"] = "é¿æå¸çå°", |
["Arathi Highlands"] = "é¿æå¸é«å°", |
["Ashenvale"] = "梣谷", |
["Auberdine"] = "奧伯ä¸", |
["Azshara"] = "è¾è©æ", |
["Badlands"] = "èèªä¹å°", |
["The Barrens"] = "貧ç ä¹å°", |
["Blackfathom Deeps"] = "é»æ深淵", |
["Blackrock Depths"] = "é»ç³æ·±æ·µ", |
["Blackrock Mountain"] = "é»ç³å±±", |
["Blackrock Spire"] = "é»ç³å¡", |
["Blackwing Lair"] = "é»ç¿¼ä¹å·¢", |
["Blasted Lands"] = "è©åä¹å°", |
["Booty Bay"] = "è寶海ç£", |
["Burning Steppes"] = "ççå¹³å", |
["Darkshore"] = "é»æµ·å²¸", |
["Darnassus"] = "éç´èæ¯", |
["The Deadmines"] = "æ»äº¡ç¤¦å", |
["Deadwind Pass"] = "é風å°å¾", |
["Deeprun Tram"] = "礦éå°éµ", |
["Desolace"] = "æ·æ¶¼ä¹å°", |
["Dire Maul"] = "åéä¹æ§", |
["Dire Maul (East)"] = "åéä¹æ§ - æ±", |
["Dire Maul (West)"] = "åéä¹æ§ - 西", |
["Dire Maul (North)"] = "åéä¹æ§ - å", |
["Dun Morogh"] = "丹è«æ´", |
["Durotar"] = "ææ´å¡", |
["Duskwood"] = "æ®è²æ£®æ", |
["Dustwallow Marsh"] = "塵泥沼澤", |
["Eastern Plaguelands"] = "æ±çç«ä¹å°", |
["Elwynn Forest"] = "è¾ç¾æ森æ", |
["Everlook"] = "æ°¸æé®", |
["Felwood"] = "è²»ä¼å¾·æ£®æ", |
["Feralas"] = "è²ææ¯", |
["The Forbidding Sea"] = "ç¦å¿ä¹æµ·", |
["Gadgetzan"] = "å åºæ£®", |
["Gates of Ahn'Qiraj"] = "å®å ¶æä¹é", |
["Gnomeregan"] = "諾å§çæ ¹", |
["The Great Sea"] = "ç¡ç¡ä¹æµ·", |
["Grom'gol Base Camp"] = "æ ¼ç¾ å§é«çå°", |
["Hall of Legends"] = "å³èªªå¤§å»³", |
["Hillsbrad Foothills"] = "å¸ç¾æ¯å¸èå¾·ä¸éµ", |
["The Hinterlands"] = "è¾ç¹è", |
["Hyjal"] = "æµ·å ç¾å±±", |
["Hyjal Summit"] = "æµ·å ç¾å±±", |
["Ironforge"] = "éµçå ¡", |
["Loch Modan"] = "æ´å è«ä¸¹", |
["Lower Blackrock Spire"] = "ä½éé»ç³å¡", |
["Maraudon"] = "çªæé ", |
["Menethil Harbor"] = "ç±³å¥å¸ç¾æ¸¯", |
["Molten Core"] = "çç«ä¹å¿", |
["Moonglade"] = "æå æå°", |
["Mulgore"] = "è«é«é·", |
["Naxxramas"] = "ç´å è©çªæ¯", |
["Onyxia's Lair"] = "奧妮å å¸äºç巢穴", |
["Orgrimmar"] = "å¥§æ ¼çª", |
["Ratchet"] = "æ£é½å", |
["Ragefire Chasm"] = "æç°è£è°·", |
["Razorfen Downs"] = "ååé«å°", |
["Razorfen Kraul"] = "åå沼澤", |
["Redridge Mountains"] = "赤èå±±", |
["Ruins of Ahn'Qiraj"] = "å®å ¶æ廢å¢", |
["Scarlet Monastery"] = "è¡è²ä¿®éé¢", |
["Scholomance"] = "ééå¸é¢", |
["Searing Gorge"] = "ç¼ç±å³½è°·", |
["Shadowfang Keep"] = "å½±çåå ¡", |
["Silithus"] = "å¸å©èæ¯", |
["Silverpine Forest"] = "éæ¾æ£®æ", |
["The Stockade"] = "ç£ç", |
["Stonard"] = "æ¯éç´å¾·", |
["Stonetalon Mountains"] = "ç³çªå±±è", |
["Stormwind City"] = "æ´é¢¨å", |
["Stranglethorn Vale"] = "èæ£è°·", |
["Stratholme"] = "æ¯å¦ç´¢å§", |
["Swamp of Sorrows"] = "æ²å·æ²¼æ¾¤", |
["Tanaris"] = "å¡ç´å©æ¯", |
["Teldrassil"] = "æ³°éå¸ç¾", |
["Temple of Ahn'Qiraj"] = "å®å ¶æç¥å»", |
["The Temple of Atal'Hakkar"] = "é¿å¡åå¡ç¥å»", |
["Theramore Isle"] = "å¡ææ©å³¶", |
["Thousand Needles"] = "åéç³æ", |
["Thunder Bluff"] = "é·éå´", |
["Tirisfal Glades"] = "æéæ¯æ³æå°", |
["Uldaman"] = "奧éæ¼", |
["Un'Goro Crater"] = "å®ææ´ç°å½¢å±±", |
["Undercity"] = "å¹½æå", |
["Upper Blackrock Spire"] = "é«éé»ç³å¡", |
["Wailing Caverns"] = "ååæ´ç©´", |
["Warsong Gulch"] = "æ°æ峽谷", |
["Western Plaguelands"] = "西çç«ä¹å°", |
["Westfall"] = "西é¨èé", |
["Wetlands"] = "æ¿å°", |
["Winterspring"] = "å¬æ³è°·", |
["Zul'Farrak"] = "ç¥ç¾æ³æå ", |
["Zul'Gurub"] = "ç¥ç¾æ ¼æå¸", |
["Champions' Hall"] = "å士大廳", |
["Blade's Edge Arena"] = "åå競æå ´", |
["Nagrand Arena"] = "ç´èè競æå ´", |
["Ruins of Lordaeron"] = "ç¾ å¾·é廢å¢", |
["Twisting Nether"] = "ææ²è空", |
["The Veiled Sea"] = "è¿·é§ä¹æµ·", |
["The North Sea"] = "åæ¹æµ·å²¸", |
["Armory"] = "è»æ¢°åº«", |
["Library"] = "åæ¸é¤¨", |
["Cathedral"] = "æå ", |
["Graveyard"] = "å¢å°", |
-- Burning Crusade |
-- Subzones used for displaying instances. |
["Plaguewood"] = "ç æ¨æ", |
["Hellfire Citadel"] = "å°çç«å ¡å£", |
["Auchindoun"] = "奧é½é ", |
["The Bone Wastes"] = "ç½éª¨èé", -- Substitute for Auchindoun, since this is what shows on the minimap. |
["Ring of Observance"] = "åå¼ç«¶æå ´", |
["Coilfang Reservoir"] = "ç¤çæ´ç©´", |
["Amani Pass"] = "é¿æ¼å°¼å°ä¿", |
["Azuremyst Isle"] = "èè¬å³¶", |
["Bloodmyst Isle"] = "è¡è¬å³¶", |
["Eversong Woods"] = "æ°¸æ森æ", |
["Ghostlands"] = "鬼éä¹å°", |
["The Exodar"] = "è¾å ç´¢é", |
["Silvermoon City"] = "éæå", |
["Shadowmoon Valley"] = "å½±æè°·", |
["Black Temple"] = "é»æç¥å»", |
["Terokkar Forest"] = "æ³°æ´å¡æ£®æ", |
["Auchenai Crypts"] = "奧å¥å¥å°ç©´", |
["Mana-Tombs"] = "æ³åå¢å°", |
["Shadow Labyrinth"] = "æ影迷宮", |
["Sethekk Halls"] = "å¡å¸å 大廳", |
["Hellfire Peninsula"] = "å°çç«å島", |
["The Dark Portal"] = "é»æä¹é", |
["Hellfire Ramparts"] = "å°çç«å£å£", |
["The Blood Furnace"] = "è¡çç", |
["The Shattered Halls"] = "ç ´ç¢å¤§å»³", |
["Magtheridon's Lair"] = "çªçéé ç巢穴", |
["Nagrand"] = "ç´èè", |
["Zangarmarsh"] = "è´æ ¼æ²¼æ¾¤", |
["The Slave Pens"] = "奴é¸ç£ç", |
["The Underbog"] = "深幽泥沼", |
["The Steamvault"] = "è¸æ±½æ´çª", |
["Serpentshrine Cavern"] = "æ¯èç¥æ®¿æ´ç©´", |
["Blade's Edge Mountains"] = "ååå±±è", |
["Gruul's Lair"] = "æé¯ç¾ä¹å·¢", |
["Netherstorm"] = "è空風æ´", |
["Tempest Keep"] = "風æ´è¦å¡", |
["The Mechanar"] = "麥å ç´ç¾", |
["The Botanica"] = "æ³¢å¡å°¼å¡", |
["The Arcatraz"] = "äºå å´è²", |
["The Eye"] = "風æ´è¦å¡", |
["Eye of the Storm"] = "æ´é¢¨ä¹ç¼", |
["Shattrath City"] = "æå¡æ¯å", |
["Karazhan"] = "å¡æè´", |
["Caverns of Time"] = "æå ä¹ç©´", |
["Old Hillsbrad Foothills"] = "å¸ç¾æ¯å¸èå¾·ä¸éµèå", |
["The Black Morass"] = "é»è²æ²¼æ¾¤", |
["Night Elf Village"] = "å¤ç²¾éæ", |
["Horde Encampment"] = "é¨è½çå°", |
["Alliance Base"] = "è¯ççå°", |
["Zul'Aman"] = "ç¥é¿æ¼", |
["Quel'thalas"] = "å¥ç¾è©ææ¯", |
["Isle of Quel'Danas"] = "å¥ç¾éç´æ¯ä¹å³¶", |
["Sunwell Plateau"] = "太é½ä¹äºé«å°", |
["Magisters' Terrace"] = "åå¸è 殿å ", |
-- Blade's Edge Plateau |
["Forge Camp: Terror"] = "ç å¶å ´:é©é§", |
["Vortex Pinnacle"] = "漩渦å°å¡", |
["Rivendark's Perch"] = "çæéç§æ£²æ", |
["Ogri'la"] = "ææ ¼å©æ", |
["Obsidia's Perch"] = "ææ¯å¸è¿ªäºæ£²æ", |
["Skyguard Outpost"] = "禦天è å´å¨", |
["Shartuul's Transporter"] = "å¤åæçå³éé", |
["Forge Camp: Wrath"] = "ç å¶å ´:æ¤æ", |
["Bash'ir Landing"] = "è²è¨±ç¾å¹³èº", |
["Crystal Spine"] = "æ°´æ¶èè", |
["Insidion's Perch"] = "å°å¸è¿ªæ©æ£²æ", |
["Furywing's Perch"] = "çæä¹ç¿¼æ£²æ", |
["Tirisfal"] = "æéæ¯æ³æå°", |
["Sunken Temple"] = "æ²æ²çç¥å»", |
} |
elseif GAME_LOCALE == "koKR" then |
lib:SetCurrentTranslations { |
["Azeroth"] = "ìì ë¡ì¤", |
["Eastern Kingdoms"] = "ëë¶ ìêµ", |
["Kalimdor"] = "칼림ëì´", |
["Outland"] = "ììëë", |
["Cosmic map"] = "ì¸ê³ ì§ë", |
["Ahn'Qiraj"] = "ìí´ë¼ì¦", |
["Alterac Mountains"] = "ìí°ë ì°ë§¥", |
["Alterac Valley"] = "ìí°ë ê³ê³¡", |
["Arathi Basin"] = "ìë¼ì ë¶ì§", |
["Arathi Highlands"] = "ìë¼ì ê³ ì", |
["Ashenvale"] = "ì¿ë¹ 골ì§ê¸°", |
["Auberdine"] = "ìì°ë²ë¤ì¸", |
["Azshara"] = "ìì¦ì¤ë¼", |
["Badlands"] = "í©ì¼ì ë ", |
["The Barrens"] = "ë¶ëª¨ì ë ", |
["Blackfathom Deeps"] = "ê²ìì¬ì°ì ëë½", |
["Blackrock Depths"] = "ê²ìë°ì ëë½", |
["Blackrock Mountain"] = "ê²ìë°ì ì°", |
["Blackrock Spire"] = "ê²ìë°ì 첨í", |
["Blackwing Lair"] = "ê²ìë ê° ë¥ì§", |
["Blasted Lands"] = "ì 주ë°ì ë ", |
["Booty Bay"] = "무ë²í", |
["Burning Steppes"] = "ë¶íë íì", |
["Darkshore"] = "ì´ë ì í´ì", |
["Darnassus"] = "ë¤ë¥´ëìì¤", |
["The Deadmines"] = "죽ìì íê´", |
["Deadwind Pass"] = "죽ìì ê³ ê°", |
["Deeprun Tram"] = "ê¹ìêµ´ ì§íì² ", |
["Desolace"] = "ìíì§ ë ", |
["Dire Maul"] = "íí¬ì ì ì¥", |
["Dire Maul (East)"] = "íí¬ì ì ì¥ ëë¶", |
["Dire Maul (West)"] = "íí¬ì ì ì¥ ìë¶", |
["Dire Maul (North)"] = "íí¬ì ì ì¥ ë¶ë¶", |
["Dun Morogh"] = "ë 모ë¡", |
["Durotar"] = "ëë¡í", |
["Duskwood"] = "ê·¸ëì²", |
["Dustwallow Marsh"] = "먼ì§ì§í ìµì§ë", |
["Eastern Plaguelands"] = "ëë¶ ìë³ì§ë", |
["Elwynn Forest"] = "ìì ì²", |
["Everlook"] = "ëë§ë£¨ ë§ì", |
["Felwood"] = "ì ë ¹ì ì²", |
["Feralas"] = "íëë¼ì¤", |
["The Forbidding Sea"] = "ì±ëíí í´ì", |
["Gadgetzan"] = "ê°ì ¯ì", |
["Gates of Ahn'Qiraj"] = "ìí´ë¼ì¦ ì±ë¬¸", |
["Gnomeregan"] = "ë리건", |
["The Great Sea"] = "ëí´", |
["Grom'gol Base Camp"] = "그롬골 주ëì§", |
["Hall of Legends"] = "ì ì¤ì ì ë¹", |
["Hillsbrad Foothills"] = "íì¤ë¸ëë 구ë¦ì§", |
["The Hinterlands"] = "ëë¶ ë´ë¥ì§", |
["Hyjal"] = "íì´ì", |
["Hyjal Summit"] = "íì´ì ì ì", |
["Ironforge"] = "ìì´ì¸í¬ì§", |
["Loch Modan"] = "ëª¨ë¨ í¸ì", |
["Lower Blackrock Spire"] = "ê²ìë°ì 첨í í층", |
["Maraudon"] = "ë§ë¼ì°ë", |
["Menethil Harbor"] = "ë©ë¤ì¤ í구", |
["Molten Core"] = "íì° ì¬ì¥ë¶", |
["Moonglade"] = "ë¬ì ì²", |
["Mulgore"] = "ë©ê³ ì´", |
["Naxxramas"] = "ëì¤ë¼ë§ì¤", |
["Onyxia's Lair"] = "ì¤ëììì ë¥ì§", |
["Orgrimmar"] = "ì¤ê·¸ë¦¬ë§", |
["Ratchet"] = "í±ëí", |
["Ragefire Chasm"] = "ì±ëë¶ê¸¸ í곡", |
["Razorfen Downs"] = "ê°ìë©êµ´ 구ë¦", |
["Razorfen Kraul"] = "ê°ìë©êµ´ ì°ë¦¬", |
["Redridge Mountains"] = "ë¶ìë§ë£¨ ì°ë§¥", |
["Ruins of Ahn'Qiraj"] = "ìí´ë¼ì¦ íí", |
["Scarlet Monastery"] = "ë¶ìììêµ° ìëì", |
["Scholomance"] = "ì¤ì¹¼ë¡ë§¨ì¤", |
["Searing Gorge"] = "ì´ê¸ê±°ë¦¬ë í곡", |
["Shadowfang Keep"] = "그림ìì¡ê³³ë ì±ì±", |
["Silithus"] = "ì¤ë¦¬ëì¤", |
["Silverpine Forest"] = "ìë¹ìë무 ì²", |
["The Stockade"] = "ì¤í°ìë ì§íê°ì¥", |
["Stonard"] = "ì¤í ëë", |
["Stonetalon Mountains"] = "ëë°í± ì°ë§¥", |
["Stormwind City"] = "ì¤í°ìë", |
["Stranglethorn Vale"] = "ê°ìë¤ë¶ 골ì§ê¸°", |
["Stratholme"] = "ì¤í¸ë¼ìë¦", |
["Swamp of Sorrows"] = "ì¬íì ëª", |
["Tanaris"] = "íë리ì¤", |
["Teldrassil"] = "í ëëì¤", |
["Temple of Ahn'Qiraj"] = "ìí´ë¼ì¦ ì¬ì", |
["The Temple of Atal'Hakkar"] = "ìíí카르 ì ì ", |
["Theramore Isle"] = "í ë¼ëª¨ì´ ì¬", |
["Thousand Needles"] = "ë²ì¯êµ¬ë¦ ë´ì°ë¦¬", |
["Thunder Bluff"] = "ì¬ë ë¸ë¬í", |
["Tirisfal Glades"] = "í°ë¦¬ì¤í ì²", |
["Uldaman"] = "ì¸ë¤ë§", |
["Un'Goro Crater"] = "ì´ê³ ë¡ ë¶í구", |
["Undercity"] = "ì¸ëìí°", |
["Upper Blackrock Spire"] = "ê²ìë°ì 첨í ì층", |
["Wailing Caverns"] = "íµê³¡ì ëêµ´", |
["Warsong Gulch"] = "ì ìë ¸ë í곡", |
["Western Plaguelands"] = "ìë¶ ìë³ì§ë", |
["Westfall"] = "ìë¶ ëª°ë½ì§ë", |
["Wetlands"] = "ì ìµì§", |
["Winterspring"] = "ì¬ëª ì ì¤ì", |
["Zul'Farrak"] = "ì¤íë½", |
["Zul'Gurub"] = "ì¤êµ¬ë£¹", |
["Champions' Hall"] = "ì©ì¬ì ì ë¹", |
["Blade's Edge Arena"] = "ì¹¼ë í¬ê¸°ì¥", |
["Nagrand Arena"] = "ëê·¸ëë í¬ê¸°ì¥", |
["Ruins of Lordaeron"] = "ë¡ë°ë¡ ì íí", |
["Twisting Nether"] = "ë¤í린 í©ì²", |
["The Veiled Sea"] = "ì¥ë§ì ë°ë¤", |
["The North Sea"] = "ë¶í´", -- check |
["Armory"] = "ë¬´ê¸°ê³ ", |
["Library"] = "ëìê´", |
["Cathedral"] = "ëì±ë¹", |
["Graveyard"] = "ë¬ì§", |
-- Burning Crusade |
-- Subzones used for displaying instances. |
["Plaguewood"] = "ìë³ì ì²", |
["Hellfire Citadel"] = "ì§ì¥ë¶ ì±ì±", |
["Auchindoun"] = "ìí¨ë", |
["The Bone Wastes"] = "í´ê³¨ 무ë¤", -- Substitute for Auchindoun, since this is what shows on the minimap. |
["Ring of Observance"] = "ê·ì¨ì ê´ì¥", |
["Coilfang Reservoir"] = "ê°í´ì¡ê³³ë ì ìì§", |
["Amani Pass"] = "ìë§ë ê³ ê°", |
["Azuremyst Isle"] = "íëìê° ì¬", |
["Bloodmyst Isle"] = "íë¹ìê° ì¬", |
["Eversong Woods"] = "ììë ¸ë ì²", |
["Ghostlands"] = "ì ë ¹ì ë ", |
["The Exodar"] = "ììë¤ë¥´", |
["Silvermoon City"] = "ì¤ë²ë¬¸", |
["Shadowmoon Valley"] = "ì´ë ë¬ ê³¨ì§ê¸°", |
["Black Temple"] = "ê²ì ì¬ì", |
["Terokkar Forest"] = "í ë¡ì¹´ë¥´ ì²", |
["Auchenai Crypts"] = "ìí¤ëì´ ë©ê³¨ë¹", |
["Mana-Tombs"] = "ë§ë 무ë¤", |
["Shadow Labyrinth"] = "ì´ë ì 미ê¶", |
["Sethekk Halls"] = "ì¸ë°í¬ ì ë¹", |
["Hellfire Peninsula"] = "ì§ì¥ë¶ ë°ë", |
["The Dark Portal"] = "ì´ë ì 문", |
["Hellfire Ramparts"] = "ì§ì¥ë¶ ì±ë£¨", |
["The Blood Furnace"] = "í¼ì ì©ê´ë¡", |
["The Shattered Halls"] = "ì¼ì¤ë¬ì§ ìì ì ë¹", |
["Magtheridon's Lair"] = "ë§ê·¸í 리ëì ë¥ì§", |
["Nagrand"] = "ëê·¸ëë", |
["Zangarmarsh"] = "ì¥ê°ë¥´ ìµì§ë", |
["The Slave Pens"] = "ê°ì ë ¸ìì", |
["The Underbog"] = "ì§íìë ", |
["The Steamvault"] = "ì¦ê¸° ì ì¥ê³ ", |
["Serpentshrine Cavern"] = "ë¶ë± ì ë¨", |
["Blade's Edge Mountains"] = "ì¹¼ë ì°ë§¥", |
["Gruul's Lair"] = "그룰ì ë¥ì§", |
["Netherstorm"] = "í©ì²ì íí", |
["Tempest Keep"] = "ííì° ìì", |
["The Mechanar"] = "ë©ì¹´ë르", |
["The Botanica"] = "ì ë¡ì ì ì", |
["The Arcatraz"] = "ìì¹´í¸ë¼ì¦", |
["The Eye"] = "ë", -- check |
["Eye of the Storm"] = "ííì ë", |
["Shattrath City"] = "ì¤í¸ë¼ì¤", |
["Karazhan"] = "ì¹´ë¼ì", |
["Caverns of Time"] = "ìê°ì ëêµ´", |
["Old Hillsbrad Foothills"] = "ì íì¤ë¸ëë 구ë¦ì§", |
["The Black Morass"] = "ê²ìëª", |
["Night Elf Village"] = "ëì´í¸ ìí ë§ì", |
["Horde Encampment"] = "í¸ë ì¼ìì§", |
["Alliance Base"] = "ì¼ë¼ì´ì¸ì¤ 주ëì§", |
["Zul'Aman"] = "ì¤ìë§", |
["Quel'thalas"] = "ì¿ ìíë¼ì¤", |
["Isle of Quel'Danas"] = "ì¿ ìë¤ëì¤ ì¬", |
["Sunwell Plateau"] = "íìì ê³ ì", |
["Magisters' Terrace"] = "ë§ë²íìì ì ì", |
-- Blade's Edge Plateau |
["Forge Camp: Terror"] = "ê³µí¬ì ê´´ì² ë¡ ê¸°ì§", |
["Vortex Pinnacle"] = "ìì©ëì´ ê³ ì", |
["Rivendark's Perch"] = "리ë¸ë¤í¬ì ë¥ì§", |
["Ogri'la"] = "ì¤ê·¸ë¦´ë¼", |
["Obsidia's Perch"] = "ìµìëìì ë¥ì§", |
["Skyguard Outpost"] = "íëê²½ë¹ë ì ì´ê¸°ì§", |
["Shartuul's Transporter"] = "ì¤í´ì ìê°ì´ë기", |
["Forge Camp: Wrath"] = "ê²©ë ¸ì ê´´ì² ë¡ ê¸°ì§", |
["Bash'ir Landing"] = "ë°ì¬ë¥´ ìì§", |
["Crystal Spine"] = "ìì ë기", |
["Insidion's Perch"] = "ì¸ìëì¨ì ë¥ì§", |
["Furywing's Perch"] = "í¨ë¦¬ìì ë¥ì§", |
} |
elseif GAME_LOCALE == "esES" then |
lib:SetCurrentTranslations { |
["Azeroth"] = "Azeroth", |
["Eastern Kingdoms"] = "Reinos del Este", |
["Kalimdor"] = "Kalimdor", |
["Outland"] = "Terrallende", |
["Cosmic map"] = "Mapa cósmico", |
["Ahn'Qiraj"] = "Ahn'Qiraj", |
["Alterac Mountains"] = "Montañas de Alterac", |
["Alterac Valley"] = "Valle de Alterac", |
["Arathi Basin"] = "Cuenca de Arathi", |
["Arathi Highlands"] = "Tierras Altas de Arathi", |
["Ashenvale"] = "Vallefresno", |
["Auberdine"] = "Auberdine", |
["Azshara"] = "Azshara", |
["Badlands"] = "Tierras Inhóspitas", |
["The Barrens"] = "Los BaldÃos", |
["Blackfathom Deeps"] = "Cavernas de Brazanegra", |
["Blackrock Depths"] = "Profundidades de Roca Negra", |
["Blackrock Mountain"] = "Montaña Roca Negra", |
["Blackrock Spire"] = "Cumbre de Roca Negra", |
["Blackwing Lair"] = "Guarida Alanegra", |
["Blasted Lands"] = "Las Tierras Devastadas", |
["Booty Bay"] = "BahÃa del BotÃn", |
["Burning Steppes"] = "Las Estepas Ardientes", |
["Darkshore"] = "Costa Oscura", |
["Darnassus"] = "Darnassus", |
["The Deadmines"] = "Las Minas de la Muerte", |
["Deadwind Pass"] = "Paso de la Muerte", |
["Deeprun Tram"] = "TranvÃa Subterráneo", |
["Desolace"] = "Desolace", |
["Dire Maul"] = "La Masacre", |
["Dire Maul (East)"] = "La Masacre (Este)", |
["Dire Maul (West)"] = "La Masacre (Oeste)", |
["Dire Maul (North)"] = "La Masacre (Norte)", |
["Dun Morogh"] = "Dun Morogh", |
["Durotar"] = "Durotar", |
["Duskwood"] = "Bosque del Ocaso", |
["Dustwallow Marsh"] = "Marjal Revolcafango", |
["Eastern Plaguelands"] = "Tierras de la Peste del Este", |
["Elwynn Forest"] = "Bosque de Elwynn", |
["Everlook"] = "Vista Eterna", |
["Felwood"] = "Frondavil", |
["Feralas"] = "Feralas", |
["The Forbidding Sea"] = "Mar Adusto", |
["Gadgetzan"] = "Gadgetzan", |
["Gates of Ahn'Qiraj"] = "Puertas de Ahn'Qiraj", |
["Gnomeregan"] = "Gnomeregan", |
["The Great Sea"] = "Mare Magnum", |
["Grom'gol Base Camp"] = "Campamento Grom'gol", |
["Hall of Legends"] = "Sala de las Leyendas", |
["Hillsbrad Foothills"] = "Laderas de Trabalomas", |
["The Hinterlands"] = "Tierras del Interior", |
["Hyjal"] = "Hyjal", |
["Hyjal Summit"] = "Hyjal Summit", |
["Ironforge"] = "Forjaz", |
["Loch Modan"] = "Loch Modan", |
["Lower Blackrock Spire"] = "Cumbre inferior de Roca Negra", |
["Maraudon"] = "Maraudon", |
["Menethil Harbor"] = "Puerto de Menethil", |
["Molten Core"] = "Núcleo de Magma", |
["Moonglade"] = "Claro de la Luna", |
["Mulgore"] = "Mulgore", |
["Naxxramas"] = "Naxxramas", |
["Onyxia's Lair"] = "Guarida de Onyxia", |
["Orgrimmar"] = "Orgrimmar", |
["Ratchet"] = "Trinquete", |
["Ragefire Chasm"] = "Sima Ãgnea", |
["Razorfen Downs"] = "Zahúrda Rajacieno", |
["Razorfen Kraul"] = "Horado Rajacieno", |
["Redridge Mountains"] = "Montañas Crestagrana", |
["Ruins of Ahn'Qiraj"] = "Ruinas de Ahn'Qiraj", |
["Scarlet Monastery"] = "Monasterio Escarlata", |
["Scholomance"] = "Scholomance", |
["Searing Gorge"] = "La Garganta de Fuego", |
["Shadowfang Keep"] = "Castillo de Colmillo Oscuro", |
["Silithus"] = "Silithus", |
["Silverpine Forest"] = "Bosque de Argénteos", |
["The Stockade"] = "Las Mazmorras", |
--["Stonard"] = "", |
["Stonetalon Mountains"] = "Sierra Espolón", |
["Stormwind City"] = "Ciudad de Ventormenta", |
["Stormwind"] = "Ventormenta", |
["Stranglethorn Vale"] = "Vega de Tuercespina", |
["Stratholme"] = "Stratholme", |
["Swamp of Sorrows"] = "Pantano de las Penas", |
["Tanaris"] = "Tanaris", |
["Teldrassil"] = "Teldrassil", |
["Temple of Ahn'Qiraj"] = "El Templo de Ahn'Qiraj", |
["The Temple of Atal'Hakkar"] = "El Templo de Atal'Hakkar", |
["Theramore Isle"] = "Isla Theramore", |
["Thousand Needles"] = "Las Mil Agujas", |
["Thunder Bluff"] = "Cima del Trueno", |
["Tirisfal Glades"] = "Claros de Tirisfal", |
["Uldaman"] = "Uldaman", |
["Un'Goro Crater"] = "Cráter de Un'Goro", |
["Undercity"] = "Entrañas", |
["Upper Blackrock Spire"] = "Cumbre de Roca Negra", |
["Wailing Caverns"] = "Cuevas de los Lamentos", |
["Warsong Gulch"] = "Garganta Grito de Guerra", |
["Western Plaguelands"] = "Tierras de la Peste del Oeste", |
["Westfall"] = "Páramos de Poniente", |
["Wetlands"] = "Los Humedales", |
["Winterspring"] = "Cuna del Invierno", |
["Zul'Farrak"] = "Zul'Farrak", |
["Zul'Gurub"] = "Zul'Gurub", |
["Champions' Hall"] = "Sala de los Campeones", |
["Hall of Champions"] = "Sala de los Campeones", |
["Blade's Edge Arena"] = "Arena Filospada", |
["Nagrand Arena"] = "Arena de Nagrand", |
["Ruins of Lordaeron"] = "Ruinas de Lordaeron", -- check |
["Twisting Nether"] = "El VacÃo Abisal", |
["The Veiled Sea"] = "Mar de la Bruma", |
["The North Sea"] = "El Mar Norte", |
["Armory"] = "ArmerÃa", |
["Library"] = "Biblioteca", |
["Cathedral"] = "Catedral", |
["Graveyard"] = "Cementerio", |
-- Burning Crusade |
-- Subzones used for displaying instances. |
["Plaguewood"] = "Bosque de la Plaga", |
["Hellfire Citadel"] = "Ciudadela del Fuego Infernal", |
["Auchindoun"] = "Auchindoun", |
["The Bone Wastes"] = "El Vertedero de Huesos", |
["Ring of Observance"] = "CÃrculo de la Observancia", |
["Coilfang Reservoir"] = "Reserva Colmillo Torcido", |
["Amani Pass"] = "Paso de Amani", |
["Azuremyst Isle"] = "Isla Bruma Azur", |
["Bloodmyst Isle"] = "Isla Bruma de Sangre", |
["Eversong Woods"] = "Bosque Canción Eterna", |
["Ghostlands"] = "Tierras Fantasma", |
["The Exodar"] = "El Exodar", |
["Silvermoon City"] = "Ciudad de Lunargenta", |
["Shadowmoon Valley"] = "Valle Sombraluna", |
["Black Temple"] = "El Templo Oscuro", -- check |
["Terokkar Forest"] = "Bosque de Terokkar", |
["Auchenai Crypts"] = "Criptas Auchenai", |
["Mana-Tombs"] = "Tumbas de Maná", |
["Shadow Labyrinth"] = "Laberinto de las Sombras", |
["Sethekk Halls"] = "Salas Sethekk", |
["Hellfire Peninsula"] = "PenÃnsula del Fuego Infernal", |
["The Dark Portal"] = "El Portal Oscuro", |
["Hellfire Ramparts"] = "Murallas del Fuego Infernal", |
["The Blood Furnace"] = "El Horno de Sangre", |
["The Shattered Halls"] = "Las Salas Arrasadas", |
["Magtheridon's Lair"] = "Guarida de Magtheridon", -- check - Magtheradon /Magtheridon ?? |
["Nagrand"] = "Nagrand", |
["Zangarmarsh"] = "Marisma de Zangar", |
["The Slave Pens"] = "Recinto de los Esclavos", |
["The Underbog"] = "La Sotiénaga", |
["The Steamvault"] = "La Cámara de Vapor", |
["Serpentshrine Cavern"] = "Caverna Santuario Serpiente", -- check |
["Blade's Edge Mountains"] = "Montañas Filospada", |
["Gruul's Lair"] = "Guarida de Gruul", |
["Netherstorm"] = "Tormenta Abisal", |
["Tempest Keep"] = "El Castillo de la Tempestad", |
["The Mechanar"] = "El Mechanar", |
["The Botanica"] = "El Invernáculo", |
["The Arcatraz"] = "El Alcatraz", |
["The Eye"] = "El Ojo", -- check |
["Eye of the Storm"] = "Ojo de la Tormenta", |
["Shattrath City"] = "Ciudad de Shattrath", |
["Shattrath"] = "Shattrath", |
["Karazhan"] = "Karazhan", |
["Caverns of Time"] = "Cavernas del Tiempo", |
["Old Hillsbrad Foothills"] = "Viejas Laderas de Trabalomas", -- doesn't work in spanish anyway |
["The Black Morass"] = "La Ciénaga Negra", |
["Night Elf Village"] = "Night Elf Village", |
["Horde Encampment"] = "Horde Encampment", |
["Alliance Base"] = "Alliance Base", |
["Zul'Aman"] = "Zul'Aman", |
["Quel'thalas"] = "Quel'thalas", |
["Isle of Quel'Danas"] = "Isla de Quel'Danas", |
["Sunwell Plateau"] = "Meseta de la Fuente del Sol", |
["Magisters' Terrace"] = "Bancal Del Magister" , |
-- Blade's Edge Plateau |
["Forge Camp: Terror"] = "", |
["Vortex Pinnacle"] = "", |
["Rivendark's Perch"] = "", |
["Ogri'la"] = "", |
["Obsidia's Perch"] = "", |
["Skyguard Outpost"] = "", |
["Shartuul's Transporter"] = "", |
["Forge Camp: Wrath"] = "", |
["Bash'ir Landing"] = "", |
["Crystal Spine"] = "", |
["Insidion's Perch"] = "", |
["Furywing's Perch"] = "", |
["Tirisfal"] = "Tirisfal", |
["Sunken Temple"] = "El Templo de Sunken", |
} |
elseif GAME_LOCALE == "esMX" then |
lib:SetCurrentTranslations { |
["Azeroth"] = "Azeroth", |
["Eastern Kingdoms"] = "Reinos del Este", |
["Kalimdor"] = "Kalimdor", |
["Outland"] = "Terrallende", |
["Cosmic map"] = "Mapa cósmico", |
["Ahn'Qiraj"] = "Ahn'Qiraj", |
["Alterac Mountains"] = "Montañas de Alterac", |
["Alterac Valley"] = "Valle de Alterac", |
["Arathi Basin"] = "Cuenca de Arathi", |
["Arathi Highlands"] = "Tierras Altas de Arathi", |
["Ashenvale"] = "Vallefresno", |
["Auberdine"] = "Auberdine", |
["Azshara"] = "Azshara", |
["Badlands"] = "Tierras Inhóspitas", |
["The Barrens"] = "Los BaldÃos", |
["Blackfathom Deeps"] = "Cavernas de Brazanegra", |
["Blackrock Depths"] = "Profundidades de Roca Negra", |
["Blackrock Mountain"] = "Montaña Roca Negra", |
["Blackrock Spire"] = "Cumbre de Roca Negra", |
["Blackwing Lair"] = "Guarida Alanegra", |
["Blasted Lands"] = "Las Tierras Devastadas", |
["Booty Bay"] = "BahÃa del BotÃn", |
["Burning Steppes"] = "Las Estepas Ardientes", |
["Darkshore"] = "Costa Oscura", |
["Darnassus"] = "Darnassus", |
["The Deadmines"] = "Las Minas de la Muerte", |
["Deadwind Pass"] = "Paso de la Muerte", |
["Deeprun Tram"] = "TranvÃa Subterráneo", |
["Desolace"] = "Desolace", |
["Dire Maul"] = "La Masacre", |
["Dire Maul (East)"] = "La Masacre (Este)", |
["Dire Maul (West)"] = "La Masacre (Oeste)", |
["Dire Maul (North)"] = "La Masacre (Norte)", |
["Dun Morogh"] = "Dun Morogh", |
["Durotar"] = "Durotar", |
["Duskwood"] = "Bosque del Ocaso", |
["Dustwallow Marsh"] = "Marjal Revolcafango", |
["Eastern Plaguelands"] = "Tierras de la Peste del Este", |
["Elwynn Forest"] = "Bosque de Elwynn", |
["Everlook"] = "Vista Eterna", |
["Felwood"] = "Frondavil", |
["Feralas"] = "Feralas", |
["The Forbidding Sea"] = "Mar Adusto", |
["Gadgetzan"] = "Gadgetzan", |
["Gates of Ahn'Qiraj"] = "Puertas de Ahn'Qiraj", |
["Gnomeregan"] = "Gnomeregan", |
["The Great Sea"] = "Mare Magnum", |
["Grom'gol Base Camp"] = "Campamento Grom'gol", |
["Hall of Legends"] = "Sala de las Leyendas", |
["Hillsbrad Foothills"] = "Laderas de Trabalomas", |
["The Hinterlands"] = "Tierras del Interior", |
["Hyjal"] = "Hyjal", |
["Hyjal Summit"] = "Hyjal Summit", |
["Ironforge"] = "Forjaz", |
["Loch Modan"] = "Loch Modan", |
["Lower Blackrock Spire"] = "Cumbre inferior de Roca Negra", |
["Maraudon"] = "Maraudon", |
["Menethil Harbor"] = "Puerto de Menethil", |
["Molten Core"] = "Núcleo de Magma", |
["Moonglade"] = "Claro de la Luna", |
["Mulgore"] = "Mulgore", |
["Naxxramas"] = "Naxxramas", |
["Onyxia's Lair"] = "Guarida de Onyxia", |
["Orgrimmar"] = "Orgrimmar", |
["Ratchet"] = "Trinquete", |
["Ragefire Chasm"] = "Sima Ãgnea", |
["Razorfen Downs"] = "Zahúrda Rajacieno", |
["Razorfen Kraul"] = "Horado Rajacieno", |
["Redridge Mountains"] = "Montañas Crestagrana", |
["Ruins of Ahn'Qiraj"] = "Ruinas de Ahn'Qiraj", |
["Scarlet Monastery"] = "Monasterio Escarlata", |
["Scholomance"] = "Scholomance", |
["Searing Gorge"] = "La Garganta de Fuego", |
["Shadowfang Keep"] = "Castillo de Colmillo Oscuro", |
["Silithus"] = "Silithus", |
["Silverpine Forest"] = "Bosque de Argénteos", |
["The Stockade"] = "Las Mazmorras", |
--["Stonard"] = "", |
["Stonetalon Mountains"] = "Sierra Espolón", |
["Stormwind City"] = "Ciudad de Ventormenta", |
["Stormwind"] = "Ventormenta", |
["Stranglethorn Vale"] = "Vega de Tuercespina", |
["Stratholme"] = "Stratholme", |
["Swamp of Sorrows"] = "Pantano de las Penas", |
["Tanaris"] = "Tanaris", |
["Teldrassil"] = "Teldrassil", |
["Temple of Ahn'Qiraj"] = "El Templo de Ahn'Qiraj", |
["The Temple of Atal'Hakkar"] = "El Templo de Atal'Hakkar", |
["Theramore Isle"] = "Isla Theramore", |
["Thousand Needles"] = "Las Mil Agujas", |
["Thunder Bluff"] = "Cima del Trueno", |
["Tirisfal Glades"] = "Claros de Tirisfal", |
["Uldaman"] = "Uldaman", |
["Un'Goro Crater"] = "Cráter de Un'Goro", |
["Undercity"] = "Entrañas", |
["Upper Blackrock Spire"] = "Cumbre de Roca Negra", |
["Wailing Caverns"] = "Cuevas de los Lamentos", |
["Warsong Gulch"] = "Garganta Grito de Guerra", |
["Western Plaguelands"] = "Tierras de la Peste del Oeste", |
["Westfall"] = "Páramos de Poniente", |
["Wetlands"] = "Los Humedales", |
["Winterspring"] = "Cuna del Invierno", |
["Zul'Farrak"] = "Zul'Farrak", |
["Zul'Gurub"] = "Zul'Gurub", |
["Champions' Hall"] = "Sala de los Campeones", |
["Hall of Champions"] = "Sala de los Campeones", |
["Blade's Edge Arena"] = "Arena Filospada", |
["Nagrand Arena"] = "Arena de Nagrand", |
["Ruins of Lordaeron"] = "Ruinas de Lordaeron", -- check |
["Twisting Nether"] = "El VacÃo Abisal", |
["The Veiled Sea"] = "Mar de la Bruma", |
["The North Sea"] = "El Mar Norte", |
["Armory"] = "ArmerÃa", |
["Library"] = "Biblioteca", |
["Cathedral"] = "Catedral", |
["Graveyard"] = "Cementerio", |
-- Burning Crusade |
-- Subzones used for displaying instances. |
["Plaguewood"] = "Bosque de la Plaga", |
["Hellfire Citadel"] = "Ciudadela del Fuego Infernal", |
["Auchindoun"] = "Auchindoun", |
["The Bone Wastes"] = "El Vertedero de Huesos", |
["Ring of Observance"] = "CÃrculo de la Observancia", |
["Coilfang Reservoir"] = "Reserva Colmillo Torcido", |
["Amani Pass"] = "Paso de Amani", |
["Azuremyst Isle"] = "Isla Bruma Azur", |
["Bloodmyst Isle"] = "Isla Bruma de Sangre", |
["Eversong Woods"] = "Bosque Canción Eterna", |
["Ghostlands"] = "Tierras Fantasma", |
["The Exodar"] = "El Exodar", |
["Silvermoon City"] = "Ciudad de Lunargenta", |
["Shadowmoon Valley"] = "Valle Sombraluna", |
["Black Temple"] = "El Templo Oscuro", -- check |
["Terokkar Forest"] = "Bosque de Terokkar", |
["Auchenai Crypts"] = "Criptas Auchenai", |
["Mana-Tombs"] = "Tumbas de Maná", |
["Shadow Labyrinth"] = "Laberinto de las Sombras", |
["Sethekk Halls"] = "Salas Sethekk", |
["Hellfire Peninsula"] = "PenÃnsula del Fuego Infernal", |
["The Dark Portal"] = "El Portal Oscuro", |
["Hellfire Ramparts"] = "Murallas del Fuego Infernal", |
["The Blood Furnace"] = "El Horno de Sangre", |
["The Shattered Halls"] = "Las Salas Arrasadas", |
["Magtheridon's Lair"] = "Guarida de Magtheridon", -- check - Magtheradon /Magtheridon ?? |
["Nagrand"] = "Nagrand", |
["Zangarmarsh"] = "Marisma de Zangar", |
["The Slave Pens"] = "Recinto de los Esclavos", |
["The Underbog"] = "La Sotiénaga", |
["The Steamvault"] = "La Cámara de Vapor", |
["Serpentshrine Cavern"] = "Caverna Santuario Serpiente", -- check |
["Blade's Edge Mountains"] = "Montañas Filospada", |
["Gruul's Lair"] = "Guarida de Gruul", |
["Netherstorm"] = "Tormenta Abisal", |
["Tempest Keep"] = "El Castillo de la Tempestad", |
["The Mechanar"] = "El Mechanar", |
["The Botanica"] = "El Invernáculo", |
["The Arcatraz"] = "El Alcatraz", |
["The Eye"] = "El Ojo", -- check |
["Eye of the Storm"] = "Ojo de la Tormenta", |
["Shattrath City"] = "Ciudad de Shattrath", |
["Shattrath"] = "Shattrath", |
["Karazhan"] = "Karazhan", |
["Caverns of Time"] = "Cavernas del Tiempo", |
["Old Hillsbrad Foothills"] = "Viejas Laderas de Trabalomas", -- doesn't work in spanish anyway |
["The Black Morass"] = "La Ciénaga Negra", |
["Night Elf Village"] = "Night Elf Village", |
["Horde Encampment"] = "Horde Encampment", |
["Alliance Base"] = "Alliance Base", |
["Zul'Aman"] = "Zul'Aman", |
["Quel'thalas"] = "Quel'thalas", |
["Isle of Quel'Danas"] = "Isla de Quel'Danas", |
["Sunwell Plateau"] = "Meseta de la Fuente del Sol", |
["Magisters' Terrace"] = "Bancal Del Magister" , |
-- Blade's Edge Plateau |
["Forge Camp: Terror"] = "", |
["Vortex Pinnacle"] = "", |
["Rivendark's Perch"] = "", |
["Ogri'la"] = "", |
["Obsidia's Perch"] = "", |
["Skyguard Outpost"] = "", |
["Shartuul's Transporter"] = "", |
["Forge Camp: Wrath"] = "", |
["Bash'ir Landing"] = "", |
["Crystal Spine"] = "", |
["Insidion's Perch"] = "", |
["Furywing's Perch"] = "", |
["Tirisfal"] = "Tirisfal", |
["Sunken Temple"] = "El Templo de Sunken", |
} |
else |
error(("%s: Locale %q not supported"):format(MAJOR_VERSION, GAME_LOCALE)) |
end |
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ |
..\FrameXML\UI.xsd"> |
<Script file="LibBabble-Zone-3.0.lua" /> |
</Ui> |
## Interface: 20400 |
## LoadOnDemand: 1 |
## Title: Lib: Babble-Zone-3.0 |
## Notes: A library to help with localization of Zones. |
## Notes-deDE: BabbleLib ist eine Bibliothek, die bei der Lokalisierung helfen soll. |
## Notes-frFR: Une bibliothèque d'aide à la localisation. |
## Notes-esES: Una biblioteca para ayudar con las localizaciones. |
## Author: ckknight |
## X-eMail: ckknight@gmail.com |
## X-Category: Library |
## X-License: MIT |
LibStub\LibStub.lua |
lib.xml |
## Interface: 20400 |
## Title: Lib: AceHook-2.1 |
## Notes: AddOn development framework |
## Author: Ace Development Team |
## LoadOnDemand: 1 |
## X-Website: http://www.wowace.com |
## X-Category: Library |
## X-License: LGPL v2.1 + MIT for AceOO-2.0 |
## Dependencies: AceLibrary, AceOO-2.0 |
AceHook-2.1.lua |
--[[ |
Name: AceHook-2.1 |
Revision: $Rev$ |
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) |
Inspired By: Ace 1.x by Turan (turan@gryphon.com) |
Website: http://www.wowace.com/ |
Documentation: http://www.wowace.com/index.php/AceHook-2.1 |
SVN: http://svn.wowace.com/root/trunk/Ace2/AceHook-2.1 |
Description: Mixin to allow for safe hooking of functions, methods, and scripts. |
Dependencies: AceLibrary, AceOO-2.0 |
License: LGPL v2.1 |
]] |
local MAJOR_VERSION = "AceHook-2.1" |
local MINOR_VERSION = "$Revision$" |
-- This ensures the code is only executed if the libary doesn't already exist, or is a newer version |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end |
--[[--------------------------------------------------------------------------------- |
Create the library object |
----------------------------------------------------------------------------------]] |
local AceOO = AceLibrary:GetInstance("AceOO-2.0") |
local AceHook = AceOO.Mixin { |
"Hook", |
"HookScript", |
"SecureHook", |
"SecureHookScript", |
"Unhook", |
"UnhookAll", |
"HookReport", |
"IsHooked", |
} |
--[[--------------------------------------------------------------------------------- |
Library Definitions |
----------------------------------------------------------------------------------]] |
local protectedScripts = { |
OnClick = true, |
} |
local _G = getfenv(0) |
local handlers, scripts, actives, registry, onceSecure |
--[[--------------------------------------------------------------------------------- |
Private definitions (Not exposed) |
----------------------------------------------------------------------------------]] |
local new, del |
do |
local list = setmetatable({}, {__mode = "k"}) |
function new() |
local t = next(list) |
if not t then |
return {} |
end |
list[t] = nil |
return t |
end |
function del(t) |
setmetatable(t, nil) |
for k in pairs(t) do |
t[k] = nil |
end |
list[t] = true |
end |
end |
local function createFunctionHook(self, func, handler, orig, secure) |
if not secure then |
if type(handler) == "string" then |
-- The handler is a method, need to self it |
local uid |
uid = function(...) |
if actives[uid] then |
return self[handler](self, ...) |
else |
return orig(...) |
end |
end |
return uid |
else |
-- The handler is a function, just call it |
local uid |
uid = function(...) |
if actives[uid] then |
return handler(...) |
else |
return orig(...) |
end |
end |
return uid |
end |
else |
-- secure hooks don't call the original method |
if type(handler) == "string" then |
-- The handler is a method, need to self it |
local uid |
uid = function(...) |
if actives[uid] then |
return self[handler](self, ...) |
end |
end |
return uid |
else |
-- The handler is a function, just call it |
local uid |
uid = function(...) |
if actives[uid] then |
return handler(...) |
end |
end |
return uid |
end |
end |
end |
local function createMethodHook(self, object, method, handler, orig, secure) |
if not secure then |
if type(handler) == "string" then |
local uid |
uid = function(...) |
if actives[uid] then |
return self[handler](self, ...) |
else |
return orig(...) |
end |
end |
return uid |
else |
-- The handler is a function, just call it |
local uid |
uid = function(...) |
if actives[uid] then |
return handler(...) |
else |
return orig(...) |
end |
end |
return uid |
end |
else |
-- secure hooks don't call the original method |
if type(handler) == "string" then |
local uid |
uid = function(...) |
if actives[uid] then |
return self[handler](self, ...) |
end |
end |
return uid |
else |
-- The handler is a function, just call it |
local uid |
uid = function(...) |
if actives[uid] then |
return handler(...) |
end |
end |
return uid |
end |
end |
end |
local function hookFunction(self, func, handler, secure) |
local orig = _G[func] |
if not orig or type(orig) ~= "function" then |
AceHook:error("Attempt to hook a non-existant function %q", func) |
end |
if not handler then |
handler = func |
end |
local uid = registry[self][func] |
if uid then |
if actives[uid] then |
-- We have an active hook from this source. Don't multi-hook |
AceHook:error("%q already has an active hook from this source.", func) |
end |
if handlers[uid] == handler then |
-- The hook is inactive, so reactivate it |
actives[uid] = true |
return |
else |
self.hooks[func] = nil |
registry[self][func] = nil |
handlers[uid] = nil |
uid = nil |
end |
end |
if type(handler) == "string" then |
if type(self[handler]) ~= "function" then |
AceHook:error("Could not find the the handler %q when hooking function %q", handler, func) |
end |
elseif type(handler) ~= "function" then |
AceHook:error("Could not find the handler you supplied when hooking %q", func) |
end |
uid = createFunctionHook(self, func, handler, orig, secure) |
registry[self][func] = uid |
actives[uid] = true |
handlers[uid] = handler |
if not secure then |
_G[func] = uid |
self.hooks[func] = orig |
else |
hooksecurefunc(func, uid) |
end |
end |
local function unhookFunction(self, func) |
if not registry[self][func] then |
AceHook:error("Tried to unhook %q which is not currently hooked.", func) |
end |
local uid = registry[self][func] |
if actives[uid] then |
-- See if we own the global function |
if self.hooks[func] and _G[func] == uid then |
_G[func] = self.hooks[func] |
self.hooks[func] = nil |
registry[self][func] = nil |
handlers[uid] = nil |
actives[uid] = nil |
-- Magically all-done |
else |
actives[uid] = nil |
end |
end |
end |
local donothing = function() end |
local function hookMethod(self, obj, method, handler, script, secure) |
if not handler then |
handler = method |
end |
if not obj or type(obj) ~= "table" then |
AceHook:error("The object you supplied could not be found, or isn't a table.") |
end |
local uid = registry[self][obj] and registry[self][obj][method] |
if uid then |
if actives[uid] then |
-- We have an active hook from this source. Don't multi-hook |
AceHook:error("%q already has an active hook from this source.", method) |
end |
if handlers[uid] == handler then |
-- The hook is inactive, reactivate it. |
actives[uid] = true |
return |
else |
if self.hooks[obj] then |
self.hooks[obj][method] = nil |
end |
registry[self][obj][method] = nil |
handlers[uid] = nil |
actives[uid] = nil |
scripts[uid] = nil |
uid = nil |
end |
end |
if type(handler) == "string" then |
if type(self[handler]) ~= "function" then |
AceHook:error("Could not find the handler %q you supplied when hooking method %q", handler, method) |
end |
elseif type(handler) ~= "function" then |
AceHook:error("Could not find the handler you supplied when hooking method %q", method) |
end |
local orig |
if script then |
if not obj.GetScript then |
AceHook:error("The object you supplied does not have a GetScript method.") |
end |
if not obj:HasScript(method) then |
AceHook:error("The object you supplied doesn't allow the %q method.", method) |
end |
orig = obj:GetScript(method) |
if type(orig) ~= "function" then |
-- Sometimes there is not a original function for a script. |
orig = donothing |
end |
else |
orig = obj[method] |
end |
if not orig then |
AceHook:error("Could not find the method or script %q you are trying to hook.", method) |
end |
if not self.hooks[obj] then |
self.hooks[obj] = new() |
end |
if not registry[self][obj] then |
registry[self][obj] = new() |
end |
local uid = createMethodHook(self, obj, method, handler, orig, secure) |
registry[self][obj][method] = uid |
actives[uid] = true |
handlers[uid] = handler |
scripts[uid] = script and true or nil |
if script then |
if not secure then |
obj:SetScript(method, uid) |
self.hooks[obj][method] = orig |
else |
obj:HookScript(method, uid) |
end |
else |
if not secure then |
obj[method] = uid |
self.hooks[obj][method] = orig |
else |
hooksecurefunc(obj, method, uid) |
end |
end |
end |
local function unhookMethod(self, obj, method) |
if not registry[self][obj] or not registry[self][obj][method] then |
AceHook:error("Attempt to unhook a method %q that is not currently hooked.", method) |
return |
end |
local uid = registry[self][obj][method] |
if actives[uid] then |
if scripts[uid] then -- If this is a script |
if obj:GetScript(method) == uid then |
-- We own the script. Revert to normal. |
if self.hooks[obj][method] == donothing then |
obj:SetScript(method, nil) |
else |
obj:SetScript(method, self.hooks[obj][method]) |
end |
self.hooks[obj][method] = nil |
registry[self][obj][method] = nil |
handlers[uid] = nil |
scripts[uid] = nil |
actives[uid] = nil |
else |
actives[uid] = nil |
end |
else |
if self.hooks[obj] and self.hooks[obj][method] and obj[method] == uid then |
-- We own the method. Revert to normal. |
obj[method] = self.hooks[obj][method] |
self.hooks[obj][method] = nil |
registry[self][obj][method] = nil |
handlers[uid] = nil |
actives[uid] = nil |
else |
actives[uid] = nil |
end |
end |
end |
if self.hooks[obj] and not next(self.hooks[obj]) then |
self.hooks[obj] = del(self.hooks[obj]) |
end |
if not next(registry[self][obj]) then |
registry[self][obj] = del(registry[self][obj]) |
end |
end |
-- ("function" [, handler] [, hookSecure]) or (object, "method" [, handler] [, hookSecure]) |
function AceHook:Hook(object, method, handler, hookSecure) |
if type(object) == "string" then |
method, handler, hookSecure = object, method, handler |
if handler == true then |
handler, hookSecure = nil, true |
end |
AceHook:argCheck(handler, 3, "function", "string", "nil") |
AceHook:argCheck(hookSecure, 4, "boolean", "nil") |
if issecurevariable(method) or onceSecure[method] then |
if hookSecure then |
onceSecure[method] = true |
else |
AceHook:error("Attempt to hook secure function %q. Use `SecureHook' or add `true' to the argument list to override.", method) |
end |
end |
hookFunction(self, method, handler, false) |
else |
if handler == true then |
handler, hookSecure = nil, true |
end |
AceHook:argCheck(object, 2, "table") |
AceHook:argCheck(method, 3, "string") |
AceHook:argCheck(handler, 4, "function", "string", "nil") |
AceHook:argCheck(hookSecure, 5, "boolean", "nil") |
if not object[method] then |
AceHook:error("Attempt to hook method %q failed, it does not exist in the given object %q.", method, object) |
end |
if not hookSecure and issecurevariable(object, method) then |
AceHook:error("Attempt to hook secure method %q. Use `SecureHook' or add `true' to the argument list to override.", method) |
end |
hookMethod(self, object, method, handler, false, false) |
end |
end |
-- ("function", handler) or (object, "method", handler) |
function AceHook:SecureHook(object, method, handler) |
if type(object) == "string" then |
method, handler = object, method |
AceHook:argCheck(handler, 3, "function", "string", "nil") |
hookFunction(self, method, handler, true) |
else |
AceHook:argCheck(object, 2, "table") |
AceHook:argCheck(method, 3, "string") |
AceHook:argCheck(handler, 4, "function", "string", "nil") |
if not object[method] then |
AceHook:error("Attempt to hook method %q failed, it does not exist in the given object %q.", method, object) |
end |
hookMethod(self, object, method, handler, false, true) |
end |
end |
function AceHook:HookScript(frame, script, handler) |
AceHook:argCheck(frame, 2, "table") |
if not frame[0] or type(frame.IsProtected) ~= "function" then |
AceHook:error("Bad argument #2 to `HookScript'. Expected frame.") |
end |
AceHook:argCheck(script, 3, "string") |
AceHook:argCheck(handler, 4, "function", "string", "nil") |
if frame:IsProtected() and protectedScripts[script] then |
AceHook:error("Cannot hook secure script %q.", script) |
end |
hookMethod(self, frame, script, handler, true, false) |
end |
function AceHook:SecureHookScript(frame, script, handler) |
AceHook:argCheck(frame, 2, "table") |
if not frame[0] or type(frame.IsProtected) ~= "function" then |
AceHook:error("Bad argument #2 to `HookScript'. Expected frame.") |
end |
AceHook:argCheck(script, 3, "string") |
AceHook:argCheck(handler, 4, "function", "string", "nil") |
hookMethod(self, frame, script, handler, true, true) |
end |
-- ("function") or (object, "method") |
function AceHook:IsHooked(obj, method) |
if type(obj) == "string" then |
if registry[self][obj] and actives[registry[self][obj]] then |
return true, handlers[registry[self][obj]] |
end |
else |
AceHook:argCheck(obj, 2, "string", "table") |
AceHook:argCheck(method, 3, "string") |
if registry[self][obj] and registry[self][obj][method] and actives[registry[self][obj][method]] then |
return true, handlers[registry[self][obj][method]] |
end |
end |
return false, nil |
end |
-- ("function") or (object, "method") |
function AceHook:Unhook(obj, method) |
if type(obj) == "string" then |
unhookFunction(self, obj) |
else |
AceHook:argCheck(obj, 2, "string", "table") |
AceHook:argCheck(method, 3, "string") |
unhookMethod(self, obj, method) |
end |
end |
function AceHook:UnhookAll() |
if type(registry[self]) ~= "table" then return end |
for key, value in pairs(registry[self]) do |
if type(key) == "table" then |
for method in pairs(value) do |
self:Unhook(key, method) |
end |
else |
self:Unhook(key) |
end |
end |
end |
function AceHook:HookReport() |
DEFAULT_CHAT_FRAME:AddMessage("This is a list of all active hooks for this object:") |
if not next(registry[self]) then |
DEFAULT_CHAT_FRAME:AddMessage("No hooks") |
end |
for key, value in pairs(registry[self]) do |
if type(value) == "table" then |
for method, uid in pairs(value) do |
DEFAULT_CHAT_FRAME:AddMessage(("object: %s method: %q |cff%s|r%s"):format(tostring(key), method, actives[uid] and "00ff00Active" or "ffff00Inactive", not self.hooks[key][method] and " |cff7f7fff-Secure-|r" or "")) |
end |
else |
DEFAULT_CHAT_FRAME:AddMessage(("function: %q |cff%s|r%s"):format(tostring(key), actives[value] and "00ff00Active" or "ffff00Inactive", not self.hooks[key] and " |cff7f7fff-Secure-|r" or "")) |
end |
end |
end |
function AceHook:OnInstanceInit(object) |
if not object.hooks then |
object.hooks = new() |
end |
if not registry[object] then |
registry[object] = new() |
end |
end |
AceHook.OnManualEmbed = AceHook.OnInstanceInit |
function AceHook:OnEmbedDisable(target) |
self.UnhookAll(target) |
end |
local function activate(self, oldLib, oldDeactivate) |
AceHook = self |
self.handlers = oldLib and oldLib.handlers or {} |
self.registry = oldLib and oldLib.registry or {} |
self.scripts = oldLib and oldLib.scripts or {} |
self.actives = oldLib and oldLib.actives or {} |
self.onceSecure = oldLib and oldLib.onceSecure or {} |
handlers = self.handlers |
registry = self.registry |
scripts = self.scripts |
actives = self.actives |
onceSecure = self.onceSecure |
self:activate(oldLib, oldDeactivate) |
if oldDeactivate then |
oldDeactivate(oldLib) |
end |
end |
AceLibrary:Register(AceHook, MAJOR_VERSION, MINOR_VERSION, activate) |
## Interface: 20400 |
## Title: Lib: AceLocale-2.2 |
## Notes: AddOn development framework |
## Author: Ace Development Team |
## LoadOnDemand: 1 |
## X-Website: http://www.wowace.com |
## X-Category: Library |
## X-License: LGPL v2.1 + MIT for AceOO-2.0 |
## Dependencies: AceLibrary |
AceLocale-2.2.lua |
AceLocale-2.2-2.lua |
--[[ |
Name: AceLocale-2.2 |
Revision: $Rev$ |
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) |
Inspired By: Ace 1.x by Turan (turan@gryphon.com) |
Website: http://www.wowace.com/ |
Documentation: http://www.wowace.com/index.php/AceLocale-2.2 |
SVN: http://svn.wowace.com/root/trunk/Ace2/AceLocale-2.2 |
Description: Localization library for addons to use to handle proper |
localization and internationalization. |
Dependencies: AceLibrary |
License: LGPL v2.1 |
]] |
local MAJOR_VERSION = "AceLocale-2.2" |
local MINOR_VERSION = "$Revision$" |
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end |
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
local AceLocale = {} |
AceLocale.prototype = { class = AceLocale } |
local BASE_TRANSLATIONS, DEBUGGING, TRANSLATIONS, BASE_LOCALE, TRANSLATION_TABLES, REVERSE_TRANSLATIONS, STRICTNESS, DYNAMIC_LOCALES, CURRENT_LOCALE, NAME |
local _G = _G |
local rawget = rawget |
local rawset = rawset |
local type = type |
local pairs = pairs |
local next = next |
local getmetatable = getmetatable |
local setmetatable = setmetatable |
local GetTime = GetTime |
local geterrorhandler = geterrorhandler |
local pcall = pcall |
local ipairs = ipairs |
local GetLocale = GetLocale |
local newRegistries = {} |
local scheduleClear |
local lastSelf |
local strict__index = function(self, key) |
lastSelf = self |
local value = (rawget(self, TRANSLATIONS) or AceLocale.prototype)[key] |
rawset(self, key, value) |
return value |
end |
local nonstrict__index = function(self, key) |
lastSelf = self |
local t = rawget(self, TRANSLATIONS) |
if t then |
local value = rawget(t, key) |
if value then |
rawset(self, key, value) |
return value |
end |
end |
local value = (rawget(self, BASE_TRANSLATIONS) or AceLocale.prototype)[key] |
rawset(self, key, value) |
return value |
end |
local __newindex = function(self, k, v) |
if type(v) ~= "function" and type(k) ~= "table" then |
AceLocale.error(self, "Cannot change the values of an AceLocale instance.") |
end |
rawset(self, k, v) |
end |
local __tostring = function(self) |
if type(rawget(self, 'GetLibraryVersion')) == "function" then |
return self:GetLibraryVersion() |
else |
return "AceLocale(" .. self[NAME] .. ")" |
end |
end |
local function clearCache(self) |
for k, v in pairs(AceLocale.prototype) do |
if type(v) == "function" and type(rawget(self, k)) == "function" then |
self[k] = nil |
end |
end |
if not rawget(self, BASE_TRANSLATIONS) then |
return |
end |
local cache = self[BASE_TRANSLATIONS] |
rawset(self, REVERSE_TRANSLATIONS, nil) |
for k in pairs(self) do |
if rawget(cache, k) ~= nil then |
self[k] = nil |
end |
end |
rawset(self, 'tmp', true) |
self.tmp = nil |
end |
local strict_instance_mt, nonstrict_instance_mt |
local baseTranslations_mt |
local function refixInstance(instance) |
if getmetatable(instance) then |
setmetatable(instance, nil) |
end |
local translations = instance[TRANSLATIONS] |
if translations then |
if getmetatable(translations) then |
setmetatable(translations, nil) |
end |
local baseTranslations = instance[BASE_TRANSLATIONS] |
if getmetatable(baseTranslations) then |
setmetatable(baseTranslations, nil) |
end |
if translations == baseTranslations or instance[STRICTNESS] then |
setmetatable(instance, strict_instance_mt) |
setmetatable(translations, baseTranslations_mt) |
else |
setmetatable(instance, nonstrict_instance_mt) |
setmetatable(baseTranslations, baseTranslations_mt) |
end |
else |
setmetatable(instance, strict_instance_mt) |
end |
clearCache(instance) |
newRegistries[instance] = true |
scheduleClear() |
return instance |
end |
function AceLocale:new(name) |
self:argCheck(name, 2, "string") |
if self.registry[name] and type(rawget(self.registry[name], 'GetLibraryVersion')) ~= "function" then |
return self.registry[name] |
end |
AceLocale.registry[name] = refixInstance({ |
[STRICTNESS] = false, |
[NAME] = name, |
}) |
newRegistries[AceLocale.registry[name]] = true |
return AceLocale.registry[name] |
end |
function AceLocale.prototype:EnableDebugging() |
if rawget(self, BASE_TRANSLATIONS) then |
AceLocale.error(self, "Cannot enable debugging after a translation has been registered.") |
end |
rawset(self, DEBUGGING, true) |
end |
function AceLocale.prototype:EnableDynamicLocales(override) |
AceLocale.argCheck(self, override, 2, "boolean", "nil") |
if not override and rawget(self, BASE_TRANSLATIONS) then |
AceLocale.error(self, "Cannot enable dynamic locales after a translation has been registered.") |
end |
if not rawget(self, DYNAMIC_LOCALES) then |
rawset(self, DYNAMIC_LOCALES, true) |
if rawget(self, BASE_LOCALE) then |
if not rawget(self, TRANSLATION_TABLES) then |
rawset(self, TRANSLATION_TABLES, {}) |
end |
self[TRANSLATION_TABLES][self[BASE_LOCALE]] = self[BASE_TRANSLATIONS] |
self[TRANSLATION_TABLES][self[CURRENT_LOCALE]] = self[TRANSLATIONS] |
end |
end |
end |
function AceLocale.prototype:RegisterTranslations(locale, func) |
AceLocale.argCheck(self, locale, 2, "string") |
AceLocale.argCheck(self, func, 3, "function") |
if locale == rawget(self, BASE_LOCALE) then |
AceLocale.error(self, "Cannot provide the same locale more than once. %q provided twice.", locale) |
end |
if rawget(self, BASE_TRANSLATIONS) and GetLocale() ~= locale then |
if rawget(self, DEBUGGING) or rawget(self, DYNAMIC_LOCALES) then |
if not rawget(self, TRANSLATION_TABLES) then |
rawset(self, TRANSLATION_TABLES, {}) |
end |
if self[TRANSLATION_TABLES][locale] then |
AceLocale.error(self, "Cannot provide the same locale more than once. %q provided twice.", locale) |
end |
local t = func() |
func = nil |
if type(t) ~= "table" then |
AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t)) |
end |
self[TRANSLATION_TABLES][locale] = t |
t = nil |
end |
func = nil |
return |
end |
local t = func() |
func = nil |
if type(t) ~= "table" then |
AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t)) |
end |
rawset(self, TRANSLATIONS, t) |
if not rawget(self, BASE_TRANSLATIONS) then |
rawset(self, BASE_TRANSLATIONS, t) |
rawset(self, BASE_LOCALE, locale) |
for key,value in pairs(t) do |
if value == true then |
t[key] = key |
end |
end |
else |
for key, value in pairs(self[TRANSLATIONS]) do |
if not rawget(self[BASE_TRANSLATIONS], key) then |
AceLocale.error(self, "Improper translation exists. %q is likely misspelled for locale %s.", key, locale) |
end |
if value == true then |
AceLocale.error(self, "Can only accept true as a value on the base locale. %q is the base locale, %q is not.", rawget(self, BASE_LOCALE), locale) |
end |
end |
end |
rawset(self, CURRENT_LOCALE, locale) |
if not rawget(self, 'reverse') then |
rawset(self, 'reverse', setmetatable({}, { __index = function(self2, key) |
local self = AceLocale.reverseToBase[self2] |
if not rawget(self, REVERSE_TRANSLATIONS) then |
self:GetReverseTranslation(key) |
end |
self.reverse = self[REVERSE_TRANSLATIONS] |
return self.reverse[key] |
end })) |
AceLocale.reverseToBase[self.reverse] = self |
end |
refixInstance(self) |
if rawget(self, DEBUGGING) or rawget(self, DYNAMIC_LOCALES) then |
if not rawget(self, TRANSLATION_TABLES) then |
rawset(self, TRANSLATION_TABLES, {}) |
end |
self[TRANSLATION_TABLES][locale] = t |
end |
t = nil |
end |
function AceLocale.prototype:SetLocale(locale) |
AceLocale.argCheck(self, locale, 2, "string", "boolean") |
if not rawget(self, DYNAMIC_LOCALES) then |
AceLocale.error(self, "Cannot call `SetLocale' without first calling `EnableDynamicLocales'.") |
end |
if not rawget(self, TRANSLATION_TABLES) then |
AceLocale.error(self, "Cannot call `SetLocale' without first calling `RegisterTranslations'.") |
end |
if locale == true then |
locale = GetLocale() |
if not self[TRANSLATION_TABLES][locale] then |
locale = self[BASE_LOCALE] |
end |
end |
if self[CURRENT_LOCALE] == locale then |
return |
end |
if not self[TRANSLATION_TABLES][locale] then |
AceLocale.error(self, "Locale %q not registered.", locale) |
end |
self[TRANSLATIONS] = self[TRANSLATION_TABLES][locale] |
self[CURRENT_LOCALE] = locale |
refixInstance(self) |
end |
function AceLocale.prototype:GetLocale() |
if not rawget(self, TRANSLATION_TABLES) then |
AceLocale.error(self, "Cannot call `GetLocale' without first calling `RegisterTranslations'.") |
end |
return self[CURRENT_LOCALE] |
end |
local function iter(t, position) |
return (next(t, position)) |
end |
function AceLocale.prototype:IterateAvailableLocales() |
if not rawget(self, DYNAMIC_LOCALES) then |
AceLocale.error(self, "Cannot call `IterateAvailableLocales' without first calling `EnableDynamicLocales'.") |
end |
if not rawget(self, TRANSLATION_TABLES) then |
AceLocale.error(self, "Cannot call `IterateAvailableLocales' without first calling `RegisterTranslations'.") |
end |
return iter, self[TRANSLATION_TABLES], nil |
end |
function AceLocale.prototype:HasLocale(locale) |
if not rawget(self, DYNAMIC_LOCALES) then |
AceLocale.error(self, "Cannot call `HasLocale' without first calling `EnableDynamicLocales'.") |
end |
AceLocale.argCheck(self, locale, 2, "string") |
return rawget(self, TRANSLATION_TABLES) and self[TRANSLATION_TABLES][locale] ~= nil |
end |
function AceLocale.prototype:SetStrictness(strict) |
AceLocale.argCheck(self, strict, 2, "boolean") |
local mt = getmetatable(self) |
if not mt then |
AceLocale.error(self, "Cannot call `SetStrictness' without a metatable.") |
end |
if not rawget(self, TRANSLATIONS) then |
AceLocale.error(self, "No translations registered.") |
end |
rawset(self, STRICTNESS, strict) |
refixInstance(self) |
end |
local function initReverse(self) |
rawset(self, REVERSE_TRANSLATIONS, setmetatable({}, { __index = function(_, key) |
AceLocale.error(self, "Reverse translation for %q does not exist", key) |
end })) |
local alpha = self[TRANSLATIONS] |
local bravo = self[REVERSE_TRANSLATIONS] |
for base, localized in pairs(alpha) do |
bravo[localized] = base |
end |
end |
function AceLocale.prototype:GetTranslation(text) |
AceLocale.argCheck(self, text, 1, "string", "number") |
if not rawget(self, TRANSLATIONS) then |
AceLocale.error(self, "No translations registered") |
end |
return self[text] |
end |
function AceLocale.prototype:GetStrictTranslation(text) |
AceLocale.argCheck(self, text, 1, "string", "number") |
local x = rawget(self, TRANSLATIONS) |
if not x then |
AceLocale.error(self, "No translations registered") |
end |
local value = rawget(x, text) |
if value == nil then |
local _, ret = pcall(AceLocale.error, self, "Translation %q does not exist for locale %s", text, self[CURRENT_LOCALE]) |
geterrorhandler()(ret) |
return text |
end |
return value |
end |
function AceLocale.prototype:GetReverseTranslation(text) |
local x = rawget(self, REVERSE_TRANSLATIONS) |
if not x then |
if not rawget(self, TRANSLATIONS) then |
AceLocale.error(self, "No translations registered") |
end |
initReverse(self) |
x = self[REVERSE_TRANSLATIONS] |
end |
local translation = x[text] |
if not translation then |
local _, ret = pcall(AceLocale.error, self, "Reverse translation for %q does not exist", text) |
geterrorhandler()(ret) |
return text |
end |
return translation |
end |
function AceLocale.prototype:GetIterator() |
local x = rawget(self, TRANSLATIONS) |
if not x then |
AceLocale.error(self, "No translations registered") |
end |
return next, x, nil |
end |
function AceLocale.prototype:GetReverseIterator() |
local x = rawget(self, REVERSE_TRANSLATIONS) |
if not x then |
if not rawget(self, TRANSLATIONS) then |
AceLocale.error(self, "No translations registered") |
end |
initReverse(self) |
x = self[REVERSE_TRANSLATIONS] |
end |
return next, x, nil |
end |
function AceLocale.prototype:HasTranslation(text) |
AceLocale.argCheck(self, text, 1, "string", "number") |
local x = rawget(self, TRANSLATIONS) |
if not x then |
AceLocale.error(self, "No translations registered") |
end |
return rawget(x, text) and true |
end |
function AceLocale.prototype:HasBaseTranslation(text) |
AceLocale.argCheck(self, text, 1, "string", "number") |
local x = rawget(self, BASE_TRANSLATIONS) |
if not x then |
AceLocale.error(self, "No translations registered") |
end |
return rawget(x, text) and true |
end |
function AceLocale.prototype:HasReverseTranslation(text) |
local x = rawget(self, REVERSE_TRANSLATIONS) |
if not x then |
if not rawget(self, TRANSLATIONS) then |
AceLocale.error(self, "No translations registered") |
end |
initReverse(self) |
x = self[REVERSE_TRANSLATIONS] |
end |
return rawget(x, text) and true |
end |
function AceLocale.prototype:Debug() |
if not rawget(self, DEBUGGING) then |
return |
end |
local words = {} |
local locales = {"enUS", "deDE", "frFR", "koKR", "zhCN", "zhTW", "esES"} |
local localizations = {} |
DEFAULT_CHAT_FRAME:AddMessage("--- AceLocale Debug ---") |
for _,locale in ipairs(locales) do |
if not self[TRANSLATION_TABLES][locale] then |
DEFAULT_CHAT_FRAME:AddMessage(("Locale %q not found"):format(locale)) |
else |
localizations[locale] = self[TRANSLATION_TABLES][locale] |
end |
end |
local localeDebug = {} |
for locale, localization in pairs(localizations) do |
localeDebug[locale] = {} |
for word in pairs(localization) do |
if type(localization[word]) == "table" then |
if type(words[word]) ~= "table" then |
words[word] = {} |
end |
for bit in pairs(localization[word]) do |
if type(localization[word][bit]) == "string" then |
words[word][bit] = true |
end |
end |
elseif type(localization[word]) == "string" then |
words[word] = true |
end |
end |
end |
for word in pairs(words) do |
if type(words[word]) == "table" then |
for bit in pairs(words[word]) do |
for locale, localization in pairs(localizations) do |
if not rawget(localization, word) or not localization[word][bit] then |
localeDebug[locale][word .. "::" .. bit] = true |
end |
end |
end |
else |
for locale, localization in pairs(localizations) do |
if not rawget(localization, word) then |
localeDebug[locale][word] = true |
end |
end |
end |
end |
for locale, t in pairs(localeDebug) do |
if not next(t) then |
DEFAULT_CHAT_FRAME:AddMessage(("Locale %q complete"):format(locale)) |
else |
DEFAULT_CHAT_FRAME:AddMessage(("Locale %q missing:"):format(locale)) |
for word in pairs(t) do |
DEFAULT_CHAT_FRAME:AddMessage((" %q"):format(word)) |
end |
end |
end |
DEFAULT_CHAT_FRAME:AddMessage("--- End AceLocale Debug ---") |
end |
setmetatable(AceLocale.prototype, { |
__index = function(self, k) |
if type(k) ~= "table" and k ~= 0 and k ~= "GetLibraryVersion" and k ~= "error" and k ~= "assert" and k ~= "argCheck" and k ~= "pcall" then -- HACK: remove "GetLibraryVersion" and such later. |
local _, ret = pcall(AceLocale.error, lastSelf or self, "Translation %q does not exist.", k) |
geterrorhandler()(ret) |
return k |
end |
return nil |
end |
}) |
local function activate(self, oldLib, oldDeactivate) |
AceLocale = self |
self.frame = oldLib and oldLib.frame or CreateFrame("Frame") |
self.registry = oldLib and oldLib.registry or {} |
self.BASE_TRANSLATIONS = oldLib and oldLib.BASE_TRANSLATIONS or {} |
self.DEBUGGING = oldLib and oldLib.DEBUGGING or {} |
self.TRANSLATIONS = oldLib and oldLib.TRANSLATIONS or {} |
self.BASE_LOCALE = oldLib and oldLib.BASE_LOCALE or {} |
self.TRANSLATION_TABLES = oldLib and oldLib.TRANSLATION_TABLES or {} |
self.REVERSE_TRANSLATIONS = oldLib and oldLib.REVERSE_TRANSLATIONS or {} |
self.STRICTNESS = oldLib and oldLib.STRICTNESS or {} |
self.NAME = oldLib and oldLib.NAME or {} |
self.DYNAMIC_LOCALES = oldLib and oldLib.DYNAMIC_LOCALES or {} |
self.CURRENT_LOCALE = oldLib and oldLib.CURRENT_LOCALE or {} |
self.reverseToBase = oldLib and oldLib.reverseToBase or {} |
BASE_TRANSLATIONS = self.BASE_TRANSLATIONS |
DEBUGGING = self.DEBUGGING |
TRANSLATIONS = self.TRANSLATIONS |
BASE_LOCALE = self.BASE_LOCALE |
TRANSLATION_TABLES = self.TRANSLATION_TABLES |
REVERSE_TRANSLATIONS = self.REVERSE_TRANSLATIONS |
STRICTNESS = self.STRICTNESS |
NAME = self.NAME |
DYNAMIC_LOCALES = self.DYNAMIC_LOCALES |
CURRENT_LOCALE = self.CURRENT_LOCALE |
strict_instance_mt = { |
__index = strict__index, |
__newindex = __newindex, |
__tostring = __tostring |
} |
nonstrict_instance_mt = { |
__index = nonstrict__index, |
__newindex = __newindex, |
__tostring = __tostring |
} |
baseTranslations_mt = { |
__index = AceLocale.prototype |
} |
local GetTime = GetTime |
local timeUntilClear = GetTime() + 5 |
scheduleClear = function() |
if next(newRegistries) then |
self.frame:Show() |
timeUntilClear = GetTime() + 5 |
end |
end |
for name, instance in pairs(self.registry) do |
local name = name |
setmetatable(instance, nil) |
instance[NAME] = name |
local strict |
if instance[STRICTNESS] ~= nil then |
strict = instance[STRICTNESS] |
elseif instance[TRANSLATIONS] ~= instance[BASE_TRANSLATIONS] then |
if getmetatable(instance[TRANSLATIONS]).__index == oldLib.prototype then |
strict = true |
end |
end |
instance[STRICTNESS] = strict and true or false |
refixInstance(instance) |
end |
self.frame:SetScript("OnEvent", scheduleClear) |
self.frame:SetScript("OnUpdate", function() -- (this, elapsed) |
if timeUntilClear - GetTime() <= 0 then |
self.frame:Hide() |
for k in pairs(newRegistries) do |
clearCache(k) |
newRegistries[k] = nil |
k = nil |
end |
end |
end) |
self.frame:UnregisterAllEvents() |
self.frame:RegisterEvent("ADDON_LOADED") |
self.frame:RegisterEvent("PLAYER_ENTERING_WORLD") |
self.frame:Show() |
if oldDeactivate then |
oldDeactivate(oldLib) |
end |
end |
AceLibrary:Register(AceLocale, MAJOR_VERSION, MINOR_VERSION, activate) |
--[[ |
if true then -- debug |
local L = AceLocale:new(MINOR_VERSION ~= 100000 and "AceLocale_DEBUG" or "AceLocale_DEBUG3") |
L:RegisterTranslations("enUS", function() return { |
Monkey = true, |
House = true, |
} end) |
L:RegisterTranslations("deDE", function() return { |
Monkey = "Affe" |
} end) |
L = AceLocale:new(MINOR_VERSION ~= 100000 and "AceLocale_DEBUG" or "AceLocale_DEBUG3") |
assert(L.Monkey == "Monkey") |
assert(L.House == "House") |
if not L.Debug then |
local pants = L.Pants |
assert(not pants) |
end |
assert(L.Debug) |
assert(L.Debug == AceLocale.prototype.Debug) |
if MINOR_VERSION == 100000 then |
L = AceLocale:new("AceLocale_DEBUG") |
assert(L.Monkey == "Monkey") |
assert(L.House == "House") |
assert(L.Debug) |
assert(type(L.Debug) == "function") |
assert(AceLocale.prototype.Debug) |
assert(type(AceLocale.prototype.Debug) == "function") |
assert(L.Debug == AceLocale.prototype.Debug) |
end |
local L = AceLocale:new(MINOR_VERSION ~= 100000 and "AceLocale_DEBUG2" or "AceLocale_DEBUG4") |
L:RegisterTranslations("deDE", function() return { |
Affe = true, |
Haus = true, |
} end) |
L:RegisterTranslations("enUS", function() return { |
Affe = "Monkey" |
} end) |
L = AceLocale:new(MINOR_VERSION ~= 100000 and "AceLocale_DEBUG2" or "AceLocale_DEBUG4") |
assert(L.Affe == "Monkey") |
assert(L.Haus == "Haus") |
assert(L.Debug) |
assert(L.Debug == AceLocale.prototype.Debug) |
if MINOR_VERSION == 100000 then |
L = AceLocale:new("AceLocale_DEBUG2") |
assert(L.Affe == "Monkey") |
assert(L.Haus == "Haus") |
assert(L.Debug) |
assert(L.Debug == AceLocale.prototype.Debug) |
end |
local L = AceLocale:new(MINOR_VERSION ~= 100000 and "AceLocale_DEBUG5" or "AceLocale_DEBUG6") |
L:RegisterTranslations("deDE", function() return { |
Affe = true, |
Haus = true, |
} end) |
L:RegisterTranslations("enUS", function() return { |
Affe = "Monkey" |
} end) |
L:SetStrictness(true) |
L = AceLocale:new(MINOR_VERSION ~= 100000 and "AceLocale_DEBUG5" or "AceLocale_DEBUG6") |
assert(L.Affe == "Monkey") |
assert(L.Haus == "Haus") |
assert(L.Debug) |
assert(L.Debug == AceLocale.prototype.Debug) |
if MINOR_VERSION == 100000 then |
L = AceLocale:new("AceLocale_DEBUG5") |
assert(L.Affe == "Monkey") |
assert(L.Haus == "Haus") |
assert(L.Debug) |
assert(L.Debug == AceLocale.prototype.Debug) |
end |
end |
]] |
-- ****************************************************************** |
-- ****************************************************************** |
-- ** LootTablet ** |
-- ****************************************************************** |
-- ****************************************************************** |
-- |
local L = AceLibrary("AceLocale-2.2"):new("MorgDKP") |
local dewdrop = AceLibrary("Dewdrop-2.0") |
function MorgDKP:OnOpen() |
if not UnitInRaid("player") or not self.db.account.defaults.InRaid then return end |
local numItems = GetNumLootItems() |
if numItems == 0 then return end |
local nitems = 0 |
self.items = { } |
local needlinks = 1 |
local raidlink = {} |
local IGNORE = { } |
local target = UnitName("target") |
for _, ignorelink in pairs(self.db.account.defaults.ignore) do |
local _,_, ignoreid = string.find(ignorelink, "item:(%d+):") |
ignoreid = tonumber(ignoreid) |
IGNORE[ignoreid] = true |
end |
raidlink[1] = (target or "") .. ": " |
for slot = 1, numItems do |
local link = GetLootSlotLink(slot) |
if link ~= nil and not LootSlotIsCoin(slot) then |
local _,_, itemId = string.find(link, "item:(%d+):") |
itemId = tonumber(itemId) |
local lootIcon, lootName, _, rarity = GetLootSlotInfo(slot) |
if rarity >= self.db.account.defaults.quality and not IGNORE[itemId] then |
if nitems == 2 or nitems == 4 or nitems == 6 or nitems == 8 then |
needlinks = needlinks + 1 |
raidlink[needlinks] = "" |
end |
raidlink[needlinks] = raidlink[needlinks] .. link |
nitems = nitems + 1 |
self:AddItemforQuery(link, itemId, lootIcon, lootName, nitems) |
self.db.account.raidlog.lootbuffer[lootName] = target |
end |
end |
end |
if not self.db.account.defaults.dkplistener then |
if nitems > 0 and not self.f then |
for _, v in pairs(raidlink) do |
SendChatMessage(v , "RAID") |
end |
self:ShowTablet() |
end |
end |
end |
function MorgDKP:CreateLootFrame() |
self.f = { } |
self.f = CreateFrame("Frame", "MorgDKPLoot", UIParent) |
local f = self.f |
f:SetFrameStrata("DIALOG") |
f:SetFrameLevel(5) |
f:SetWidth(270) |
f:SetHeight((#self.items * 50) + 45) |
f:SetMovable(1) |
f:EnableMouse(1) |
f:RegisterForDrag("LeftButton") |
f:SetScript("OnDragStart", function() f:StartMoving() end) |
f:SetScript("OnDragStop", function() |
f:StopMovingOrSizing() |
self.db.account.defaults.lootframex = f:GetLeft() |
self.db.account.defaults.lootframey = f:GetTop() |
end) |
f:ClearAllPoints() |
f:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", self.db.account.defaults.lootframex, self.db.account.defaults.lootframey) |
f.title = f:CreateFontString() |
f.title:SetPoint("CENTER", f, "TOP", 0, -15) |
f.title:SetTextColor(1.0, 0.819, 0.0) |
f.title:SetWidth(150) |
f.title:SetFontObject(GameFontNormal) |
f.title:SetText(L["lootdistro"]) |
f.close = CreateFrame("Button", "CloseButton", f) |
f.close:SetScript("OnClick", function() |
f:Hide() |
self.f = nil |
self.items = nil |
end) |
f.close:SetWidth(32) |
f.close:SetHeight(32) |
f.close:SetNormalTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Up") |
f.close:SetPushedTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Down") |
f.close:SetHighlightTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Highlight") |
f.close:ClearAllPoints() |
f.close:SetPoint("TOPRIGHT", f, "TOPRIGHT", 3, 3) |
f.close:SetHitRectInsets(5, 5, 5, 5) |
f.close:Show() |
f.menu = CreateFrame("Button", "MenuButton", f) |
f.menu:SetScript("OnClick", function() self:ShowMainMenu(f) end) |
f.menu:SetWidth(24) |
f.menu:SetHeight(24) |
f.menu:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up") |
f.menu:SetPushedTexture("Interface\\Buttons\\UI-PlusButton-Down") |
f.menu:SetHighlightTexture("Interface\\Buttons\\UI-PlusButton-Hilight") |
f.menu:ClearAllPoints() |
f.menu:SetPoint("TOPLEFT", f, "TOPLEFT", 4, -3) |
f.menu:SetHitRectInsets(5, 5, 5, 5) |
f.menu:Show() |
f:SetBackdrop({ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", edgeSize = 16, insets = { left = 3, right = 3, top = 3, bottom = 3 } }) |
f:SetBackdropColor(.25, .25, .25, .75) |
f:SetBackdropBorderColor(1, 1, 1, 1) |
end |
function MorgDKP:ShowTablet() |
if self.f then return end |
self:CreateLootFrame() |
local f = self.f |
f.class = { } |
f.altclass = { } |
f.icon = { } |
f.value = { } |
f.query = { } |
f.multi = { } |
for item = 1, #self.items do |
f.class[item] = CreateFrame("Button", "LootFrame"..item, f, "UIPanelButtonTemplate") |
f.class[item]:SetWidth(60) |
f.class[item]:SetHeight(20) |
f.class[item]:SetText(L["classmain"]) |
f.class[item]:ClearAllPoints() |
f.class[item]:SetPoint("LEFT", f, "TOPLEFT", 18, -50 * item) |
f.class[item]:SetScript("OnClick", function() MorgDKP:ShowClassMenu(this:GetParent(), this:GetName()) end) |
f.class[item]:Show() |
f.altclass[item] = CreateFrame("Button", "AltClassFrame"..item, f, "UIPanelButtonTemplate") |
f.altclass[item]:SetWidth(60) |
f.altclass[item]:SetHeight(20) |
f.altclass[item]:SetText(L["classalt"]) |
f.altclass[item]:ClearAllPoints() |
f.altclass[item]:SetPoint("TOPLEFT", f.class[item], "BOTTOMLEFT", 0, -2) |
f.altclass[item]:SetScript("OnClick", function() MorgDKP:ShowAltClassMenu(this:GetParent(), this:GetName()) end) |
f.altclass[item]:Show() |
f.icon[item] = CreateFrame("Button", "LootIcon"..item, f) |
f.icon[item]:SetWidth(45) |
f.icon[item]:SetHeight(45) |
f.icon[item]:SetNormalTexture(self.items[item].icon) |
f.icon[item]:ClearAllPoints() |
f.icon[item]:SetPoint("TOPLEFT", f.class[item], "TOPRIGHT", 8, 0) |
f.icon[item]:SetScript("OnEnter", function() |
GameTooltip:SetOwner(this, "ANCHOR_RIGHT") |
GameTooltip:SetHyperlink(self.items[item].link) |
CursorUpdate() |
end) |
f.icon[item]:SetScript("OnLeave", function() GameTooltip:Hide() end) |
f.icon[item]:Show() |
f.value[item] = CreateFrame("Button", "LootValue"..item, f) |
f.value[item]:EnableMouseWheel(1) |
f.value[item]:SetWidth(38) |
f.value[item]:SetHeight(38) |
f.value[item]:ClearAllPoints() |
f.value[item]:SetPoint("LEFT", f.icon[item], "RIGHT", 5, 0) |
f.value[item]:SetNormalTexture("Interface\\Buttons\\ButtonHilight-Square") |
f.value[item]:SetTextFontObject("GameFontNormal") |
f.value[item]:SetTextColor(0,1,0) |
f.value[item]:SetText(self.db.account.items[self.items[item].id].points or 0) |
f.value[item]:SetScript("OnMouseWheel", function() self:SetValue(this:GetParent(), this:GetName(), arg1) end) |
f.value[item]:SetScript("OnMouseDown", function() self:SetValue(this:GetParent(), this:GetName(), arg1) end) |
f.value[item]:SetScript("OnEnter", function() |
GameTooltip:SetOwner(this, "ANCHOR_RIGHT") |
GameTooltip:SetText(L["valuehint"]) |
end) |
f.value[item]:SetScript("OnLeave", function() GameTooltip:Hide() end) |
f.value[item]:Show() |
local offset = 0 |
if self.db.account.defaults.multiPool then |
f.multi[item] = CreateFrame("Button", "MultiFrame"..item, f, "UIPanelButtonTemplate") |
f.multi[item]:SetWidth(80) |
f.multi[item]:SetHeight(20) |
f.multi[item]:SetText(self.db.account.items[self.items[item].id].pool) |
f.multi[item]:ClearAllPoints() |
f.multi[item]:SetPoint("LEFT", f.value[item], "RIGHT", 5, 10) |
f.multi[item]:SetScript("OnClick", function() MorgDKP:ShowPoolMenu(this:GetParent(), this:GetName()) end) |
f.multi[item]:Show() |
offset = 10 |
end |
f.query[item] = CreateFrame("Button", "QueryButton"..item, f, "UIPanelButtonTemplate") |
f.query[item]:SetWidth(60) |
f.query[item]:SetHeight(20) |
f.query[item]:SetText(L["query"]) |
f.query[item]:ClearAllPoints() |
f.query[item]:SetPoint("LEFT", f.value[item], "RIGHT", 5, 0 - offset) |
f.query[item]:SetScript("OnClick", function() MorgDKP:StartItemQuery(this:GetParent(), this:GetName()) end) |
f.query[item]:Show() |
end |
end |
function MorgDKP:ShowMainMenu(frame) |
self.hasitem = nil |
dewdrop:Open(frame, |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.opts) |
end, |
'cursorX', true, |
'cursorY', true |
) |
end |
function MorgDKP:ShowClassMenu(frame, name) |
_, _, index = string.find(name, "LootFrame(%d+)") |
index = tonumber(index) |
if not self.items[index] then return end |
myid = self.items[index].id |
dewdrop:Open(frame.class[index], |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.classopts) |
end, |
'cursorX', true, |
'cursorY', true |
) |
end |
function MorgDKP:ShowAltClassMenu(frame, name) |
_, _, index = string.find(name, "AltClassFrame(%d+)") |
index = tonumber(index) |
if not self.items[index] then return end |
myid = self.items[index].id |
dewdrop:Open(frame.altclass[index], |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.altclassopts) |
end, |
'cursorX', true, |
'cursorY', true |
) |
end |
function MorgDKP:ShowPoolMenu(frame, name) |
_, _, index = string.find(name, "MultiFrame(%d+)") |
index = tonumber(index) |
self.poolindex = index |
dewdrop:Open(frame.multi[index], |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.Poolopts) |
end, |
'cursorX', true, |
'cursorY', true |
) |
end |
function MorgDKP:SetRollPool(pool) |
self.f.multi[self.poolindex]:SetText(pool) |
self.db.account.items[self.items[self.poolindex].id].pool = pool |
end |
function MorgDKP:SetValue(frame, name, button) |
_, _, index = string.find(name, "LootValue(%d+)") |
index = tonumber(index) |
local value = self.db.account.items[self.items[index].id].points |
local step = 5 |
if IsShiftKeyDown() then step = 1 end |
if IsAltKeyDown() then step = 20 end |
if button == 1 then value = value + step |
elseif button == -1 then value = value - step |
elseif button == "LeftButton" then value = value + step |
elseif button == "RightButton" then value = value - step |
end |
frame.value[index]:SetText(value) |
self.db.account.items[self.items[index].id].points = value |
if self.db.account.raidlog.loot then |
for num, loot in pairs(self.db.account.raidlog.loot) do |
if loot.ID == self.items[index].id then |
loot.Costs = value |
loot.Note = string.gsub(loot.Note, "%d+.00 DKP", tostring(value)..".00 DKP") |
end |
end |
end |
end |
function MorgDKP:StartItemQuery(frame, name) |
_, _, index = string.find(name, "QueryButton(%d+)") |
index = tonumber(index) |
if not self.items[index] then return end |
id = self.items[index].id |
link = self.items[index].link |
if IsShiftKeyDown() then |
self.random[id] = true |
end |
self:StartQuery(id, link) |
table.remove(self.items, index) |
if #self.items > 0 then |
self.f:Hide() |
self.f = nil |
self:ShowTablet() |
return |
end |
self.f:Hide() |
self.f = nil |
self.items = nil |
end |
function MorgDKP:ManualItem(id, link) |
local index |
if not self.items then |
self.items = { } |
index = 1 |
else index = #self.items + 1 end |
local sName, _, _, _, _, _, _, _, _, iconGIF = GetItemInfo(id) |
self:AddItemforQuery(link, id, iconGIF, sName, index) |
if self.f then |
self.f:Hide() |
self.f = nil |
end |
self:ShowTablet() |
end |
function MorgDKP:AddItemforQuery(link, id, icon, name, index) |
self:IteminDB(id) |
self.items[index] = { |
name = name, |
id = id, |
link = link, |
icon = icon |
} |
end |
[InternetShortcut] |
URL=http://www3.telus.net/MorgDKP/ |
local L = AceLibrary("AceLocale-2.2"):new("MorgDKP") |
L:RegisterTranslations("enUS", function() return { |
cmd1 = "/mdkp", |
cmd2 = "/MorgDKP", |
Bar_Hint = "|c000070ddL-Click:|r Announce.\n|c000070ddR-Click:|r Close tablet.", |
Bar_Hint_DKPlist = "|c000070ddL-Click:|r Invite.\n|c000070ddSHIFT-Click:|r Output.\n|c000070ddCTRL-Click:|r Delete Character.\n|c000070ddALT-Click:|r Add to waitlist.\n|c000070ddR-Click:|r Close tablet.", |
Bar_Hint_Version = "|c000070ddL-Click:|r Send tells.\n|c000070ddR-Click:|r Close tablet.", |
Bar_Hint_Sync = "|c000070ddL-Click:|r Sync with.\n|c000070ddSHIFT-Click:|r Sync all.\n|c000070ddR-Click:|r Close tablet.", |
Bar_Hint_Waitlist = "|c000070ddL-Click:|r Invite.\n|c000070ddCTRL-Click:|r Remove.\n|c000070ddR-Click:|r Close tablet.", |
BidWarBar_Hint = "|c000070ddL-Click:|r End Auction.\n|c000070ddR-Click:|r Close tablet.", |
AcceptSYNC = "Accept sync data from %s?", |
AcceptLeaderRequest = "%s is requesting leader status. Disable your MorgDKP?", |
ad = "Add", |
add = "Added ", |
adddkp = "Add DKP", |
adddkpdesc = "Add DKP to a raid member. \nFormat: <charname> <points>", |
addnewchar = "Added new character ", |
alias = "Aliases", |
aliasadd = "Added alias: ", |
aliasexists = "Alias name already exihists", |
All = "All", |
alreadybid = "Sorry this is a silent auction and you have already placed your bid.", |
attadded = " attendees added.", |
attend = " attendees.", |
auctionbegin = "Beginning auction for %s: ID = %s", |
autozone = "Autozone", |
autozonedesc = "Automatically start a raid when zoning into a trackable zone.", |
badformat = "Can't add an event with incomplete information.", |
bidaccepted = "Your response has been accepted: %s", |
bidformat = "Bid Format = mbid ID [need/take/pass/bid value]", |
bidwaroptions = "BidWar Options", |
bidwaroptionsdesc = "Different BidWar options.", |
bossattemptmode = "Boss Attempt Mode", |
bossattemptmodedesc = "Enable's a mode where a boss attempt is recorded when you die via a confirmation dialogue.", |
bosskill = " recorded at ", |
broadlead = "Broadcast Leader", |
broadleaddesc = "Broadcast leader status to raid.", |
bwarsteps = "BidWar Step", |
bwarstepsdesc = "Changes the DKP step for BidWar mode. Passes this value to MorgBid clients.", |
changedcost = "Changed item cost from %s to %s for %s.", |
charpoints = "You must format the string correctly: <character> <points>", |
classlist = "Classes", |
classmain = "Main", |
classalt = "Offspec", |
cleardb = "Clear raid database?", |
clearraid = "Clear Raid DB", |
clearraiddesc = "Clear the raid database.", |
cleared = "Cleared the MorgDKP Raid database.", |
convert = "Convert DB", |
convertdesc = "Convert pre MorgDKP 6.0 database to work with MorgDKP 6.0 and above.", |
converted = "Converted old MorgDKP Database.", |
closemenu = "Close", |
complete = "COMPLETED", |
custom = "Custom event", |
customdesc = "Add a custom raid event. This will record all attendees when you click the event menu by adding Attempt to the end of the boss name you have targeted. You can change event name value through raid tracker.", |
customname = "Custom name", |
deletechar = "Deleting %s from MorgDKP database.", |
deleteimportfile = "Please delete the ItemData.lua file from the MorgDKP directory now.", |
denchanter = "Disenchanter", |
denchanterdesc = "Person assigned to be disenchanter.", |
devmode = "Developer mode", |
disablemod = "Disable MOD", |
disablemoddesc = "Send MorgDKP to STANDBY mode.", |
dkpword = " DKP ", |
dkp = "DKP Functions", |
dkpaward = "DKP Award/Time", |
dkpawarddesc = "Enable DKP awarding per unit of time in minutes to raid members who have been present at least for that amount of time.", |
dkpchange = "Adjust DKP", |
dkpdesc = "Functions related to tracking DKP.", |
dkplisten = "DKP Listener", |
dkplistendesc = "When you are in a tracked zone you will track DKP but you will not get the loot popup window or link to raid. You will act like a backup raidlog.", |
dkpp = " DKP Points: ", |
dkpstand = "DKP Standings for ", |
dkpsys = "DKP System", |
dkptypes = "DKP Types", |
dkptypesdesc = "Different DKP variations.", |
doresult = "Results for: ", |
enablebidwar = "BidWar", |
enablebidwardesc = "Enable BidWar mode. This mode changes the MorgBid query to allow players to bid on items. Also the MorgDKP tablet uses bids after this NOT member DKP.", |
enablejustenough = "Just Enough", |
enablejustenoughdesc = "Enable BidWar mode where the winner is charged the 2nd highest bid value for the item.", |
enablemlde = "Enable ML/DE mode", |
enablemldedesc = "If ML/DE Mode is on then no loot will be recorded for the master looter or disenchanter defined by the mod.", |
enablepercent = "Percent", |
enablepercentdesc = "Enable percent DKP system. Items will cost a percentage of the members total DKP.", |
enablerandom = "Random", |
enablerandomdesc = "Enable random rolling for items.", |
enablerelationaldkp = "Relational DKP", |
enablerelationaldkpdesc = "Enable RDKP for calculating the earned/spent dkp ratio.", |
enablesilentauction = "Silent Auction", |
enablesilentauctiondesc = "Enable BidWar mode with only one round of bidding and no reporting to raid chat.", |
enablewait = "Award DKP", |
enablewaitdesc = "Award DKP to the current members of the waitlist.", |
enablewhisper = "Whisper System", |
enablewhisperdesc = "Enable whisper system - sends whispers to everyone (even if they have MorgBid) so they can reply and bid using whispers.", |
enablezerosum = "0-sum", |
enablezerosumdesc = "Enables the zero sum DKP system.", |
endbidding = "Bidding is now closed.", |
endraid = "End Raid", |
endraiddesc = "Close the raid database for the current raid.", |
endraidadd = "End %s", |
endandadd = "and add these attendees < %s min?", |
eventformat = "Event format", |
eventformatdesc = "Format for the event names that are automatically recorded. Format = <[zone]> - <[boss]>. Choose one or two in any order. Example: [zone] - [boss]", |
exceedoverbid = "You have exceeded the overbid amount of %s. Your bid has been reset to the maximum.", |
events = "Events", |
from = " from ", |
fubarhint = "|c000070ddClick:|r MorgBid Base query.\n|c000070ddALT-Click:|r Toggle ML/DE\n|c000070ddSHIFT-Click:|r Invite & Waitlist.\n|c000070ddCTRL-Click:|r Raid Tracker.\n|c000070ddCTRL-Click Itemlink:|r Ignore item.", |
fubarhintdisabled = "On STANDBY.\n|c000070ddClick:|r to enable.", |
fubaropts = "Fubar Options", |
giveboe = "Give BOE", |
giveboedesc = "Give a player in the raid a BOE and record in the raid loot database.", |
highbidder = "New high bidder for %s: %s = %s", |
ignorelist = "Ignored items", |
ignorelistdesc = "List of currently ignored items. Click to remove ignored item.", |
ImportdefaultDB = "Import saved item database?", |
invalidformat = "Sorry your response format is incorrect or no item with that ID is up for bidding. Format = mbid ID [need/take/pass/bid value]", |
itemhistory = "Item History", |
itemhistorydesc = "Show history of items looted in this raid. \nNote: Since you last started a new raid.", |
joinraid = " joined the raid at ", |
leftraid = " left the raid at ", |
listdkp = "List DKP", |
listdkpdesc = "Lists the DKP of the selected classes in tablet.", |
logquality = "Log Quality", |
logqualitydesc = "Anything below this quality level will NOT be logged.", |
lootdistro = "Eligible Items:", |
lootquery = "Give %s to %s, are you sure?", |
manualitem = "Add manual item", |
manualitemdesc = "Add an item for distribution from your inventory. Useful for some BOE's and items you can not loot.", |
Menu = "FuBar Options", |
mldefunc = "ML/DE mode", |
mloot = "Master Looter", |
mlootdesc = "Person assigned to be master looter. The mod will determine this automatically if it can.", |
morgbidcheck = "MorgBid Base", |
morgbidcheckdesc = "Determine MorgBid user base. \nAlso useful to check DKP for alts.", |
morgbidmaxwhisper = "Current bid for ID: %s = %s (Reply format: mbid ID [pass/bid value])", |
morgbidwhisper = "%s: ID = %s DKP/Bid value = %s (Reply format: mbid ID [need/take/pass/bid value])", |
morgtitle = "MorgDKP", |
multi = "multiPool", |
multidesc = "Enable more than one DKP pool for rolling on items. When starting auction you have to choose the alternate pool to use or it will be main pool that is used.", |
mvquery = "MorgBid Version Query", |
needraid = "You can not use this function out of a raid group.", |
newdkp = " New DKP: ", |
noauction = "This item is not currently up for bid.", |
noitem = "Item does not exist!", |
nolootrec = "ML Mode is currently on so no loot will be recorded for ML/DE.", |
nomain = "This main character does not exhist. No changes made.", |
noquery = "Either no classes are selected or no members need this item.", |
noraid = "No current raid exists.", |
normal = "Standard", |
notexi = " does not exist.", |
option = "Options", |
olddkp = ": Old DKP: ", |
onerun = "Single Run event", |
onerundesc = "Use one event for entire raid. Boss kills will not be tracked separately.", |
otheroptions = "Other Options", |
otheroptionsdesc = "Miscellaneous DKP/tracking options.", |
overbidmax = "Overbid", |
overbidmaxdesc = "Maximum to allow members to bid above their present DKP.", |
pending = "PENDING...", |
percenttake = "% Take Mode", |
percenttakedesc = "When using the percent DKP system this option enables TAKE looting. This means if the winning member rolled TAKE he will not be charged x% DKP he will instead be charged the base price of the item (Set using original itempoints.", |
playfrom = " players from ", |
pointsto = " points each to ", |
pool = "Main DKP Pool", |
pooldesc = "Set DKP Pool to be primary (or only if not multiPool) DKP pool.", |
pooluse = "Pool", |
poolusedesc = "Choose DKP pool to use for this item roll.", |
pools = "Currently loaded DKP pools....", |
query = "Query", |
queryraid = "Query Raid", |
queryraiddesc = "Query raid members interest in the given item.", |
querysent = "MorgBid query sent: ", |
raidatt = " raid attendees.", |
raids = "Raids", |
raidstartadd = " attendees to raid start.", |
raidtrack = "Raid Tracking", |
raidtrackdesc = "Opens the raid tracking functions window.", |
receive = " Receives ", |
recordbossattempt = "Record boss attempt for %s?", |
removed = "Removed ", |
requestsync = "Requesting database sync from %s...", |
rightclickclose = "|c000070ddClick:|r Edit item value. |c000070ddR-Click|r to close.", |
rollingbegin = "Now querying for %s ID = %s DKP %s....", |
roundbid = "Bids for this round:", |
rundkp = "Export Raid", |
rundkpdesc = "Output raid data for Morgimport\nDatabase reset is recommended after or raid logs may get large.", |
runevent = "Sorry deleteing the run event is not allowed as trash drops are recorded in this event.", |
runrewardtime = "Minimum Run Time", |
runrewardtimedesc = "Minimum time in minutes a member must be in the raid before they recieve run DKP. ie 30 min", |
sentsync = "Transmitted item database over sync channel to %s.", |
setitempoints = "Set Item Points", |
setitempointsdesc = "DKP charge for selected item.", |
startformat = "Start format", |
startformatdesc = "Format of start event name: <[zone]> <text>. Example: [zone] Start", |
startraid = "Start Raid", |
startraiddesc = "Starts a new raid database to begin tracking a raid.", |
startruntrack = "Start Event", |
startruntrackdesc = "Track raidstart event.", |
statusoff = "|c009d9d9dOFF|r", |
statuson = "|c001eff00ON|r", |
sub = "Subtracted ", |
subdkp = "Remove DKP", |
subdkpdesc = "Remove DKP from a raid member. \nFormat: <charname> <points>", |
syncdb = "Sync DB", |
syncdbdesc = "Sync your database with another MorgDKP user.\nAdds new items to your DB does not overwrite already present items.\n Also adds new players to your database and overwrites DKP values, class, and aliases if sync data is newer.", |
syncdone = "Database transfer complete. %s items were transferred and %s members updated.", |
syncquery = "SYNC", |
syncrequest = "%s has requested your database information.", |
syncstart = "Querying MorgDKP databases available in %s channel...", |
syncwait = "Waiting for sync data from %s...", |
to = " to ", |
transfer = "Transferred ", |
transferitem = "Transferred item from %s to %s: Cost = %s.", |
trashformat = "Trash format", |
trashformatdesc = "Format of trash event name: <[zone]> <text>. Example: [zone] Run", |
twinkaltmain = "You must format the string correctly: <twinkalt> <twinkmain>", |
twinks = "Add Twink", |
twinksdesc = "Add a player to this raid who is on an alt with DKP under a main. The mod will remember this.\n Format: <alt> <main>", |
updatedkp = "Updating DKP Points..", |
updatemorgbid = "Please update your MorgBid. http://www3.telus.net/MorgDKP/MorgBid3.6.exe or check in the vent chat window. Thank-you:)", |
validname = "You must enter a valid name.", |
valuehint = "|c000070ddMousewheel up/Click|r - Increase value.\n|c000070ddMousewheel down/R-Click|r - decrease value.\n|c000070ddSHIFT|r - change value by +/-1\n|c000070ddALT|r - change value by +/-20", |
waitlist = "Waitlist", |
waitadd = "Added you to the waitlist.", |
waitbossamt = "Waitlist boss DKP", |
waitbossamtdesc = "Amount of DKP to award to the waitlist per boss kill.", |
waitlistdesc = "Options related to the waitlist.", |
waitmain = "Please log on to your main for an invite to the raid. Whisper me when online.", |
waitsub = "Removed you from the waitlist.", |
waitstartamt = "Waitlist start DKP", |
waitstartamtdesc = "Amount of start bonus DKP to award to the waitlist at the start of the run.", |
waitrunamt = "Waitlist run DKP", |
waitrunamtdesc = "Amount of run DKP to award to the waitlist. Applied at start of run.", |
waitotimeamt = "Waitlist DKP/time", |
waitotimeamtdesc = "Amount of DKP/time to award to the waitlist. Note: Only works if you are awarding DKP/time to the raid.", |
whisperformat = "Please whisper: dkplist [poolname] [class] [class] .... [all]", |
Romulo = "Romulo", |
Julianne = "Julianne", |
RomuloandJulianne = "Romulo & Julianne", |
Chessevent = "Chess Event", |
DEFAULTBOSS = "Trash mob", |
WorldBoss = "World Boss", |
NEW = "NEW", |
NONE = "NONE", |
MORGTRACKER_MAJORDOMO_YELL = "Impossible! Stay your attack, mortals... I submit! I submit!", |
MORGTRACKER_ROMULO_YELL="What devil art thou, that dost torment me thus?", |
MORGTRACKER_CHESS_EMOTE = "The halls of Karazhan shake, as the curse binding the doors of the Gamesman's Hall is lifted.", |
MORGTRACKER_LADYVASHJP2_YELL = "The time is now! Leave none standing!", |
MORGTRACKER_LADYVASHJP3_YELL = "You may want to take cover.", |
MORGTRACKER_RAGEENTERS_YELL = "The Legion's final conquest has begun! Once again the subjugation of this world is within our grasp. Let none survive!", |
MORGTRACKER_ANETHERONENTERS_YELL = "You are defenders of a doomed world! Flee here, and perhaps you will prolong your pathetic lives!", |
MORGTRACKER_KAZROGALENTERS_YELL = "Cry for mercy! Your meaningless lives will soon be forfeit!", |
MORGTRACKER_AZGALORENTERS_YELL = "Abandon all hope! The Legion has returned to finish what was begun so many years ago. This time, there will be no escape!", |
MORGTRACKER_ERADOR_YELL = "These are the hallmarks...", |
MORGTRACKER_LOOT_RECEIVES1 = "([^%s]+) receives loot: (.+)%.", |
MORGTRACKER_LOOT_RECEIVES1_COUNT = "([^%s]+) receives loot: (|c%x+|Hitem:%d+:%d+:%d+:%d+|h%[.-%]|h|r)x(%d+)%.", |
MORGTRACKER_LOOT_RECEIVES2 = "You receive loot: (.+)%.", |
MORGTRACKER_LOOT_RECEIVES2_COUNT = "You receive loot: (|c%x+|Hitem:%d+:%d+:%d+:%d+|h%[.-%]|h|r)x(%d+)%.", |
MorgTracker_IgnoreMobs = { |
["Son of Flame"] = true, |
["Onyxian Whelp"] = true, |
["Kil'rek"] = true, |
["Amani Dragonhawk Spirit"] = true, |
}, |
classcount = { |
["PALADIN"] = 8, |
["WARLOCK"] = 7, |
["MAGE"] = 13, |
["DRUID"] = 12, |
["WARRIOR"] = 7, |
["HUNTER"] = 9, |
["PRIEST"] = 11, |
["ROGUE"] = 11, |
["SHAMAN"] = 8, |
["NEED"] = 10, |
["TAKE"] = 10, |
["PASS"] = 11, |
["PENDING"] = 5 |
}, |
} end) |
-- ****************************************************************** |
-- ****************************************************************** |
-- ** MorgDKP ** |
-- ****************************************************************** |
-- ****************************************************************** |
local L = AceLibrary("AceLocale-2.2"):new("MorgDKP") |
function MorgDKP:UpdateRaidlist() |
local temp = {} |
local count = 1 |
if not MorgDKP_DKP1 then self:DefaultDKP() end |
for i = 1,5 do |
local dkp = getglobal("MorgDKP_DKP" .. i) |
if dkp then temp[count] = dkp |
count = count + 1 |
end |
end |
local skipupdate = 1 |
local timestamp |
if not self.db.account.Timestamp or self:TimeStampDiff(temp[1].Timestamp, self.db.account.Timestamp) then |
skipupdate = nil |
timestamp = tostring(temp[1].Timestamp) |
if string.len(timestamp) < 12 then timestamp = "0" .. timestamp end |
self.db.account.Timestamp = timestamp |
timestamp = self:GetServerTime() |
DEFAULT_CHAT_FRAME:AddMessage(L["updatedkp"]) |
end |
if not skipupdate then |
self.db.account.defaults.eqDKP = { } |
self.db.account.defaults.raidlist = { } |
if not self.db.account.defaults.raid or self.db.account.defaults.raid == "Export your DKP!" then self.db.account.defaults.raid = temp[1].Pool end |
for i, dkpray in pairs(temp) do |
if dkpray.Pool then |
self.db.account.defaults.raidlist[i] = dkpray.Pool |
self.db.account.defaults.eqDKP[dkpray.Pool] = { } |
self.db.account.defaults.eqDKP[dkpray.Pool]["eqDKPsite"] = dkpray.eqdkpsite |
self.db.account.defaults.eqDKP[dkpray.Pool]["prefix"] = dkpray.prefix |
if dkpray.Events then |
self.db.account.defaults.eqDKP[dkpray.Pool]["Events"] = { } |
for event, details in pairs(dkpray.Events) do |
self.db.account.defaults.eqDKP[dkpray.Pool]["Events"][event] = { } |
self.db.account.defaults.eqDKP[dkpray.Pool]["Events"][event] = { ["id"] = details.id, ["value"] = details.value} |
end |
end |
if dkpray.Aliases then |
local aliascounter = 1 |
self.db.account.defaults.eqDKP[dkpray.Pool]["Aliases"] = { } |
for alias, main in pairs(dkpray.Aliases) do |
self.db.account.defaults.eqDKP[dkpray.Pool]["Aliases"][aliascounter] = { } |
self.db.account.defaults.eqDKP[dkpray.Pool]["Aliases"][aliascounter] = { ["main"] = main, ["alt"] = alias} |
aliascounter = aliascounter + 1 |
self:PlayerinDB(main) |
self:PlayerinDB(alias) |
local present = false |
if not self.db.account.info[main].aliases then self.db.account.info[main].aliases = { } end |
for numalias = 1 , #self.db.account.info[main].aliases do |
if self.db.account.info[main].aliases[numalias].alt == alias and self.db.account.info[main].aliases[numalias].raid == dkpray.Pool then |
present = true |
end |
end |
if not present then table.insert(self.db.account.info[main].aliases , {raid = dkpray.Pool, alt = alias}) end |
end |
table.sort(self.db.account.defaults.eqDKP[dkpray.Pool].Aliases, function(a,b) return a.alt<b.alt end) |
end |
end |
if dkpray.Points then |
local count = 0 |
for name, v in pairs(dkpray.Points) do |
if not self.db.account.info[name] then self.db.account.info[name] = { } end |
self.db.account.info[name][dkpray.Pool] = {earned = v.earn + v.adj, spent = v.spent, points = v.bal } |
if self.db.account.defaults.devmode then self:Print(name.." and "..v.bal) end |
self.db.account.info[name].raidloot = 0 |
self.db.account.info[name].lastupdate = timestamp |
count = count + 1 |
if self.db.account.info[name].aliases then |
for m = 1, #self.db.account.info[name].aliases do |
if self.db.account.info[name].aliases[m].raid == self.db.account.defaults.raid then |
local alt = self.db.account.info[name].aliases[m].alt |
local mainpoints = self.db.account.info[name][dkpray.Pool].points |
if not self.db.account.info[alt] then self.db.account.info[alt] = { } end |
self.db.account.info[alt][dkpray.Pool] = { points = mainpoints, |
earned = self.db.account.info[name][dkpray.Pool].earned, |
spent = self.db.account.info[name][dkpray.Pool].spent } |
self.db.account.info[alt].raidloot = 0 |
self.db.account.info[alt].lastupdate = timestamp |
if self.db.account.defaults.devmode then self:Print(L["aliasadd"]..alt.." of "..name.." with "..mainpoints.." DKP.") end |
end |
end |
end |
end |
DEFAULT_CHAT_FRAME:AddMessage(L["add"]..tostring(count)..L["playfrom"]..dkpray.Pool) |
end |
end |
MorgDKP_DKP1 = nil |
MorgDKP_DKP2 = nil |
MorgDKP_DKP3 = nil |
MorgDKP_DKP4 = nil |
MorgDKP_DKP5 = nil |
end |
self:ReclaimPool() |
end |
function MorgDKP:DefaultDKP() |
local name = UnitName("player") |
MorgDKP_DKP1 = { |
Timestamp = 010120000800, |
Pool = "Export your DKP!", |
eqdkpsite = "aqdkp", |
prefix = "eqdkp_", |
Points = { |
[name] = {earn = 1397.00,spent = 405.00,adj = 0.00,bal = 992} |
}, |
Aliases = { |
["TestAlias"] = name |
}, |
Events = { |
["Void Reaver"] = {id = 77,value = 3.00} |
}, |
} |
end |
function MorgDKP:ConvertDB() |
local POOL = self.db.account.defaults.raid |
local update = self:GetServerTime() |
if self.db.account.defaults.dbupdated == 0 then return end |
if self.db.account.defaults.dbupdated < 2 then |
for index,v in pairs(self.db.account.info) do |
local temp = { } |
temp.raidloot = 0 |
temp.lastupdate = v.lastupdate or update |
temp.aliases = v.aliases |
temp.items = v.items |
temp.class = v.class |
temp[POOL] = {points = 0, earned = 0, spent = 0} |
self.db.account.info[index] = temp |
end |
for id,data in pairs(self.db.account.items) do |
if not data.pool then self.db.account.items[id].pool = POOL end |
end |
for id,data in pairs(self.db.account.items) do |
if not data.altclasses then self.db.account.items[id].altclasses = { } end |
end |
if self.db.account.raidlogbackup then self.db.account.raidlogbackup = nil end |
else |
for name,data in pairs(self.db.account.info) do |
local temp = {} |
if data.items then |
for slot, itemdata in pairs(data.items) do |
if itemdata then |
for itemlink, _ in pairs(itemdata) do |
local _, _, ID = strfind(itemlink, "[^:]+:(%d+):") |
ID = tonumber(ID) |
table.insert(temp, ID) |
end |
end |
end |
self.db.account.info[name].items = temp |
end |
end |
end |
DEFAULT_CHAT_FRAME:AddMessage(L["converted"]) |
self:ClearRaidDB() |
end |
function MorgDKP:ImportMorgItems() |
itemcount = self:ImportItemDB(MorgDKP_Items) |
DEFAULT_CHAT_FRAME:AddMessage(string.format(L["syncdone"], itemcount, 0)) |
DEFAULT_CHAT_FRAME:AddMessage(L["deleteimportfile"]) |
MorgDKP_Items = nil |
end |
function MorgDKP:ImportItemDB(items) |
local itemcount = 0 |
if not self.db.account.items then self.db.account.items = { } end |
for id, data in pairs(items) do |
if not self.db.account.items[id] then |
self.db.account.items[id] = data |
itemcount = itemcount + 1 |
end |
end |
return itemcount |
end |
function MorgDKP:AdjustDKPPoints(new, old, pool, newcost, oldcost) |
local update = self:GetServerTime() |
if new ~= old then |
self.db.account.info[old][pool].points = self.db.account.info[old][pool].points + newcost |
self.db.account.info[old][pool].spent = self.db.account.info[old][pool].spent - newcost |
self.db.account.info[old].raidloot = 0 |
self.db.account.info[old].lastupdate = update |
self.db.account.info[new][pool].points = self.db.account.info[new][pool].points - newcost |
self.db.account.info[new][pool].spent = self.db.account.info[new][pool].spent + newcost |
self.db.account.info[new].raidloot = 1 |
self.db.account.info[new].lastupdate = update |
DEFAULT_CHAT_FRAME:AddMessage(string.format(L["transferitem"], old, new, newcost)) |
else |
local costdiff |
if not newcost then |
costdiff = oldcost |
newcost = 0 |
self.db.account.info[old].raidloot = 0 |
else costdiff = oldcost - newcost end |
self.db.account.info[old][pool].points = self.db.account.info[old][pool].points + costdiff |
self.db.account.info[old][pool].spent = self.db.account.info[old][pool].spent - costdiff |
self.db.account.info[old].lastupdate = update |
DEFAULT_CHAT_FRAME:AddMessage(string.format(L["changedcost"], oldcost, newcost, old)) |
end |
end |
function MorgDKP:GetPool(raidid) |
for pool, data in pairs(self.db.account.defaults.eqDKP) do |
if data.eqDKPsite == self.db.account.raidlog[raidid].eqdkp then return pool end |
end |
return false |
end |
function MorgDKP:AwardDKP(new, old, pool, attendees, wait, quiet) |
local update = self:GetServerTime() |
if new == old then return end |
local diff |
if new then |
diff = new - old |
elseif old == 0 then return |
else diff = old end |
local counter = 0 |
for _, name in pairs(attendees) do |
self.db.account.info[name][pool].points = self.db.account.info[name][pool].points + diff |
self.db.account.info[name][pool].earned = self.db.account.info[name][pool].earned + diff |
self.db.account.info[name].lastupdate = update |
counter = counter + 1 |
end |
if not quiet then |
if wait then DEFAULT_CHAT_FRAME:AddMessage(L["add"]..tostring(diff)..L["dkpword"] .."to ".. L["waitlist"] ..L["attend"]) |
else |
if #attendees == 1 then DEFAULT_CHAT_FRAME:AddMessage(L["add"]..tostring(diff)..L["dkpword"] .."to "..attendees[1]) |
else DEFAULT_CHAT_FRAME:AddMessage(L["add"]..tostring(diff)..L["dkpword"] .."to "..tostring(counter)..L["attend"]) |
end |
end |
end |
end |
function MorgDKP:AwardWaitlistDKP(value, POOL, Boss, id) |
if #self.db.account.defaults.Waitlist.members == 0 then return end |
if not id then |
local eventnum |
for num, data in pairs(self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills) do |
if string.find(data.name, Boss) or string.find(data.note, Boss) then eventnum = num break end |
end |
if not eventnum then return end |
if self.db.account.defaults.waitboss == 0 then return end |
if self.db.account.defaults.waitboss == value then |
for num, name in pairs(self.db.account.defaults.Waitlist.members) do |
table.insert(self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[eventnum].attendees, name) |
end |
else |
self:AwardWaitotimeDKP(self.db.account.defaults.waitboss, POOL, Boss, self.db.account.defaults.Waitlist.members, "Group", "Group") |
end |
self:AwardDKP(nil, self.db.account.defaults.waitboss, POOL, self.db.account.defaults.Waitlist.members, 1) |
elseif id == 1 then |
if self.db.account.defaults.waitstart == 0 then return end |
if self.db.account.defaults.waitstart == value then |
for num, name in pairs(self.db.account.defaults.Waitlist.members) do |
table.insert(self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[1].attendees, name) |
end |
else |
self:AwardWaitotimeDKP(self.db.account.defaults.waitstart, POOL, Boss, self.db.account.defaults.Waitlist.members, "Group", "Group") |
end |
self:AwardDKP(nil, self.db.account.defaults.waitstart, POOL, self.db.account.defaults.Waitlist.members, 1) |
end |
end |
function MorgDKP:AwardWaitotimeDKP(value, POOL, eventname, attendees, name, type) |
self:Initialisedkpevents() |
table.insert(self.db.account.raidlog.dkpevents[POOL], {name = name, |
value = value, |
members = attendees, |
eqdkp = self.db.account.defaults.eqDKP[POOL].eqDKPsite, |
prefix = self.db.account.defaults.eqDKP[POOL].prefix, |
addtype = type, |
event = eventname}) |
end |
function MorgDKP:AddIndividualWait(name) |
local POOL = self.db.account.defaults.raid |
local id = self:GetStartEvent() |
if self.db.account.defaults.waitstart > 0 and id then |
if self.db.account.defaults.waitstart == self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[id].value then |
table.insert(self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[id].attendees, name) |
else self:AwardWaitotimeDKP(self.db.account.defaults.waitstart, POOL, self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[id].name, {[1] = name}, name, "individual") |
end |
self:AwardDKP(nil, self.db.account.defaults.waitstart, POOL, {[1] = name}, 1) |
end |
end |
function MorgDKP:TimestamptoTimestring(timestamp) |
local hours, minutes, day, month, year, result |
minutes = string.sub(timestamp, -2) |
hours = string.sub(timestamp, -4, -3) |
year = string.sub(timestamp, -6, -5) |
month = string.sub(timestamp, -10, -9) |
day = string.sub(timestamp, 1, strlen(timestamp) - 10) |
if strlen(day) == 1 then day = "0" .. day end |
result = month .. "/" .. day .. "/" .. year .. " " .. hours .. ":" .. minutes .. ":00" |
return result |
end |
function MorgDKP:TimeDiff(time1, time2) --time1 is join time, time2 is current time |
local hours1, hours2, min1, min2, sec1, sec2, day1, day2, total1, total2, timediff |
if time1 and time2 then |
local _, _, day1, hours1, min1, sec1 = string.find(time1, "%d+/(%d+)/%d+ (%d+):(%d+):(%d+)") |
local _, _, day2, hours2, min2, sec2 = string.find(time2, "%d+/(%d+)/%d+ (%d+):(%d+):(%d+)") |
--DEFAULT_CHAT_FRAME:AddMessage("d"..day1.."h"..hours1.."m"..min1.."s"..sec1) |
total1 = ((( hours1 * 60 ) + min1) *60) + sec1 |
total2 = ((( hours2 * 60 ) + min2) *60) + sec2 |
if day2 ~= day1 then |
if day2 > day1 then total2 = total2 + 86400 |
else total1 = total1 + 86400 end |
end |
timediff = total2 - total1 |
return timediff |
end |
return 0 |
end |
function MorgDKP:TimeStampDiff(time1, time2) |
local hours1, hours2, min1, min2, day1, day2, month1, month2, year1, year2, total1, total2, timediff |
if time1 and time2 then |
time1 = tostring(time1) |
time2 = tostring(time2) |
if strlen(time1) < 12 then time1 = "0" .. time1 end |
if strlen(time2) < 12 then time2 = "0" .. time2 end |
local _, _, day1, month1, year1, hours1, min1 = string.find(time1, "(%d%d)(%d%d)(%d%d%d%d)(%d%d)(%d%d)") |
local _, _, day2, month2, year2, hours2, min2 = string.find(time2, "(%d%d)(%d%d)(%d%d%d%d)(%d%d)(%d%d)") |
total1 = ((((((month1 * 30) + day1) * 24) + hours1) * 60 ) + min1) |
total2 = ((((((month2 * 30) + day2) * 24) + hours2) * 60 ) + min2) |
if year1 > year2 then return true |
elseif total1 > total2 then return true |
else return false |
end |
end |
return false |
end |
function MorgDKP:GetServerTime() |
--get UTC time |
local hour = date("!%H") |
local minute = date("!%M") |
local sec = date("!%S") |
local month = date("!%m") |
local day = date("!%d") |
local year = date("!%y") |
if strlen(day) == 1 then day = "0" .. day end |
if strlen(minute) == 1 then minute = "0" .. minute end |
if strlen(hour) == 1 then hour = "0" .. hour end |
if strlen(sec) == 1 then sec = "0" .. sec end |
local timereturn = month .. "/" .. day .. "/" .. year .. " " .. hour .. ":" .. minute .. ":" .. sec |
if self.db.account.defaults.devmode then self:Print(timereturn) end |
return timereturn |
end |
-- ****************************************************************** |
-- ****************************************************************** |
-- ** MorgDKP ** |
-- ****************************************************************** |
-- ****************************************************************** |
local L = AceLibrary("AceLocale-2.2"):new("MorgDKP") |
local BC = AceLibrary("Babble-Class-2.2") |
local dewdrop = AceLibrary("Dewdrop-2.0") |
local FuBar = AceLibrary("FuBarPlugin-2.0") |
local classes = { [1] = BC["Paladin"], [2] = BC["Warrior"], [3] = BC["Hunter"], [4] = BC["Rogue"], [5] = BC["Druid"], [6] = BC["Mage"], [7] = BC["Warlock"], [8] = BC["Priest"], [9] = BC["Shaman"], [10] = L["All"]} |
local classcolors = {[1] = "|c00"..BC:GetHexColor("Paladin"), [2] = "|c00"..BC:GetHexColor("Warrior"), [3] = "|c00"..BC:GetHexColor("Hunter"), [4] = "|c00"..BC:GetHexColor("Rogue"), [5] = "|c00"..BC:GetHexColor("Druid"), [6] = "|c00"..BC:GetHexColor("Mage"), [7] = "|c00"..BC:GetHexColor("Warlock"), [8] = "|c00"..BC:GetHexColor("Priest"), [9] = "|c00"..BC:GetHexColor("Shaman")} |
local Quality = {[1] = "|c009d9d9dPoor|r", [2] = "|c00ffffffCommon|r", [3] = "|c001eff00Uncommon|r", [4] = "|c000070ddRare|r", [5] = "|c00a335eeEpic|r", [6] = "|c00ff8000Legendary|r", [7] = "|c00e6cc80Artifact|r"} |
local BidStep = {[1] = "5", [2] = "10", [3] = "25", [4] = "50", [5] = "100", [6] = "200", [7] = "500"} |
function MorgDKP:optGetKey(table, value) |
for k,v in pairs(table) do |
if value == v then |
return k |
end |
end |
end |
function MorgDKP:DoOptions() |
local db = MorgDKP.db.account |
MorgDKP.classopts = { |
type = "group", |
args = { |
class1 = { |
type = "toggle", |
name = classcolors[1]..classes[1], |
desc = classcolors[1]..classes[1], |
get = function() return db.items[myid].classes[classes[1]] end, |
set = function(v) db.items[myid].classes[classes[1]] = v end, |
order = 1 |
}, |
class2 = { |
type = "toggle", |
name = classcolors[2]..classes[2], |
desc = classcolors[2]..classes[2], |
get = function() return db.items[myid].classes[classes[2]] end, |
set = function(v) db.items[myid].classes[classes[2]] = v end, |
order = 2 |
}, |
class3 = { |
type = "toggle", |
name = classcolors[3]..classes[3], |
desc = classcolors[3]..classes[3], |
get = function() return db.items[myid].classes[classes[3]] end, |
set = function(v) db.items[myid].classes[classes[3]] = v end, |
order = 3 |
}, |
class4 = { |
type = "toggle", |
name = classcolors[4]..classes[4], |
desc = classcolors[4]..classes[4], |
get = function() return db.items[myid].classes[classes[4]] end, |
set = function(v) db.items[myid].classes[classes[4]] = v end, |
order = 4 |
}, |
class5 = { |
type = "toggle", |
name = classcolors[5]..classes[5], |
desc = classcolors[5]..classes[5], |
get = function() return db.items[myid].classes[classes[5]] end, |
set = function(v) db.items[myid].classes[classes[5]] = v end, |
order = 5 |
}, |
class6 = { |
type = "toggle", |
name = classcolors[6]..classes[6], |
desc = classcolors[6]..classes[6], |
get = function() return db.items[myid].classes[classes[6]] end, |
set = function(v) db.items[myid].classes[classes[6]] = v end, |
order = 6 |
}, |
class7 = { |
type = "toggle", |
name = classcolors[7]..classes[7], |
desc = classcolors[7]..classes[7], |
get = function() return db.items[myid].classes[classes[7]] end, |
set = function(v) db.items[myid].classes[classes[7]] = v end, |
order = 7 |
}, |
class8 = { |
type = "toggle", |
name = classcolors[8]..classes[8], |
desc = classcolors[8]..classes[8], |
get = function() return db.items[myid].classes[classes[8]] end, |
set = function(v) db.items[myid].classes[classes[8]] = v end, |
order = 8 |
}, |
class9 = { |
type = "toggle", |
name = classcolors[9]..classes[9], |
desc = classcolors[9]..classes[9], |
get = function() return db.items[myid].classes[classes[9]] end, |
set = function(v) db.items[myid].classes[classes[9]] = v end, |
order = 9 |
}, |
class10 = { |
type = "toggle", |
name = classcolors[8]..classes[10], |
desc = classcolors[8]..classes[10], |
get = function() return db.items[myid].classes[classes[10]] end, |
set = function(v) |
db.items[myid].classes[classes[10]] = v |
for num = 1 , 9 do |
db.items[myid].classes[classes[num]] = v |
end |
end, |
order = 10 |
}, |
closeit = { |
type = "execute", |
name = L["closemenu"], |
desc = L["closemenu"], |
func = function() dewdrop:Close() end, |
order = 11 |
} |
} |
} |
MorgDKP.altclassopts = { |
type = "group", |
args = { |
class1 = { |
type = "toggle", |
name = classcolors[1]..classes[1], |
desc = classcolors[1]..classes[1], |
get = function() return db.items[myid].altclasses[classes[1]] end, |
set = function(v) db.items[myid].altclasses[classes[1]] = v end, |
order = 1 |
}, |
class2 = { |
type = "toggle", |
name = classcolors[2]..classes[2], |
desc = classcolors[2]..classes[2], |
get = function() return db.items[myid].altclasses[classes[2]] end, |
set = function(v) db.items[myid].altclasses[classes[2]] = v end, |
order = 2 |
}, |
class3 = { |
type = "toggle", |
name = classcolors[3]..classes[3], |
desc = classcolors[3]..classes[3], |
get = function() return db.items[myid].altclasses[classes[3]] end, |
set = function(v) db.items[myid].altclasses[classes[3]] = v end, |
order = 3 |
}, |
class4 = { |
type = "toggle", |
name = classcolors[4]..classes[4], |
desc = classcolors[4]..classes[4], |
get = function() return db.items[myid].altclasses[classes[4]] end, |
set = function(v) db.items[myid].altclasses[classes[4]] = v end, |
order = 4 |
}, |
class5 = { |
type = "toggle", |
name = classcolors[5]..classes[5], |
desc = classcolors[5]..classes[5], |
get = function() return db.items[myid].altclasses[classes[5]] end, |
set = function(v) db.items[myid].altclasses[classes[5]] = v end, |
order = 5 |
}, |
class6 = { |
type = "toggle", |
name = classcolors[6]..classes[6], |
desc = classcolors[6]..classes[6], |
get = function() return db.items[myid].altclasses[classes[6]] end, |
set = function(v) db.items[myid].altclasses[classes[6]] = v end, |
order = 6 |
}, |
class7 = { |
type = "toggle", |
name = classcolors[7]..classes[7], |
desc = classcolors[7]..classes[7], |
get = function() return db.items[myid].altclasses[classes[7]] end, |
set = function(v) db.items[myid].altclasses[classes[7]] = v end, |
order = 7 |
}, |
class8 = { |
type = "toggle", |
name = classcolors[8]..classes[8], |
desc = classcolors[8]..classes[8], |
get = function() return db.items[myid].altclasses[classes[8]] end, |
set = function(v) db.items[myid].altclasses[classes[8]] = v end, |
order = 8 |
}, |
class9 = { |
type = "toggle", |
name = classcolors[9]..classes[9], |
desc = classcolors[9]..classes[9], |
get = function() return db.items[myid].altclasses[classes[9]] end, |
set = function(v) db.items[myid].altclasses[classes[9]] = v end, |
order = 9 |
}, |
class10 = { |
type = "toggle", |
name = classcolors[8]..classes[10], |
desc = classcolors[8]..classes[10], |
get = function() return db.items[myid].altclasses[classes[10]] end, |
set = function(v) |
db.items[myid].altclasses[classes[10]] = v |
for num = 1 , 9 do |
db.items[myid].altclasses[classes[num]] = v |
end |
end, |
order = 10 |
}, |
closeit = { |
type = "execute", |
name = L["closemenu"], |
desc = L["closemenu"], |
func = function() dewdrop:Close() end, |
order = 11 |
} |
} |
} |
MorgDKP.MLopts = { |
type = "text", |
name = L["mloot"], |
desc = L["mlootdesc"], |
get = function() return self.db.account.defaults.mlooter end, |
set = function(v) self.db.account.defaults.mlooter = v end, |
validate = self.db.account.defaults.raidmembers, |
order = 4 |
} |
MorgDKP.DEopts = { |
type = "text", |
name = L["denchanter"], |
desc = L["denchanterdesc"], |
get = function() return self.db.account.defaults.disenchanter end, |
set = function(v) self.db.account.defaults.disenchanter = v end, |
validate = self.db.account.defaults.raidmembers, |
order = 5 |
} |
MorgDKP.RaidDBopts = { |
type = "text", |
name = L["pool"], |
desc = L["pooldesc"], |
get = function() return db.defaults.raid end, |
set = function(v) db.defaults.raid = v end, |
validate = db.defaults.raidlist |
} |
MorgDKP.Poolopts = { |
type = "text", |
name = L["pooluse"], |
desc = L["poolusedesc"], |
get = function() return v end, |
set = function(v) |
MorgDKP:SetRollPool(v) |
end, |
validate = db.defaults.raidlist |
} |
MorgDKP.dkpsystem = { |
type = "group", |
args = { |
randomrolls = { |
type = "toggle", |
name = L["enablerandom"], |
desc = L["enablerandomdesc"], |
get = function() |
return db.defaults.random |
end, |
set = function(v) |
db.defaults.random = v |
end, |
disabled = function() return MorgDKP:IsValid() end, |
order = 110 |
}, |
multipool = { |
type = "toggle", |
name = L["multi"], |
desc = L["multidesc"], |
get = function() |
return db.defaults.multiPool |
end, |
set = function(v) |
db.defaults.multiPool = v |
end, |
disabled = function() return db.defaults.random end, |
order = 111 |
}, |
zsum = { |
type = "toggle", |
name = L["enablezerosum"], |
desc = L["enablezerosumdesc"], |
get = function() |
return db.defaults.zerosum |
end, |
set = function(v) |
db.defaults.zerosum = v |
end, |
disabled = function() return db.defaults.random or db.defaults.percent > 0 end, |
order = 112 |
}, |
reldkp = { |
type = "toggle", |
name = L["enablerelationaldkp"], |
desc = L["enablerelationaldkpdesc"], |
get = function() |
return db.defaults.relational |
end, |
set = function(v) |
db.defaults.relational = v |
end, |
disabled = function() return db.defaults.random or db.defaults.bidwar end, |
order = 114 |
}, |
bwar = { |
type = "toggle", |
name = L["enablebidwar"], |
desc = L["enablebidwardesc"], |
get = function() |
return db.defaults.bidwar |
end, |
set = function(v) |
db.defaults.bidwar = v |
end, |
disabled = function() return db.defaults.random or db.defaults.relational or db.defaults.percent > 0 end, |
order = 116 |
}, |
pcnt = { |
type = "range", |
name = L["enablepercent"], |
desc = L["enablepercentdesc"], |
get = function() |
return db.defaults.percent |
end, |
set = function(v) |
db.defaults.percent = v |
end, |
step = 1, |
min = 0, |
max = 100, |
disabled = function() return db.defaults.random or db.defaults.zerosum or db.defaults.bidwar end, |
order = 118 |
}, |
bossattempt = { |
type = "toggle", |
name = L["bossattemptmode"], |
desc = L["bossattemptmodedesc"], |
get = function() |
return db.defaults.attemptmode |
end, |
set = function(v) |
db.defaults.attemptmode = v |
self:TogglePlayerDies(db.defaults.attemptmode) |
end, |
order = 120 |
} |
} |
} |
MorgDKP.qualmenu = { |
type = "text", |
name = L["logquality"], |
desc = L["logqualitydesc"], |
get = function() return Quality[db.defaults.quality+1] end, |
set = function(v) db.defaults.quality = MorgDKP:optGetKey(Quality, v) - 1 end, |
validate = Quality, |
order = 105 |
} |
MorgDKP.custommenu = { |
type = "text", |
name = L["custom"], |
desc = L["customdesc"], |
get = function() return db.defaults.custom end, |
set = function(v) db.defaults.custom = v end, |
validate = MorgTracker_ZoneBosses[db.defaults.menuzone] |
} |
MorgDKP.opts = { |
type = "group", |
args = { |
header = { |
type = "header", |
name = "|c000070dd"..L["morgtitle"].." |c00a335ee"..MorgDKP.version, |
icon = "Interface\\GroupFrame\\UI-Group-MasterLooter", |
iconHeight = 15, |
iconWidth = 15, |
handler = MorgDKP, |
order = 1 |
}, |
disable = { |
type = "execute", |
name = L["disablemod"], |
desc = L["disablemoddesc"], |
func = function() MorgDKPFu:DisableMorgDKP() end, |
disabled = "~IsActive", |
order = 2 |
}, |
mldemode = { |
type = "toggle", |
name = L["enablemlde"], |
desc = L["enablemldedesc"], |
get = function() |
return self.MLmode |
end, |
set = function(v) |
self.MLmode = v |
end, |
disabled = "~IsActive", |
order = 3 |
}, |
morgbidc = { |
type = "execute", |
name = L["morgbidcheck"], |
desc = L["morgbidcheckdesc"], |
func = function() MorgDKP:MorgBidQuery() end, |
disabled = "~IsActive", |
order = 6 |
}, |
dkpfunc = { |
type = "group", |
name = L["dkp"], |
desc = L["dkpdesc"], |
order = 7, |
args = { |
load = { |
type = "text", |
name = L["pool"], |
desc = L["pooldesc"], |
get = function() return db.defaults.raid end, |
set = function(v) db.defaults.raid = v end, |
validate = db.defaults.raidlist, |
disabled = "~IsActive", |
order = 100 |
}, |
startrd = { |
type = "execute", |
name = L["startraid"], |
desc = L["startraiddesc"], |
func = function() MorgDKP:BeginRaid() end, |
disabled = "~IsActive", |
order = 101 |
}, |
endrd = { |
type = "execute", |
name = L["endraid"], |
desc = L["endraiddesc"], |
func = function() MorgDKP:EndRaid() end, |
disabled = "~IsActive", |
order = 102 |
}, |
runbonus = { |
type = "execute", |
name = L["rundkp"], |
desc = L["rundkpdesc"], |
func = function() MorgDKP:ExportRaids() end, |
disabled = "~IsActive", |
order = 103 |
}, |
raidtracker = { |
type = "execute", |
name = L["raidtrack"], |
desc = L["raidtrackdesc"], |
func = function() MorgDKP:RaidTablet() end, |
order = 104 |
}, |
custommenu = { |
type = "text", |
name = L["custom"], |
desc = L["customdesc"], |
get = function() return db.defaults.custom end, |
set = function(v) |
db.defaults.custom = v |
MorgDKP:CustomEvent() |
end, |
validate = MorgTracker_ZoneBosses[db.defaults.menuzone], |
disabled = "~IsActive", |
order = 106 |
}, |
clearraids = { |
type = "execute", |
name = L["clearraid"], |
desc = L["clearraiddesc"], |
func = function() MorgDKP:ClearRaidDB() end, |
order = 107 |
}, |
syncdb = { |
type = "execute", |
name = L["syncdb"], |
desc = L["syncdbdesc"], |
func = function() MorgDKP:SyncItemDB() end, |
disabled = "~IsActive", |
order = 108 |
}, |
itemhis = { |
type = "execute", |
name = L["itemhistory"], |
desc = L["itemhistorydesc"], |
func = function() MorgDKP:ItemHistory() end, |
order = 109 |
}, |
ignore = { |
type = "text", |
name = L["ignorelist"], |
desc = L["ignorelistdesc"], |
get = false, |
set = function(v) |
for id,link in pairs(db.defaults.ignore) do |
if link == v then table.remove(db.defaults.ignore, id) break end |
end |
end, |
validate = db.defaults.ignore, |
disabled = function() return not db.defaults.ignore[1] end, |
order = 110 |
}, |
dkptype = { |
type = "group", |
name = L["dkptypes"], |
desc = L["dkptypesdesc"], |
order = 112, |
args = { |
randomrolls = { |
type = "toggle", |
name = L["enablerandom"], |
desc = L["enablerandomdesc"], |
get = function() |
return db.defaults.random |
end, |
set = function(v) |
db.defaults.random = v |
end, |
disabled = function() return MorgDKP:IsValid() end, |
order = 200 |
}, |
multipool = { |
type = "toggle", |
name = L["multi"], |
desc = L["multidesc"], |
get = function() |
return db.defaults.multiPool |
end, |
set = function(v) |
db.defaults.multiPool = v |
end, |
disabled = function() return db.defaults.random end, |
order = 202 |
}, |
zsum = { |
type = "toggle", |
name = L["enablezerosum"], |
desc = L["enablezerosumdesc"], |
get = function() |
return db.defaults.zerosum |
end, |
set = function(v) |
db.defaults.zerosum = v |
end, |
disabled = function() return db.defaults.random or db.defaults.percent > 0 end, |
order = 204 |
}, |
reldkp = { |
type = "toggle", |
name = L["enablerelationaldkp"], |
desc = L["enablerelationaldkpdesc"], |
get = function() |
return db.defaults.relational |
end, |
set = function(v) |
db.defaults.relational = v |
end, |
disabled = function() return db.defaults.random or db.defaults.bidwar end, |
order = 206 |
}, |
bwar = { |
type = "toggle", |
name = L["enablebidwar"], |
desc = L["enablebidwardesc"], |
get = function() |
return db.defaults.bidwar |
end, |
set = function(v) |
db.defaults.bidwar = v |
end, |
disabled = function() return db.defaults.random or db.defaults.relational or db.defaults.percent > 0 end, |
order = 208 |
}, |
pcnt = { |
type = "range", |
name = L["enablepercent"], |
desc = L["enablepercentdesc"], |
get = function() |
return db.defaults.percent |
end, |
set = function(v) |
db.defaults.percent = v |
end, |
step = 1, |
min = 0, |
max = 100, |
disabled = function() return db.defaults.random or db.defaults.zerosum or db.defaults.bidwar end, |
order = 210 |
}, |
}, |
}, |
otherO = { |
type = "group", |
name = L["otheroptions"], |
desc = L["otheroptionsdesc"], |
order = 114, |
args = { |
bwarwhisper = { |
type = "toggle", |
name = L["enablewhisper"], |
desc = L["enablewhisperdesc"], |
get = function() |
return db.defaults.whisper |
end, |
set = function(v) |
db.defaults.whisper = v |
end, |
order = 200 |
}, |
azone = { |
type = "toggle", |
name = L["autozone"], |
desc = L["autozonedesc"], |
get = function() |
return db.defaults.autozone |
end, |
set = function(v) |
db.defaults.autozone = v |
end, |
order = 202 |
}, |
dkplisten = { |
type = "toggle", |
name = L["dkplisten"], |
desc = L["dkplistendesc"], |
get = function() |
return db.defaults.dkplistener |
end, |
set = function(v) |
db.defaults.dkplistener = v |
end, |
order = 203 |
}, |
broadcastlead = { |
type = "toggle", |
name = L["broadlead"], |
desc = L["broadleaddesc"], |
get = function() |
return db.defaults.leadbroadcast |
end, |
set = function(v) |
db.defaults.leadbroadcast = v |
end, |
order = 204 |
}, |
starttrack = { |
type = "toggle", |
name = L["startruntrack"], |
desc = L["startruntrackdesc"], |
get = function() |
return db.defaults.startrun |
end, |
set = function(v) |
db.defaults.startrun = v |
end, |
order = 205 |
}, |
eventname = { |
type = "text", |
name = L["eventformat"], |
desc = L["eventformatdesc"], |
usage = "<char>", |
get = function() |
return db.defaults.eventformat |
end, |
set = function(text) |
self:EventFormat(text) |
end, |
disabled = "~IsActive", |
order = 206 |
}, |
startname = { |
type = "text", |
name = L["startformat"], |
desc = L["startformatdesc"], |
usage = "<char>", |
get = function() |
return db.defaults.startformat |
end, |
set = function(text) |
self:StartFormat(text) |
end, |
disabled = "~IsActive", |
order = 207 |
}, |
trashname = { |
type = "text", |
name = L["trashformat"], |
desc = L["trashformatdesc"], |
usage = "<char>", |
get = function() |
return db.defaults.trashformat |
end, |
set = function(text) |
self:TrashFormat(text) |
end, |
disabled = "~IsActive", |
order = 208 |
}, |
onerun = { |
type = "toggle", |
name = L["onerun"], |
desc = L["onerundesc"], |
get = function() |
return db.defaults.OneEvent |
end, |
set = function(v) |
db.defaults.OneEvent = v |
end, |
order = 209 |
}, |
percenttake = { |
type = "toggle", |
name = L["percenttake"], |
desc = L["percenttakedesc"], |
get = function() |
return db.defaults.percenttake |
end, |
set = function(v) |
db.defaults.percenttake = v |
end, |
order = 210 |
}, |
bossattempt = { |
type = "toggle", |
name = L["bossattemptmode"], |
desc = L["bossattemptmodedesc"], |
get = function() |
return db.defaults.attemptmode |
end, |
set = function(v) |
db.defaults.attemptmode = v |
self:TogglePlayerDies(db.defaults.attemptmode) |
end, |
order = 211 |
}, |
runtime = { |
type = "text", |
name = L["runrewardtime"], |
desc = L["runrewardtimedesc"], |
usage = "<char>", |
get = function() |
return math.floor(db.defaults.runrewardtime) / 60 |
end, |
set = function(text) |
self:SetRunTime(text) |
end, |
disabled = "~IsActive", |
order = 212 |
}, |
dkpadd = { |
type = "text", |
name = L["adddkp"], |
desc = L["adddkpdesc"], |
usage = "<char>", |
get = false, |
set = function(text) |
charstring = text |
adding = 1 |
MorgDKP:ChangeDKP() |
end, |
disabled = "~IsActive", |
order = 220 |
}, |
dkpsub = { |
type = "text", |
name = L["subdkp"], |
desc = L["subdkpdesc"], |
usage = "<char>", |
get = false, |
set = function(text) |
charstring = text |
adding = nil |
MorgDKP:ChangeDKP() |
end, |
disabled = "~IsActive", |
order = 221 |
}, |
devmode = { |
type = "toggle", |
name = L["devmode"], |
desc = L["devmode"], |
get = function() |
return db.defaults.devmode |
end, |
set = function(v) |
db.defaults.devmode = v |
end, |
order = 225 |
}, |
}, |
}, |
waitopts = { |
type = "group", |
name = L["waitlist"], |
desc = L["waitlistdesc"], |
order = 115, |
args = { |
award = { |
type = "toggle", |
name = L["enablewait"], |
desc = L["enablewaitdesc"], |
get = function() |
return db.defaults.waitaward |
end, |
set = function(v) |
db.defaults.waitaward = v |
end, |
order = 200 |
}, |
waitstart = { |
type = "range", |
name = L["waitstartamt"], |
desc = L["waitstartamtdesc"], |
get = function() |
return db.defaults.waitstart |
end, |
set = function(v) |
db.defaults.waitstart = v |
end, |
step = 1, |
min = 0, |
max = 100, |
disabled = function() return not db.defaults.waitaward end, |
order = 202 |
}, |
waitrun = { |
type = "range", |
name = L["waitrunamt"], |
desc = L["waitrunamtdesc"], |
get = function() |
return db.defaults.waitrun |
end, |
set = function(v) |
db.defaults.waitrun = v |
end, |
step = 1, |
min = 0, |
max = 100, |
disabled = function() return not db.defaults.waitaward end, |
order = 204 |
}, |
waitboss = { |
type = "range", |
name = L["waitbossamt"], |
desc = L["waitbossamtdesc"], |
get = function() |
return db.defaults.waitboss |
end, |
set = function(v) |
db.defaults.waitboss = v |
end, |
step = 1, |
min = 0, |
max = 100, |
disabled = function() return not db.defaults.waitaward end, |
order = 204 |
}, |
waitotime = { |
type = "range", |
name = L["waitotimeamt"], |
desc = L["waitotimeamtdesc"], |
get = function() |
return db.defaults.waitotime |
end, |
set = function(v) |
db.defaults.waitotime = v |
end, |
step = 1, |
min = 0, |
max = 100, |
disabled = function() return not db.defaults.waitaward end, |
order = 206 |
}, |
}, |
}, |
bidwarO = { |
type = "group", |
name = L["bidwaroptions"], |
desc = L["bidwaroptionsdesc"], |
order = 116, |
args = { |
silent = { |
type = "toggle", |
name = L["enablesilentauction"], |
desc = L["enablesilentauctiondesc"], |
get = function() |
return db.defaults.silent |
end, |
set = function(v) |
db.defaults.silent = v |
end, |
disabled = function() return not db.defaults.bidwar end, |
order = 200 |
}, |
bwarstep = { |
type = "text", |
name = L["bwarsteps"], |
desc = L["bwarstepsdesc"], |
get = function() return BidStep[MorgDKP:optGetKey(BidStep, db.defaults.bidstep)] end, |
set = function(v) db.defaults.bidstep = v end, |
validate = BidStep, |
disabled = function() return not db.defaults.bidwar end, |
order = 202 |
}, |
overbid = { |
type = "text", |
name = L["overbidmax"], |
desc = L["overbidmaxdesc"], |
usage = "<char>", |
get = function() return db.defaults.overbid end, |
set = function(text) db.defaults.overbid = text end, |
disabled = function() return not db.defaults.bidwar end, |
order = 204 |
}, |
jenough = { |
type = "toggle", |
name = L["enablejustenough"], |
desc = L["enablejustenoughdesc"], |
get = function() |
return db.defaults.justenough |
end, |
set = function(v) |
db.defaults.justenough = v |
end, |
disabled = function() return not db.defaults.bidwar end, |
order = 206 |
}, |
}, |
}, |
}, |
}, |
teinly = { |
type = "text", |
name = L["twinks"], |
desc = L["twinksdesc"], |
usage = "<char>", |
get = false, |
set = function(text) self:AddTwink(text) end, |
disabled = "~IsActive", |
order = 8 |
}, |
list = { |
type = "text", |
name = L["listdkp"], |
desc = L["listdkpdesc"], |
usage = "<all> <paladin> <rogue> <druid> <...>", |
get = false, |
set = function(text) self:ListDKP(text) end, |
validate = classes, |
disabled = "~IsActive", |
order = 9 |
}, |
boes = { |
type = "text", |
name = L["giveboe"], |
desc = L["giveboedesc"], |
get = false, |
set = function(text) charstring = text MorgDKP:GiveBOE(myid, mylink) end, |
validate = self.db.account.defaults.raidmembers, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 10 |
}, |
additem = { |
type = "execute", |
name = L["manualitem"], |
desc = L["manualitemdesc"], |
func = function() MorgDKP:ManualItem(myid, mylink) end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 11 |
}, |
setpt = { |
type = "text", |
name = L["setitempoints"], |
desc = L["setitempointsdesc"], |
usage = "<char>", |
get = function() return db.items[myid].points end, |
set = function(text) db.items[myid].points = text end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 12 |
}, |
qraid = { |
type = "execute", |
name = L["queryraid"], |
desc = L["queryraiddesc"], |
func = function() MorgDKP:StartQuery(myid, mylink) end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 13 |
}, |
spacer1 = { |
type = "header", |
order = 20 |
}, |
class1 = { |
type = "toggle", |
name = classcolors[1]..classes[1], |
desc = classcolors[1]..classes[1], |
get = function() return db.items[myid].classes[classes[1]] end, |
set = function(v) db.items[myid].classes[classes[1]] = v end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 1000 |
}, |
class2 = { |
type = "toggle", |
name = classcolors[2]..classes[2], |
desc = classcolors[2]..classes[2], |
get = function() return db.items[myid].classes[classes[2]] end, |
set = function(v) db.items[myid].classes[classes[2]] = v end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 1002 |
}, |
class3 = { |
type = "toggle", |
name = classcolors[3]..classes[3], |
desc = classcolors[3]..classes[3], |
get = function() return db.items[myid].classes[classes[3]] end, |
set = function(v) db.items[myid].classes[classes[3]] = v end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 1004 |
}, |
class4 = { |
type = "toggle", |
name = classcolors[4]..classes[4], |
desc = classcolors[4]..classes[4], |
get = function() return db.items[myid].classes[classes[4]] end, |
set = function(v) db.items[myid].classes[classes[4]] = v end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 1006 |
}, |
class5 = { |
type = "toggle", |
name = classcolors[5]..classes[5], |
desc = classcolors[5]..classes[5], |
get = function() return db.items[myid].classes[classes[5]] end, |
set = function(v) db.items[myid].classes[classes[5]] = v end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 1008 |
}, |
class6 = { |
type = "toggle", |
name = classcolors[6]..classes[6], |
desc = classcolors[6]..classes[6], |
get = function() return db.items[myid].classes[classes[6]] end, |
set = function(v) db.items[myid].classes[classes[6]] = v end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 1010 |
}, |
class7 = { |
type = "toggle", |
name = classcolors[7]..classes[7], |
desc = classcolors[7]..classes[7], |
get = function() return db.items[myid].classes[classes[7]] end, |
set = function(v) db.items[myid].classes[classes[7]] = v end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 1012 |
}, |
class8 = { |
type = "toggle", |
name = classcolors[8]..classes[8], |
desc = classcolors[8]..classes[8], |
get = function() return db.items[myid].classes[classes[8]] end, |
set = function(v) db.items[myid].classes[classes[8]] = v end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 1014 |
}, |
class9 = { |
type = "toggle", |
name = classcolors[9]..classes[9], |
desc = classcolors[9]..classes[9], |
get = function() return db.items[myid].classes[classes[9]] end, |
set = function(v) db.items[myid].classes[classes[9]] = v end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 1016 |
}, |
class10 = { |
type = "toggle", |
name = classcolors[8]..classes[10], |
desc = classcolors[8]..classes[10], |
get = function() return db.items[myid].classes[classes[10]] end, |
set = function(v) |
db.items[myid].classes[classes[10]] = v |
for num = 1 , 9 do |
db.items[myid].classes[classes[num]] = v |
end |
end, |
hidden = function() return not self.hasitem end, |
disabled = "~IsActive", |
order = 1018 |
}, |
Menu = { |
type = "group", |
name = L["Menu"], |
desc = L["Menu"], |
args = FuBar:GetAceOptionsDataTable(MorgDKPFu), |
hidden = function() return self.hasitem end, |
order = 300, |
} |
} |
} |
MorgDKP.opts.args.mlootdet = MorgDKP.MLopts |
MorgDKP.opts.args.deer = MorgDKP.DEopts |
MorgDKP.opts.args.dkpfunc.args.logqual = MorgDKP.qualmenu |
end |
<Ui xmlns="http://www.blizzard.com/wow/ui/" |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
xsi:schemaLocation="http://www.blizzard.com/wow/ui/FrameXML/UI.xsd"> |
<Frame name="URLFrame" toplevel="true" frameStrata="DIALOG" movable="true" enableMouse="true" hidden="true" parent="UIParent" enableKeyboard="true"> |
<Size> |
<AbsDimension x="400" y="125"/> |
</Size> |
<Anchors> |
<Anchor point="CENTER"/> |
</Anchors> |
<Backdrop bgFile="Interface\DialogFrame\UI-DialogBox-Background" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true"> |
<BackgroundInsets> |
<AbsInset left="11" right="12" top="12" bottom="11"/> |
</BackgroundInsets> |
<TileSize> |
<AbsValue val="32"/> |
</TileSize> |
<EdgeSize> |
<AbsValue val="32"/> |
</EdgeSize> |
</Backdrop> |
<Layers> |
<Layer level="ARTWORK"> |
<Texture name="URLFrameHeader" file="Interface\DialogFrame\UI-DialogBox-Header"> |
<Size> |
<AbsDimension x="256" y="64"/> |
</Size> |
<Anchors> |
<Anchor point="TOP"> |
<Offset> |
<AbsDimension x="0" y="12"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Texture> |
<FontString inherits="GameFontNormal" text="DKP String"> |
<Anchors> |
<Anchor point="TOP" relativeTo="URLFrameHeader"> |
<Offset> |
<AbsDimension x="0" y="-14"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
</Layer> |
</Layers> |
<Frames> |
<EditBox name="URLFrameEditBox" historyLines="0" letters="99999999"> |
<Size> |
<AbsDimension x="300" y="16"/> |
</Size> |
<Anchors> |
<Anchor point="TOP"> |
<Offset> |
<AbsDimension x="0" y="-50" /> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="BACKGROUND"> |
<Texture name="$parentLeft" file="Interface\ChatFrame\UI-ChatInputBorder-Left"> |
<Size> |
<AbsDimension x="65" y="32"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<TexCoords left="0" right="0.2539" top="0" bottom="1.0"/> |
</Texture> |
<Texture name="$parentRight" file="Interface\ChatFrame\UI-ChatInputBorder-Right"> |
<Size> |
<AbsDimension x="25" y="32"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT"> |
<Offset> |
<AbsDimension x="10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<TexCoords left="0.9" right="1.0" top="0" bottom="1.0"/> |
</Texture> |
<Texture file="Interface\ChatFrame\UI-ChatInputBorder-Left"> |
<Size> |
<AbsDimension x="5" y="32"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentLeft" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
<Anchor point="RIGHT" relativeTo="$parentRight" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<TexCoords left="0.29296875" right="1.0" top="0" bottom="1.0"/> |
</Texture> |
</Layer> |
</Layers> |
<FontString inherits="ChatFontNormal"/> |
<Scripts> |
<OnEscapePressed> |
URLFrame:Hide(); |
</OnEscapePressed> |
<OnEnterPressed> |
URLFrame:Hide(); |
</OnEnterPressed> |
</Scripts> |
</EditBox> |
<Button name="URLFrameDone" inherits="OptionsButtonTemplate" text="Close"> |
<Anchors> |
<Anchor point="BOTTOM"> |
<Offset> |
<AbsDimension x="0" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
URLFrame:Hide(); |
</OnClick> |
</Scripts> |
</Button> |
</Frames> |
</Frame> |
<EditBox name="MorgDKP_EditboxTemplate" letters="100" autoFocus="false" hidden="false" virtual="true"> |
<Size> |
<AbsDimension x="230" y="25"/> |
</Size> |
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true"> |
<BackgroundInsets> |
<AbsInset left="3" right="3" top="3" bottom="3"/> |
</BackgroundInsets> |
<TileSize> |
<AbsValue val="16"/> |
</TileSize> |
<EdgeSize> |
<AbsValue val="16"/> |
</EdgeSize> |
<Color r="0" g="0" b="0" a="1.0"/> |
</Backdrop> |
<FontString inherits="GameFontNormal" > |
<Color r="1" g="1" b="1"/> |
<FontHeight> |
<AbsValue val="10"/> |
</FontHeight> |
</FontString> |
<TextInsets> |
<AbsInset left="7" right="5" top="5" bottom="5"/> |
</TextInsets> |
<Scripts> |
<OnEscapePressed> |
MorgDKP:TextEscapePressed(this) |
</OnEscapePressed> |
<OnEnterPressed> |
MorgDKP:TextEnterPressed(this) |
</OnEnterPressed> |
</Scripts> |
</EditBox> |
<EditBox name="MorgDKP_EditboxTemplateSmall" letters="100" autoFocus="false" hidden="false" virtual="true"> |
<Size> |
<AbsDimension x="230" y="25"/> |
</Size> |
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true"> |
<BackgroundInsets> |
<AbsInset left="3" right="3" top="3" bottom="3"/> |
</BackgroundInsets> |
<TileSize> |
<AbsValue val="16"/> |
</TileSize> |
<EdgeSize> |
<AbsValue val="16"/> |
</EdgeSize> |
<Color r="0" g="0" b="0" a="1.0"/> |
</Backdrop> |
<FontString inherits="GameFontNormalSmall" > |
<Color r="1" g="1" b="1"/> |
<FontHeight> |
<AbsValue val="10"/> |
</FontHeight> |
</FontString> |
<TextInsets> |
<AbsInset left="7" right="5" top="5" bottom="5"/> |
</TextInsets> |
<Scripts> |
<OnEscapePressed> |
MorgDKP:TextEscapePressed(this) |
</OnEscapePressed> |
<OnEnterPressed> |
MorgDKP:TextEnterPressed(this) |
</OnEnterPressed> |
</Scripts> |
</EditBox> |
<ScrollFrame name="MorgDKP_ScrollframeTemplate" inherits="FauxScrollFrameTemplate" hidden="false" virtual="true"> |
<Size> |
<AbsDimension x="240" y="440"/> |
</Size> |
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true"> |
<BackgroundInsets> |
<AbsInset left="3" right="3" top="3" bottom="3"/> |
</BackgroundInsets> |
<TileSize> |
<AbsValue val="8"/> |
</TileSize> |
<EdgeSize> |
<AbsValue val="8"/> |
</EdgeSize> |
<Color r="0" g="0" b="0" a="1.0"/> |
</Backdrop> |
<Scripts> |
<OnVerticalScroll> |
FauxScrollFrame_OnVerticalScroll(35, MorgDKP.ScrollBar_Update) |
</OnVerticalScroll> |
</Scripts> |
</ScrollFrame> |
<Button name="MorgDKP_ScrollButtonTemplate" inherits="OptionsButtonTemplate" hidden="true" virtual="true"> |
<Size> |
<AbsDimension x="220" y="30"/> |
</Size> |
<NormalTexture file="Interface/Buttons/UI-DialogBox-Button-Up"/> |
<PushedTexture file="Interface/Buttons/UI-DialogBox-Button-Down"/> |
<HighlightTexture file="Interface/Buttons/UI-DialogBox-Button-Highlight" alphaMode="ADD"/> |
<ButtonText name="$parentText" justifyH="CENTER"> |
<Size> |
<AbsDimension x="220" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="5"/> |
</Offset> |
</Anchor> |
</Anchors> |
</ButtonText> |
<Scripts> |
<OnEnter> |
MorgDKP:EditEvent(this:GetParent(), this:GetName()) |
</OnEnter> |
</Scripts> |
</Button> |
<ScrollFrame name="MorgDKP_ScrollframeTemplate2" inherits="FauxScrollFrameTemplate" hidden="true" virtual="true"> |
<Size> |
<AbsDimension x="200" y="195"/> |
</Size> |
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true"> |
<BackgroundInsets> |
<AbsInset left="3" right="3" top="3" bottom="3"/> |
</BackgroundInsets> |
<TileSize> |
<AbsValue val="16"/> |
</TileSize> |
<EdgeSize> |
<AbsValue val="12"/> |
</EdgeSize> |
<Color r="0" g="0" b="0" a="1.0"/> |
</Backdrop> |
<Scripts> |
<OnVerticalScroll> |
FauxScrollFrame_OnVerticalScroll(35, MorgDKP.ScrollBar_Update2) |
</OnVerticalScroll> |
</Scripts> |
</ScrollFrame> |
<Frame name="MorgDKP_ScrollButtonTemplate2" hidden="true" enableMouse="true" virtual="true"> |
<Size> |
<AbsDimension x="200" y="42"/> |
</Size> |
<Layers> |
<Layer level="ARTWORK"> |
<FontString name="$parentID" justifyH="LEFT" inherits="GameFontNormalSmall" hidden="true"> |
<Size> |
<AbsDimension x="28" y="16"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="8" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="1.0" a="1.0" /> |
</FontString> |
<FontString name="$parentName" justifyH="LEFT" justifyV="TOP" inherits="GameFontNormalSmall"> |
<Size> |
<AbsDimension x="140" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="56" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="1.0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
<Frames> |
<Button name="$parentTexture"> |
<Size> |
<AbsDimension x="40" y="40" /> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="8" y="0" /> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnUpdate> |
local _, _, _, _, _, _, _, _, _, texture = GetItemInfo(getglobal(this:GetParent():GetName().."ID"):GetText()) |
getglobal(this:GetParent():GetName().."Texture"):SetNormalTexture(texture) |
</OnUpdate> |
<OnEnter> |
GameTooltip:SetOwner(this, "ANCHOR_LEFT") |
GameTooltip:SetHyperlink(getglobal(this:GetParent():GetName().."ID"):GetText(), 1, 1, 1, 1, 1) |
GameTooltip:Show() |
MorgDKP:EditItem(this:GetParent(), this:GetName()) |
</OnEnter> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP:EditItem(this:GetParent(), this:GetName()) |
</OnClick> |
</Scripts> |
<NormalTexture name="$parentNormalTexture" file="Interface\Icons\INV_Misc_QuestionMark" /> |
</Button> |
</Frames> |
</Frame> |
<Button name="MorgDKP_DownButtonTemplate" inherits="OptionsButtonTemplate" hidden="false" virtual="true"> |
<Size> |
<AbsDimension x="25" y="25"/> |
</Size> |
<NormalTexture file="Interface/Buttons/UI-ScrollBar-ScrollDownButton-Up"/> |
<PushedTexture file="Interface/Buttons/UI-ScrollBar-ScrollDownButton-Down"/> |
<HighlightTexture file="Interface/Buttons/UI-ScrollBar-ScrollDownButton-Highlight" alphaMode="ADD"/> |
</Button> |
<Frame name="MorgDKP_EndRaid" toplevel="true" frameStrata="DIALOG" movable="true" resizable="true" enableMouse="true" hidden="true" parent="UIParent" enableKeyboard="true"> |
<Size> |
<AbsDimension x="200" y="100"/> |
</Size> |
<Anchors> |
<Anchor point="CENTER"/> |
</Anchors> |
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true"> |
<BackgroundInsets> |
<AbsInset left="3" right="3" top="3" bottom="3"/> |
</BackgroundInsets> |
<TileSize> |
<AbsValue val="16"/> |
</TileSize> |
<EdgeSize> |
<AbsValue val="16"/> |
</EdgeSize> |
<Color r="0" g="0" b="0" a="1.0"/> |
</Backdrop> |
<Layers> |
<Layer level="ARTWORK"> |
<FontString name="$parentRaidname" inherits="GameFontNormal"> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="10" y="-10"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentQmark" inherits="GameFontNormal" text="?" hidden="true"> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentRaidname" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentEndstring" inherits="GameFontNormalSmall" hidden="true"> |
<Anchors> |
<Anchor point="BOTTOMLEFT" relativeTo="$parentRaidname" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="20" y="-30"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
</Layer> |
</Layers> |
<Scripts> |
<OnMouseDown> |
if (arg1 == "LeftButton") then |
this:StartMoving(); |
end |
</OnMouseDown> |
<OnMouseUp> |
if (arg1 == "LeftButton") then |
this:StopMovingOrSizing(); |
end |
</OnMouseUp> |
</Scripts> |
<Frames> |
<EditBox name="$parentAttendees" inherits="MorgDKP_EditboxTemplateSmall" letters="6000" hidden="true" multiLine="true"> |
<Size> |
<AbsDimension x="200" y="200"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="45" y="-45"/> |
</Offset> |
</Anchor> |
</Anchors> |
</EditBox> |
<Button name="$parentNO" inherits="OptionsButtonTemplate" hidden="false" text="CANCEL"> |
<Size> |
<AbsDimension x="75" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="BOTTOMRIGHT" relativeTo="$parent" relativePoint="BOTTOMRIGHT"> |
<Offset> |
<AbsDimension x="-20" y="10"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
this:GetParent():Hide() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentYESADD" inherits="OptionsButtonTemplate" hidden="true" text="Yes + Add"> |
<Size> |
<AbsDimension x="90" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parentNO" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="-95" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:AddandEnd() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentYES" inherits="OptionsButtonTemplate" hidden="false" text="YES"> |
<Size> |
<AbsDimension x="75" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parentNO" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:EndRaid() |
this:GetParent():Hide() |
</OnClick> |
</Scripts> |
</Button> |
</Frames> |
</Frame> |
<Frame name="MorgDKP_Raid" toplevel="true" frameStrata="DIALOG" movable="true" resizable="true" enableMouse="true" hidden="true" parent="UIParent" enableKeyboard="true"> |
<Size> |
<AbsDimension x="700" y="700"/> |
</Size> |
<Anchors> |
<Anchor point="CENTER"/> |
</Anchors> |
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true"> |
<BackgroundInsets> |
<AbsInset left="3" right="3" top="3" bottom="3"/> |
</BackgroundInsets> |
<TileSize> |
<AbsValue val="16"/> |
</TileSize> |
<EdgeSize> |
<AbsValue val="16"/> |
</EdgeSize> |
<Color r="0" g="0" b="0" a="1.0"/> |
</Backdrop> |
<Layers> |
<Layer level="ARTWORK"> |
<Texture name="URLFrameHeader" file="Interface\DialogFrame\UI-DialogBox-Header"> |
<Size> |
<AbsDimension x="350" y="60"/> |
</Size> |
<Anchors> |
<Anchor point="TOP"> |
<Offset> |
<AbsDimension x="0" y="12"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Texture> |
<FontString inherits="GameFontNormal" text="MorgDKP Raidtracker"> |
<Anchors> |
<Anchor point="TOP" relativeTo="MorgDKP_Raid"> |
<Offset> |
<AbsDimension x="0" y="-2"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
</Layer> |
</Layers> |
<Scripts> |
<OnMouseDown> |
if (arg1 == "LeftButton") then |
this:StartMoving(); |
end |
</OnMouseDown> |
<OnMouseUp> |
if (arg1 == "LeftButton") then |
this:StopMovingOrSizing(); |
end |
</OnMouseUp> |
</Scripts> |
<Frames> |
<Frame name="MorgDKP_RaidsPage1" hidden="true"> |
<Anchors> |
<Anchor point="TOPLEFT"/> |
<Anchor point="BOTTOMRIGHT"/> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentItemLabel" inherits="GameFontNormal" text="Items:"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parent" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="45" y="-400"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentRaidNameLabel" inherits="GameFontNormal" text="Name:"> |
<Size> |
<AbsDimension x="55" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPRIGHT" relativeTo="$parent" relativePoint="TOPRIGHT"> |
<Offset> |
<AbsDimension x="-295" y="-100"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentRaidNoteLabel" inherits="GameFontNormal" text="Note:"> |
<Size> |
<AbsDimension x="70" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOP" relativeTo="$parentRaidNameLabel" relativePoint="BOTTOM"> |
<Offset> |
<AbsDimension x="0" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentRaidValueLabel" inherits="GameFontNormal" text="Value:"> |
<Size> |
<AbsDimension x="70" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOP" relativeTo="$parentRaidNoteLabel" relativePoint="BOTTOM"> |
<Offset> |
<AbsDimension x="0" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentRaidAttendeesLabel" inherits="GameFontNormal" text="Attendees:"> |
<Size> |
<AbsDimension x="100" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOP" relativeTo="$parentRaidValueLabel" relativePoint="BOTTOM"> |
<Offset> |
<AbsDimension x="16" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentItemWinnerLabel" inherits="GameFontNormal" text="Winner:"> |
<Size> |
<AbsDimension x="70" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentItemLabel" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="200" y="-20"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentItemValueLabel" inherits="GameFontNormal" text="DKP:"> |
<Size> |
<AbsDimension x="50" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentItemWinnerLabel" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-30"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
</Layer> |
</Layers> |
<Frames> |
<Button name="$parentRaid" inherits="OptionsButtonTemplate" hidden="false"> |
<Anchors> |
<Anchor point="TOP"> |
<Offset> |
<AbsDimension x="0" y="-30"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnEnter> |
MorgDKP:ShowDropMenu(this:GetParent()) |
</OnEnter> |
<OnClick> |
MorgDKP:ShowDropMenu(this:GetParent()) |
</OnClick> |
<OnShow> |
MorgDKP:SetupDropMenu() |
</OnShow> |
</Scripts> |
</Button> |
<EditBox name="$parentName" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentRaidNameLabel" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</EditBox> |
<EditBox name="$parentNote" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentRaidNoteLabel" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="2" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</EditBox> |
<Button name="$parentEventChoose" inherits="MorgDKP_DownButtonTemplate"> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentName" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ChooseEvent(this) |
</OnClick> |
</Scripts> |
</Button> |
<EditBox name="$parentValue" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="70" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentRaidValueLabel" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="2" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</EditBox> |
<EditBox name="$parentAttendees" inherits="MorgDKP_EditboxTemplateSmall" letters="6000" hidden="false" multiLine="true"> |
<Size> |
<AbsDimension x="200" y="500"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentValue" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-40"/> |
</Offset> |
</Anchor> |
</Anchors> |
</EditBox> |
<EditBox name="$parentItemWinner" inherits="MorgDKP_EditboxTemplate" hidden="true"> |
<Size> |
<AbsDimension x="120" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentItemWinnerLabel" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="4" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</EditBox> |
<EditBox name="$parentItemValue" inherits="MorgDKP_EditboxTemplate" hidden="true"> |
<Size> |
<AbsDimension x="70" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentItemValueLabel" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="4" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</EditBox> |
<Button name="$parentAdd" inherits="OptionsButtonTemplate" hidden="false" text="Add Event"> |
<Size> |
<AbsDimension x="100" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="BOTTOMRIGHT" relativeTo="$parent" relativePoint="BOTTOMRIGHT"> |
<Offset> |
<AbsDimension x="-50" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:AddNewRaid() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentClear" inherits="OptionsButtonTemplate" hidden="true" text="Clear Current"> |
<Size> |
<AbsDimension x="120" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="BOTTOMRIGHT" relativeTo="$parent" relativePoint="BOTTOMRIGHT"> |
<Offset> |
<AbsDimension x="-50" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ClearCurrentData() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentDelete" inherits="OptionsButtonTemplate" hidden="true" text="Delete Event"> |
<Size> |
<AbsDimension x="120" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parentClear" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:DeleteCurrentRaid() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentUpdate" inherits="OptionsButtonTemplate" hidden="true" text="Update attendees"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parentDelete" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:UpdateCurrentAttend() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentExportCurrent" inherits="OptionsButtonTemplate" hidden="true" text="Export Raid"> |
<Size> |
<AbsDimension x="110" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parentUpdate" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ExportCurrentRaid(this:GetName()) |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentDeleteItem" inherits="OptionsButtonTemplate" hidden="true" text="Delete Item"> |
<Size> |
<AbsDimension x="100" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parentExportCurrent" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:DeleteCurrentRaidItem() |
</OnClick> |
</Scripts> |
</Button> |
<ScrollFrame name="$parentScrollBar" inherits="MorgDKP_ScrollframeTemplate"> |
<Size> |
<AbsDimension x="240" y="270"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="25" y="-110"/> |
</Offset> |
</Anchor> |
</Anchors> |
</ScrollFrame> |
<Button name="$parentButton1" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentScrollBar" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="10" y="-15"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton2" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton1" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton3" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton2" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton4" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton3" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton5" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton4" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton6" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton5" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton7" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton6" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton8" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton7" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton9" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton8" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<ScrollFrame name="$parentScrollBar2" inherits="MorgDKP_ScrollframeTemplate2"> |
<Size> |
<AbsDimension x="200" y="180"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentScrollBar" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-40"/> |
</Offset> |
</Anchor> |
</Anchors> |
</ScrollFrame> |
<Button name="$parentButton11" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentScrollBar2" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="10" y="-15"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton12" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton11" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton13" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton12" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton14" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton13" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton15" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton14" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton16" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton15" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
</Frames> |
</Frame> |
<Frame name="MorgDKP_RaidsPage2" hidden="true"> |
<Anchors> |
<Anchor point="TOPLEFT"/> |
<Anchor point="BOTTOMRIGHT"/> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentValueLabel" inherits="GameFontNormal" text="Value:"> |
<Size> |
<AbsDimension x="55" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parent" relativePoint="TOPRIGHT"> |
<Offset> |
<AbsDimension x="-360" y="-130"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentClassLabel" inherits="GameFontNormal" text="Class:"> |
<Size> |
<AbsDimension x="50" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentValueLabel" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-5"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentAltClassLabel" inherits="GameFontNormal" text="Alt Class:"> |
<Size> |
<AbsDimension x="70" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentClassLabel" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="60" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentItemName" inherits="GameFontNormalLarge" text="Dummy"> |
<Size> |
<AbsDimension x="350" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parent" relativePoint="TOPRIGHT"> |
<Offset> |
<AbsDimension x="-400" y="-90"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
</Layer> |
</Layers> |
<Frames> |
<EditBox name="$parentValue" inherits="MorgDKP_EditboxTemplate" hidden="true"> |
<Size> |
<AbsDimension x="90" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentValueLabel" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</EditBox> |
<CheckButton name="$parentClass1" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentClassLabel" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="10" y="-10"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentClass2" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentClass1" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentClass3" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentClass2" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentClass4" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentClass3" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentClass5" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentClass4" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentClass6" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentClass5" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentClass7" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentClass6" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentClass8" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentClass7" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentClass9" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentClass8" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentClass10" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentClass9" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentAltClass1" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentClass1" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="85" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleAltClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentAltClass2" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentClass2" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="85" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleAltClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentAltClass3" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentClass3" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="85" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleAltClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentAltClass4" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentClass4" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="85" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleAltClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentAltClass5" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentClass5" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="85" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleAltClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentAltClass6" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentClass6" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="85" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleAltClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentAltClass7" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentClass7" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="85" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleAltClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentAltClass8" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentClass8" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="85" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleAltClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentAltClass9" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentClass9" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="85" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleAltClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentAltClass10" inherits="OptionsCheckButtonTemplate" hidden="true"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentClass10" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="85" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ToggleAltClass(this) |
</OnClick> |
</Scripts> |
</CheckButton> |
<Button name="$parentDeleteItem" inherits="OptionsButtonTemplate" hidden="true" text="Delete Item"> |
<Size> |
<AbsDimension x="100" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentAltClass10" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="10" y="-40"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:DeleteCurrentItem() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentIgnoreItem" inherits="OptionsButtonTemplate" hidden="true" text="Ignore Item"> |
<Size> |
<AbsDimension x="100" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parentDeleteItem" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:IgnoreCurrentItem() |
</OnClick> |
</Scripts> |
</Button> |
<ScrollFrame name="$parentScrollBar2" inherits="MorgDKP_ScrollframeTemplate2"> |
<Size> |
<AbsDimension x="220" y="620"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="25" y="-40"/> |
</Offset> |
</Anchor> |
</Anchors> |
</ScrollFrame> |
<Button name="$parentButton1" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentScrollBar2" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="10" y="-15"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton2" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton1" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton3" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton2" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton4" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton3" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton5" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton4" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton6" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton5" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton7" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton6" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton8" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton7" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton9" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton8" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton10" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton9" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton11" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton10" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton12" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton11" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton13" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton12" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton14" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton13" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton15" inherits="MorgDKP_ScrollButtonTemplate2"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton14" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
</Frames> |
</Frame> |
<Frame name="MorgDKP_RaidsPage3" hidden="true"> |
<Anchors> |
<Anchor point="TOPLEFT"/> |
<Anchor point="BOTTOMRIGHT"/> |
</Anchors> |
<Layers> |
<Layer level="ARTWORK"> |
<FontString inherits="GameFontNormal" text="Pending Changes:"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parent" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="70" y="-70"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentValueLabel" inherits="GameFontNormal" text="DKP Amount (% for decay)"> |
<Anchors> |
<Anchor point="TOPRIGHT" relativeTo="$parent" relativePoint="TOPRIGHT"> |
<Offset> |
<AbsDimension x="-130" y="-160"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
</Layer> |
</Layers> |
<Frames> |
<Button name="$parentPool" inherits="OptionsButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="120" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOP"> |
<Offset> |
<AbsDimension x="0" y="-30"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnEnter> |
MorgDKP:ShowDropMenu(this:GetParent()) |
</OnEnter> |
<OnClick> |
MorgDKP:ShowDropMenu(this:GetParent()) |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentIndividual" inherits="OptionsButtonTemplate" hidden="false" text="Individual"> |
<Size> |
<AbsDimension x="100" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPRIGHT" relativeTo="$parent" relativePoint="TOPRIGHT"> |
<Offset> |
<AbsDimension x="-285" y="-120"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnEnter> |
MorgDKP:IndividualDKPRaid(this) |
</OnEnter> |
</Scripts> |
</Button> |
<Button name="$parentGroup" inherits="OptionsButtonTemplate" hidden="false" text="Group"> |
<Size> |
<AbsDimension x="75" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentIndividual" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="5" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnEnter> |
MorgDKP:GroupDKPRaid(this) |
</OnEnter> |
</Scripts> |
</Button> |
<Button name="$parentDecay" inherits="OptionsButtonTemplate" hidden="false" text="Decay"> |
<Size> |
<AbsDimension x="75" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentGroup" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="5" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnEnter> |
MorgDKP:GroupDKPRaid(this) |
</OnEnter> |
</Scripts> |
</Button> |
<EditBox name="$parentValue" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="50" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentIndividual" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-8"/> |
</Offset> |
</Anchor> |
</Anchors> |
</EditBox> |
<EditBox name="$parentMembers" inherits="MorgDKP_EditboxTemplateSmall" letters="6000" hidden="true" multiLine="true"> |
<Size> |
<AbsDimension x="200" y="500"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentValue" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-20"/> |
</Offset> |
</Anchor> |
</Anchors> |
</EditBox> |
<Button name="$parentDelete" inherits="OptionsButtonTemplate" hidden="false" text="Delete"> |
<Size> |
<AbsDimension x="100" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="BOTTOMRIGHT" relativeTo="$parent" relativePoint="BOTTOMRIGHT"> |
<Offset> |
<AbsDimension x="-50" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:DeleteCurrentDKPChange() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentAdd" inherits="OptionsButtonTemplate" hidden="false" text="Add"> |
<Size> |
<AbsDimension x="100" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parentDelete" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:AddDKPChange() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentTarget" inherits="OptionsButtonTemplate" hidden="false" text="Add target"> |
<Size> |
<AbsDimension x="110" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parentAdd" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:AddTarget(this:GetName()) |
</OnClick> |
</Scripts> |
</Button> |
<ScrollFrame name="$parentScrollBar" inherits="MorgDKP_ScrollframeTemplate"> |
<Size> |
<AbsDimension x="120" y="440"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="25" y="-110"/> |
</Offset> |
</Anchor> |
</Anchors> |
</ScrollFrame> |
<Button name="$parentButton1" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentScrollBar" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="10" y="-15"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton2" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton1" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton3" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton2" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton4" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton3" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton5" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton4" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton6" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton5" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton7" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton6" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton8" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton7" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton9" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton8" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton10" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton9" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton11" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton10" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton12" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton11" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton13" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton12" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton14" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton13" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton15" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton14" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
</Frames> |
</Frame> |
<Frame name="MorgDKP_RaidsPage4" hidden="true"> |
<Anchors> |
<Anchor point="TOPLEFT"/> |
<Anchor point="BOTTOMRIGHT"/> |
</Anchors> |
<Layers> |
<Layer level="ARTWORK"> |
<FontString inherits="GameFontNormal" text="Current Aliases:"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parent" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="70" y="-70"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
<FontString name="$parentLabel" inherits="GameFontNormal" text="Alias Member"> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="330" y="-105"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
</Layer> |
</Layers> |
<Frames> |
<Button name="$parentPool" inherits="OptionsButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="120" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOP"> |
<Offset> |
<AbsDimension x="0" y="-30"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnEnter> |
MorgDKP:ShowDropMenu(this:GetParent()) |
</OnEnter> |
</Scripts> |
</Button> |
<Button name="$parentAliasChoose" inherits="MorgDKP_DownButtonTemplate"> |
<Anchors> |
<Anchor point="TOPRIGHT"> |
<Offset> |
<AbsDimension x="-370" y="-120"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ChooseAlias(this) |
</OnClick> |
</Scripts> |
</Button> |
<EditBox name="$parentAlias" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="150" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentAliasChoose" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</EditBox> |
<Button name="$parentNext" inherits="OptionsButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="20" y="20"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentAlias" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<NormalTexture file="Interface/Buttons/UI-SpellbookIcon-NextPage-Up"/> |
</Button> |
<EditBox name="$parentMember" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="150" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentNext" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
</EditBox> |
<Button name="$parentMemberChoose" inherits="MorgDKP_DownButtonTemplate"> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentMember" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ChooseMember(this) |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentDelete" inherits="OptionsButtonTemplate" hidden="false" text="Delete"> |
<Size> |
<AbsDimension x="100" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="BOTTOMRIGHT" relativeTo="$parent" relativePoint="BOTTOMRIGHT"> |
<Offset> |
<AbsDimension x="-50" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:DeleteCurrentAlias() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentAdd" inherits="OptionsButtonTemplate" hidden="false" text="Add"> |
<Size> |
<AbsDimension x="100" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parentDelete" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:AddAlias() |
</OnClick> |
</Scripts> |
</Button> |
<ScrollFrame name="$parentScrollBar" inherits="MorgDKP_ScrollframeTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="25" y="-110"/> |
</Offset> |
</Anchor> |
</Anchors> |
</ScrollFrame> |
<Button name="$parentButton1" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentScrollBar" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="10" y="-15"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton2" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton1" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton3" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton2" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton4" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton3" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton5" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton4" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton6" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton5" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton7" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton6" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton8" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton7" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton9" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton8" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton10" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton9" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton11" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton10" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton12" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton11" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton13" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton12" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton14" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton13" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
<Button name="$parentButton15" inherits="MorgDKP_ScrollButtonTemplate"> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentButton14" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
</Button> |
</Frames> |
</Frame> |
<Frame name="MorgDKP_RaidsPage5" hidden="true"> |
<Anchors> |
<Anchor point="TOPLEFT"/> |
<Anchor point="BOTTOMRIGHT"/> |
</Anchors> |
<Frames> |
<CheckButton name="$parentAutozone" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="50" y="-40"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.autozone = not MorgDKP.db.account.defaults.autozone |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentStartrun" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentAutozone" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.startrun = not MorgDKP.db.account.defaults.startrun |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentOneRun" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentStartrun" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.OneEvent = not MorgDKP.db.account.defaults.OneEvent |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentWhisper" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentOneRun" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.whisper = not MorgDKP.db.account.defaults.whisper |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentMultipool" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentWhisper" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.multiPool = not MorgDKP.db.account.defaults.multiPool |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentBossAttempt" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentMultipool" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.attemptmode = not MorgDKP.db.account.defaults.attemptmode |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentDKPListen" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentBossAttempt" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.dkplistener = not MorgDKP.db.account.defaults.dkplistener |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentBroadcastLead" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentDKPListen" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.leadbroadcast = not MorgDKP.db.account.defaults.leadbroadcast |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<EditBox name="$parentEventFormat" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentBroadcastLead" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-30"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentEventFormatText" justifyH="LEFT" inherits="GameFontNormalSmall" text="Event Format"> |
<Size> |
<AbsDimension x="100" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
</Scripts> |
</EditBox> |
<EditBox name="$parentStartFormat" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentEventFormat" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-15"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentStartFormatText" justifyH="LEFT" inherits="GameFontNormalSmall" text="Start Format"> |
<Size> |
<AbsDimension x="100" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
</Scripts> |
</EditBox> |
<EditBox name="$parentTrashFormat" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentStartFormat" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-15"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentTrashFormatText" justifyH="LEFT" inherits="GameFontNormalSmall" text="Trash Format"> |
<Size> |
<AbsDimension x="100" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
</Scripts> |
</EditBox> |
<EditBox name="$parentRunTime" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentTrashFormat" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-15"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentRunTimeText" justifyH="LEFT" inherits="GameFontNormalSmall" text="Minimum Run Time"> |
<Size> |
<AbsDimension x="150" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
</Scripts> |
</EditBox> |
<CheckButton name="$parentDkpaward" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentRunTime" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-30"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.dkpaward = not MorgDKP.db.account.defaults.dkpaward |
MorgDKP:ToggleDKPAward() |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<EditBox name="$parentDKP" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="45" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentDkpaward" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="5" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentDKPText" inherits="GameFontNormalSmall" text="DKP /"> |
<Size> |
<AbsDimension x="50" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="LEFT"> |
<Offset> |
<AbsDimension x="40" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
</EditBox> |
<EditBox name="$parentTime" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="45" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentDKP" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="40" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentTimeText" inherits="GameFontNormalSmall" text="Minutes"> |
<Size> |
<AbsDimension x="50" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="LEFT"> |
<Offset> |
<AbsDimension x="45" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
</EditBox> |
<EditBox name="$parentSyncPW" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentDKP" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-30"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentSyncPWText" justifyH="LEFT" inherits="GameFontNormalSmall" text="SyncPW"> |
<Size> |
<AbsDimension x="50" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
</EditBox> |
<CheckButton name="$parentRandom" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="300" y="-40"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.random = not MorgDKP.db.account.defaults.random |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentZsum" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentRandom" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.zerosum = not MorgDKP.db.account.defaults.zerosum |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentRelational" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentZsum" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.relational = not MorgDKP.db.account.defaults.relational |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<EditBox name="$parentPTakeNum" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentRelational" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="3" y="-20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentPTakeNumText" justifyH="LEFT" inherits="GameFontNormalSmall" text="Percent DKP"> |
<Size> |
<AbsDimension x="100" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
</EditBox> |
<CheckButton name="$parentPTake" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentPTakeNum" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="20" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.percenttake = not MorgDKP.db.account.defaults.percenttake |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentBidwar" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentPTake" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="-20" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.bidwar = not MorgDKP.db.account.defaults.bidwar |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentSilent" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentBidwar" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="20" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.silent = not MorgDKP.db.account.defaults.silent |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<CheckButton name="$parentJustEnough" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentSilent" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.justenough = not MorgDKP.db.account.defaults.justenough |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<EditBox name="$parentOverBID" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentJustEnough" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="3" y="-20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentOverbidFontText" justifyH="LEFT" inherits="GameFontNormalSmall" text="Overbid"> |
<Size> |
<AbsDimension x="100" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
</EditBox> |
<CheckButton name="$parentWaitlist" inherits="OptionsCheckButtonTemplate" hidden="false"> |
<Size> |
<AbsDimension x="30" y="30"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentOverBID" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="-20" y="-30"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLeave> |
GameTooltip:Hide() |
</OnLeave> |
<OnClick> |
MorgDKP.db.account.defaults.waitaward = not MorgDKP.db.account.defaults.waitaward |
MorgDKP:UpdateOptionFrame() |
</OnClick> |
</Scripts> |
</CheckButton> |
<EditBox name="$parentWaitStart" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentWaitlist" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="23" y="-20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentWaitStartFontText" justifyH="LEFT" inherits="GameFontNormalSmall" text="Wait start DKP"> |
<Size> |
<AbsDimension x="100" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
</EditBox> |
<EditBox name="$parentWaitRun" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentWaitStart" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-15"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentWaitRunFontText" justifyH="LEFT" inherits="GameFontNormalSmall" text="Wait run DKP"> |
<Size> |
<AbsDimension x="100" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
</EditBox> |
<EditBox name="$parentWaitBoss" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentWaitRun" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-15"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentWaitBossFontText" justifyH="LEFT" inherits="GameFontNormalSmall" text="Wait Boss DKP"> |
<Size> |
<AbsDimension x="100" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
</EditBox> |
<EditBox name="$parentWaitOtime" inherits="MorgDKP_EditboxTemplate" hidden="false"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativeTo="$parentWaitBoss" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="0" y="-15"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="$parentWaitOtimeFontText" justifyH="LEFT" inherits="GameFontNormalSmall" text="Wait over time DKP"> |
<Size> |
<AbsDimension x="150" y="28"/> |
</Size> |
<FontHeight> |
<AbsValue x="11" /> |
</FontHeight> |
<Anchors> |
<Anchor point="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Color r="1.0" g="1.0" b="0" a="1.0" /> |
</FontString> |
</Layer> |
</Layers> |
</EditBox> |
<Button name="$parentExport" inherits="OptionsButtonTemplate" hidden="false" text="Export Raids"> |
<Size> |
<AbsDimension x="120" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="BOTTOMRIGHT" relativeTo="$parent" relativePoint="BOTTOMRIGHT"> |
<Offset> |
<AbsDimension x="-50" y="20"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ExportRaids() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentClearraidDB" inherits="OptionsButtonTemplate" hidden="false" text="Clear Raids"> |
<Size> |
<AbsDimension x="120" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parentExport" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:ClearRaidDB() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentConvert" inherits="OptionsButtonTemplate" hidden="false" text="Sync DB"> |
<Size> |
<AbsDimension x="140" y="25"/> |
</Size> |
<Anchors> |
<Anchor point="RIGHT" relativeTo="$parentClearraidDB" relativePoint="LEFT"> |
<Offset> |
<AbsDimension x="-10" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
MorgDKP:SyncItemDB() |
</OnClick> |
</Scripts> |
</Button> |
</Frames> |
</Frame> |
<Button name="$parentTab1" inherits="CharacterFrameTabButtonTemplate" id="1" text="Raids"> |
<Anchors> |
<Anchor point="CENTER" relativePoint="BOTTOMLEFT"> |
<Offset> |
<AbsDimension x="50" y="-8"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
PanelTemplates_SetTab(MorgDKP_Raid, 1); |
MorgDKP_RaidsPage1:Show(); |
MorgDKP_RaidsPage2:Hide(); |
MorgDKP_RaidsPage3:Hide(); |
MorgDKP_RaidsPage4:Hide(); |
MorgDKP_RaidsPage5:Hide(); |
MorgDKP:ShowDefaultRaid(); |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentTab2" inherits="CharacterFrameTabButtonTemplate" id="2" text="ItemDB"> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentTab1" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="-16" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
PanelTemplates_SetTab(MorgDKP_Raid, 2); |
MorgDKP_RaidsPage1:Hide(); |
MorgDKP_RaidsPage2:Show(); |
MorgDKP_RaidsPage3:Hide(); |
MorgDKP_RaidsPage4:Hide(); |
MorgDKP_RaidsPage5:Hide(); |
MorgDKP:ShowItemsFrame(this:GetParent()); |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentTab3" inherits="CharacterFrameTabButtonTemplate" id="3" text="Adjust DKP"> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentTab2" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="-16" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
PanelTemplates_SetTab(MorgDKP_Raid, 3); |
MorgDKP_RaidsPage1:Hide(); |
MorgDKP_RaidsPage2:Hide(); |
MorgDKP_RaidsPage3:Show(); |
MorgDKP_RaidsPage4:Hide(); |
MorgDKP_RaidsPage5:Hide(); |
MorgDKP:ShowDKPFrame(this:GetParent()); |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentTab4" inherits="CharacterFrameTabButtonTemplate" id="4" text="Aliases"> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentTab3" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="-16" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
PanelTemplates_SetTab(MorgDKP_Raid, 4); |
MorgDKP_RaidsPage1:Hide(); |
MorgDKP_RaidsPage2:Hide(); |
MorgDKP_RaidsPage3:Hide(); |
MorgDKP_RaidsPage4:Show(); |
MorgDKP_RaidsPage5:Hide(); |
MorgDKP:ShowAliasFrame(this:GetParent()); |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentTab5" inherits="CharacterFrameTabButtonTemplate" id="5" text="Options"> |
<Anchors> |
<Anchor point="LEFT" relativeTo="$parentTab4" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="-16" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnClick> |
PanelTemplates_SetTab(MorgDKP_Raid, 5); |
MorgDKP_RaidsPage1:Hide(); |
MorgDKP_RaidsPage2:Hide(); |
MorgDKP_RaidsPage3:Hide(); |
MorgDKP_RaidsPage4:Hide(); |
MorgDKP_RaidsPage5:Show(); |
MorgDKP:ShowOptionFrame(this:GetParent()); |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentClose"> |
<Size> |
<AbsDimension x="32" y="32"/> |
</Size> |
<Anchors> |
<Anchor point="TOPRIGHT" relativeTo="$parent" relativePoint="TOPRIGHT"> |
<Offset> |
<AbsDimension x="-3" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<NormalTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Up"/> |
<HighlightTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Highlight" alphaMode="ADD"/> |
<PushedTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Down"/> |
<Scripts> |
<OnClick> |
this:GetParent():Hide(); |
MorgDKP:CloseRaidtracker() |
</OnClick> |
</Scripts> |
</Button> |
<Button name="$parentResize"> |
<Size> |
<AbsDimension x="24" y="24"/> |
</Size> |
<Anchors> |
<Anchor point="BOTTOMRIGHT" relativeTo="$parent" relativePoint="BOTTOMRIGHT"> |
<Offset> |
<AbsDimension x="0" y="-2"/> |
</Offset> |
</Anchor> |
</Anchors> |
<NormalTexture file="Interface/Glues/Common/Glue-Panel-Button-Up"/> |
<HighlightTexture file="Interface/Glues/Common/Glue-Panel-Button-Highlight" alphaMode="ADD"/> |
<PushedTexture file="Interface/Glues/Common/Glue-Panel-Button-Down"/> |
<Scripts> |
<OnMouseDown> |
this:GetParent():StartSizing(); |
</OnMouseDown> |
<OnMouseUp> |
this:GetParent():StopMovingOrSizing(); |
</OnMouseUp> |
</Scripts> |
</Button> |
</Frames> |
</Frame> |
</Ui> |
-- ****************************************************************** |
-- ****************************************************************** |
-- ** MorgDKP ** |
-- ****************************************************************** |
-- ****************************************************************** |
-- |
-- All code courtesy Fryguy:) Thanks |
-- |
local L = AceLibrary("AceLocale-2.2"):new("MorgDKP") |
--------------- |
-- tooltip parsing (Stolen from Mendeleev) |
--------------- |
local linkFuncs = { |
SetAuctionItem = GetAuctionItemLink, |
SetBagItem = GetContainerItemLink, |
SetCraftItem = function(skill, id) return (id) and GetCraftReagentItemLink(skill, id) or GetCraftItemLink(skill) end, |
SetHyperlink = function(link) return link end, |
SetInventoryItem = function(type, slot) return (type) and GetInventoryItemLink(type, slot) or GetContainerItemLink(BANK_CONTAINER,this:GetID()) end, |
SetLootItem = GetLootSlotLink, |
SetMerchantItem = GetMerchantItemLink, |
SetQuestItem = GetQuestItemLink, |
SetQuestLogItem = GetQuestLogItemLink, |
SetTradePlayerItem = GetTradePlayerItemLink, |
SetTradeSkillItem = function(skill, id) return (id) and GetTradeSkillReagentItemLink(skill, id) or GetTradeSkillItemLink(skill) end, |
SetTradeTargetItem = GetTradeTargetItemLink, |
SetLootRollItem = function(index) return GetLootRollItemLink(index) end, |
} |
function MorgDKP:SetItemRef(link, text, button) |
self.hooks.SetItemRef(link, text, button) |
if not strfind(link, "item") or IsControlKeyDown() or IsShiftKeyDown() then return end |
self:ParseTooltip(ItemRefTooltip, link) |
end |
function MorgDKP:HookStuff() |
self:HookTooltips() |
--self:SecureHook("SetItemRef") |
self:Hook("ContainerFrameItemButton_OnModifiedClick", true) |
hooksecurefunc("HandleModifiedItemClick", MorgDKP.HandleModifiedItemClick) |
end |
function MorgDKP:HookTooltips() |
for key, value in pairs(linkFuncs) do |
local orig, linkFunc = key,value -- I cant leave this out, dont ask me why. |
local func = function(tooltip,a,b,c) |
self:ParseTooltip(tooltip,linkFunc(a,b,c)) |
return |
end |
self:SecureHook(GameTooltip,orig,func) |
end |
self:SecureHook("SetItemRef") |
end |
function MorgDKP:ParseTooltip(frame,link,id) |
if link == nil then return end |
local _, _, tid = string.find(link, "item:(%d+):%d+:%d+:%d+") |
local id = tonumber(tid) |
if link == self.link then |
self:DrawTooltip(frame) |
return |
elseif tid == nil then |
--self:debug("malformed link") |
return |
else |
self.link = link |
--self.compost:Reclaim(self.TT, 1) |
--self.TT = self.compost:Acquire() |
self.TT = { } |
end |
MorgDKP:DoTooltip(frame,link,id) |
self:DrawTooltip(frame) |
end |
function MorgDKP:DrawTooltip(frame) |
for _,z in ipairs(self.TT) do |
if (KC_Items and KC_Items.tooltip) then |
--KC_Tooltip:AddTextLine(frame, z.Stringa, z.Stringb, " ", "|cffffffff") |
KC_Items.tooltip:AddTextLine(frame, z.Stringa, z.Stringb, " ", "|cffffffff") |
else |
frame:AddDoubleLine(z.Stringa,z.Stringb,1,1,1,1,1,1) |
end |
end |
frame:Show() |
end |
function MorgDKP:DoTooltip(frame,link,id) |
local players = self:GetPlayersNeedItem(id) |
if not players then return end |
local ct = 0 |
for i,v in ipairs(players) do |
--DEFAULT_CHAT_FRAME:AddMessage("#" .. i .. " " .. v.name .. "(" .. v.points .. ") ") |
ct = ct + 1 |
if ct == 5 then return end |
self:AddLine("|cffffffcf#" .. i .. " " .. v.name, "|cfcffffcf("..v.points..")") |
--DEFAULT_CHAT_FRAME:AddMessage("#" .. i .. " " .. v.name .. "(" .. v.points .. ") ") |
end |
--self:AddLine("test", "Test!") |
end |
function MorgDKP:AddLine(Stringa,Stringb) |
local i = #self.TT + 1 |
local t = { } --self.compost:Acquire() |
t.Stringa = Stringa |
t.Stringb = Stringb |
table.insert(self.TT, t) |
end |
------------------ |
-- item setting stuffs |
------------------ |
function MorgDKP:HandleModifiedItemClick(button) |
if IsAltKeyDown() and IsShiftKeyDown() then |
local index = this:GetID() |
if LootSlotIsItem(index) then |
local iteminfo = GetLootSlotLink(index) |
MorgDKP:MakeDewDropMenu(UIParent, iteminfo) |
return |
end |
end |
--return self.hooks.HandleModifiedItemClick(button) |
end |
function MorgDKP:SetItemRef(link, text, button) |
-- make sure it's an item |
if strsub(link, 1, 6) ~= "player" then |
if IsAltKeyDown() and IsShiftKeyDown() and button=="LeftButton" then |
self:MakeDewDropMenu(this, text) |
end |
end |
return |
--self.hooks.SetItemRef(link, text, button) |
end |
function MorgDKP:ContainerFrameItemButton_OnModifiedClick(button) |
if IsShiftKeyDown() and IsAltKeyDown() and button=="LeftButton" then |
self:OpenItemOptions(this) |
else |
--return self:CallHook("ContainerFrameItemButton_OnClick", button, ignoreModifiers) |
return self.hooks.ContainerFrameItemButton_OnModifiedClick(button) |
end |
end |
function MorgDKP:OpenItemOptions(frame, slot) |
local bag = slot and frame or frame:GetParent():GetID() |
slot = slot or frame:GetID() |
local itemlink = GetContainerItemLink(bag, slot) |
self:MakeDewDropMenu(frame, itemlink) |
end |
local L = AceLibrary("AceLocale-2.2"):new("MorgDKP") |
local BC = AceLibrary("Babble-Class-2.2") |
local tablet = AceLibrary("Tablet-2.0") |
local dewdrop = AceLibrary("Dewdrop-2.0") |
local rosterlib = AceLibrary("Roster-2.1") |
local roster = rosterlib.roster |
MorgBid_Version = "3.6" |
local qso |
local MaxBid = { } |
local AuctionStatus = { } |
function MorgDKP:StartQuery(id, link) |
if not self:IsRaided() then return end |
self:Scan() |
local itempoints = self.db.account.items[id].points or 0 |
self.origitempoints[id] = itempoints |
needquery = self:HasItem(id) |
if not self.queryneeded then DEFAULT_CHAT_FRAME:AddMessage(L["noquery"]) return end |
AuctionStatus[id] = 1 |
local POOL = self:CheckPool(id) |
for qname in pairs(needquery) do |
self:PointsPoolExists(qname, POOL) |
local dkppoints = self:PointsFormat(qname, POOL) |
if self.db.account.defaults.random or self.random[id] then dkppoints = "NONE" end |
if self.db.account.defaults.bidwar then |
MaxBid[id] = 0 |
BidWarDone = nil |
SendAddonMessage("MORGBID", "BIDWAR "..id.." "..itempoints.." "..qname.." "..self.db.account.info[qname][POOL].points .." "..self.db.account.defaults.bidstep.." "..self.db.account.defaults.overbid, "RAID") |
else SendAddonMessage("MORGBID", "QUERY "..id.." "..itempoints.." "..qname.." "..dkppoints, "RAID") |
end |
if self.db.account.defaults.whisper then |
SendChatMessage(string.format(L["morgbidwhisper"], link, id, itempoints), "WHISPER", nil, qname) |
end |
end |
DEFAULT_CHAT_FRAME:AddMessage(L["querysent"]..id.." "..itempoints) |
local t = { } |
local points |
local mainstring = L["classmain"] .. ": " |
local altstring = L["classalt"] .. ": " |
local isaltstring = nil |
for mclass, value in pairs(self.db.account.items[id].classes) do |
if mclass ~= "All" and value then mainstring = mainstring .. mclass .. ", " end |
end |
for aclass, value in pairs(self.db.account.items[id].altclasses) do |
if aclass ~= "All" and value then |
altstring = altstring .. aclass .. ", " |
isaltstring = 1 |
end |
end |
for qname in pairs(needquery) do |
qclass = needquery[qname].class |
self:PointsPoolExists(qname, POOL) |
local points |
local priority = needquery[qname].priority |
if not self.db.account.defaults.bidwar then points = self:PointsFormat(qname, POOL) end |
if self.db.account.defaults.bidwar or self.db.account.defaults.random or self.random[id] then points = 0 end |
table.insert(t, {qname, qclass, "PENDING", points, priority}) |
end |
if self.db.account.defaults.bidwar then |
SendChatMessage(string.format(L["auctionbegin"], link, id), "RAID") |
SendChatMessage(L["bidformat"], "RAID") |
else |
SendChatMessage(string.format(L["rollingbegin"], link, id, itempoints), "RAID") |
mainstring = string.sub(mainstring, 1, -3) |
SendChatMessage(mainstring, "RAID") |
if isaltstring then |
altstring = string.sub(altstring, 1, -3) |
SendChatMessage(altstring, "RAID") |
end |
end |
self.querytooltips[id] = t |
local sName, _, _, _, _, _, _, _, _, _ = GetItemInfo(id) |
local item = "item"..id |
if self.db.account.defaults.bidwar then local hint = L["BidWarBar_Hint"] |
else local hint = L["Bar_Hint"] end |
qso = { PENDING = 2, NEED = 4, TAKE = 3, PASS = 1 } |
self:CreateQueryTooltip(id, item, sName, hint) |
end |
function MorgDKP:MorgBidQuery() |
--if not self:IsRaided() then return end |
SendAddonMessage("MORGBID", "CHECK", "RAID") |
self:Scan() |
local POOL = self.db.account.defaults.raid |
local t = { } |
for name, data in pairs(roster) do |
if data.class ~= "PET" then |
local class = BC[data.class] |
self:PointsPoolExists(name, POOL) |
points = self:PointsFormat(name, self.db.account.defaults.raid) |
table.insert(t, {name, class, "NONE", points}) |
end |
end |
local title = L["mvquery"] |
local item = "version" |
local hint = L["Bar_Hint_Version"] |
local id = nil |
self.querytooltips[item] = t |
qso = { [3.6] = 1, [3.5] = 2, [3.4] = 3, [3.3] = 4, [3.2] = 5, [3.1] = 6, [2.9] = 7, [2.8] = 8, [2.6] = 9, [2.5] = 10, ["NONE"] = 11} |
self:CreateQueryTooltip(id, item, title, hint) |
end |
function MorgDKP:ItemHistory() |
if self.db.account.defaults.raidnum < 1 then return end |
local t = nil |
t = { } |
for num, loot in pairs(self.db.account.raidlog[self.db.account.defaults.raidnum].loot) do |
name = loot.Player |
local class = "Unknown" |
if self.db.account.raidlog[self.db.account.defaults.raidnum].playerinfo[name] then class = self.db.account.raidlog[self.db.account.defaults.raidnum].playerinfo[name].class end |
ItemLink = "|c"..loot.Color.."[|Hitem:"..loot.ItemID.."|h"..loot.ItemName.."|h]|r" |
points = loot.Costs |
table.insert(t, {ItemLink, class, name, points}) |
end |
if #t < 1 then DEFAULT_CHAT_FRAME:AddMessage("The item history is empty.") return end |
local zone = "UNKNOWN" |
if self.db.account.raidlog[self.db.account.defaults.raidnum].zone then zone = self.db.account.raidlog[self.db.account.defaults.raidnum].zone end |
local title = L["itemhistory"]..": "..zone |
local item = "history" |
local hint = L["rightclickclose"] |
local id = nil |
self.querytooltips[item] = t |
self:CreateQueryTooltip(id, item, title, hint) |
end |
function MorgDKP:CreateQueryTooltip(id, item, title, hint) |
if not tablet:IsRegistered(item) then |
local x,y |
local xoffset = { 0, -240, -480, 240, 480} |
local numitems = 0 |
if self.items then numitems = #self.items end |
if id then |
if numitems < 6 then x = xoffset[numitems] |
else x = 0 end |
y = 60 |
elseif item == "waitlist" then x ,y = -500,50 |
elseif item == "listdkp" then x,y = -240,100 |
else x,y = 0,0 end |
tablet:Register(item, |
'detachedData', { offsetx = x, offsety= y }, |
'children', function() |
tablet:SetTitle(title) |
tablet:SetHint(hint) |
self:UpdateQueryTooltip(id, item) |
end, |
'clickable', true, |
'cantAttach', true, |
'showTitleWhenDetached', true, |
'showHintWhenDetached', true, |
'hideWhenEmpty', true, |
'strata', "HIGH", |
'menu', function() |
dewdrop:Close() |
if id then |
self.querytooltips[id] = nil |
tablet:Attach("item"..id) |
else |
tablet:Attach(item) |
self.querytooltips[item] = nil |
end |
end |
) |
end |
if tablet:IsAttached(item) then tablet:Detach(item) end |
end |
function MorgDKP:UpdateQueryTooltip(id, item) |
local cat = tablet:AddCategory('columns', 3) |
if id then t = self.querytooltips[id] |
else t = self.querytooltips[item] end |
if item ~= "history" and item ~= "listdkp" and item ~= "waitlist" and item ~= "sync" then |
table.sort(t, function(a,b) |
local ao = qso[a[3]] or 0 |
local bo = qso[b[3]] or 0 |
if ao == bo then |
if a[5] == b[5] then |
if a[4] == b[4] then |
return a[2]>b[2] |
else |
return a[4]>b[4] |
end |
else |
return a[5]<b[5] |
end |
else |
return ao>bo |
end |
end) |
end |
for i,v in ipairs(t) do |
if item == "history" then |
r,g,b = 0,0,0 |
r2,g2,b2 = BC:GetColor(v[2]) |
r3,g3,b3 = 0,1,0 |
elseif item == "listdkp" then |
if v[2] == 2 then r,g,b = 1,1,1 |
elseif v[2] == 1 then r,g,b = 0,1,0 |
else r,g,b = 1,0,0 end |
r2,g2,b2 = BC:GetColor(v[3]) |
elseif item == "waitlist" then |
if v[2] then |
r,g,b = BC:GetColor(v[3]) |
r2,g2,b2 = r,g,b |
else |
r,g,b = 1,1,1 |
r2,g2,b2 = r,g,b |
end |
r3,g3,b3 = 0,1,0 |
elseif item == "sync" then |
r,g,b = 1,1,1 |
if v[3] == "PW" then r2,g2,b2 = 0,1,0 |
else r2,g2,b2 = 1,0,0 end |
if v[4] < self.version then r3,g3,b3 = 1,1,0 |
else r3,g3,b3 = 0,1,0 end |
else |
r,g,b = BC:GetColor(v[2]) |
r3,g3,b3 = MorgDKP.db.account.info[v[1]].raidloot, MorgDKP.db.account.info[v[1]].raidloot and 1, 0 |
if (v[3] == "NONE") or (v[3] == "PENDING") then r2,g2,b2 = 1,1,0 |
elseif (v[3] == "PASS") then r2,g2,b2 = 1,0,0 |
else r2,g2,b2 = 0,1,0 end |
end |
local colortog = 0 |
if (v[3] == "NONE") or (v[3] == "PASS") or (v[3] == "PENDING") then colortog = 1 end |
cat:AddLine( |
'text', v[1], |
'textR', r, |
'textG', g, |
'textB', b, |
'text2', string.format("%s",v[3]), |
'text2R', r2, |
'text2G', g2, |
'text2B', b2, |
'text3', v[4], |
'text3R', r3, |
'text3G', g3, |
'text3B', b3, |
'func', function() self:ShowResults(id, item, v[1]) end, |
'onEnterFunc', function() |
GameTooltip:SetOwner(this, "ANCHOR_LEFT") |
self:ShowTooltip(id, item, v[1]) |
end, |
'onLeaveFunc', function() GameTooltip:Hide() end |
) |
end |
end |
function MorgDKP:ShowResults(id, item, historyitem) |
if id and self.db.account.defaults.bidwar then |
SendChatMessage(L["endbidding"], "RAID") |
SendAddonMessage("MORGBID","CLOSE "..id, "RAID") |
AuctionStatus[id] = nil |
end |
if id then self:OutputResults(id, item, historyitem) end |
if item == "version" then |
for num , data in ipairs(self.querytooltips[item]) do |
if data[3] == "NONE" or (tonumber(data[3]) or 1) < tonumber(MorgBid_Version) then SendChatMessage(L["updatemorgbid"], "WHISPER", nil, data[1]) end |
end |
elseif item == "listdkp" then |
if IsShiftKeyDown() then |
SendChatMessage(L["dkpstand"]..self.db.account.defaults.raid..":", "RAID") |
local spaces = " " |
local numspace = {10, 7, 5, 2, 1} |
for num, v in ipairs(self.querytooltips[item]) do |
local message = string.upper(v[1]) |
message = message ..string.sub(spaces,1,(45 - self:CalcSpaces(string.upper(v[1]))))..string.upper(v[3]) |
message = message ..string.sub(spaces,1,(self:CalcSpaces(string.upper(v[3]))))..string.sub(spaces,1,numspace[string.len(v[4])])..v[4].." DKP" |
SendChatMessage(message, "RAID") |
end |
elseif IsControlKeyDown() then |
self.db.account.info[historyitem] = nil |
for num, v in ipairs(self.querytooltips[item]) do |
if v[1] == historyitem then |
table.remove(self.querytooltips[item], num) |
break |
end |
end |
DEFAULT_CHAT_FRAME:AddMessage(string.format(L["deletechar"], historyitem)) |
tablet:Refresh("listdkp") |
elseif IsAltKeyDown() then |
self:AddWait(historyitem) |
else |
InviteUnit(historyitem) |
end |
elseif item == "waitlist" then |
if IsControlKeyDown() then |
self:SubWait(historyitem) |
else |
local Onlinemembers = self:GetOnlineGuildMembers() |
if not Onlinemembers[historyitem] then self:InformOnlineAlias(historyitem, Onlinemembers) |
else InviteUnit(historyitem) end |
end |
elseif item == "sync" then |
if IsShiftKeyDown() then |
self:SyncDB("all") |
else self:SyncDB(historyitem) |
end |
elseif item == "history" then |
local _,_, ItemID = string.find(historyitem, "item:(%d+):") |
ItemID = tonumber(ItemID) |
self:ManualItem(ItemID, historyitem) |
end |
end |
function MorgDKP:OnAddonMsg(prefix, message, type, sender) |
if not UnitInRaid("player") then return end |
if prefix == "MORGBID" then |
local args = {self:Explode(message, " ")} |
if args[1] == "PASS" or args[1] == "TAKE" or args[1] == "NEED" then |
local item = tonumber(args[2]) |
if self.db.account.defaults.devmode then self:Print("From "..sender..": "..args[1]) end |
if not self.querytooltips[item] then |
if self.db.account.defaults.devmode then self:Print("No query for "..args[2]) end |
return |
end |
for i,v in ipairs(self.querytooltips[item]) do |
if v[1] == sender then |
v[3] = args[1] |
if self.db.account.defaults.bidwar and args[1] ~= "PASS" then |
local bid = tonumber(args[3]) |
local overbid = self.db.account.info[sender][self.db.account.items[item].pool].points + self.db.account.defaults.overbid |
if bid > overbid then |
bid = overbid |
SendChatMessage(string.format(L["exceedoverbid"], self.db.account.defaults.overbid), "WHISPER", nil, sender) |
end |
v[4] = bid |
if bid > MaxBid[item] and AuctionStatus[item] then |
MaxBid[item] = bid |
self:BidWarQueryNeeded(item, sender) |
elseif bid == MaxBid[item] and AuctionStatus[item] then |
self:BidWarQueryNeeded(item, " ") |
end |
end |
if (self.db.account.defaults.random or self.random[item]) and args[1] ~= "PASS" then v[4] = math.random(100) end |
break |
end |
end |
tablet:Refresh("item"..item) |
elseif args[1] == "REPLY" then |
if not self.querytooltips["version"] then |
if self.db.account.defaults.devmode then self:Print("No version query.") end |
return |
end |
for i,v in ipairs(self.querytooltips["version"]) do |
if v[1] == sender then v[3] = args[3] break end |
end |
tablet:Refresh("version") |
end |
end |
end |
function MorgDKP:OnCommReceive(prefix, sender, distribution, version, password, command, morgdkpdata, items, dkpinfo) |
if tonumber(version) < self.commVersion then return end |
if command == "REQUESTSYNC" then |
self:SendCommMessage(distribution, self.commVersion, self.db.account.defaults.dbpassword, "SYNCINFO", self.version, #self.db.account.items) |
DEFAULT_CHAT_FRAME:AddMessage(string.format(L["syncrequest"], sender)) |
elseif command == "SYNCINFO" then |
if not self.requestsync then return end |
local pass = "PW" |
local needtab = nil |
if password ~= self.db.account.defaults.dbpassword then pass = "Bad PW!" end |
if not self.querytooltips["sync"] then |
self.querytooltips['sync'] = { } |
needtab = true |
end |
local match = nil |
for _, data in pairs(self.querytooltips["sync"]) do |
if data[1] == sender then match = true break end |
end |
if not match then |
table.insert(self.querytooltips['sync'], {sender, items, pass, morgdkpdata}) |
end |
if needtab then |
local title = L["syncquery"] |
local item = "sync" |
local hint = L["Bar_Hint_Sync"] |
local id = nil |
self:CreateQueryTooltip(id, item, title, hint) |
end |
tablet:Refresh("sync") |
elseif command == "SYNCREQUESTDATA" then |
if morgdkpdata ~= UnitName("player") then return end |
local temp = { } |
for name, data in pairs(self.db.account.info) do |
temp[name] = { } |
for item, itemdata in pairs(data) do |
if item ~= "items" and item ~= "raidloot" then |
if item == "aliases" then |
if #itemdata > 0 then temp[name][item] = itemdata end |
else temp[name][item] = itemdata end |
end |
end |
end |
local defaults = self.db.account.defaults |
self:SendCommMessage(distribution, self.commVersion, self.db.account.defaults.dbpassword, "SYNCDATA", defaults, self.db.account.items, temp) |
DEFAULT_CHAT_FRAME:AddMessage(string.format(L["sentsync"], sender)) |
elseif command == "SYNCDATA" then |
if not self.requestsync then return end |
self.syncitems = items |
self.syncdkp = dkpinfo |
self.defaults = morgdkpdata |
StaticPopup_Show ("MorgAcceptSYNC", sender) |
elseif command == "REQUESTLEAD" then |
if morgdkpdata == UnitName("player") or self.repliedleader then return end |
StaticPopup_Show ("MorgAcceptLeader", morgdkpdata) |
end |
end |
function MorgDKP:SyncDB(name) |
local distro = "GUILD" |
if UnitInRaid("player") then distro = "GROUP" end |
if name == "all" then |
for num, v in ipairs(self.querytooltips["sync"]) do |
if v[3] == "PW" then |
self:SendCommMessage(distro, self.commVersion, self.db.account.defaults.dbpassword, "SYNCREQUESTDATA", v[1]) |
DEFAULT_CHAT_FRAME:AddMessage(string.format(L["syncwait"], v[1])) |
end |
end |
else |
for num, v in ipairs(self.querytooltips["sync"]) do |
if v[1] == name and v[3] == "PW" then |
self:SendCommMessage(distro, self.commVersion, self.db.account.defaults.dbpassword, "SYNCREQUESTDATA", name) |
DEFAULT_CHAT_FRAME:AddMessage(string.format(L["syncwait"], name)) |
break |
end |
end |
end |
end |
function MorgDKP:AcceptSyncData() |
if self.defaults.eqDKP then self.db.account.defaults.eqDKP = self.defaults.eqDKP end |
self.db.account.defaults.raid = self.defaults.raid |
self.db.account.defaults.raidlist = self.defaults.raidlist |
local itemcount = self:ImportItemDB(self.syncitems) |
local membercount = 0 |
if not self.db.account.info then self.db.account.info = { } end |
for name, data in pairs(self.syncdkp) do |
if not self.db.account.info[name] then |
self.db.account.info[name] = data |
membercount = membercount + 1 |
if self.db.account.info[name].aliases then self:IsNewAlias(name) end |
else |
if self:TimeDiff(self.db.account.info[name].lastupdate, data.lastupdate) > 0 then |
for item, itemdata in pairs(data) do |
if item == "aliases" then |
if #self.db.account.info[name]["aliases"] > 0 then |
for newnum, newaliasdata in pairs(itemdata) do |
local match = nil |
for accountnum, aliasdata in pairs(self.db.account.info[name]["aliases"]) do |
if aliasdata.alt == newaliasdata.alt and aliasdata.raid == newaliasdata.raid then |
match = true |
break |
end |
end |
if not match then |
table.insert(self.db.account.info[name]["aliases"], newaliasdata) |
table.insert(self.db.account.defaults.eqDKP[self.db.account.defaults.raid].Aliases, {alt = newaliasdata.alt, main = name}) |
end |
end |
else |
self.db.account.info[name][item] = itemdata |
end |
else self.db.account.info[name][item] = itemdata |
end |
end |
membercount = membercount + 1 |
end |
end |
end |
self.syncdkp = nil |
self.syncitems = nil |
self.defaults = nil |
self.requestsync = nil |
self:ClearRaidDB() |
DEFAULT_CHAT_FRAME:AddMessage(string.format(L["syncdone"], itemcount, membercount)) |
end |
function MorgDKP:IsNewAlias(name) |
if #self.db.account.info[name]["aliases"] > 0 then |
for _, newaliasdata in pairs(self.db.account.info[name]["aliases"]) do |
local match = nil |
for _, aliasdata in pairs(self.db.account.defaults.eqDKP[self.db.account.defaults.raid].Aliases) do |
if aliasdata.alt == newaliasdata.alt then |
match = true |
break |
end |
end |
if not match then |
table.insert(self.db.account.defaults.eqDKP[self.db.account.defaults.raid].Aliases, {alt = newaliasdata.alt, main = name}) |
end |
end |
end |
end |
function MorgDKP:DenySyncData() |
self.syncitems = nil |
self.syncdkp = nil |
self.requestsync = nil |
end |
function MorgDKP:SyncItemDB() |
local distro = "GUILD" |
if UnitInRaid("player") then distro = "GROUP" end |
self.requestsync = true |
self:SendCommMessage(distro, self.commVersion, self.db.account.defaults.dbpassword, "REQUESTSYNC") |
DEFAULT_CHAT_FRAME:AddMessage(string.format(L["syncstart"], distro)) |
end |
function MorgDKP:RequestLeader() |
if not UnitInRaid("player") or not self.db.account.defaults.leadbroadcast then return end |
self:SendCommMessage("GROUP", self.commVersion, self.db.account.defaults.dbpassword, "REQUESTLEAD", UnitName("player")) |
end |
function MorgDKP:AcceptLeader() |
self.db.account.defaults.restoreautozone = self.db.account.defaults.autozone |
self.db.account.defaults.autozone = nil |
if self.db.account.defaults.InRaid then self:EndRaid() end |
MorgDKPFu:DisableMorgDKP() |
self.repliedleader = true |
end |
function MorgDKP:DenyLeader() |
self.repliedleader = true |
end |
function MorgDKP:OutputResults(dkpitem, tabletname, clickedname) |
Lootitem, ItemLink, iQuality, _, _, _, _, _, _, _ = GetItemInfo(dkpitem) |
local itempoints = self.db.account.items[dkpitem].points |
SendAddonMessage("MORGBID","CLOSE "..dkpitem, "RAID") |
AuctionStatus[dkpitem] = nil |
local spaces = " " |
local numspace = {9, 7, 5, 3, 1} |
Lootwinner = nil |
if self.db.account.defaults.bidwar then |
if self.db.account.defaults.justenough and #self.querytooltips[dkpitem] > 1 then |
if self.querytooltips[dkpitem][2][4] > 0 then |
itempoints = self.querytooltips[dkpitem][2][4] |
self.querytooltips[dkpitem][1][4] = itempoints |
end |
else itempoints = self.querytooltips[dkpitem][1][4] |
end |
self.db.account.items[dkpitem].points = itempoints |
end |
if ItemLink and itempoints then |
if self.db.account.defaults.random or self.random[dkpitem] then SendChatMessage(L["doresult"]..ItemLink, "RAID") |
else SendChatMessage(L["doresult"]..ItemLink.." DKP= "..itempoints, "RAID") end |
end |
for i,v in ipairs(self.querytooltips[dkpitem]) do |
if i == 1 then |
if v[3] ~= "PASS" then Lootwinner = string.upper(string.sub(v[1],1,1))..string.sub(v[1],2,-1) end |
end |
local message = string.upper(v[1]) |
message = message ..string.sub(spaces,1,(40 - self:CalcSpaces(string.upper(v[1]))))..string.upper(v[2]) |
message = message ..string.sub(spaces,1,(self:CalcSpaces(string.upper(v[2]))))..string.upper(v[3]) |
message = message ..string.sub(spaces,1,(self:CalcSpaces(string.upper(v[3]))))..string.sub(spaces,1,numspace[string.len(v[4])])..v[4] |
SendChatMessage(message , "RAID") |
if i == 10 then break end |
if self.db.account.defaults.silent and self.db.account.defaults.bidwar and i == 1 then break end |
end |
self.given = true |
if not Lootwinner then |
Lootwinner = self.db.account.defaults.disenchanter |
self.given = nil |
elseif Lootwinner ~= clickedname then Lootwinner = clickedname |
end |
if (GetNumLootItems()>0) and Lootitem and Lootwinner then |
StaticPopup_Show ("MorgLoot", ItemLink, Lootwinner) |
end |
end |
function MorgDKP:HasItem(id) |
if not self.db.account.items[id] then return end |
local classes = self.db.account.items[id].classes |
local altclasses = self.db.account.items[id].altclasses |
local _, _, _, _, _, _, _, _, iEquipLoc, _ = GetItemInfo(id) |
needquery = { } |
self.queryneeded = nil |
for pname, data in pairs(roster) do |
if data.class ~= "PET" then |
local playerClass = BC[string.upper(string.sub(data.class,1,1))..string.lower(string.sub(data.class,2,-1))] |
local realClass = BC[data.class] |
hasitem = nil |
if classes[playerClass] or altclasses[playerClass] then |
if self.db.account.info[pname] then |
if self.db.account.info[pname].items then |
local items = self.db.account.info[pname].items |
if items then |
for _,ID in pairs(items) do |
id = tonumber(id) |
if ID == id and (id ~= 19147 or id ~= 19140 or id ~= 17071) then |
hasitem = 1 |
end |
end |
end |
end |
end |
if not hasitem then |
needquery[pname] = { } |
needquery[pname].class = realClass |
if classes[playerClass] then needquery[pname].priority = 1 |
else needquery[pname].priority = 2 end |
self.queryneeded = 1 |
end |
end |
end |
end |
return needquery |
end |
function MorgDKP:CalcSpaces(word) |
local Letters = {["A"] = 2, ["B"] = 1.5, ["C"] = 1.8, ["D"] = 2, ["E"] = 1.5, ["F"] = 1.5, ["G"] = 2, ["H"] = 2, ["I"] =.9, ["J"] = 1, ["K"] = 1.8, ["L"] = 1.5, ["M"] = 2.3, ["N"] = 2.2, ["O"] = 2.3, ["P"] = 1.5, ["Q"] = 2.3, ["R"] = 1.8, ["S"] = 1.5, ["T"] = 1.8, ["U"] = 2, ["V"] = 1.7, ["W"] = 2.2, ["X"] = 1.7, ["Y"] = 1.7, ["Z"] = 1.7} |
if L["classcount"][word] then return L["classcount"][word] end |
local l = string.len(word) |
local count = 0 |
for i = 1, l do |
let = string.sub(word,i,i) |
val = Letters[let] or 0 |
count = count + val |
end |
return count |
end |
function MorgDKP:OnWaitWhisper(sender, action, member) |
action = string.upper(action) |
local POOL = self.db.account.defaults.raid |
local main = self:CheckforAlias(sender, POOL) |
if action == "WAIT" or action == "WAIT+" then |
if member then self:AddTwink(sender .. " " .. member) end |
self:AddWait(main) |
SendChatMessage(L["waitadd"], "WHISPER", nil, sender) |
elseif action == "WAIT-" then |
self:SubWait(main) |
SendChatMessage(L["waitsub"], "WHISPER", nil, sender) |
end |
end |
function MorgDKP:OnBidWhisper(txt, sender) |
local args = {self:Explode(txt, " ")} |
if string.upper(args[1]) ~= "MBID" then return end |
if string.find(string.upper(args[2]), "WAIT") then self:OnWaitWhisper(sender, args[2], args[3]) return end |
if #args < 3 then SendChatMessage(L["invalidformat"], "WHISPER", nil, sender) return end |
local item = tonumber(args[2]) |
if not AuctionStatus[item] then |
SendChatMessage(L["noauction"], "WHISPER", nil, sender) |
return |
end |
if not self.querytooltips[item] then |
SendChatMessage(L["invalidformat"], "WHISPER", nil, sender) |
return |
end |
args[3] = string.upper(args[3]) |
if args[3] == "PASS" or args[3] == "TAKE" or args[3] == "NEED" then |
for i,v in ipairs(self.querytooltips[item]) do |
if v[1] == sender then |
v[3] = args[3] |
SendChatMessage(string.format(L["bidaccepted"], v[3]), "WHISPER", nil, sender) |
if (self.db.account.defaults.random or self.random[item]) and args[3] ~= "PASS" then v[4] = math.random(100) end |
end |
end |
else |
if self.db.account.defaults.bidwar then |
local bid = tonumber(args[3]) |
if bid and bid > 0 then |
for i,v in ipairs(self.querytooltips[item]) do |
if v[1] == sender then |
if self.db.account.defaults.silent and tonumber(v[4]) ~= 0 then |
SendChatMessage(L["alreadybid"], "WHISPER", nil, sender) |
return |
end |
v[3] = "TAKE" |
local overbid = self.db.account.info[sender][self.db.account.items[item].pool].points + self.db.account.defaults.overbid |
if bid > overbid then |
bid = overbid |
SendChatMessage(string.format(L["exceedoverbid"], self.db.account.defaults.overbid), "WHISPER", nil, sender) |
end |
v[4] = bid |
if bid > MaxBid[item] then |
MaxBid[item] = bid |
SendChatMessage(string.format(L["bidaccepted"], bid), "WHISPER", nil, sender) |
self:BidWarQueryNeeded(item, sender) |
elseif bid == MaxBid[item] then |
SendChatMessage(string.format(L["bidaccepted"], bid), "WHISPER", nil, sender) |
self:BidWarQueryNeeded(item, " ") |
end |
end |
end |
end |
end |
end |
tablet:Refresh("item"..item) |
end |
function MorgDKP:BidWarQueryNeeded(id, bidder) |
self.db.account.items[id].points = MaxBid[id] |
local POOL = self.db.account.items[id].pool |
if self.db.account.defaults.silent then return end |
local _, Link, _, _, _, _, _, _,_, _ = GetItemInfo(id) |
SendChatMessage(string.format(L["highbidder"], Link, bidder, MaxBid[id]), "RAID") |
for i,v in ipairs(self.querytooltips[id]) do |
if v[3] == "TAKE" and v[1] ~= bidder then |
v[3] = "PENDING" |
SendAddonMessage("MORGBID", "BIDWAR "..id.." "..MaxBid[id].." "..v[1].." "..self.db.account.info[v[1]][POOL].points.." "..self.db.account.defaults.bidstep.." "..self.db.account.defaults.overbid, "RAID") |
end |
end |
tablet:Refresh("item"..id) |
end |
function MorgDKP:ShowTooltip(itemid, tooltiptype, itemlink) |
if tooltiptype == "history" then |
GameTooltip:SetHyperlink(itemlink) |
GameTooltip:Show() |
elseif itemid ~= nil then |
if self.db.account.info[itemlink].raidloot == 0 then return end |
GameTooltip:AddLine(itemlink.."'s Loot:", 0, 0, 1) |
GameTooltip:AddLine("\n", 0, 0, 1) |
for num, loot in pairs(self.db.account.raidlog[self.db.account.defaults.raidnum].loot) do |
local name = loot.Player |
if name == itemlink then |
GameTooltip:AddLine(loot.ItemLink) |
end |
end |
GameTooltip:Show() |
end |
end |
function MorgDKP:ShowWaitlist() |
if #self.db.account.defaults.Waitlist.members == 0 then return end |
local waitlist = { } |
local POOL = self.db.account.defaults.raid |
local class |
for index, name in pairs(self.db.account.defaults.Waitlist.members) do |
class = nil |
if self.db.account.info[name].class then class = self.db.account.info[name].class end |
table.insert(waitlist, {name, class, class or "Unknown", (self.db.account.info[name][POOL].points or 0)}) |
end |
local item = "waitlist" |
local title = L["waitlist"] |
local hint = L["Bar_Hint_Waitlist"] |
local id = nil |
self.querytooltips[item] = waitlist |
self:CreateQueryTooltip(id, item, title, hint) |
end |
function MorgDKP:AddWait(addname) |
if UnitInRaid(addname) then return end |
local wait = nil |
local POOL = self.db.account.defaults.raid |
local class = nil |
local ttime = date("%m/%d/%y %H:%M:%S") |
if not self.db.account.defaults.Waitlist then self.db.account.defaults.Waitlist = {members = {}, join = {} } end |
for num, name in pairs(self.db.account.defaults.Waitlist.members) do |
if name == addname then wait = true break end |
end |
if not wait then |
table.insert(self.db.account.defaults.Waitlist.members, addname) |
self.db.account.defaults.Waitlist.join[addname] = ttime |
DEFAULT_CHAT_FRAME:AddMessage(L["add"] .. addname .. L["to"] .. L["waitlist"]) |
self:PlayerinDB(addname) |
if self.db.account.defaults.InRaid then self:AddIndividualWait(addname) end |
if self.querytooltips["waitlist"] then |
if self.db.account.info[addname].class then class = self.db.account.info[addname].class end |
table.insert(self.querytooltips["waitlist"], {addname, class, class or "Unknown", (self.db.account.info[addname][POOL].points or 0)}) |
tablet:Refresh("waitlist") |
end |
end |
end |
function MorgDKP:SubWait(subname) |
for num,name in pairs(self.db.account.defaults.Waitlist.members) do |
if name == subname then |
table.remove(self.db.account.defaults.Waitlist.members, num) |
self.db.account.defaults.Waitlist.join[subname] = nil |
break |
end |
end |
DEFAULT_CHAT_FRAME:AddMessage(L["removed"] .. subname) |
if self.querytooltips["waitlist"] then |
for num, v in pairs(self.querytooltips["waitlist"]) do |
if v[1] == subname then |
table.remove(self.querytooltips["waitlist"], num) |
break |
end |
end |
tablet:Refresh("waitlist") |
end |
end |
function MorgDKP:InformOnlineAlias(main, Onlinemembers) |
local pool = self.db.account.defaults.raid |
for _, data in pairs(self.db.account.defaults.eqDKP[pool].Aliases) do |
if data.main == main then |
if Onlinemembers[data.alt] then SendChatMessage(L["waitmain"], "WHISPER", nil, data.alt) end |
break |
end |
end |
end |
-- ****************************************************************** |
-- ****************************************************************** |
-- ** MorgDKP ** |
-- ****************************************************************** |
-- ****************************************************************** |
local L = AceLibrary("AceLocale-2.2"):new("MorgDKP") |
local BC = AceLibrary("Babble-Class-2.2") |
local BB = LibStub("LibBabble-Boss-3.0"):GetLookupTable() |
local rosterlib = AceLibrary("Roster-2.1") |
local roster = rosterlib.roster |
local tablet = AceLibrary("Tablet-2.0") |
function MorgDKP:BeginRaid() |
if not self:IsRaided() then return end |
self:RequestLeader() |
local StartDate = date("%m/%d/%y %H:%M:%S") |
local ZoneName = GetRealZoneText() |
local Startname, Runname, Startnote, Runnote |
self:Scan() |
self.waitlistdone = {} |
self.db.account.raidlog.attendancedone = {} |
if not self.db.account.defaults.raidnum then self.db.account.defaults.raidnum = 0 end |
self.db.account.defaults.raidnum = self.db.account.defaults.raidnum + 1 |
self.db.account.raidlog[self.db.account.defaults.raidnum] = { } |
self.db.account.raidlog[self.db.account.defaults.raidnum].playerinfo = { } |
self.db.account.raidlog[self.db.account.defaults.raidnum].join = { } |
self.db.account.raidlog[self.db.account.defaults.raidnum].leave = { } |
self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills = { } |
self.db.account.raidlog[self.db.account.defaults.raidnum].loot = { } |
self.db.account.raidlog[self.db.account.defaults.raidnum].zone = ZoneName |
self.db.account.raidlog[self.db.account.defaults.raidnum].raidstart = StartDate |
self.db.account.raidlog.lootbuffer = { } |
if not self.db.account.raidlog.dkpevents then self.db.account.raidlog.dkpevents = { } end |
if not self.db.account.raidlog.aliases then self.db.account.raidlog.aliases = { } end |
for name, _ in pairs(self.db.account.info) do |
self.db.account.info[name].raidloot = 0 |
end |
self.db.account.raidlog[self.db.account.defaults.raidnum].eqdkp = self.db.account.defaults.eqDKP[self.db.account.defaults.raid].eqDKPsite |
self.db.account.raidlog[self.db.account.defaults.raidnum].prefix = self.db.account.defaults.eqDKP[self.db.account.defaults.raid].prefix |
self.db.account.raidlog.raidstart = StartDate |
self.db.account.raidlog.raidend = L["pending"] |
self.db.account.raidlog.raidexport = L["pending"] |
if self.db.account.defaults.startrun then |
Startnote = string.gsub(self.db.account.defaults.startformat, "<zone>", ZoneName, 1) |
Startname = self:GetEventName(Startnote) |
self:LogBossKill(StartDate, Startname, 1, Startnote, nil, 1) |
end |
Runnote = string.gsub(self.db.account.defaults.trashformat, "<zone>", ZoneName, 1) |
Runname = self:GetEventName(Runnote) |
self:LogBossKill(StartDate, Runname, 1, Runnote, 1, 2) |
self.db.account.defaults.InRaid = 1 |
self.db.account.defaults.raidend = nil |
if self.db.account.defaults.dkpaward then self:ScheduleRepeatingEvent("MorgDKP_Award", self.RecurrentReward, self.db.account.defaults.dkpsched, self ) end |
self:ScheduleRepeatingEvent("MorgDKP_Attendance", self.CheckAttendance, 60, self ) --600 |
local attendees = { } |
local counter = 0 |
for name in pairs(roster) do |
tbl = roster[name] |
if tbl.oldclass ~= "PET" and tbl.class ~= "PET" then |
local raidID = tbl.unitid |
local _, race = UnitRace(raidID) |
local level = UnitLevel(raidID) |
local guild, _, _ = GetGuildInfo(raidID) |
local class = BC[string.upper(string.sub(tbl.class,1,1))..string.lower(string.sub(tbl.class,2,-1))] |
if name and name ~= "" and name ~= "UNKNOWN" then |
if not attendees[name] then attendees[name] = { } end |
if class then attendees[name].class = class end |
if race then attendees[name].race = race end |
if level > 0 then attendees[name].level = level end |
if guild then attendees[name].guild = guild end |
end |
self.db.account.raidlog[self.db.account.defaults.raidnum].join[name] = StartDate |
counter = counter + 1 |
end |
end |
self.db.account.raidlog[self.db.account.defaults.raidnum].playerinfo = attendees |
DEFAULT_CHAT_FRAME:AddMessage(L["add"]..tostring(counter)..L["raidstartadd"]) |
end |
function MorgDKP:EndRaid() |
if not self.db.account.defaults.InRaid then DEFAULT_CHAT_FRAME:AddMessage(L["noraid"]) return end |
if self:IsEventScheduled("MorgDKP_Award") then self:CancelScheduledEvent("MorgDKP_Award") end |
if self:IsEventScheduled("MorgDKP_Attendance") then self:CancelScheduledEvent("MorgDKP_Attendance") end |
local EndTime = date("%m/%d/%y %H:%M:%S") |
self.db.account.raidlog.raidend = EndTime |
self.db.account.defaults.raidend = 1 |
self.db.account.defaults.InRaid = nil |
counter = 0 |
for name in pairs(roster) do |
local tbl = roster[name] |
local raidID = tbl.unitid |
if tbl.oldclass ~= "PET" and tbl.class ~= "PET" then |
if name and name ~= "" and name ~= "UNKNOWN" then |
self.db.account.raidlog[self.db.account.defaults.raidnum].leave[name] = EndTime |
end |
counter = counter + 1 |
end |
end |
self.db.account.defaults.Waitlist = {members = {}, join = {}} |
self.db.account.raidlog.attendancedone = {} |
self.db.account.defaults.custom = L["NEW"] |
DEFAULT_CHAT_FRAME:AddMessage(L["removed"]..tostring(counter)..L["raidatt"]) |
end |
function MorgDKP:GetEventName(boss) |
local zone = GetRealZoneText() |
local note |
local event = self.db.account.defaults.eventformat |
event = string.gsub(event, "<zone>", zone) |
event = string.gsub(event, "<boss>", boss) |
return event |
end |
function MorgDKP:FillDKPChanges() |
local temp = { } |
for pool, data in pairs(self.db.account.raidlog.dkpevents) do |
for index, changes in pairs(data) do |
if changes.addtype == "Decay" then |
for key, name in pairs(changes.members) do |
name = self:CheckforAlias(name, pool) |
self:PointsPoolExists(name, pool) |
local value = 0 - (math.floor((self.db.account.info[name][pool].points * changes.value/100) + 0.5)) |
table.insert(temp, { name = name, |
value = value, |
members = {[1] = name}, |
eqdkp = changes.eqdkp, |
prefix = changes.prefix, |
addtype = "individual", |
event = changes.event}) |
end |
else table.insert(temp, changes) |
end |
end |
end |
return temp |
end |
function MorgDKP:CheckforAlias(name, pool) |
for _, data in pairs(self.db.account.defaults.eqDKP[pool].Aliases) do |
if data.alt == name then return data.main end |
end |
return name |
end |
function MorgDKP:OutputRaid(raidlog, raidid) |
local DKPChanges = self:FillDKPChanges() |
local link = "<MorgDKP>" |
if raidlog.aliases then |
link = link.."<Aliases>" |
local index = 1 |
for pool, data in pairs(raidlog.aliases) do |
table.sort(data, function (a, b) return a.alt < b.alt end) |
for _, data2 in pairs(data) do |
link = link.."<key"..index..">" |
link = link.."<alt>"..data2.alt.."</alt>" |
link = link.."<main>"..data2.main.."</main>" |
link = link.."<eqdkp>"..data2.eqdkp.."</eqdkp>" |
link = link.."<prefix>"..self.db.account.defaults.eqDKP[pool].prefix.."</prefix>" |
link = link.."<action>"..data2.action.."</action>" |
link = link.."</key"..index..">" |
index = index + 1 |
end |
end |
link = link.."</Aliases>" |
end |
if DKPChanges then |
link = link.."<DKPChanges>" |
for key, data in pairs(DKPChanges) do |
link = link.."<key"..key..">" |
link = link.."<name>"..data.name.."</name>" |
link = link.."<value>"..data.value.."</value>" |
link = link.."<eqdkp>"..data.eqdkp.."</eqdkp>" |
link = link.."<prefix>"..data.prefix.."</prefix>" |
link = link.."<event>"..data.event.."</event>" |
link = link.."<addtype>"..data.addtype.."</addtype>" |
link = link.."<members>" |
for key2, val2 in pairs(data.members) do |
link = link.."<key"..key2..">" ..val2.. "</key"..key2..">" |
end |
link = link.."</members>" |
link = link.."</key"..key..">" |
end |
link = link.."</DKPChanges>" |
end |
link = link.."<Raids>" |
if self.db.account.defaults.raidnum > 0 then |
for raidindex = 1, self.db.account.defaults.raidnum do |
if not raidid or raidindex == raidid then |
local raiddata = raidlog[raidindex] |
link = link.."<key"..raidindex..">" |
link = link.."<zone>"..raiddata.zone.."</zone>" |
link = link.."<date>"..raiddata.raidstart.."</date>" |
link = link.."<eqdkp>"..raiddata.eqdkp.."</eqdkp>" |
link = link.."<prefix>"..raiddata.prefix.."</prefix>" |
link = link.."<Attendees>" |
local index = 1 |
for key, _ in pairs(raiddata.playerinfo) do |
link = link.."<key"..index..">" |
link = link.."<name>"..key.."</name>" |
for key2, val2 in pairs(raiddata.playerinfo[key]) do |
link = link.."<"..key2..">"..val2.."</"..key2..">" |
end |
link = link.."</key"..index..">" |
index = index + 1 |
end |
link = link.."</Attendees>" |
link = link.."<Bosskills>" |
for key, data in pairs(raiddata.bosskills) do |
link = link.."<key"..key..">" |
link = link.."<name>"..data.name.."</name>" |
link = link.."<note>"..data.note.."</note>" |
link = link.."<time>"..data.time.."</time>" |
link = link.."<value>"..data.value.."</value>" |
link = link.."<trash>"..data.trash.."</trash>" |
link = link.."<attendees>" |
for key2, val2 in pairs(data.attendees) do |
link = link.."<key"..key2..">" ..val2.. "</key"..key2..">" |
end |
link = link.."</attendees>" |
link = link.."</key"..key..">" |
end |
link = link.."</Bosskills>" |
link = link.."<Loot>" |
for key, data in pairs(raiddata.loot) do |
link = link.."<key"..key..">" |
for key2, val2 in pairs(data) do |
link = link.."<"..key2..">"..val2.."</"..key2..">" |
end |
link = link.."</key"..key..">" |
end |
link = link.."</Loot>" |
link = link.."</key"..raidindex..">" |
raidindex = raidindex + 1 |
end |
end |
end |
link = link.."</Raids>" |
link = link.."</MorgDKP>" |
MorgDKP:OutputLink(link) |
end |
function MorgDKP:OutputLink(link) |
URLFrameEditBox:SetText(link) |
URLFrameEditBox:HighlightText() |
URLFrame:Show() |
end |
function MorgDKP:CombatLogEvent(timestamp, eventtype, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, ...) |
if not UnitInRaid("player") or not self.db.account.defaults.InRaid then return end |
--DEFAULT_CHAT_FRAME:AddMessage(eventtype..","..(srcName or "nil")..","..(srcFlags or "nil")..","..(dstName or "nil")..","..(dstFlags or "nil")) |
if eventtype == "UNIT_DIED" or eventtype == "UNIT_DESTROYED" then self:HostileDeath(dstName, dstGUID) end |
end |
function MorgDKP:HostileDeath(mobName, GUID) |
local killTime = date("%m/%d/%y %H:%M:%S") |
if not L["MorgTracker_IgnoreMobs"][mobName] then self.db.account.raidlog[self.db.account.defaults.raidnum].lastmob = mobName end |
if mobName ~= nil then |
local Boss |
if mobName == L["Romulo"] or mobName == L["Julianne"] then |
Boss = L["RomuloandJulianne"] |
self.killed[Boss] = self.killed[Boss] + 1 |
if self.killed[Boss] < 4 or self.db.account.raidlog[self.db.account.defaults.raidnum].lastboss == Boss then return end |
elseif mobName == BB["Essence of Anger"] then Boss = BB["Reliquary of Souls"] |
elseif mobName == BB["Lady Sacrolash"] or mobName == BB["Grand Warlock Alythess"] then |
Boss = BB["Eredar Twins"] |
self.killed[Boss] = self.killed[Boss] + 1 |
if self.killed[Boss] < 2 then return end |
else |
for _, bossname in pairs(MorgTracker_ZoneBosses[self.db.account.defaults.menuzone]) do |
if mobName == bossname then Boss = mobName break end |
end |
end |
if Boss then |
local Eventname = self:GetEventName(Boss) |
self:LogBossKill(killTime, Eventname, nil, Boss) |
end |
end |
end |
function MorgDKP:LogBossKill(killTime, Boss, notboss, Note, quiet, id) |
if not self.db.account.defaults.OneEvent or id == 2 then |
local attendees = { } |
if id ~= 2 then |
counter = 0 |
for name in pairs(roster) do |
if name and name ~= "" and name ~= "UNKNOWN" then |
local tbl = roster[name] |
if tbl.class ~= "PET" and tbl.oldclass ~= "PET" then |
table.insert(attendees, name) |
counter = counter + 1 |
end |
end |
end |
end |
local value = 0 |
if self.db.account.defaults.eqDKP[self.db.account.defaults.raid]["Events"][Boss] then value = self.db.account.defaults.eqDKP[self.db.account.defaults.raid]['Events'][Boss].value end |
table.insert(self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills, |
{ |
["name"] = Boss, |
["note"] = Note, |
["time"] = killTime, |
["attendees"] = attendees, |
["value"] = value, |
["trash"] = id or 0 |
} |
) |
local POOL = self.db.account.defaults.raid |
if not quiet then |
DEFAULT_CHAT_FRAME:AddMessage(Note..L["bosskill"]..killTime.." and "..tostring(counter)..L["attadded"]) |
self:AwardDKP(nil, value, POOL, attendees) |
if self.db.account.defaults.waitaward then self:AwardWaitlistDKP(value, POOL, Boss, id) end |
end |
end |
if not notboss then |
self.db.account.raidlog[self.db.account.defaults.raidnum].lastboss = Boss |
end |
if Boss == BB["Rage Winterchill"] or Boss == BB["Anetheron"] or Boss == BB["Kaz'rogal"] then self:ChangeLootMethod("group") end |
end |
function MorgDKP:HostileYell() |
if not UnitInRaid("player") or not self.db.account.defaults.InRaid then return end |
if arg1 == L["MORGTRACKER_MAJORDOMO_YELL"] then |
local killTime = date("%m/%d/%y %H:%M:%S") |
local Boss = BB["Majordomo Executus"] |
local Eventname = self:GetEventName(Boss) |
self:LogBossKill(killTime, Eventname, nil, Boss) |
elseif arg1 == L["MORGTRACKER_ROMULO_YELL"] then |
self.killed[L["RomuloandJulianne"]] = 0 |
elseif arg1 == L["MORGTRACKER_ERADOR_YELL"] then |
self.killed[BB["Eredar Twins"]] = 0 |
elseif arg1 == L["MORGTRACKER_LADYVASHJP2_YELL"] then self:ChangeLootMethod("freeforall") |
elseif arg1 == L["MORGTRACKER_LADYVASHJP3_YELL"] then self:ChangeLootMethod("master") |
elseif arg1 == L["MORGTRACKER_RAGEENTERS_YELL"] then self:ChangeLootMethod("master") |
elseif arg1 == L["MORGTRACKER_ANETHERONENTERS_YELL"] then self:ChangeLootMethod("master") |
elseif arg1 == L["MORGTRACKER_KAZROGALENTERS_YELL"] then self:ChangeLootMethod("master") |
elseif arg1 == L["MORGTRACKER_AZGALORENTERS_YELL"] then self:ChangeLootMethod("master") |
end |
end |
function MorgDKP:HostileEmote() |
if not UnitInRaid("player") or not self.db.account.defaults.InRaid then return end |
if arg1 == L["MORGTRACKER_CHESS_EMOTE"] then |
local killTime = date("%m/%d/%y %H:%M:%S") |
local Boss = BB["Chess Event"] |
self.db.account.raidlog[self.db.account.defaults.raidnum].lastmob = BB["Chess Event"] |
local Eventname = self:GetEventName(Boss) |
self:LogBossKill(killTime, Eventname, nil, Boss) |
end |
end |
function MorgDKP:LeaderDied() |
if not self.db.account.defaults.InRaid then return end |
StaticPopup_Show ("BossAttempt", self.db.account.defaults.custom) |
end |
function MorgDKP:ChangeLootMethod(method) |
self:PrepareRaidmembers() |
if not self.lootmaster then self.lootmaster = UnitName("player") end |
if method == "master" then SetLootMethod("master", self.lootmaster) |
else SetLootMethod(method) end |
end |
function MorgDKP:ProcessRosterChange(unitid, name, class, subgroup, rank, oldname, oldunitid, oldclass, oldsubgroup, oldrank) |
if not UnitInRaid("player") then return end |
self:PrepareRaidmembers() |
if not self.db.account.defaults.InRaid and not self.querytooltips["listdkp"] then return end |
local ttime = date("%m/%d/%y %H:%M:%S") |
if not name then |
if oldclass ~= "PET" and class ~= "PET" then |
if self.oldname ~= oldname then |
if name ~= UnitName("player") and not UnitCanAttack("player", oldunitid) then |
if not self.db.account.raidlog[self.db.account.defaults.raidnum].leave then self.db.account.raidlog[self.db.account.defaults.raidnum].leave = { } end |
self.db.account.raidlog[self.db.account.defaults.raidnum].leave[oldname] = ttime |
DEFAULT_CHAT_FRAME:AddMessage(oldname..L["leftraid"]..ttime) |
self.oldname = oldname |
end |
end |
end |
elseif not oldname then |
if oldclass ~= "PET" and class ~= "PET" then |
if self.name ~= name then |
local _, race = UnitRace(unitid) |
local level = UnitLevel(unitid) |
local guild = GetGuildInfo(unitid) |
local classtrue = BC[string.upper(string.sub(class,1,1))..string.lower(string.sub(class,2,-1))] |
if not self.db.account.raidlog[self.db.account.defaults.raidnum].playerinfo then self.db.account.raidlog[self.db.account.defaults.raidnum].playerinfo = { } end |
if not self.db.account.raidlog[self.db.account.defaults.raidnum].playerinfo[name] then self.db.account.raidlog[self.db.account.defaults.raidnum].playerinfo[name] = { } end |
if classtrue then self.db.account.raidlog[self.db.account.defaults.raidnum].playerinfo[name].class = classtrue end |
if race then self.db.account.raidlog[self.db.account.defaults.raidnum].playerinfo[name].race = race end |
if level > 0 then self.db.account.raidlog[self.db.account.defaults.raidnum].playerinfo[name].level = level end |
if guild then self.db.account.raidlog[self.db.account.defaults.raidnum].playerinfo[name].guild = guild end |
if not self.db.account.raidlog[self.db.account.defaults.raidnum].join then self.db.account.raidlog[self.db.account.defaults.raidnum].join = { } end |
if not self.db.account.raidlog[self.db.account.defaults.raidnum].join[name] then |
self.db.account.raidlog[self.db.account.defaults.raidnum].join[name] = ttime |
if self.db.account.raidlog[self.db.account.defaults.raidnum].leave then |
if self.db.account.raidlog[self.db.account.defaults.raidnum].leave[name] then self.db.account.raidlog[self.db.account.defaults.raidnum].leave[name] = nil end |
end |
DEFAULT_CHAT_FRAME:AddMessage(name..L["joinraid"]..ttime) |
if not self:IsEventScheduled("MorgDKP_Attendance") then self:ScheduleRepeatingEvent("MorgDKP_Attendance", self.CheckAttendance, 60, self ) end |
end |
self:PlayerinDB(name , classtrue) |
self.name = name |
for num,waitname in pairs(self.db.account.defaults.Waitlist.members) do |
if waitname == name then |
self:SubWait(name) |
end |
end |
if self.querytooltips["waitlist"] then |
tablet:Refresh("waitlist") |
end |
end |
end |
end |
if self.querytooltips["listdkp"] then self:Onlinemembers() end |
self:RequestLeader() |
end |
function MorgDKP:ReclaimAll() |
MorgDKP.opts.args.deer.validate = self.db.account.defaults.raidmembers |
MorgDKP.opts.args.boes.validate = self.db.account.defaults.raidmembers |
MorgDKP.DEopts.validate = self.db.account.defaults.raidmembers |
end |
function MorgDKP:ReclaimML() |
MorgDKP.opts.args.mlootdet.validate = self.db.account.defaults.raidmembers |
MorgDKP.MLopts.validate = self.db.account.defaults.raidmembers |
end |
function MorgDKP:ReclaimZone() |
MorgDKP.opts.args.dkpfunc.args.custommenu.validate = MorgTracker_ZoneBosses[self.db.account.defaults.menuzone] |
MorgDKP.custommenu.validate = MorgTracker_ZoneBosses[self.db.account.defaults.menuzone] |
end |
function MorgDKP:ReclaimPool() |
MorgDKP.opts.args.dkpfunc.args.load.validate = self.db.account.defaults.raidlist |
MorgDKP.RaidDBopts.validate = self.db.account.defaults.raidlist |
end |
function MorgDKP:RecurrentReward() |
if not UnitInRaid("player") then return end |
if not self.db.account.defaults.dkpaward or not self.db.account.defaults.InRaid then return end |
local POOL = self.db.account.defaults.raid |
local award = self.db.account.defaults.dkpamount |
local currtime = date("%m/%d/%y %H:%M:%S") |
local attendees = { } |
local counter = 0 |
local Runname = self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[self:GetRunEvent()].note |
for i = 1, GetNumRaidMembers() do |
local name = UnitName("raid"..i) |
local jointime = self.db.account.raidlog[self.db.account.defaults.raidnum].join[name] |
if self:TimeDiff(jointime, currtime) >= self.db.account.defaults.dkpsched then |
self.db.account.info[name][POOL].points = self.db.account.info[name][POOL].points + award |
self.db.account.info[name][POOL].earned = self.db.account.info[name][POOL].earned + award |
table.insert(attendees, name) |
counter = counter + 1 |
end |
end |
if counter > 0 then |
self:AwardWaitotimeDKP(award, POOL, Runname, attendees, "Group", "Group") |
DEFAULT_CHAT_FRAME:AddMessage(L["add"]..tostring(award)..L["dkpword"] .."to "..tostring(counter)..L["attend"]) |
end |
if self.db.account.defaults.waitaward and self.db.account.defaults.waitotime ~= 0 and #self.db.account.defaults.Waitlist.members ~= 0 then |
self:AwardWaitotimeDKP(self.db.account.defaults.waitotime, POOL, Runname, self.db.account.defaults.Waitlist.members, "Group", "Group") |
self:AwardDKP(nil, self.db.account.defaults.waitotime, POOL, self.db.account.defaults.Waitlist.members, 1) |
end |
end |
function MorgDKP:Initialisedkpevents() |
local POOL = self.db.account.defaults.raid |
if not self.db.account.raidlog.dkpevents then self.db.account.raidlog.dkpevents = { } end |
if not self.db.account.raidlog.dkpevents[POOL] then self.db.account.raidlog.dkpevents[POOL] = { } end |
end |
function MorgDKP:CheckAttendance() |
if not UnitInRaid("player") or not self.db.account.defaults.InRaid then return end |
if self.db.account.defaults.devmode then self:Print("Checking attendees...") end |
local POOL = self.db.account.defaults.raid |
local currtime = date("%m/%d/%y %H:%M:%S") |
local value = 0 |
local id = self:GetRunEvent() |
if self.db.account.defaults.eqDKP[self.db.account.defaults.raid]['Events'][self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[id].name] then |
value = self.db.account.defaults.eqDKP[self.db.account.defaults.raid]['Events'][self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[id].name].value |
end |
for name, jointime in pairs(self.db.account.raidlog[self.db.account.defaults.raidnum].join) do |
if not self.db.account.raidlog.attendancedone[name] and not self.db.account.raidlog[self.db.account.defaults.raidnum].leave[name] then |
if self:TimeDiff(jointime, currtime) >= self.db.account.defaults.runrewardtime then |
table.insert(self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[id].attendees, name) |
self.db.account.raidlog.attendancedone[name] = true |
if self.db.account.defaults.devmode then self:Print("Added "..name.." to run.") end |
if value then self:AwardDKP(nil, value, POOL, {[1] = name}, nil, 1) end |
end |
end |
end |
local attdone = true |
for name, jointime in pairs(self.db.account.raidlog[self.db.account.defaults.raidnum].join) do |
if not self.db.account.raidlog.attendancedone[name] then attdone = nil end |
end |
if attdone and self:IsEventScheduled("MorgDKP_Attendance") then self:CancelScheduledEvent("MorgDKP_Attendance") end |
if self.db.account.defaults.waitrun == 0 or not self.waitlistdone then return end |
local temp = {} |
for _, name in pairs(self.db.account.defaults.Waitlist.members) do |
if not self.waitlistdone[name] then |
if self:TimeDiff(self.db.account.defaults.Waitlist.join[name], currtime) >= self.db.account.defaults.runrewardtime then |
table.insert(temp, name) |
if self.db.account.defaults.devmode then self:Print("Added "..name.." to run.") end |
self.waitlistdone[name] = true |
end |
end |
end |
if #temp > 0 then |
if self.db.account.defaults.waitrun == value then |
for _, name in pairs(temp) do |
table.insert(self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[id].attendees, name) |
end |
else |
self:AwardWaitotimeDKP(self.db.account.defaults.waitrun, POOL, self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills[id].name, temp, "Group", "Group") |
end |
self:AwardDKP(nil, self.db.account.defaults.waitrun, POOL, temp, 1, 1) |
end |
end |
function MorgDKP:GetRunEvent() |
for id, event in pairs(self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills) do |
if event.trash == 2 then return id end |
end |
return false |
end |
function MorgDKP:GetStartEvent() |
for id, event in pairs(self.db.account.raidlog[self.db.account.defaults.raidnum].bosskills) do |
if event.trash == 1 then return id end |
end |
return false |
end |
local L = AceLibrary("AceLocale-2.2"):new("MorgDKP") |
local BZ = LibStub("LibBabble-Zone-3.0"):GetLookupTable() |
local BC = AceLibrary("Babble-Class-2.2") |
local tablet = AceLibrary("Tablet-2.0") |
local dewdrop = AceLibrary("Dewdrop-2.0") |
local MorgDKP = MorgDKP |
MorgDKPFu = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0", "AceDB-2.0", "FuBarPlugin-2.0") |
MorgDKPFu.hasIcon = "Interface\\AddOns\\MorgDKP\\Icons\\AquaOFF" |
MorgDKPFu.category = "Raid" |
MorgDKPFu.title = "MorgDKP" |
MorgDKPFu.defaultPosition = "RIGHT" |
MorgDKPFu.clickableTooltip = true |
MorgDKPFu.overrideMenu = true |
MorgDKPFu.hasNoText = true |
MorgDKPFu.tooltipHiddenWhenEmpty = true |
MorgTracker_ZoneTriggers = { |
[BZ["Molten Core"]] = true, |
[BZ["Blackwing Lair"]] = true, |
[BZ["Zul'Gurub"]]= true, |
[BZ["Onyxia's Lair"]] = true, |
[BZ["Ruins of Ahn'Qiraj"]] = true, |
[BZ["Ahn'Qiraj"]] = true, |
[BZ["Naxxramas"]] = true, |
[BZ["Karazhan"]] = true, |
[BZ["Gruul's Lair"]] = true, |
[BZ["Magtheridon's Lair"]] = true, |
[BZ["Serpentshrine Cavern"]] = true, |
[BZ["Caverns of Time"]] = true, |
[BZ["Black Temple"]] = true, |
[BZ["Tempest Keep"]] = true, |
[BZ["Hyjal Summit"]] = true, |
[BZ["Alliance Base"]] = true, |
[BZ["Horde Encampment"]] = true, |
[BZ["Zul'Aman"]] = true, |
[BZ["Sunwell Plateau"]] = true, |
[L["WorldBoss"]] = true, |
} |
function MorgDKPFu:OnInitialize() |
self:RegisterDB("MorgDKPFuBarDB") |
end |
function MorgDKPFu:OnEnable() |
self:RegisterEvent("PLAYER_ENTERING_WORLD", "EnterWorld") |
self:RegisterEvent("ZONE_CHANGED_NEW_AREA", "ZoneChange") |
self:RegisterEvent("CHAT_MSG_WHISPER", "WhisperHandler") |
self:ChangeState() |
end |
function MorgDKPFu:ChangeState() |
if MorgDKP:IsActive() then |
self:SetIcon("Interface\\AddOns\\MorgDKP\\Icons\\AquaON") |
MorgDKPFu.hint = L["fubarhint"] |
else |
self:SetIcon("Interface\\AddOns\\MorgDKP\\Icons\\AquaOFF") |
MorgDKPFu.hint = L["fubarhintdisabled"] |
end |
self:Update() |
end |
function MorgDKPFu:EnterWorld() |
self:IsTrackedZone() |
end |
function MorgDKPFu:ZoneChange() |
if self:IsTrackedZone() then |
if not MorgDKP.db.account.defaults.InRaid and MorgDKP.db.account.defaults.autozone then MorgDKP:BeginRaid() end |
elseif not UnitIsGhost("player") and MorgDKP.db.account.defaults.InRaid and MorgDKP.db.account.defaults.autozone then MorgDKP:ShowEndRaidFrame() |
end |
end |
function MorgDKPFu:IsTrackedZone() |
local ZoneName = GetRealZoneText() |
if MorgTracker_ZoneTriggers[ZoneName] then |
if ZoneName == BZ["Alliance Base"] or ZoneName == BZ["Horde Encampment"] then ZoneName = BZ["Hyjal Summit"] end |
MorgDKP.db.account.defaults.menuzone = ZoneName |
self:ActivateMorgDKP() |
return true |
else |
MorgDKP.db.account.defaults.menuzone = L["WorldBoss"] |
self:DeActivateMorgDKP() |
end |
return false |
end |
function MorgDKPFu:ActivateMorgDKP() |
if MorgDKP.db.account.defaults.autozone and not UnitIsGhost("player") then |
if not MorgDKP:IsActive() then MorgDKP:ToggleActive(true) end |
end |
MorgDKP:ReclaimZone() |
self:ChangeState() |
end |
function MorgDKPFu:DeActivateMorgDKP() |
if MorgDKP:IsActive() and MorgDKP.db.account.defaults.autozone and not UnitIsGhost("player") then MorgDKP:ToggleActive(false) end |
MorgDKP:ReclaimZone() |
self:ChangeState() |
end |
function MorgDKPFu:DisableMorgDKP() |
MorgDKP:ToggleActive(false) |
self:ChangeState() |
end |
function MorgDKPFu:WhisperHandler(txt, sender) |
local command = string.upper(string.sub(txt, 1, 4)) |
if command ~= "MBID" and command ~= "DKPL" then return end |
local active = MorgDKP:IsActive() |
if not active then |
MorgDKP:ToggleActive(true) |
self:ChangeState() |
end |
local raided = nil |
if MorgDKP:CheckRaid(sender) then raided = true end |
if MorgDKP.db.account.info[sender] and MorgDKP.db.account.info[sender].class then pclass = MorgDKP.db.account.info[sender].class end |
if command == "MBID" then |
MorgDKP:OnBidWhisper(txt, sender) |
if not active then self:DisableMorgDKP() end |
return |
end |
if command == "DKPL" and string.find(string.upper(txt), "POOLS") then |
MorgDKP:ShowPools(txt, sender) |
if not active then self:DisableMorgDKP() end |
return |
end |
dkplist = MorgDKP:FillDKPTable(sender, pclass, txt, raided) |
local spaces = " " |
local numspace = {10, 7, 5, 2, 1} |
for i,v in ipairs(dkplist) do |
local message = string.upper(v[1]) |
message = message ..string.sub(spaces,1,(45 - MorgDKP:CalcSpaces(string.upper(v[1]))))..string.upper(v[2]) |
message = message ..string.sub(spaces,1,(MorgDKP:CalcSpaces(string.upper(v[2]))))..string.sub(spaces,1,numspace[string.len(v[4])])..v[4].." DKP" |
SendChatMessage(message, "WHISPER", nil, sender) |
end |
if not active then self:DisableMorgDKP() end |
end |
function MorgDKPFu:OnMenuRequest() |
MorgDKP.hasitem = nil |
dewdrop:FeedAceOptionsTable(MorgDKP.opts) |
end |
function MorgDKPFu:OnClick() |
if MorgDKP:IsActive() then |
if IsAltKeyDown() then |
MorgDKP.MLmode = not MorgDKP.MLmode |
self:Update() |
elseif IsShiftKeyDown() then |
MorgDKP:ListDKP("All") |
MorgDKP:ShowWaitlist() |
elseif IsControlKeyDown() then |
MorgDKP:RaidTablet() |
else |
MorgDKP:MorgBidQuery() |
end |
else |
MorgDKP:ToggleActive(true) |
self:ChangeState() |
end |
end |
function MorgDKPFu:OnTooltipUpdate() |
tablet:SetHint(self.hint) |
if not MorgDKP:IsActive() then return end |
local cat = tablet:AddCategory('columns', 2) |
local colortog = 0 |
local inraid = UnitInRaid("player") |
local MLstatustext = L["statusoff"] |
local attstatus = L["pending"] |
local dkpstatus = L["normal"] |
local Quality = {[1] = "|c009d9d9dPoor|r", [2] = "|c00ffffffCommon|r", [3] = "|c001eff00Uncommon|r", [4] = "|c000070ddRare|r", [5] = "|c00a335eeEpic|r", [6] = "|c00ff8000Legendary|r", [7] = "|c00e6cc80Artifact|r"} |
if not inraid or not MorgDKP.db.account.defaults.mlooter then colortog = 1 end |
if MorgDKP.MLmode then MLstatustext = L["statuson"] end |
if MorgDKP.db.account.defaults.relational and MorgDKP.db.account.defaults.zerosum then dkpstatus = L["enablerelationaldkp"] .. " & " .. L["enablezerosum"] |
elseif MorgDKP.db.account.defaults.relational then dkpstatus = L["enablerelationaldkp"] |
elseif MorgDKP.db.account.defaults.zerosum then dkpstatus = L["enablezerosum"] |
elseif MorgDKP.db.account.defaults.percent > 0 then dkpstatus = L["enablepercent"] end |
if MorgDKP.db.account.defaults.bidwar then dkpstatus = dkpstatus .. " & " .. L["enablebidwar"] end |
if MorgDKP.db.account.defaults.random then dkpstatus = L["enablerandom"] end |
cat:AddLine( |
'text', L["mloot"], |
'textR', 0, |
'textG', 0.7, |
'textB', 0.8, |
'text2', MorgDKP.db.account.defaults.mlooter or "NONE", |
'text2R', 1 and colortog, |
'text2G', 1, |
'text2B', 0, |
'func', function() |
dewdrop:Open(this, |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.MLopts) |
end, |
'point', function(parent) return "LEFT", "RIGHT" end, |
'strata', "HIGH") |
end |
) |
local colortog = 0 |
if not inraid or not MorgDKP.db.account.defaults.disenchanter then colortog = 1 end |
cat:AddLine( |
'text', L["denchanter"], |
'textR', 0, |
'textG', 0.7, |
'textB', 0.8, |
'text2', MorgDKP.db.account.defaults.disenchanter or "NONE", |
'text2R', 1 and colortog, |
'text2G', 1, |
'text2B', 0, |
'func', function() |
dewdrop:Open(this, |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.DEopts) |
end, |
'point', function(parent) return "LEFT", "RIGHT" end, |
'strata', "HIGH") |
end |
) |
cat:AddLine( |
'text', L["customname"], |
'textR', 0, |
'textG', 0.7, |
'textB', 0.8, |
'text2', MorgDKP.db.account.defaults.custom , |
'text2R', 0, |
'text2G', 1, |
'text2B', 0, |
'func', function() |
dewdrop:Open(this, |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.custommenu) |
end, |
'point', function(parent) return "LEFT", "RIGHT" end, |
'strata', "HIGH") |
end |
) |
cat:AddLine( |
'text', L["pool"], |
'textR', 0, |
'textG', 0.7, |
'textB', 0.8, |
'text2', MorgDKP.db.account.defaults.raid or "NONE", |
'text2R', 0, |
'text2G', 1, |
'text2B', 0, |
'func', function() |
dewdrop:Open(this, |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.RaidDBopts) |
end, |
'point', function(parent) return "LEFT", "RIGHT" end, |
'strata', "HIGH") |
end |
) |
cat:AddLine( |
'text', L["mldefunc"], |
'textR', 0, |
'textG', 0.7, |
'textB', 0.8, |
'text2', MLstatustext, |
'text2R', 0, |
'text2G', 1, |
'text2B', 0 |
) |
cat:AddLine( |
'text', L["dkpsys"], |
'textR', 0, |
'textG', 0.7, |
'textB', 0.8, |
'text2', dkpstatus, |
'text2R', 0, |
'text2G', 1, |
'text2B', 0, |
'func', function() |
dewdrop:Open(this, |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.dkpsystem) |
end, |
'point', function(parent) return "LEFT", "RIGHT" end, |
'strata', "HIGH") |
end |
) |
cat:AddLine( |
'text', L["logquality"], |
'textR', 0, |
'textG', 0.7, |
'textB', 0.8, |
'text2', Quality[MorgDKP.db.account.defaults.quality+1], |
'func', function() |
dewdrop:Open(this, |
'children', function(level, value) |
dewdrop:FeedAceOptionsTable(MorgDKP.qualmenu) |
end, |
'point', function(parent) return "LEFT", "RIGHT" end, |
'strata', "HIGH") |
end |
) |
cat:AddLine('text', "\n") |
local colortog = 0 |
if not MorgDKP.db.account.defaults.InRaid then colortog = 1 end |
cat:AddLine( |
'text', L["startraid"], |
'textR', colortog, |
'textG', 1, |
'textB', 0, |
'text2', MorgDKP.db.account.raidlog.raidstart, |
'text2R', colortog, |
'text2G', 1, |
'text2B', 0, |
'func', function() MorgDKP:BeginRaid() end |
) |
local colortog = 0 |
if not MorgDKP.db.account.defaults.raidend then colortog = 1 end |
cat:AddLine( |
'text', L["endraid"], |
'textR', colortog, |
'textG', 1, |
'textB', 0, |
'text2', MorgDKP.db.account.raidlog.raidend, |
'text2R', colortog, |
'text2G', 1, |
'text2B', 0, |
'func', function() MorgDKP:ShowEndRaidFrame() end |
) |
local colortog = 0 |
if MorgDKP.db.account.raidlog.raidexport ~= L["complete"] then colortog = 1 end |
cat:AddLine( |
'text', L["rundkp"], |
'textR', colortog, |
'textG', 1, |
'textB', 0, |
'text2', MorgDKP.db.account.raidlog.raidexport, |
'text2R', colortog, |
'text2G', 1, |
'text2B', 0, |
'func', function() MorgDKP:ExportRaids() end |
) |
cat:AddLine( |
'text', L["custom"], |
'textR', 0, |
'textG', 1, |
'textB', 0, |
'text2', MorgDKP.db.account.defaults.custom, |
'text2R', 0, |
'text2G', 1, |
'text2B', 0, |
'func', function() MorgDKP:CustomEvent() end |
) |
cat:AddLine('text', "\n") |
if MorgDKP.db.account.defaults.raidnum ~= 0 and MorgDKP.db.account.raidlog[MorgDKP.db.account.defaults.raidnum].loot then |
for num, loot in pairs(MorgDKP.db.account.raidlog[MorgDKP.db.account.defaults.raidnum].loot) do |
local name = loot.Player |
if loot.ID ~= 20725 then |
local r, g, b = 1, 1, 1 |
if name and MorgDKP.db.account.info[name] and MorgDKP.db.account.info[name].class then r, g, b = BC:GetColor(MorgDKP.db.account.info[name].class) |
else name = "UNKNOWN" end |
if loot.ItemLink then |
cat:AddLine( |
'text', loot.ItemLink, |
'text2', name, |
'text2R', r, |
'text2G', g, |
'text2B', b, |
'onEnterFunc', function() |
GameTooltip:SetOwner(this, "ANCHOR_LEFT") |
GameTooltip:SetHyperlink(loot.ItemLink) |
GameTooltip:Show() |
end, |
'onLeaveFunc', function() GameTooltip:Hide() end, |
'func', function() self:FubartabletClick(loot.ID, loot.ItemLink) end |
) |
end |
end |
end |
end |
end |
function MorgDKPFu:FubartabletClick(itemID, itemlink) |
if IsShiftKeyDown() then |
ChatFrameEditBox:Insert(itemlink) |
elseif IsControlKeyDown() then |
table.insert(MorgDKP.db.account.defaults.ignore, itemlink) |
else MorgDKP:ManualItem(itemID, itemlink) |
end |
end |