<?php

function MyERR($cmd)
{
  $callers = debug_backtrace();
  echo "Error from ".$callers[1]['function']."() -- ". mysql_error(). "\nCaused by: $cmd\n";
  exit(200);
}

function MySTR($str)
{
  return "'".mysql_real_escape_string($str)."'";
}

function MyOP($cmd)
{
  if ($res = mysql_query($cmd))  return $res;
  MyERR($cmd);
}

function MyOPcount($cmd)
{
   if (strspn($cmd, " \t\r\n") < strlen($cmd)) { MyOP($cmd); return mysql_affected_rows(); }
   return 0;
}

function MyRUN() // multiple SQL statements: 1) as single multiline argument, 2) as multiple arguments
{
  $rows = 0;
  $argc = func_num_args();
  if ($argc <= 1) {
      $arg = func_get_arg(0);
      $lines = preg_split('/\r?\n/', $arg, -1, PREG_SPLIT_NO_EMPTY);
      for($i = 0; $i < count($lines); $i++)  $rows += MyOPcount( $lines[$i] );
  } else {
      for($i = 0; $i < $argc; $i++) $rows += MyOPcount( func_get_arg($i) );
  }
  return $rows;
}

function MyROW($cmd)
{
  if ($res = mysql_query("$cmd LIMIT 1"))  return mysql_fetch_row($res);
  MyERR($cmd);
}

function MyROWobj($cmd)
{
  if ($res = mysql_query("$cmd LIMIT 1"))  return mysql_fetch_object($res);
  MyERR($cmd);
}

function MyVAL($cmd)
{
  if (substr($cmd, 0, 7) == "SELECT ")  $cmd .= " LIMIT 1";
  $r = mysql_query($cmd);
  if (!$r)  MyERR($cmd);
  $r = mysql_fetch_row($r);
  return $r ? $r[0] : null;
}

function MySTART($dbname = "")
{
  global $MyDB;
  $connect = @mysql_connect("localhost", "root", "ascent");
  if (!$connect)
	 MyERR("mysql_connect()");
  if (@$dbname == "") {
      $dbname = "world";
      $res = MyOP("SHOW DATABASES");
      while($r = mysql_fetch_row($res))
        if (in_array($r[0], array("world","mangos"))) { $dbname = $r[0]; break; }
  }
  MyOP("USE $dbname");
  $MyDB = $dbname;
  return $connect;
}


function IsCreatureGuidExists($entry)
{
  return MyVAL("SELECT guid FROM creature WHERE id=$entry") !== null ? true : false;
}


// World of Warcraft - Trinity Core specific part


