WoWInterface SVN MorgDKP

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 21 to Rev 22
    Reverse comparison

Rev 21 → Rev 22

trunk/MorgDKP/plugins/morgdkp/Morgimport.php New file
0,0 → 1,19
<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>
\ No newline at end of file
trunk/MorgDKP/plugins/morgdkp/Morgfunc.php New file
0,0 → 1,680
<?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;
}
 
?>
\ No newline at end of file
trunk/MorgDKP/plugins/morgdkp/Morgaction.php New file
0,0 → 1,247
<?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>&nbsp;&nbsp;<?php echo $RAID[$i]['eqdkp']?><br><br>
<b>Zone</b>&nbsp;&nbsp;&nbsp;&nbsp;<input name="raidfield[<?php echo $i?>][zone]" value="<?php echo $RAID[$i]['zone']?>">&nbsp;&nbsp;&nbsp;&nbsp;Use 0-sum DKP&nbsp;&nbsp;<input type="checkbox" name="raidfield[<?php echo $i?>][zsum]"><br><br>
<?php $event = 0;
while ($RAID[$i]['events'][$event]): ?>
<b>Event</b>&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;&nbsp;<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>&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;<?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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<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]): ?>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<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>
\ No newline at end of file
trunk/MorgDKP/plugins/morgdkp/DKPInfo.lua New file
0,0 → 1,213
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}
},
}
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/plugins/morgdkp/Morgexport.php New file
0,0 → 1,208
<?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?>">&nbsp;&nbsp;&nbsp;In Game Database Name =&nbsp;<input name="DBName[1]" value="<?php echo $DBNamecook1?>"><br>
2. <input name="eqDKP[2]" value="<?php echo $DKPcook2?>">&nbsp;&nbsp;&nbsp;In Game Database Name =&nbsp;<input name="DBName[2]" value="<?php echo $DBNamecook2?>"><br>
3. <input name="eqDKP[3]" value="<?php echo $DKPcook3?>">&nbsp;&nbsp;&nbsp;In Game Database Name =&nbsp;<input name="DBName[3]" value="<?php echo $DBNamecook3?>"><br>
4. <input name="eqDKP[4]" value="<?php echo $DKPcook4?>">&nbsp;&nbsp;&nbsp;In Game Database Name =&nbsp;<input name="DBName[4]" value="<?php echo $DBNamecook4?>"><br>
5. <input name="eqDKP[5]" value="<?php echo $DKPcook5?>">&nbsp;&nbsp;&nbsp;In Game Database Name =&nbsp;<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>
\ No newline at end of file
trunk/MorgDKP/plugins/morgdkp/Morgresults.php New file
0,0 → 1,316
<?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>
\ No newline at end of file
trunk/MorgDKP/plugins/morgdkp/morgdkp_plugin_class.php New file
0,0 → 1,46
<?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;
}
}
?>
trunk/MorgDKP/plugins/morgdkp/language/english/lang_main.php New file
0,0 → 1,7
<?php
 
$lang['morgexport'] = "Export Standings";
$lang['morgimport'] = "Import Raids";
$lang['morgdkp_adminmenu_title'] = "MorgDKP";
 
?>
trunk/MorgDKP/plugins/morgdkp/language/german/lang_main.php New file
0,0 → 1,7
<?php
 
$lang['morgexport'] = "Export Standings";
$lang['morgimport'] = "Import Raids";
$lang['morgdkp_adminmenu_title'] = "MorgDKP";
 
