source: aowow/includes/game.php

Last change on this file was 170, checked in by maron, 15 years ago
  • Property svn:executable set to *
File size: 16.0 KB
Line 
1<?php
2
3require_once ('includes/allitems.php');
4require_once ('includes/alllocales.php');
5
6// Классы персонажей (битовые маски)
7define ("CLASS_WARRIOR", 1);
8define ("CLASS_PALADIN", 2);
9define ("CLASS_HUNTER", 4);
10define ("CLASS_ROGUE", 8);
11define ("CLASS_PRIEST", 16);
12define ("CLASS_SHAMAN", 64);
13define ("CLASS_MAGE", 128);
14define ("CLASS_WARLOCK", 256);
15define ("CLASS_DRUID", 1024);
16
17// Классы персонажей (архив)
18$classes = array(
19 1 => LOCALE_WARRIOR,
20 2 => LOCALE_PALADIN,
21 3 => LOCALE_HUNTER,
22 4 => LOCALE_ROGUE,
23 5 => LOCALE_PRIEST,
24 6 => LOCALE_DEATH_KNIGHT,
25 7 => LOCALE_SHAMAN,
26 8 => LOCALE_MAGE,
27 9 => LOCALE_WARLOCK,
28 11 => LOCALE_DRUID
29);
30
31define ("RACE_HUMAN", 1);
32define ("RACE_ORC", 2);
33define ("RACE_DWARF", 4);
34define ("RACE_NIGHTELF", 8);
35define ("RACE_UNDEAD", 16);
36define ("RACE_TAUREN", 32);
37define ("RACE_GNOME", 64);
38define ("RACE_TROLL", 128);
39define ("RACE_BLOODELF", 512);
40define ("RACE_DRAENEI", 1024);
41
42// Типы разделов
43global $types;
44$types = array(
45 1 => 'npc',
46 2 => 'object',
47 3 => 'item',
48 4 => 'itemset',
49 5 => 'quest',
50 6 => 'spell',
51 7 => 'zone',
52 8 => 'faction'
53);
54
55// Отношения со фракциями
56$reputations = array(
57 1 => LOCALE_NEUTRAL,
58 3000 => LOCALE_FRIENDLY,
59 9000 => LOCALE_HONORED,
60 21000 => LOCALE_REVERED,
61 42000 => LOCALE_EXALTED
62);
63
64function sec_to_time($secs)
65{
66 $time = array();
67 if ($secs>=3600)
68 {
69 $time['h'] = floor($secs/3600);
70 $secs = $secs - $time['h']*3600;
71 }
72 if ($secs>=60)
73 {
74 $time['m'] = floor($secs/60);
75 $secs = $secs - $time['m']*60;
76 }
77 if ($secs>0)
78 $time['s'] = $secs;
79 return $time;
80}
81
82function money2coins($money)
83{
84 $coins = array();
85 if ($money>=10000)
86 {
87 $coins['moneygold'] = floor($money/10000);
88 $money = $money - $coins['moneygold']*10000;
89 }
90 if ($money>=100)
91 {
92 $coins['moneysilver'] = floor($money/100);
93 $money = $money - $coins['moneysilver']*100;
94 }
95 if ($money>0)
96 $coins['moneycopper'] = $money;
97 return $coins;
98}
99
100// Классы, для которых предназначена вещь
101function classes($class)
102{
103 $tmp = '';
104 if ($class & CLASS_WARRIOR)
105 $tmp = LOCALE_WARRIOR;
106 if ($class & CLASS_PALADIN)
107 if ($tmp) $tmp = $tmp.', '.LOCALE_PALADIN; else $tmp = LOCALE_PALADIN;
108 if ($class & CLASS_HUNTER)
109 if ($tmp) $tmp = $tmp.', '.LOCALE_HUNTER; else $tmp = LOCALE_HUNTER;
110 if ($class & CLASS_ROGUE)
111 if ($tmp) $tmp = $tmp.', '.LOCALE_ROGUE; else $tmp = LOCALE_ROGUE;
112 if ($class & CLASS_PRIEST)
113 if ($tmp) $tmp = $tmp.', '.LOCALE_PRIEST; else $tmp = LOCALE_PRIEST;
114 if ($class & CLASS_SHAMAN)
115 if ($tmp) $tmp = $tmp.', '.LOCALE_SHAMAN; else $tmp = LOCALE_SHAMAN;
116 if ($class & CLASS_MAGE)
117 if ($tmp) $tmp = $tmp.', '.LOCALE_MAGE; else $tmp = LOCALE_MAGE;
118 if ($class & CLASS_WARLOCK)
119 if ($tmp) $tmp = $tmp.', '.LOCALE_WARLOCK; else $tmp = LOCALE_WARLOCK;
120 if ($class & CLASS_DRUID)
121 if ($tmp) $tmp = $tmp.', '.LOCALE_DRUID; else $tmp = LOCALE_DRUID;
122 if ($tmp == LOCALE_WARRIOR.', '.LOCALE_PALADIN.', '.LOCALE_HUNTER.', '.LOCALE_ROGUE
123 .', '.LOCALE_PRIEST.', '.LOCALE_SHAMAN.', '.LOCALE_MAGE.', '.LOCALE_WARLOCK.', '.LOCALE_DRUID)
124 return;
125 else
126 return $tmp;
127}
128
129function races($race)
130{
131 // Простые варианты:
132 if($race == RACE_HUMAN|RACE_ORC|RACE_DWARF|RACE_NIGHTELF|RACE_UNDEAD|RACE_TAUREN|RACE_GNOME|RACE_TROLL|RACE_BLOODELF|RACE_DRAENEI || $race == 0)
133 return array('side' => 3, 'name' => LOCALE_BOTH);
134 elseif($race == RACE_ORC|RACE_UNDEAD|RACE_TAUREN|RACE_TROLL|RACE_BLOODELF)
135 return array('side' => 2, 'name' => LOCALE_HORDE);
136 elseif($race == RACE_HUMAN|RACE_DWARF|RACE_NIGHTELF|RACE_GNOME|RACE_DRAENEI)
137 return array('side' => 1, 'name' => LOCALE_ALLIANCE);
138 else
139 {
140 $races = array('name' => '', 'side' => 0);
141 if ($race & RACE_HUMAN)
142 {
143 (($races['side']==2) or ($races['side']==3))? $races['side']=3 : $races['side']=1;
144 if ($races['name']) $races['name'] .= ', '; $races['name'] .= LOCALE_HUMAN;
145 }
146 if ($race & RACE_ORC)
147 {
148 (($races['side']==1) or ($races['side']==3))? $races['side']=3 : $races['side']=2;
149 if ($races['name']) $races['name'] .= ', '; $races['name'] .= LOCALE_ORC;
150 }
151 if ($race & RACE_DWARF)
152 {
153 (($races['side']==2) or ($races['side']==3))? $races['side']=3 : $races['side']=1;
154 if ($races['name']) $races['name'] .= ', '; $races['name'] .= LOCALE_DWARF;
155 }
156 if ($race & RACE_NIGHTELF)
157 {
158 (($races['side']==2) or ($races['side']==3))? $races['side']=3 : $races['side']=1;
159 if ($races['name']) $races['name'] .= ', '; $races['name'] .= LOCALE_NIGHT_ELF;
160 }
161 if ($race & RACE_UNDEAD)
162 {
163 (($races['side']==1) or ($races['side']==3))? $races['side']=3 : $races['side']=2;
164 if ($races['name']) $races['name'] .= ', '; $races['name'] .= LOCALE_UNDEAD;
165 }
166 if ($race & RACE_TAUREN)
167 {
168 (($races['side']==1) or ($races['side']==3))? $races['side']=3 : $races['side']=2;
169 if ($races['name']) $races['name'] .= ', '; $races['name'] .= LOCALE_TAUREN;
170 }
171 if ($race & RACE_GNOME)
172 {
173 (($races['side']==2) or ($races['side']==3))? $races['side']=3 : $races['side']=1;
174 if ($races['name']) $races['name'] .= ', '; $races['name'] .= LOCALE_GNOME;
175 }
176 if ($race & RACE_TROLL)
177 {
178 (($races['side']==1) or ($races['side']==3))? $races['side']=3 : $races['side']=2;
179 if ($races['name']) $races['name'] .= ', '; $races['name'] .= LOCALE_TROLL;
180 }
181 if ($race & RACE_BLOODELF)
182 {
183 (($races['side']==1) or ($races['side']==3))? $races['side']=3 : $races['side']=2;
184 if ($races['name']) $races['name'] .= ', '; $races['name'] .= LOCALE_BLOOD_ELF;
185 }
186 if ($race & RACE_DRAENEI)
187 {
188 (($races['side']==2) or ($races['side']==3))? $races['side']=3 : $races['side']=1;
189 if ($races['name']) $races['name'] .= ', '; $races['name'] .= LOCALE_DRAENEI;
190 }
191 return $races;
192 }
193}
194
195function sum_subarrays_by_key( $tab, $key ) {
196 $sum = 0;
197 foreach($tab as $sub_array) {
198 $sum += $sub_array[$key];
199 }
200 return $sum;
201}
202
203function coord_mangos2wow($mapid, $x, $y, $global)
204{
205 // Карты
206 global $map_images;
207 // Подключение к базе
208 global $DB;
209
210 $rows = $DB->select("SELECT * FROM ?_zones WHERE (mapID=? and x_min<? and x_max>? and y_min<? and y_max>?)", $mapid, $x, $x, $y, $y);
211
212 foreach ($rows as $numRow=>$row) {
213 // Сохраяняем имя карты и координаты
214 $wow['zone'] = $row['areatableID'];
215 $wow['name'] = $row['name'];
216
217 // Т.к. в игре координаты начинают отсчёт с левого верхнего угла
218 // а в системе координат сервера с правого нижнего,
219 // делаем соответствующее преобразование.
220 $tx = 100 - ($y - $row["y_min"]) / (($row["y_max"] - $row["y_min"]) / 100);
221 $ty = 100 - ($x - $row["x_min"]) / (($row["x_max"] - $row["x_min"]) / 100);
222
223 // А если ещё и с цветом совпала - нах цикл, это всё наше :) Оо
224 // Если ещё не загружена - загружаем.
225 if (!isset($map_images[$wow['zone']])) {
226 $mapname = str_replace("\\", "/", getcwd()).'/images/tmp/'.$row['areatableID'].'.png';
227 if (file_exists($mapname)) {
228 $map_images[$wow['zone']] = @ImageCreateFromPNG($mapname);
229 } else {
230 echo "<font color=red>....Map $mapname not found (ID=".$wow['zone'].")</font><br>";
231 }
232 }
233
234 // Если так и не загрузилась... Возможно такой карты ещё просто нету :)
235 if ($map_images[$wow['zone']]) {
236 if (@ImageColorAt($map_images[$wow['zone']], round($tx * 10), round($ty * 10)) === 0) {
237 break;
238 }
239 }
240 }
241
242 if (count($rows)==0)
243 {
244 // Ничего не найдено. Мб инста??
245
246 $row = $DB->selectRow("SELECT * FROM ?_zones WHERE (mapID=? and x_min=0 and x_max=0 and y_min=0 and y_max=0)", $mapid);
247 if ($row) {
248 $wow['zone'] = $row['areatableID'];
249 $wow['name'] = $row['name'];
250 } else {
251 echo "<font color=red>....Location for Map with ID=$mapid not found</font><br>";
252 return;
253 }
254 }
255
256 // округляем до 2 цифер после запятой
257 // почему до 2?
258 if (isset($tx, $ty)) {
259 $wow["x"] = /*round(*/$tx;//, 2);
260 $wow["y"] = /*round(*/$ty;//, 2);
261 }
262
263 return $wow;
264}
265
266// Преобразование целого массива координат
267// Всегда пользовацца только им!
268function mass_coord(&$data)
269{
270 // Карты
271 global $map_images;
272 // Объявляем новый массив с преобразованными данными
273 $xdata = array();
274 // Перебираем по порядку все координаты, посланные функции
275 // Если таких же координат (уже преобразованных) ещё нет, добавляем в новый массив
276 foreach ($data as $ndata) {
277 // Если помимо координат есть ещё данные о респауне, преобразуем их к удобочитаемому виду:
278 if (isset($ndata['spawntimesecs']))
279 $tmp = array_merge(coord_mangos2wow($ndata['m'], $ndata['x'], $ndata['y'], false), array('r' => sec_to_time($ndata['spawntimesecs'])));
280 else
281 $tmp = coord_mangos2wow($ndata['m'], $ndata['x'], $ndata['y'], false);
282 $xdata[] = $tmp;
283 }
284 // Освобождаем всю память выделенную под карты
285 if ($map_images)
286 foreach ($map_images as $map_image)
287 imagedestroy($map_image);
288
289 // Возвращаем новый массив
290 return $xdata;
291}
292
293// Функция информации о фракции
294function factioninfo($id)
295{
296 global $DB;
297 $row = $DB->selectRow("SELECT name FROM ?_factions WHERE factionID = ?d LIMIT 1", $id);
298 $faction['name'] = $row['name'];
299 $faction['entry'] = $id;
300 return $faction;
301}
302
303// Function, that creates loot_table (without references) from lootid
304// $table - table, in which we search
305// $lootid - loot ident
306// $repetition_factor - repetition factor
307
308function loot_table($table, $lootid, $max_percent=100)
309{
310 // Все элементы
311 global $DB;
312 global $loot_groups;
313 global $item_cols;
314 $loot = array();
315 $groups = array();
316 // Мего запрос :)
317 $rows = $DB->select('
318 SELECT l.ChanceOrQuestChance, l.mincountOrRef, l.maxcount as `d-max`, l.groupid, ?#, i.entry, i.maxcount
319 {, loc.name_loc?d AS `name_loc`}
320 FROM ?# l
321 LEFT JOIN (?_icons a, item_template i) ON l.item=i.entry AND a.id=i.displayid
322 {LEFT JOIN (locales_item loc) ON loc.entry=i.entry AND ?d}
323 WHERE
324 l.entry=?d
325 {LIMIT ?d}
326 ',
327 $item_cols[2],
328 ($_SESSION['locale'])? $_SESSION['locale']: DBSIMPLE_SKIP,
329 $table,
330 ($_SESSION['locale'])? 1: DBSIMPLE_SKIP,
331 $lootid,
332 ($AoWoWconf['limit']!=0)? $AoWoWconf['limit']: DBSIMPLE_SKIP
333 );
334
335 // Перебираем
336 foreach ($rows as $i => $row)
337 {
338 if ($row['mincountOrRef']>0)
339 {
340 // Не ссылка!
341 if ($row['groupid']>0)
342 {
343 // Групповой лут!
344 $groups[$row['groupid']][] = array(
345 'mincount' => $row['mincountOrRef'],
346 'maxcount' => $row['d-max'],
347 'percent' => $row['ChanceOrQuestChance']*$max_percent/100,
348 'item' => iteminfo2($row,0)
349 );
350 // Общее число элементов группы с равнозначным шансом
351 if (!(IsSet($group_idx[$row['groupid']]['num-equal'])))
352 $group_idx[$row['groupid']]['num-equal'] = 0;
353 // Общий шанс дропа для группового лута
354 if (!(IsSet($group_idx[$row['groupid']]['percent'])))
355 $group_idx[$row['groupid']]['percent'] = 0;
356 // Если шанс дропа=0, значит это равнозначный лут в группе
357 // Иначе, увеличиваем зарезервированный шанс для элементов лута с четко определенным шансом дропа
358 if ($row['ChanceOrQuestChance']==0)
359 $group_idx[$row['groupid']]['num-equal'] ++;
360 else
361 $group_idx[$row['groupid']]['percent'] += abs($row['ChanceOrQuestChance']);
362 } else {
363 // Старый добрый обычный лут :)
364 $loot[] = array_merge(array(
365 'percent' => ($max_percent!=100)? $max_percent : $row['ChanceOrQuestChance'],
366 'mincount' => $row['mincountOrRef'],
367 'maxcount' => $row['d-max'],
368 'group' => 0
369 ), iteminfo2($row, 0));
370 }
371 } else {
372 // Ссылка!
373 // Вот если это ссылка, то ######
374 // Наша задача - вызвать эту же функцию, но с предопределенным значением percent и maxcount
375 for ($j=1;$j<=$row['d-max'];$j++)
376 $loot = array_merge($loot, loot_table($table, -$row['mincountOrRef'], $row['ChanceOrQuestChance']));
377 }
378 }
379 // Перебираем группы лута
380 foreach ($groups as $groupid => $group)
381 {
382 foreach($group as $field => $group_item)
383 {
384 if(isset($group_item['item']))
385 $loot[] = array_merge(array(
386 'mincount' => $group_item['mincount'],
387 'maxcount' => $group_item['maxcount'],
388 'percent' => ($group_item['percent']==0)? (($max_percent-$group_idx[$groupid]['percent'])/$group_idx[$groupid]['num-equal']) : $group_item['percent'],
389 'group' => $loot_groups,
390 'grouppercent' => ($group_idx[$groupid]['num-equal']>0)? $max_percent : $group_idx[$groupid]['percent']
391 ), $group_item['item']);
392 }
393 $loot_groups++;
394 }
395 return $loot;
396}
397
398function loot($table, $lootid)
399{
400 global $loot_groups;
401 $loot_groups=1;
402 $loot = loot_table($table, $lootid);
403 return $loot;
404}
405
406// Кто дропает
407function drop($table, $item)
408{
409 global $DB;
410 $rows = $DB->select('
411 SELECT l.ChanceOrQuestChance, l.mincountOrRef, l.maxcount, l.entry
412 FROM ?# l
413 WHERE
414 l.item=?
415 {LIMIT ?d}
416 ',
417 $table,
418 $item,
419 ($AoWoWconf['limit']!=0)? $AoWoWconf['limit']: DBSIMPLE_SKIP
420 );
421 $drop = array();
422 foreach ($rows as $i => $row)
423 {
424 if ($row['mincountOrRef'] > 0)
425 {
426 $num = $row['entry'];
427 $drop[$num] = array();
428 $drop[$num]['percent'] = abs($row['ChanceOrQuestChance']);
429 $drop[$num]['mincount'] = $row['mincountOrRef'];
430 $drop[$num]['maxcount'] = $row['maxcount'];
431
432 // Ищем лут, который ссылается на этот лут
433 $refrows = $DB->select('SELECT entry FROM ?# WHERE mincountOrRef=? LIMIT 200',$table, -$num);
434 foreach ($refrows as $i => $refrow)
435 {
436 $num = $refrow['entry'];
437 $drop[$num] = array();
438 $drop[$num]['percent'] = abs($row['ChanceOrQuestChance']);
439 $drop[$num]['mincount'] = $row['mincountOrRef'];
440 $drop[$num]['maxcount'] = $row['maxcount'];
441 }
442 }
443 }
444 return $drop;
445}
446
447// позиция
448function position($data)
449{
450 global $smarty, $exdata, $zonedata;
451 if(count($data) > 0)
452 {
453 $data = mass_coord($data);
454
455 // Сортируем массив. Зачем???
456 if($data)
457 sort($data);
458
459 // Во временную переменную tmp заносим номер локации
460 $j = 0;
461 $tmp = $data[$j]['zone'];
462 // Номер массива
463 $n = 0;
464 $k = 0;
465 $zonedata[$n] = array();
466 $zonedata[$n]['zone'] = $data[$j]['zone'];
467 $zonedata[$n]['name'] = $data[$j]['name'];
468
469 for($j=0; $j<count($data); $j++)
470 {
471 // Если изменился номер карты, то начинаем новый массив
472 if($tmp!=$data[$j]['zone'])
473 {
474 // Количество объектов на зоне
475 $zonedata[$n]['count'] = $k;
476 $n++;
477 $exdata[$n] = array();
478 $zonedata[$n] = array();
479 $tmp=$data[$j]['zone'];
480 // Заносим номер зоны в список зон
481 $zonedata[$n]['zone'] = $data[$j]['zone'];
482 // TODO: Заносим название зоны в список зон
483 $zonedata[$n]['name'] = $data[$j]['name'];
484 $k=0;
485 }
486 $exdata[$n][$k] = array();
487 $exdata[$n][$k] = $data[$j];
488 $k++;
489 }
490
491 // Количество объектов на зоне
492 $zonedata[$n]['count'] = $k;
493
494 // Сортировка массивов по количеству объектов на зоне.
495 for($i=0; $i<=$n; $i++)
496 {
497 for($j=$i; $j<=$n; $j++)
498 {
499 if($zonedata[$j]['count'] > $zonedata[$i]['count'])
500 {
501 unset($tmp);
502 $tmp = $zonedata[$i];
503 $zonedata[$i] = $zonedata[$j];
504 $zonedata[$j] = $tmp;
505 unset($tmp);
506 $tmp = $exdata[$i];
507 $exdata[$i] = $exdata[$j];
508 $exdata[$j] = $tmp;
509 }
510 }
511 }
512
513 $smarty->assign('zonedata',$zonedata);
514 $smarty->assign('exdata',$exdata);
515 }
516}
517?>
Note: See TracBrowser for help on using the repository browser.