$wowmaps = array(  //  ID  Name  Type  AreaTableID  Expansion  MaxPlayers
0 => "Eastern Kingdoms", // 0  0  0  0
1 => "Kalimdor", // 0  0  0  0
13 => "Testing", // 0  3817  0  0
25 => "Scott Test", // 0  0  0  0
30 => "Alterac Valley", // 3  0  0  0
33 => "Shadowfang Keep", // 1  0  0  10
34 => "Stormwind Stockade", // 1  717  0  10
35 => "<unused>StormwindPrison", // 0  717  0  0
36 => "Deadmines", // 1  0  0  10
37 => "Azshara Crater", // 0  0  0  0
42 => "Collin's Test", // 0  0  0  0
43 => "Wailing Caverns", // 1  718  0  10
44 => "<unused> Monastery", // 1  0  0  10
47 => "Razorfen Kraul", // 1  0  0  10
48 => "Blackfathom Deeps", // 1  719  0  10
70 => "Uldaman", // 1  1337  0  10
90 => "Gnomeregan", // 1  721  0  10
109 => "Sunken Temple", // 1  1477  0  10
129 => "Razorfen Downs", // 1  0  0  10
169 => "Emerald Dream", // 2  0  0  40
189 => "Scarlet Monastery", // 1  0  0  10
209 => "Zul'Farrak", // 1  0  0  10
229 => "Blackrock Spire", // 1  1583  0  10
230 => "Blackrock Depths", // 1  1584  0  5
249 => "Onyxia's Lair", // 2  2159  0  40
269 => "Opening of the Dark Portal", // 1  0  1  5
289 => "Scholomance", // 1  0  0  5
309 => "Zul'Gurub", // 2  1977  0  20
329 => "Stratholme", // 1  0  0  5
349 => "Maraudon", // 1  2100  0  10
369 => "Deeprun Tram", // 0  2257  0  0
389 => "Ragefire Chasm", // 1  2437  0  10
409 => "Molten Core", // 2  2717  0  40
429 => "Dire Maul", // 1  2557  0  5
449 => "Alliance PVP Barracks", // 0  2918  0  0
450 => "Horde PVP Barracks", // 0  2917  0  0
451 => "Development Land", // 0  0  2  0
469 => "Blackwing Lair", // 2  2677  0  40
489 => "Warsong Gulch", // 3  3277  0  0
509 => "Ruins of Ahn'Qiraj", // 2  3429  0  20
529 => "Arathi Basin", // 3  3358  0  0
530 => "Outland", // 0  0  1  0
531 => "Ahn'Qiraj Temple", // 2  3428  0  40
532 => "Karazhan", // 2  3457  1  10
533 => "Naxxramas", // 2  3456  2  25
534 => "The Battle for Mount Hyjal", // 2  616  1  25
540 => "Hellfire Citadel: The Shattered Halls", // 1  3714  1  5
542 => "Hellfire Citadel: The Blood Furnace", // 1  3713  1  5
543 => "Hellfire Citadel: Ramparts", // 1  3562  1  5
544 => "Magtheridon's Lair", // 2  3836  1  25
545 => "Coilfang: The Steamvault", // 1  3715  1  5
546 => "Coilfang: The Underbog", // 1  3716  1  5
547 => "Coilfang: The Slave Pens", // 1  3717  1  5
548 => "Coilfang: Serpentshrine Cavern", // 2  3607  1  25
550 => "Tempest Keep", // 2  3845  1  25
552 => "Tempest Keep: The Arcatraz", // 1  3848  1  5
553 => "Tempest Keep: The Botanica", // 1  3847  1  5
554 => "Tempest Keep: The Mechanar", // 1  3849  1  5
555 => "Auchindoun: Shadow Labyrinth", // 1  3789  1  5
556 => "Auchindoun: Sethekk Halls", // 1  3791  1  5
557 => "Auchindoun: Mana-Tombs", // 1  3792  1  5
558 => "Auchindoun: Auchenai Crypts", // 1  3790  1  5
559 => "Nagrand Arena", // 4  0  0  0
560 => "The Escape From Durnholde", // 1  267  1  5
562 => "Blade's Edge Arena", // 4  3702  0  0
564 => "Black Temple", // 2  0  1  25
565 => "Gruul's Lair", // 2  3923  1  25
566 => "Eye of the Storm", // 3  0  1  0
568 => "Zul'Aman", // 2  0  1  10
571 => "Northrend", // 0  0  2  0
572 => "Ruins of Lordaeron", // 4  0  0  0
573 => "ExteriorTest", // 0  0  2  0
574 => "Utgarde Keep", // 1  0  2  5
575 => "Utgarde Pinnacle", // 1  0  2  5
576 => "The Nexus", // 1  4265  2  5
578 => "The Oculus", // 1  0  2  5
580 => "The Sunwell", // 2  0  1  25
582 => "Transport: Rut'theran to Auberdine", // 0  0  0  0
584 => "Transport: Menethil to Theramore", // 0  0  0  0
585 => "Magister's Terrace", // 1  0  1  5
586 => "Transport: Exodar to Auberdine", // 0  0  0  0
587 => "Transport: Feathermoon Ferry", // 0  0  0  0
588 => "Transport: Menethil to Auberdine", // 0  0  0  0
589 => "Transport: Orgrimmar to Grom'Gol", // 0  0  0  0
590 => "Transport: Grom'Gol to Undercity", // 0  0  0  0
591 => "Transport: Undercity to Orgrimmar", // 0  0  0  0
592 => "Transport: Borean Tundra Test", // 0  0  0  0
593 => "Transport: Booty Bay to Ratchet", // 0  0  0  0
594 => "Transport: Howling Fjord Sister Mercy (Quest)", // 0  0  2  0
595 => "The Culling of Stratholme", // 1  0  2  5
596 => "Transport: Naglfar", // 0  0  2  0
597 => "Craig Test", // 0  0  0  0
598 => "Sunwell Fix (Unused)", // 1  0  1  5
599 => "Halls of Stone", // 1  0  2  5
600 => "Drak'Tharon Keep", // 1  0  2  5
601 => "Azjol-Nerub", // 1  0  2  5
602 => "Halls of Lightning", // 1  0  2  5
603 => "Ulduar", // 2  0  2  5
604 => "Gundrak", // 1  0  2  5
605 => "Development Land (non-weighted textures)", // 0  0  0  0
606 => "QA and DVD", // 0  0  2  0
607 => "Strand of the Ancients", // 3  0  2  0
608 => "Violet Hold", // 1  0  2  5
609 => "Ebon Hold", // 0  0  2  0
610 => "Transport: Tirisfal to Vengeance Landing", // 0  0  0  0
612 => "Transport: Menethil to Valgarde", // 0  0  0  0
613 => "Transport: Orgrimmar to Warsong Hold", // 0  0  0  0
614 => "Transport: Stormwind to Valiance Keep", // 0  0  0  0
615 => "The Obsidian Sanctum", // 2  0  2  0
616 => "The Eye of Eternity", // 2  0  2  5
617 => "Dalaran Sewers", // 4  0  0  0
618 => "The Ring of Valor", // 4  0  0  0
619 => "Ahn'kahet: The Old Kingdom", // 1  0  2  0
620 => "Transport: Moa'ki to Unu'pe", // 0  0  2  0
621 => "Transport: Moa'ki to Kamagua", // 0  0  2  0
622 => "Transport: Orgrim's Hammer", // 0  0  2  0
623 => "Transport: The Skybreaker", // 0  0  2  0
624 => "Vault of Archavon", // 2  0  2  0
628 => "Isle of Conquest", // 3  0  2  0
631 => "Icecrown Citadel", // 2  0  2  0
632 => "The Forge of Souls", // 1  0  2  0
641 => "Transport: Alliance Airship BG", // 0  0  2  0
642 => "Transport: HordeAirshipBG", // 0  0  2  0
647 => "Transport: Orgrimmar to Thunder Bluff", // 0  0  2  0
649 => "Trial of the Crusader", // 2  0  2  0
650 => "Trial of the Champion", // 1  0  2  0
658 => "Pit of Saron", // 1  0  2  0
668 => "Halls of Reflection", // 1  0  2  0
672 => "Transport: The Skybreaker (Icecrown Citadel Raid)", // 0  0  2  0
673 => "Transport: Orgrim's Hammer (Icecrown Citadel Raid)", // 0  0  2  0
712 => "Transport: The Skybreaker (IC Dungeon)", // 0  0  2  0
713 => "Transport: Orgrim's Hammer (IC Dungeon)", // 0  0  2  0
718 => "Trasnport: The Mighty Wind (Icecrown Citadel Raid)", // 0  0  2  0
723 => "Stormwind", // 0  0  0  0
724 => "The Ruby Sanctum", // 2  0  2  0
);


