3 define('ACHIEVEMENT_FLAG_COUNTER', 0x0001); // Just count statistic (nether stop and complete)
4 define('ACHIEVEMENT_FLAG_UNK2', 0x0002); // no used possibly min criteria value
5 define('ACHIEVEMENT_FLAG_MAX_VALUE', 0x0004); // Show max criteria value (only value)
6 define('ACHIEVEMENT_FLAG_SUMM', 0x0008); // Show summ criteria value from all reqirements
7 define('ACHIEVEMENT_FLAG_MAX_USED', 0x0010); // Show max criteria
8 define('ACHIEVEMENT_FLAG_REQ_COUNT', 0x0020); // Show not zero req count
9 define('ACHIEVEMENT_FLAG_AVERANGE', 0x0040); // Show as averange value (value / time_in_days) depend from other flag
10 define('ACHIEVEMENT_FLAG_BAR', 0x0080); // Show as progress bar (value / max vale) depend from other flag
11 define('ACHIEVEMENT_FLAG_REALM_FIRST_REACH', 0x0100); //
12 define('ACHIEVEMENT_FLAG_REALM_FIRST_KILL', 0x0200); //
14 define('CUSTOM_ACHIEVEMENT_SHOW', ACHIEVEMENT_FLAG_SUMM|ACHIEVEMENT_FLAG_MAX_USED|ACHIEVEMENT_FLAG_REQ_COUNT
);
16 define('ACHIEVEMENT_CRITERIA_FLAG_SHOW_PROGRESS_BAR', 0x00000001); // Show progress as bar
17 define('ACHIEVEMENT_CRITERIA_FLAG_HIDE_CRITERIA', 0x00000002); // Not show criteria in client
18 define('ACHIEVEMENT_CRITERIA_FLAG_UNK3', 0x00000004); // BG related??
19 define('ACHIEVEMENT_CRITERIA_FLAG_UNK4', 0x00000008); //
20 define('ACHIEVEMENT_CRITERIA_FLAG_UNK5', 0x00000010); // not used
21 define('ACHIEVEMENT_CRITERIA_FLAG_MONEY_COUNTER', 0x00000020); // Displays counter as money
23 $player_total_time_in_days = 0;
25 function getFormattedDate($timestamp)
27 return date("Y-m-d H:i:s", $timestamp);
30 function getFormattedDateSmall($timestamp)
32 return date("Y-m-d", $timestamp);
37 if (($a['date']) ||
$b['date'])
38 return $a['date'] > $b['date'] ?
-1 : 1;
39 return ($a['OrderInCategory'] < $b['OrderInCategory']) ?
-1 : 1;
42 function uploadAchievementData($cat, $faction, $guid, &$achievements)
46 // Upload achievement by category
47 $achievements = $wDB->select(
63 FROM `wowd_achievement`
65 categoryId = ?d AND (factionFlag = ?d OR factionFlag = '-1')
66 ORDER BY OrderInCategory", $cat, $faction);
67 // Prepare achievement list for load its criteria
68 $key = array_keys($achievements);
69 foreach ($achievements as $id=>$a)
70 if ($a['refAchievement'] && !@$achievements[$a['refAchievement']])
71 $key[] = $a['refAchievement'];
73 // Upload criteria list
74 $criteria = $wDB->select(
76 `referredAchievement` AS ARRAY_KEY_1,
91 FROM `wowd_achievement_criteria`
93 `referredAchievement` IN (?a)
94 ORDER BY `order`", $key);
95 // Upload player progress
98 $completed = $cDB->selectCol("SELECT `achievement` AS ARRAY_KEY, `date` FROM `character_achievement` WHERE `guid` = ?d", $guid);
99 $progress = $cDB->select("SELECT `criteria` AS ARRAY_KEY, `counter`, `date` FROM `character_achievement_progress` WHERE `guid` = ?d", $guid);
101 foreach ($achievements as $id=>$ach)
103 $a =& $achievements[$id];
104 $req_id = $a['refAchievement'] ?
$a['refAchievement'] : $id;
105 $a['requirement'] = @$criteria[$req_id]; // Use loaded criteria
106 $a['date'] =@$completed[$id]; // Set completed time
107 if ($a['requirement'])
108 foreach ($a['requirement'] as $i=>$req) // Get achievement progress
110 $r=&$a['requirement'][$i];
111 $r['counter'] = @$progress[$r['id']]['counter'];
112 $r['date'] = @$progress[$r['id']]['date'];
117 // Merge completed achievements tree in last one
118 foreach ($achievements as $id=>$ach)
120 $a =& $achievements[$id];
121 if ($parent = $a['parentAchievement'])
123 $p =& $achievements[$parent];
126 // Disable parent output
127 $p['parentAchievement'] = 1;
128 $a['points']+
=$p['points'];
129 // add parent req to child
130 $a['requirement'] = array_merge($p['requirement'], $a['requirement']);
131 foreach ($a['requirement'] as $i=>$r)
132 $a['requirement'][$i]['completionFlag']=0;
135 $a['parentAchievement'] = 0;
139 usort($achievements, 'cmp');
142 function getAchievementValue($a, &$value, &$maxvalue)
144 $value = 0; $maxvalue = 0;
145 if (!isset($a['requirement']))
147 if ($a['flags']&ACHIEVEMENT_FLAG_SUMM
)
149 // Need calculate summ completed and use (averange? all max equal) max value
150 foreach($a['requirement'] as $r){$value+
=$r['counter'];$maxvalue=$r['value'];}
152 else if ($a['flags']&ACHIEVEMENT_FLAG_MAX_USED
)
154 $max = 0; $text = '--';
155 // Need select max value (and also show name)
156 foreach($a['requirement'] as $r)
157 if ($max<=$r['counter'])
159 if ($max = $r['counter'])
160 $text = $r['name'].' ('.$r['counter'].')';
161 $value = $r['counter'];
162 $maxvalue=$r['value'];
166 else if ($a['flags']&ACHIEVEMENT_FLAG_REQ_COUNT
)
168 foreach($a['requirement'] as $r) {$maxvalue++
;if ($r['counter']) $value++
;}
169 // Use count as max value
171 $maxvalue = $a['count'];
173 else if ($a['flags']&ACHIEVEMENT_FLAG_COUNTER
) // Only counters
175 // Need calculate summ completed
176 foreach($a['requirement'] as $r)
177 $value+
=$r['counter'];
179 if ($a['requirement'][0]['completionFlag']&ACHIEVEMENT_CRITERIA_FLAG_MONEY_COUNTER
)
180 return money($value, 8);
184 function getAchievementFaction($guid, $faction)
186 if ($guid && $player = getCharacter($guid, 'race'))
187 return getPlayerFaction($player['race'])==0?
1:0;
191 //=======================================================
192 //=======================================================
193 function renderProgress($value, $total, $money=0)
195 $value=intval($value);
196 $pct = ($value/$total*100);
197 if ($pct>100) $pct=100;
199 $txt = $pct>=100?
money($total, 6):money($value, 6);
201 $txt = $pct>=100?
$total:$value.' / '.$total;
202 return '<div class=ach_bar><div class=bar style="width: '.$pct.'%;"></div><div class=pr>'.$txt.'</div></div>';
205 function renderAchievement($id, &$a, $guid)
207 // Skip show if not completed parent present or no_points not completed
208 if ($a['parentAchievement'] ||
(!$a['date'] && !$a['points'] && $guid))
210 echo '<div class="ach_show'.($a['date'] ?
'':' locked').'" onclick="showAchReq(this);">';
212 echo '<img class=ach_icon src="'.getSpellIcon($a['iconId']).'">';
213 echo '<div class=ach_frame></div>';
216 echo '<div class=ach_point>'.$a['points'].'</div>';
217 echo '<div class=ach_title>'.$a['name'].'</div>';
218 echo '<div class=ach_desc>'.$a['description'].'</div>';
219 // echo '<div class=ach_desc>Flags - 0x'.dechex($a['flags']).' - '.$a['count'].'</div>';
220 // Render requirements
221 echo '<div class=ach_req id='.$id.'>';
222 if ($a['flags']&CUSTOM_ACHIEVEMENT_SHOW
)
224 getAchievementValue(&$a, &$value, &$maxvalue);
225 if ($a['flags']&ACHIEVEMENT_FLAG_BAR
)
226 echo '<div class="sub bar">'.renderProgress($value, $maxvalue).'</div>';
227 else if ($a['flags']&ACHIEVEMENT_FLAG_MAX_USED
)
228 echo '<div class="sub bar">'.renderProgress($value, $maxvalue).'</div>';
230 echo '<div class="sub '.($value>=$maxvalue ?
'compl' : '').'">'.$value.'</div>';
232 foreach($a['requirement'] as $r)
234 if ($r['completionFlag']&ACHIEVEMENT_CRITERIA_FLAG_HIDE_CRITERIA
)
236 if ($r['completionFlag']&ACHIEVEMENT_CRITERIA_FLAG_SHOW_PROGRESS_BAR
)
237 echo '<div class=sub_bar>'.renderProgress(@$r['counter'], $r['value'], $r['completionFlag']&ACHIEVEMENT_CRITERIA_FLAG_MONEY_COUNTER
).'</div>';
240 $text=$r['name']?
$r['name'] : $a['name'];
241 $completed = $r['counter'] ?
($r['counter'] >=$r['value'] ?
'compl' : '') : '';
242 // $text.="-> $r[id] - f=$r[completionFlag], c=$r[counter], d=$r[data], v=$r[value]";
243 echo '<div class="sub '.$completed.'">'.$text.'</div>';
246 echo '<br clear="all"/></div>'."\n";
249 echo '<div class=ach_date>'.getFormattedDate($a['date']).'</div>';
250 if ($a['titleReward'])
251 echo '<div class=ach_reward>'.$a['titleReward'].'</div>';
255 function getComplCount($progress, $cat, $faction, &$count)
258 $ach = $wDB->select("SELECT `id`, `points` FROM `wowd_achievement` WHERE `categoryId` = ?d AND (factionFlag = ?d OR factionFlag = '-1')", $cat, $faction);
262 $count[0]++
; $count[2]+
=$a['points'];
263 if (@$progress[$a['id']]) {$count[1]++
; $count[3]+
=$a['points'];}
267 // Player Achievement
268 function renderPlayerAchievementStats($category, $faction, $guid)
272 global $cDB, $wDB, $config, $lang;
273 echo '<div class=ach_s_list>';
274 $completed = $cDB->selectCol(
276 `achievement` AS ARRAY_KEY,
278 FROM `character_achievement` WHERE `guid` = ?d ORDER BY `date` DESC", $guid);
279 $total = array(0,0,0,0);
280 // Get base achievement category list (exclude statistic category = 1)
281 $baseCat = $wDB->select("SELECT `id`, `name` FROM `wowd_achievement_category` WHERE `parent` = '-1' AND `id` NOT IN (1) ORDER BY `sortOrder`");
282 foreach ($baseCat as $id=>$cat)
284 $count = array(0,0,0,0);
285 getComplCount($completed, $cat['id'], $faction, &$count);
286 $subCat = $wDB->select("SELECT `id`, `name` FROM `wowd_achievement_category` WHERE `parent` = ?d", $cat['id']);
287 foreach ($subCat as $sub)
288 getComplCount($completed, $sub['id'], $faction, &$count);
289 $baseCat[$id]['count'] = $count;
291 foreach($total as $i=>$t)
292 $total[$i] +
= $count[$i];
295 echo '<div class=ach_bar><div class=bar style="width: '.($total[1]/$total[0]*100).'%;"></div><div class=pr>'.$lang['achievment_complete'].' '.$total[1].' / '.$total[0].'</div></div>';
298 foreach ($baseCat as $cat)
302 $progress = $cat['count'][1]/$cat['count'][0]*100;
303 $count_txt = $cat['count'][1].' / '.$cat['count'][0];
308 $count_txt = $cat['count'][1];
310 echo '<div class=ach_progress>';
311 echo ' '.$cat['name'].':';
312 echo '<div class=ach_bar><div class=bar style="width: '.$progress.'%;"></div><div class=pr>'.$count_txt.'</div></div>';
315 echo '<br clear="all"/><br>';
317 echo '<b>'.$lang['achievment_last'].'</b>';
318 $count = $config['achievement_last'];
319 foreach ($completed as $id=>$c)
321 $a = $wDB->selectRow("SELECT * FROM `wowd_achievement` WHERE `id` = ?d", $id);
322 echo '<div class=a_last_c>';
323 echo '<div class=a_last_cdate>';
325 echo $a['points'].' <img src=images/achievement/points_sm.gif> ';
326 echo getFormattedDateSmall($c).'</div>';
327 echo '<b>'.$a['name'].'</b> - '.$a['description'];
335 function renderAchievementCategoryList($cat, $faction, $guid)
337 // Out player data for 0 categiry
340 renderPlayerAchievementStats($cat, $faction, $guid);
343 uploadAchievementData($cat, $faction, $guid, $achievements);
345 foreach ($achievements as $id=>$arc)
346 if ($arc['flags']&ACHIEVEMENT_FLAG_COUNTER
)
353 $total = 0; $compl = 0;
354 foreach ($achievements as $id=>$a)
355 if (!$a['parentAchievement'] && $a['points']) {$total++
;if (@$a['date']) $compl++
;}
357 echo '<div class=ach_s_list><div class=ach_bar><div class=bar style="width: '.($compl/$total*100).'%;"></div><div class=pr>'.$compl.' / '.$total.'</div></div></div>';
359 foreach ($achievements as $id=>$arc)
360 renderAchievement($id, &$achievements[$id], $guid);
365 $name = $wDB->selectCell("SELECT `name` FROM `wowd_achievement_category` WHERE `id` = ?d", $cat);
366 echo '<div class="ach_stats_name">'.$name.'</div>';
368 foreach ($achievements as $id=>$a)
370 echo '<div class="ach_stats'.($i&1 ?
' second' : '').'">';
371 // Render requirements
372 echo '<div class=ach_value>'.getAchievementValue($a, &$value, &$maxvalue).'</div>';
375 echo ' ('.$id.') - 0x'.dechex($a['flags']);
376 foreach($a['requirement'] as $r)
378 $text=$r['name']? $r['name'] : $a['name'];
379 $completed = @$r['counter'] ? @$r['counter'] : 0;
380 echo '<div class=a_stat_value>'.$completed.'</div>';
381 $text="->($r[id]) $text - f=$r[completionFlag], c=$r[requiredType]";
387 $subcat = $wDB->select("SELECT * FROM `wowd_achievement_category` WHERE `parent` = ?d ORDER BY `sortOrder`", $cat);
389 foreach($subcat as $c)
390 renderAchievementCategoryList($c['id'], $faction, $guid);
394 // Render achievement table (other data uploads by Ajax)
395 function renderAchievementData($category, $guid, $faction)
398 $baseptr = "?achievement";
400 $baseptr.= "&guid=".$guid;
402 $baseptr.= "&faction=".$faction;
404 echo '<br><script type="text/javascript" src="js/achievement.js"></script>';
405 echo '<table class=achievement cellSpacing=0 cellPadding=0><tbody>';
406 echo '<tr><td class="a_cat" id="a_category">';
408 // Output player achievement statistic
409 echo '<div class=a_topcat></div>';
410 $category_list = $wDB->select(
413 `parent` AS PARENT_KEY,
417 `wowd_achievement_category`
418 ORDER BY `sortOrder`");
419 // Show 1 category if no exist
420 if ($category==0 && !$guid)
422 reset($category_list);
423 $category = key($category_list);
426 echo '<div class=a_bodycat'.($category==0?
'_sel':'').'><a id=ach_0 href='.$baseptr.' onclick=\'return selectCat(0);\'>'.$lang['achievment_total'].'</a></div>';
427 foreach ($category_list as $id=>$cat)
432 if ($id == $category) $sel_cat = '_sel';
433 else foreach ($cat['childNodes'] as $i=>$sub) if ($i==$category) $sel_cat = '_sel';
434 echo '<div class=a_bodycat'.$sel_cat.'>';
435 echo "<a id='ach_".$id."' href=".$baseptr."&category=".$id." onclick='return selectCat(".$id.");'>".$cat['name']."</a>";
436 foreach ($cat['childNodes'] as $i=>$sub)
437 echo "<a id='ach_".$i."' class=".($i==$category?
"sel":"sub")." href=".$baseptr."&category=".$i." onclick='return selectCat(".$i.");'>".$sub['name']."</a>";
440 foreach ($category_list['1']['childNodes'] as $id=>$cat)
443 if ($id == $category) $sel_cat = '_sel';
444 else foreach ($cat['childNodes'] as $i=>$sub) if ($i==$category) $sel_cat = '_sel';
445 echo '<div class=a_bodycat'.$sel_cat.'>';
446 echo "<a id='ach_".$id."' href=".$baseptr."&category=".$id." onclick='return selectCat(".$id.");'>".$cat['name']."</a>";
447 foreach ($cat['childNodes'] as $i=>$sub)
448 echo "<a id='ach_".$i."' class=".($i==$category?
"sel":"sub")." href=".$baseptr."&category=".$i." onclick='return selectCat(".$i.");'>".$sub['name']."</a>";
452 echo '<div class=a_bottomcat></div>';
454 echo '<td class="a_data">';
455 echo '<div class="a_topdata"></div>';
456 echo '<div class="a_bdydata" id="a_data">';
457 renderAchievementCategoryList($category, $faction, $guid);
459 echo '<div class="a_btmdata"></div>';
462 echo '</tbody></table>';
463 echo '<script type="text/javascript">
464 ChangeCssProperty(".ach_show .ach_req", "display", "none");
465 ChangeCssProperty("div.a_bodycat a.sub", "display", "none");
466 cacheCat("'.$baseptr."&category=".$category.'");