?>
trunk/MorgDKP/MorgDKP.txt New file
0,0 → 1,73
{\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
}
 
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:eol-style + native
trunk/MorgDKP/MorgDKP-deDE.lua New file
0,0 → 1,295
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)
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
trunk/MorgDKP/ImportItemData/ItemData.lua New file
0,0 → 1,5185
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"] = {
},
},
}
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/MorgDKP.lua New file
0,0 → 1,959
-- ******************************************************************
-- ******************************************************************
-- ** 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
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
trunk/MorgDKP/MorgDKP.toc New file
0,0 → 1,45
## 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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/RaidFunctions.lua New file
0,0 → 1,1189
-- ******************************************************************
-- ******************************************************************
-- ** 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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/Tablet-2.0/Tablet-2.0.lua New file
0,0 → 1,2959
--[[
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)
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
trunk/MorgDKP/libs/AceConsole-2.0/AceConsole-2.0.lua New file
0,0 → 1,2675
--[[
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)
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/AceConsole-2.0/AceConsole-2.0.toc New file
0,0 → 1,12
## 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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/Babble-Class-2.2/Babble-Class-2.2.lua New file
0,0 → 1,219
--[[
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
\ No newline at end of file Property changes : Added: svn:keywords + Revision Date Added: svn:eol-style + native Added: svn:mime-type + text/plain
trunk/MorgDKP/libs/Babble-Class-2.2/Babble-Class-2.2.toc New file
0,0 → 1,16
## 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
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
trunk/MorgDKP/libs/FuBarPlugin-2.0/FuBarPlugin-2.0.lua New file
0,0 → 1,1826
--[[
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)
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/Roster-2.1/Roster-2.1.lua New file
0,0 → 1,474
--[[
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)
 
Property changes : Added: svn:keywords + Revision Date Added: svn:eol-style + native Added: svn:mime-type + text/plain
trunk/MorgDKP/libs/AceLibrary/AceLibrary.lua New file
0,0 → 1,799
--[[
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)
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/AceLibrary/AceLibrary.toc New file
0,0 → 1,10
## 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
Property changes : Added: svn:keywords + Revision Date Added: svn:eol-style + native Added: svn:mime-type + text/plain
trunk/MorgDKP/libs/AceOO-2.0/AceOO-2.0.lua New file
0,0 → 1,980
--[[
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)
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
trunk/MorgDKP/libs/AceOO-2.0/AceOO-2.0.toc New file
0,0 → 1,12
## 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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/AceEvent-2.0/AceEvent-2.0.lua New file
0,0 → 1,998
--[[
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)
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/AceEvent-2.0/AceEvent-2.0.toc New file
0,0 → 1,12
## 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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
trunk/MorgDKP/libs/AceAddon-2.0/AceAddon-2.0.lua New file
0,0 → 1,1393
--[[
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)
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/AceAddon-2.0/AceAddon-2.0.toc New file
0,0 → 1,12
## 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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
trunk/MorgDKP/libs/AceDB-2.0/AceDB-2.0.lua New file
0,0 → 1,2191
--[[
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)
Property changes : Added: svn:keywords + Revision Date Added: svn:eol-style + native Added: svn:mime-type + text/plain
trunk/MorgDKP/libs/AceDB-2.0/AceDB-2.0.toc New file
0,0 → 1,12
## 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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/AceDebug-2.0/AceDebug-2.0.lua New file
0,0 → 1,219
--[[
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)
 
Property changes : Added: svn:keywords + Revision Date Added: svn:eol-style + native Added: svn:mime-type + text/plain
trunk/MorgDKP/libs/AceDebug-2.0/AceDebug-2.0.toc New file
0,0 → 1,12
## 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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/LibBabble-Boss-3.0/LibBabble-Boss-3.0.lua New file
0,0 → 1,4839
--[[
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
trunk/MorgDKP/libs/LibBabble-Boss-3.0/LibBabble-Boss-3.0.toc New file
0,0 → 1,17
## 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
 
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/LibBabble-Boss-3.0/LibStub/LibStub.lua New file
0,0 → 1,30
-- 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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/LibBabble-Boss-3.0/lib.xml New file
0,0 → 1,4
<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>
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/xml
trunk/MorgDKP/libs/AceComm-2.0/AceComm-2.0.toc New file
0,0 → 1,12
## 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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/AceComm-2.0/AceComm-2.0.lua New file
0,0 → 1,2768
--[[
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
]]
 
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/Dewdrop-2.0/Dewdrop-2.0.lua New file
0,0 → 1,3487
--[[
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)
Property changes : Added: svn:keywords + Revision Date Added: svn:eol-style + native Added: svn:mime-type + text/plain
trunk/MorgDKP/libs/LibBabble-Zone-3.0/LibStub/LibStub.lua New file
0,0 → 1,30
-- 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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
trunk/MorgDKP/libs/LibBabble-Zone-3.0/LibBabble-Zone-3.0.lua New file
0,0 → 1,1888
--[[
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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/LibBabble-Zone-3.0/lib.xml New file
0,0 → 1,4
<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>
\ No newline at end of file Property changes : Added: svn:mime-type + text/xml Added: svn:eol-style + native
trunk/MorgDKP/libs/LibBabble-Zone-3.0/LibBabble-Zone-3.0.toc New file
0,0 → 1,14
## 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
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/AceHook-2.1/AceHook-2.1.toc New file
0,0 → 1,12
## 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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/AceHook-2.1/AceHook-2.1.lua New file
0,0 → 1,554
--[[
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)
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/AceLocale-2.2/AceLocale-2.2.toc New file
0,0 → 1,13
## 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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/libs/AceLocale-2.2/AceLocale-2.2.lua New file
0,0 → 1,669
--[[
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
]]
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/LootTablet.lua New file
0,0 → 1,328
-- ******************************************************************
-- ******************************************************************
-- ** 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
 
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
trunk/MorgDKP/Morgdkp Instructions.url New file
0,0 → 1,2
[InternetShortcut]
URL=http://www3.telus.net/MorgDKP/
trunk/MorgDKP/MorgDKP-enUS.lua New file
0,0 → 1,287
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)
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/Points.lua New file
0,0 → 1,363
-- ******************************************************************
-- ******************************************************************
-- ** 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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/MorgDKPOptions.lua New file
0,0 → 1,1130
-- ******************************************************************
-- ******************************************************************
-- ** 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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/MorgDKP.xml New file
0,0 → 1,3204
<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>
Property changes : Added: svn:mime-type + text/xml Added: svn:eol-style + native
trunk/MorgDKP/Hooks.lua New file
0,0 → 1,154
-- ******************************************************************
-- ******************************************************************
-- ** 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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
trunk/MorgDKP/BidQuery.lua New file
0,0 → 1,796
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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
trunk/MorgDKP/DKPtracker.lua New file
0,0 → 1,536
-- ******************************************************************
-- ******************************************************************
-- ** 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
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
trunk/MorgDKP/icons/AquaOFF.tga Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes : Added: svn:mime-type + application/octet-stream
trunk/MorgDKP/icons/AquaON.tga Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes : Added: svn:mime-type + application/octet-stream
trunk/MorgDKP/MorgDKPFu.lua New file
0,0 → 1,386
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date