$bits_immunity = array(   // dword creature_template::mechanic_immune_mask
"Charm",
"Disoriented",
"Disarm",
"Distract",
"Fear",
"Grip", // Death Grip and similar effects
"Root",
"Pacify", // Not used: 0 spells with this mechanic
"Silence",
"Sleep",
"Snare",
"Stun",
"Freeze",
"Knockout", // Incapacitate effects such as Repentance (Paladin)
"Bleed",
"Bandage", // Healing etc.
"Polymorph",
"Banish",
"Shield",
"Shackle", // Shackle Undead only
"Mount", // Any effect that summons a mount
"Infected", // Frost Fever, Blood Plague etc. | Persuade (Mangos; 0 spells use it)
"Turn", // e.g. Turn Evil
"Horror", // e.g. Death Coil (Warlock)
"Invulnerability", // Forbearance, Nether Protection, Diplomatic Immunity only
"Interrupt",
"Daze",
"Discovery", // Any Create Item effect
"ImmuneShield", // Divine Shield, Ice Block, Hand of Protection...
"Sapped",
"Enraged",
);



$item_class = array(
0 => "Consumable",
1 => "Container",
2 => "Weapon",
3 => "Gem",
4 => "Armor",
5 => "Reagent",
6 => "Projectile",
7 => "Trade Goods",
8 => "Generic(OBSOLETE)",
9 => "Recipe",
10 => "Money(OBSOLETE)",
11 => "Quiver",
12 => "Quest",
13 => "Key",
14 => "Permanent(OBSOLETE)",
15 => "Miscellaneous",
16 => "Glyph",
);

