Требование: PHP => 5.3, часть 2
[cswow.git] / include / achievements.php
blobefd59e5af7328addbe97f9ae81a935d71e04a28e
1 <?php
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);
35 function cmp($a, $b)
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)
44 global $wDB, $cDB;
46 // Upload achievement by category
47 $achievements = $wDB->select(
48 "SELECT
49 `id` AS ARRAY_KEY,
50 `factionFlag`,
51 `mapID`,
52 `parentAchievement`,
53 `name`,
54 `description`,
55 `categoryId`,
56 `points`,
57 `OrderInCategory`,
58 `flags`,
59 `iconId`,
60 `titleReward`,
61 `count`,
62 `refAchievement`
63 FROM `wowd_achievement`
64 WHERE
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(
75 "SELECT
76 `referredAchievement` AS ARRAY_KEY_1,
77 NULL AS ARRAY_KEY_2,
78 `id`,
79 `requiredType`,
80 `data`,
81 `value`,
82 `additional_type_1`,
83 `additional_value_1`,
84 `additional_type_2`,
85 `additional_value_2`,
86 `name`,
87 `completionFlag`,
88 `groupFlag`,
89 `unk1`,
90 `timeLimit`
91 FROM `wowd_achievement_criteria`
92 WHERE
93 `referredAchievement` IN (?a)
94 ORDER BY `order`", $key);
95 // Upload player progress
96 if ($guid)
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'];
115 if(!$guid)
116 return;
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];
124 if ($a['date'])
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;
134 if ($p['date'])
135 $a['parentAchievement'] = 0;
138 // Sort it
139 usort($achievements, 'cmp');
142 function getAchievementValue($a, &$value, &$maxvalue)
144 $value = 0; $maxvalue = 0;
145 if (!isset($a['requirement']))
146 return 0;
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'];
164 return $text;
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
170 if ($a['count'])
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);
181 return $value;
184 function getAchievementFaction($guid, $faction)
186 if ($guid && $player = getCharacter($guid, 'race'))
187 return getPlayerFaction($player['race'])==0?1:0;
188 return $faction;
191 //=======================================================
192 //=======================================================
193 function renderProgress($value, $total, $money=0)
195 $value=intval($value);
196 $pct = ($value/$total*100);
197 if ($pct>100) $pct=100;
198 if ($money)
199 $txt = $pct>=100?money($total, 6):money($value, 6);
200 else
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))
209 return;
210 echo '<div class="ach_show'.($a['date'] ? '':' locked').'" onclick="showAchReq(this);">';
211 // Render icon
212 echo '<img class=ach_icon src="'.getSpellIcon($a['iconId']).'">';
213 echo '<div class=ach_frame></div>';
214 // Render points
215 if ($a['points'])
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>';
229 else
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)
235 continue;
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>';
238 else
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";
247 // render date
248 if ($a['date'])
249 echo '<div class=ach_date>'.getFormattedDate($a['date']).'</div>';
250 if ($a['titleReward'])
251 echo '<div class=ach_reward>'.$a['titleReward'].'</div>';
252 echo '</div>';
255 function getComplCount($progress, $cat, $faction, &$count)
257 global $wDB;
258 $ach = $wDB->select("SELECT `id`, `points` FROM `wowd_achievement` WHERE `categoryId` = ?d AND (factionFlag = ?d OR factionFlag = '-1')", $cat, $faction);
259 if ($ach)
260 foreach ($ach as $a)
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)
270 if (!$guid)
271 return;
272 global $cDB, $wDB, $config, $lang;
273 echo '<div class=ach_s_list>';
274 $completed = $cDB->selectCol(
275 "SELECT
276 `achievement` AS ARRAY_KEY,
277 `date`
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;
290 if ($count[2])
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>';
296 echo '<br>';
298 foreach ($baseCat as $cat)
300 if ($cat['id']!=81)
302 $progress = $cat['count'][1]/$cat['count'][0]*100;
303 $count_txt = $cat['count'][1].' / '.$cat['count'][0];
305 else
307 $progress = 0;
308 $count_txt = $cat['count'][1];
310 echo '<div class=ach_progress>';
311 echo '&nbsp;'.$cat['name'].':';
312 echo '<div class=ach_bar><div class=bar style="width: '.$progress.'%;"></div><div class=pr>'.$count_txt.'</div></div>';
313 echo '</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>';
324 if ($a['points'])
325 echo $a['points'].' <img src=images/achievement/points_sm.gif> ';
326 echo getFormattedDateSmall($c).'</div>';
327 echo '<b>'.$a['name'].'</b> - '.$a['description'];
328 echo '</div>';
329 if (!(--$count))
330 break;
332 echo '</div>';
335 function renderAchievementCategoryList($cat, $faction, $guid)
337 // Out player data for 0 categiry
338 if ($cat == 0)
340 renderPlayerAchievementStats($cat, $faction, $guid);
341 return;
343 uploadAchievementData($cat, $faction, $guid, $achievements);
344 $asstat = 1;
345 foreach ($achievements as $id=>$arc)
346 if ($arc['flags']&ACHIEVEMENT_FLAG_COUNTER)
347 $asstat = 0;
349 if ($asstat)
351 if ($guid)
353 $total = 0; $compl = 0;
354 foreach ($achievements as $id=>$a)
355 if (!$a['parentAchievement'] && $a['points']) {$total++;if (@$a['date']) $compl++;}
356 if ($total)
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);
362 else
364 global $wDB;
365 $name = $wDB->selectCell("SELECT `name` FROM `wowd_achievement_category` WHERE `id` = ?d", $cat);
366 echo '<div class="ach_stats_name">'.$name.'</div>';
367 $i=0;
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>';
373 echo $a['name'];
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]";
382 echo '<br>'.$text;
383 }/**/
384 echo '</div>';
385 $i++;
387 $subcat = $wDB->select("SELECT * FROM `wowd_achievement_category` WHERE `parent` = ?d ORDER BY `sortOrder`", $cat);
388 if ($subcat)
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)
397 global $wDB, $lang;
398 $baseptr = "?achievement";
399 if ($guid)
400 $baseptr.= "&guid=".$guid;
401 else
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(
411 "SELECT
412 `id` AS ARRAY_KEY,
413 `parent` AS PARENT_KEY,
414 `parent`,
415 `name`
416 FROM
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);
425 if ($guid)
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)
429 if ($id==1)
430 continue;
431 $sel_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>";
438 echo '</div>';
440 foreach ($category_list['1']['childNodes'] as $id=>$cat)
442 $sel_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>";
449 echo '</div>';
451 echo '</div>';
452 echo '<div class=a_bottomcat></div>';
453 echo '</td>';
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);
458 echo '</div>';
459 echo '<div class="a_btmdata"></div>';
460 echo '</td>';
461 echo '</tr>';
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.'");
467 </script>';