$item_subclass = array(
"0 0" => "Consumable", // Usability in combat is decided by the spell assigned
"0 1" => "Potion",
"0 2" => "Elixir",
"0 3" => "Flask",
"0 4" => "Scroll",
"0 5" => "Food & Drink",
"0 6" => "Item Enhancement",
"0 7" => "Bandage",
"0 8" => "Other",
"1 0" => "Bag",
"1 1" => "Soul Bag",
"1 2" => "Herb Bag",
"1 3" => "Enchanting Bag",
"1 4" => "Engineering Bag",
"1 5" => "Gem Bag",
"1 6" => "Mining Bag",
"1 7" => "Leatherworking Bag",
"1 8" => "Inscription Bag",
"2 0" => "Axe",
"2 1" => "2H Axe",
"2 2" => "Bow",
"2 3" => "Gun",
"2 4" => "Mace",
"2 5" => "2H Mace",
"2 6" => "Polearm",
"2 7" => "Sword",
"2 8" => "2H Sword",
"2 9" => "Obsolete",
"2 10" => "Staff",
"2 11" => "Exotic",
"2 12" => "Exotic",
"2 13" => "Fist Weapon",
"2 14" => "Misc.", // Blacksmith Hammer, Mining Pick, etc.
"2 15" => "Dagger",
"2 16" => "Thrown",
"2 17" => "Spear",  // seems unused, all spears are "Polearm"
"2 18" => "Crossbow",
"2 19" => "Wand",
"2 20" => "Fishing Pole",
"3 0" => "Red",
"3 1" => "Blue",
"3 2" => "Yellow",
"3 3" => "Purple",
"3 4" => "Green",
"3 5" => "Orange",
"3 6" => "Meta",
"3 7" => "Simple",
"3 8" => "Prismatic",
"4 0" => "Miscellaneous",
"4 1" => "Cloth",
"4 2" => "Leather",
"4 3" => "Mail",
"4 4" => "Plate",
"4 5" => "Buckler(OBSOLETE)",
"4 6" => "Shield",
"4 7" => "Libram",
"4 8" => "Idol",
"4 9" => "Totem",
"4 10" => "Sigil",
"5 0" => "Reagent",
"6 0" => "Wand(OBSOLETE)",
"6 1" => "Bolt(OBSOLETE)",
"6 2" => "Arrow",
"6 3" => "Bullet",
"6 4" => "Thrown(OBSOLETE)",
"7 0" => "Trade Goods",
"7 1" => "Parts",
"7 2" => "Explosives",
"7 3" => "Devices",
"7 4" => "Jewelcrafting",
"7 5" => "Cloth",
"7 6" => "Leather",
"7 7" => "Metal & Stone",
"7 8" => "Meat",
"7 9" => "Herb",
"7 10" => "Elemental",
"7 11" => "Other",
"7 12" => "Enchanting",
"7 13" => "Materials",
"7 14" => "Armor Enchantment",
"7 15" => "Weapon Enchantment",
"8 0" => "Generic(OBSOLETE)",
"9 0" => "Book",
"9 1" => "Leatherworking",
"9 2" => "Tailoring",
"9 3" => "Engineering",
"9 4" => "Blacksmithing",
"9 5" => "Cooking",
"9 6" => "Alchemy",
"9 7" => "First Aid",
"9 8" => "Enchanting",
"9 9" => "Fishing",
"9 10" => "Jewelcrafting",
"10 0" => "Money(OBSOLETE)",
"11 0" => "Quiver(OBSOLETE)",
"11 1" => "Quiver(OBSOLETE)",
"11 2" => "Quiver", // Can hold arrows
"11 3" => "Ammo Pouch", // Can hold bullets
"12 0" => "Quest",
"13 0" => "Key",
"13 1" => "Lockpick",
"14 0" => "Permanent",
"15 0" => "Junk",
"15 1" => "Reagent",
"15 2" => "Pet",
"15 3" => "Holiday",
"15 4" => "Other",
"15 5" => "Mount",
"16 1" => "Warrior",
"16 2" => "Paladin",
"16 3" => "Hunter",
"16 4" => "Rogue",
"16 5" => "Priest",
"16 6" => "Death Knight",
"16 7" => "Shaman",
"16 8" => "Mage",
"16 9" => "Warlock",
"16 11" => "Druid",
);

$item_quality = array(
0 => "Poor", // Grey
1 => "Common", // White
2 => "Uncommon", // Green
3 => "Rare", // Blue
4 => "Epic", // Purple
5 => "Legendary", // Orange
6 => "Artifact", // Red
7 => "Heirloom", // Gold
);

$item_stat = array(
0 => "Mana+",
1 => "Health+",
3 => "Agi+",
4 => "Str+",
5 => "Int+",
6 => "Spi+",
7 => "Sta+",
12 => "Defense",
13 => "Dodge",
14 => "Parry",
15 => "Block",
16 => "Hit(melee)",
17 => "Hit(ranged)",
18 => "Hit(spell)",
19 => "Crit(melee)",
20 => "Crit(ranged)",
21 => "Crit(spell)",
22 => "Hit_taken(melee)",
23 => "Hit_taken(ranged)",
24 => "Hit_taken(spell)",
25 => "Crit_taken(melee)",
26 => "Crit_taken(ranged)",
27 => "Crit_taken(spell)",
28 => "Haste(melee)",
29 => "Haste(ranged)",
30 => "Haste(spell)",
31 => "Hit",
32 => "Crit",
33 => "Hit_taken",
34 => "Crit_taken",
35 => "Resil",
36 => "Haste",
37 => "Expertise",
38 => "Attack Power +",
39 => "Ranged Attack Power +",
40 => "Feral Attack Power", // (not used as of 3.3)
41 => "Spell Healing +",
42 => "Spell Damage +",
43 => "Mana Regen",
44 => "Armor Penetration",
45 => "Spell Power +",
46 => "Health Regen +",
47 => "Spell Penetration",
48 => "Block Value",
);

$item_spelltrigger = array(
0 => "Use",
1 => "On Equip",
2 => "Chance on Hit",
4 => "Soulstone",
5 => "Use with no delay",
6 => "Learn Spell ID",
);

$item_invslot = array(
0 => "N/E",
1 => "Head",
2 => "Neck",
3 => "Shoulder",
4 => "Shirt",
5 => "Chest",
6 => "Waist",
7 => "Legs",
8 => "Feet",
9 => "Wrist",
10 => "Hands",
11 => "Finger",
12 => "Trinket",
13 => "One-hand",
14 => "Shield",
15 => "Ranged/bows",
16 => "Back",
17 => "Two-hand",
18 => "Bag",
19 => "Tabard",
20 => "Robe",
21 => "Main-hand",
22 => "Off-hand",
23 => "Holdable",  // tome, etc.
24 => "Ammo",
25 => "Thrown",
26 => "Ranged/other",  // wand, gun, crossbow
27 => "Quiver",
28 => "Relic",
);

$item_bonding = array(
0 => "",
1 => "BoP",
2 => "BoE",
3 => "BoU",
4 => "Q",
5 => "Q1",
);


// CMangos Classic
$bits_npcflag = array("Gossip","Questgiver","Vendor","Flightmaster","Trainer","Spirithealer","SpiritGuide","Innkeeper","Banker","Petitioner","TabardDesigner","Battlemaster","Auctioneer","Stablemaster","Repair");
$bits_unitflag = array("","NonAttackable","DisableMove","PvpAttackable","Rename","Resting","","","OOCnotAttackable","Passive","","","Pvp","Silenced","","Swimming","","Pacified","DisableRotate","InCombat","","","","","","NotSelectable","Skinnable","AurasVisible","","","Sheathe","NoXPReward??");
$bits_dynflag = array("Lootable","Track_unit","Tapped","Rooted","Specialinfo","Dead");
$bits_typeflag = array("Tameable","GhostVisible","BoosTooltip??","","FactionTooltip??","SoundRelated??","","","HerbLoot","MiningLoot","","NountedCast??","Can_assist","","","EngineerLoot");
$bits_flagextra = array("InstanceBind","NoAggro","NoParry","NoParryHasten","NoBlock","NoCrush","NoXPatKill","Invisible","NotTauntable","AggroZone","Guard");

function rdbits($val, $bitnames)
{
  $t = ""; $i = 0;
  while($val >= 1) {
    if ($val&1) { $t .= ($t=="" ? " :: ":" "). (@$bitnames[$i] != "" ? $bitnames[$i] : sprintf("0x%x",1<<$i));}
    $val = (int)($val / 2);  // unsigned >>1
    ++$i;
  }
  return $t;
}

function readable($t)
{
  $t = preg_replace_callback('/^ *\[npcflag] *=> *(\d+) *$/im',
       create_function('$matches', 'return $matches[0].rdbits($matches[1], $GLOBALS["bits_npcflag"]);'), $t );
  $t = preg_replace_callback('/^ *\[unit_flags] *=> *(\d+) *$/im',
       create_function('$matches', 'return $matches[0].rdbits($matches[1], $GLOBALS["bits_unitflag"]);'), $t );
  $t = preg_replace_callback('/^ *\[dynamicflags] *=> *(\d+) *$/im',
       create_function('$matches', 'return $matches[0].rdbits($matches[1], $GLOBALS["bits_dynflag"]);'), $t );
  $t = preg_replace_callback('/^ *\[type_flags] *=> *(\d+) *$/im',
       create_function('$matches', 'return $matches[0].rdbits($matches[1], $GLOBALS["bits_typeflag"]);'), $t );
  $t = preg_replace_callback('/^ *\[flags_extra] *=> *(\d+) *$/im',
       create_function('$matches', 'return $matches[0].rdbits($matches[1], $GLOBALS["bits_flagextra"]);'), $t );
  $t = preg_replace_callback('/^ *\[mechanic_?immune_?mask\] *=> *(\d+) *$/im',
       create_function('$matches', 'return $matches[0].rdbits($matches[1], $GLOBALS["bits_immunity"]);'), $t );
  return $t;
}


function floatfmt($value, $n)
{
  $t = sprintf("%f", $value);
  if (strchr($t, '.') === FALSE)  return $t;

  while(substr($t, -1) == '0' || strlen($t) > $n) {
     if (substr($t, -1) == '.') break;
     $t = substr($t, 0, -1);
  }
  if (substr($t, -1) == '.') $t = substr($t, 0, -1);
  return $t;
}


function DBnameFromArgv()
{
  global $argv; // may modify argv[] removing DBname (if found)
  $dbname = "";
  if (count($argv) > 1 and substr($argv[1], 0, 1) == ':') {
     $dbname = substr($argv[1], 1);
     array_shift($argv);
  }
  return $dbname;
}

function EntryConditionFromArgv(&$refargs = null, $nameField = "name", $entryField = "entry")
{
global $argv, $item_invslot;

if (count($argv) <= 1)  $args = (string)$refargs;
else {
   $args = "";
   for($i = 1; $i < count($argv); $i++)  $args = ($args == "" ? "" : "$args ").$argv[$i];
   $refargs = $args;
}
if (intval($args) > 0)  return "$entryField IN ($args)";
if (substr($args,0,1) != '(' or substr($args,-1,1) != ')')
    return "INSTR($nameField, ". MySTR($args) .")";

foreach($item_invslot as $i => $inv)
  if (strtolower($args)==strtolower("($inv)"))  return "(InventoryType".($args == "(chest)" ? " IN ($i,20)" : "=$i")." AND (Quality>=3 OR Quality=2 AND bonding=1))";
return $args;
}


function rankstr($rank)
{
  return
   $rank == 0 ? "normal":
  ($rank == 1 ? "elite" :
  ($rank == 2 ? "rare elite" :
  ($rank == 3 ? "boss" :
  ($rank == 4 ? "rare" : "?rank_$rank?" ))));
}


function PrintItem(& $item, $pretext="", $posttext="\n")
{
global $item_class, $item_subclass, $item_quality, $item_stat, $item_spelltrigger, $item_invslot, $item_bonding;

if (($iclass = @$item_class[$item->class]) == "")  $iclass = "unknown ($item->class)";
if (($isubclass = @$item_subclass["$item->class $item->subclass"]) == "")  $iclass = "($item->subclass)";
if (($iQuality = @$item_quality[$item->Quality]) == "")  $iQuality = "??=$item->Quality";
if (($islot = @$item_invslot[$item->InventoryType]) == "")  $islot = "??=$item->InventoryType";
else if ($islot == "Bag")  $islot .= "($item->ContainerSlots)";
$ibind = ($item->bonding < 0 or $item->bonding > 6) ? "??=$item->bonding" : @$item_bonding[$item->bonding];
if ($ibind != "")  $ibind = " $ibind";

printf("%s%5d %s", $pretext, $item->entry, $item->name);
echo "; $iclass:$isubclass", ($item->delay == 0 ? "": sprintf(" %.2f",$item->delay/1000.0))," @$islot";
echo "; $iQuality $item->ItemLevel [$item->RequiredLevel]$ibind";
echo "; Sell $item->SellPrice", ($item->BuyPrice == $item->SellPrice*4 ? "" : " Buy $item->BuyPrice");
// стандартная цена покупки вещи = 4 * цена продажи
$sep = "; ";

$sumstats = 0;
for($i = 1; $i <= (isset($item->StatsCount) ? min($item->StatsCount,10) : 10); $i++) {
  eval("\$sv = \$item->stat_value$i;");
  if ($sv == 0)  continue; // Mangos
  $sumstats += $sv;
  eval("\$st = \$item->stat_type$i;");
  if (($istat = @$item_stat[$st]) == "")  $istat = "$st";
  echo ($sep != ", " || $st<3 || $st>7 ? $sep : " "), $istat, (substr($istat,"-1") == '+' ? "":" "), $sv;
  $sep = ", ";
}
if ($sumstats != 0) echo " {".$sumstats."}";

foreach(array("holy","fire","nature","frost","shadow","arcane") as $resist) {
  eval("\$val = \$item->${resist}_res;");
  if ($val != 0)  echo $sep, "$resist $val";
  $sep = ", ";
}

if (@$item->RandomProperty != 0)  { echo $sep, "RandomProperty $item->RandomProperty"; $sep = ", "; }
if (@$item->RandomSuffix != 0)  { echo $sep, "RandomSuffix $item->RandomSuffix"; $sep = ", "; }
if ($item->ScriptName != 0)  { echo $sep, "Script $item->ScriptName"; $sep = ", "; }

for($k = 1; $k <= 5; $k++) {
  eval("\$spid = \$item->spellid_$k;");
  eval("\$spt = \$item->spelltrigger_$k;");
  if ($spid != 0)  {
     if (($ispelltrigger = @$item_spelltrigger[$spt]) == "")  $ispelltrigger = "??=$spt";
     echo $sep, "$ispelltrigger $spid";

     global $dbcdata_use;
     if (!isset($dbcdata_use) || $dbcdata_use < 0)
        $dbcdata_use = mysql_query("SELECT description FROM dbcdata.spell LIMIT 1") === FALSE ? 0 : ($dbcdata_use < 0 ? -$dbcdata_use : 100);
     if ($dbcdata_use > 0) {
        --$dbcdata_use;
        echo " ";
        $desc = MyROW("SELECT name,description,effectBasePoints1 FROM dbcdata.spell WHERE ID=$spid");

        if (preg_match("/^(Increase[\w ]+ |Attack Power (Ranged )?|Ranged Hit Bonus \+)\d+$/i", $desc[0]))
            echo $desc[0];
        elseif (preg_match('/^(Increase[\w ]+ )\+?\$s1\.$/i', @$desc[1], $capt))
            echo $capt[1], 1+$desc[2]; // Defense, Block value, Fishing, Daggers ...
        else {
            echo (@$desc[1] == "" ? $desc[0] : $desc[1]);
        }
     }

     $sep = ", ";
  }
}

if ($item->block != 0) { echo $sep, "Block $item->block"; $sep = ", "; }
if ($item->armor != 0) { echo $sep, "Armor $item->armor"; $sep = ", "; }

$dmgMin = 0; $dmgMax = 0;
//$dmgMin += $item->dmg_min1; $dmgMax += $item->dmg_max1;
for($i = 1; $i <= 5; $i++) eval("\$dmgMin += @\$item->dmg_min$i; \$dmgMax += @\$item->dmg_max$i;");
if ($dmgMin !=0 or $dmgMax != 0) {
    printf("${sep}DPS %.1f [%d-%d]", @($dmgMin + $dmgMax) / 2.0 / (max($item->delay,1)/1000.0), $dmgMin, $dmgMax);
    $sep = ", ";
}
echo $posttext;

}


function ViewRelatedData($obj, $reqMemVar, $arrRequests, $reqTail, $msgNoAccess, $msgNoData, $desc)
// for creature_template, gameobject_template
{
  if (!isset($reqMemVar)) {
      $reqMemVar = false;
      foreach($arrRequests as $r) {
        $res = mysql_query($r.$obj->entry. $reqTail);
        if ($res)  { $reqMemVar = $r; break; }
      }
  } else
      $res = $reqMemVar ? mysql_query($reqMemVar.$obj->entry. $reqTail) : false;

  if (!$res)  echo "  $msgNoAccess\n";
  elseif (mysql_num_rows($res) == 0)  echo "  $msgNoData\n";
  else
  while($r = mysql_fetch_row($res)) {
     $sep = "";
     echo "  (";
     foreach($r as $val) { echo $sep, $val; $sep = ", "; }
     echo ");", ($desc == "" ? "" : " -- $desc"), "\n";
  }
}


////// Object Pools (currently only supported for MangosZero and CMangos DBs)

function Amount1($n, $rndseed)
{
   return 1;
}

function AmountHalve($n, $rndseed)
{
   return max(1, round($n * 0.5));
}

function AmountOfResources($n, $rndseed)
{
   mt_srand($rndseed);
   $limit = ($n <=  2 ? 1 :
            ($n <=  6 ? 2 :
            ($n <= 15 ? 3 :
            ($n <= 25 ? 4 :
            ($n <= 50 ? mt_rand(4,5) :
            ($n <=100 ? mt_rand(5,6) :
            mt_rand(5,7)
   ))))));
   return $limit;
}

function AmountOfResourcesLow($n, $rndseed) // предпочтительнее для Single Player
{
   mt_srand($rndseed);
   $limit = ($n <=  5 ? 1 :
            ($n <= 20 ? mt_rand(1,2) :
            ($n <= 40 ? mt_rand(2,3) :
            ($n <=100 ? mt_rand(2,4) :
            mt_rand(3,5)
   ))));
   return $limit;
}

function AmountOfFishings($n, $rndseed)
{
   mt_srand($rndseed);
   $limit = ($n <=  3 ? 1 :
            ($n <=  5 ? mt_rand(1, 2) :
            ($n <=  8 ? 2 :
            mt_rand(2, 3)
   )));
   return $limit;
}


function CreateObjectPools($title, $table, $cellsizeXY, $cellsizeZ, $overwriteAllPools, $FuncAmount, $objectList)
{

$newEntry = MyVAL("SELECT MAX(entry) FROM pool_template") + 10;
//echo "NEW ENTRY = $newEntry\n";

$res = MyOP("
SELECT *,FLOOR(position_x / $cellsizeXY) AS clusterX, FLOOR(position_y / $cellsizeXY) AS clusterY, FLOOR(position_z / $cellsizeZ + 0.5) AS clusterZ
FROM $table
WHERE
  ".($overwriteAllPools ? "" : "
  NOT guid IN (SELECT guid FROM pool_$table WHERE guid=$table.guid) AND
  ")."
  id IN (SELECT entry FROM ${table}_template WHERE ".(substr($objectList,0,1) != '(' ? "name IN ($objectList)" : "$objectList").")
ORDER BY map,clusterX,clusterY,clusterZ, position_x,position_y,position_z
"
);

$totalGuids = 0;
$totalPools = 0;
$totalSingles = 0;
$totalLimit = 0;

$guidlist = array();
$prevobj = null;
$nDistinct = 0;
$map = 0;
$clusterX = 0;
$clusterY = 0;
$clusterZ = 0;

for(;;) {
  $obj = mysql_fetch_object($res);

  if (!$obj or $clusterX != $obj->clusterX or $clusterY != $obj->clusterY or $clusterZ != $obj->clusterZ or $map != $obj->map) {
     $n = count($guidlist);

     if ($n >= 2) {
         // create new pool
         $limit = $FuncAmount($nDistinct /* $n */, $guidlist[0]);
         $totalLimit += $limit;
         MyOP("INSERT INTO pool_template SET entry=$newEntry, max_limit=$limit, description=''");
         foreach ($guidlist as $g) {
           MyOP("REPLACE INTO pool_$table SET guid=$g,pool_entry=$newEntry,chance=0,description=''");
           ++$totalGuids;
         }
         //printf("%3d:%3d => %d\n", $n, $nDistinct, $limit);
         ++$totalPools;
         ++$newEntry;
     }
     elseif ($n == 1) {
         ++$totalLimit;
         ++$totalSingles;
         if ($overwriteAllPools)  MyOP("DELETE FROM pool_$table WHERE guid=$guidlist[0]");
     }

     if (!$obj) break;

     $guidlist = array();
     $prevobj = null;
     $nDistinct = 0;
     $map = $obj->map;
     $clusterX = $obj->clusterX;
     $clusterY = $obj->clusterY;
     $clusterZ = $obj->clusterZ;
  }

  $guidlist[] = $obj->guid;
  if ($prevobj == null or $prevobj->position_x != $obj->position_x or $prevobj->position_y != $obj->position_y or $prevobj->position_z != $obj->position_z)
     ++$nDistinct;
  $prevobj = $obj;
}

printf(" ■ %s: %d ${table}s assigned to %d pools + %d singles; maxcount %d\n",
  $title, $totalGuids, $totalPools, $totalSingles, $totalLimit );

}

?>
