01-26-2015, 12:03 PM
Копирую со старой темы.
http://hauthd.org/files/transfer.zip
Летом 2010 года занимался разработкой скрипта, который позволяет перейти с Hellbound от Guard'ов (nextdev.org, la2guard.com, guardex.org) на Gracia Epilogue от l2jserver.com.
Перенесено все, что реально было перенести, за исключением некоторых мелочей (макросы, панели с ярлыками). Персонажы, кланы, альянсы, предметы, аугментации, атрибуты, питомцы, скиллы, холлы, замки, олимпиада и т. д. и т. п. Перенесены даже квесты (насколько это возможно): текущий шаг активных квестов, список выполненных квестов, состояние альянса с Варкой и Кетрой.
База учетных записей (lin2db) не перенесена, потому что был переписан авторизационный сервер (hAuthD) для работы с L2J (одновременно с PTS) с целью сохранить защиту.
Прошло уже 9 месяцев, многое изменилось (в первую очередь я говорю про таблицы и их стуктуры), но, возможно, скрипт кому-то еще будет полезен (проще дописать, чем написать с нуля).
С L2J можно проделать небольшой трюк: скачать Epilogue, перенести БД, а потом выполнить скрипты для перехода с Epilogue на Freya (раньше это работало, потому что Freya только появилась и требовалось накатить только одно обновление).
http://hauthd.org/files/transfer.zip
В init.php надо указать реквизиты базы l2j (заменить mysql://root:password@127.0.0.1/l2j), а в lib\classes\database.php для mssql (заменить mssql://sa:password@127.0.0.1/lin2world).
В папку data надо загрузить нужные файлы (что-то из PTS, что-то из L2J).
Еще есть quest_names.inc, где хранится таблица соответствия id квестов и названий из L2J. К сожалению, скрипта генерации этого файла не осталось (там анализируется папка AI из L2J, из скриптов выдираются идентификаторы).
Чтобы запустить процесс, надо открыть в браузере index.php. Процесс конвертирования отображается в браузере. Статус хранится во временной таблице в MySQL tmp_progress (если что-то сбивается, то иногда приходится очищать таблицу вручную). Страницу в браузере можно закрывать и перезагружать (процесс не прерывается). Время конвертирования зависит от размера базы, от мощности сервера, от настроек БД (у меня на перенос ушло чуть больше часа, серверу было 4 года, пиковый онлайн в лучшие времена был 2000+).
P. S. Забавно было читать ответы в этой теме:
http://postpacific.ru/archive/index.php/t-551.html
Основной скрипт:
http://hauthd.org/files/transfer.zip
Летом 2010 года занимался разработкой скрипта, который позволяет перейти с Hellbound от Guard'ов (nextdev.org, la2guard.com, guardex.org) на Gracia Epilogue от l2jserver.com.
Перенесено все, что реально было перенести, за исключением некоторых мелочей (макросы, панели с ярлыками). Персонажы, кланы, альянсы, предметы, аугментации, атрибуты, питомцы, скиллы, холлы, замки, олимпиада и т. д. и т. п. Перенесены даже квесты (насколько это возможно): текущий шаг активных квестов, список выполненных квестов, состояние альянса с Варкой и Кетрой.
База учетных записей (lin2db) не перенесена, потому что был переписан авторизационный сервер (hAuthD) для работы с L2J (одновременно с PTS) с целью сохранить защиту.
Прошло уже 9 месяцев, многое изменилось (в первую очередь я говорю про таблицы и их стуктуры), но, возможно, скрипт кому-то еще будет полезен (проще дописать, чем написать с нуля).
С L2J можно проделать небольшой трюк: скачать Epilogue, перенести БД, а потом выполнить скрипты для перехода с Epilogue на Freya (раньше это работало, потому что Freya только появилась и требовалось накатить только одно обновление).
http://hauthd.org/files/transfer.zip
В init.php надо указать реквизиты базы l2j (заменить mysql://root:password@127.0.0.1/l2j), а в lib\classes\database.php для mssql (заменить mssql://sa:password@127.0.0.1/lin2world).
В папку data надо загрузить нужные файлы (что-то из PTS, что-то из L2J).
Еще есть quest_names.inc, где хранится таблица соответствия id квестов и названий из L2J. К сожалению, скрипта генерации этого файла не осталось (там анализируется папка AI из L2J, из скриптов выдираются идентификаторы).
Чтобы запустить процесс, надо открыть в браузере index.php. Процесс конвертирования отображается в браузере. Статус хранится во временной таблице в MySQL tmp_progress (если что-то сбивается, то иногда приходится очищать таблицу вручную). Страницу в браузере можно закрывать и перезагружать (процесс не прерывается). Время конвертирования зависит от размера базы, от мощности сервера, от настроек БД (у меня на перенос ушло чуть больше часа, серверу было 4 года, пиковый онлайн в лучшие времена был 2000+).
P. S. Забавно было читать ответы в этой теме:
http://postpacific.ru/archive/index.php/t-551.html
Основной скрипт:
PHP код:
<?php
/**
* Database converter from PTS (MSSQL) to L2J (MySQL)
* @author Hint aka Ilya
*/
ini_set('display_errors', 'On');
set_time_limit(0);
ignore_user_abort(true);
require_once 'init.php';
require_once 'quest_names.inc';
$progress = new Progress($my);
function databaseErrorHandler($message, $info)
{
$GLOBALS['progress']->error(print_r($info, true));
}
$my->setErrorHandler('databaseErrorHandler');
function p($value)
{
$GLOBALS['progress']->error(print_r($value, true));
}
function timeToJava($time)
{
if (is_float($time)) $time = intval($time);
return $time ? (is_int($time) ? $time : strtotime($time)) . '001' : 0;
}
function defineOffset($name, $offset)
{
$res = round($offset + 1, -6) + 1000000;
define(strtoupper($name) . '_OFFSET', $res);
}
function insertExtItemData($objectId, $bless, $eroded)
{
$bless = intval($bless);
$eroded = intval($eroded);
$elemType = ($eroded & 0xF0000000) >> 28;
$elemValue = ($eroded & 0x0FFF0000) >> 16;
$elem = $elemType >= 0 && $elemValue > 0;
if ($bless > 0 || $elem)
{
$ext = array('itemId' => $objectId, 'augAttributes' => -1, 'augSkillId' => -1, 'augSkillLevel' => -1, 'elemType' => -1, 'elemValue' => -1);
if ($bless > 0)
{
$aug = array($bless & 0xFFFF, $bless >> 16);
$ext['augAttributes'] = $bless;
$ext['augSkillId'] = 0;
$ext['augSkillLevel'] = 0;
$augSkills = &$GLOBALS['augSkills'];
foreach ($aug as $id)
{
if (isset($augSkills[$id]))
{
list($ext['augSkillId'], $ext['augSkillLevel']) = $augSkills[$id];
}
}
}
if ($elem)
{
$ext['elemType'] = $elemType;
$ext['elemValue'] = $elemValue;
}
$GLOBALS['my']->query('INSERT INTO item_attributes(?#) VALUES(?a)', array_keys($ext), array_values($ext));
return true;
}
else
{
return false;
}
}
function getQuestCondFromState(&$state)
{
if ($state < 0)
{
$tmp = $state;
$skip = null;
$cond = 0;
for ($i = 1; $i < 32; $i++)
{
if ($tmp & 1 == 1)
{
$cond = $i;
}
else
{
if (is_null($skip)) $skip = $i;
}
$tmp = $tmp >> 1;
}
if (is_null($skip) || $skip > $cond) $state = $cond;
}
else
{
$cond = $state;
}
if ($cond < 1) $cond = 1;
return $cond;
}
$db = $ms->getLink();
$varkaKetraItems = array(7221 => -1, 7222 => -2, 7223 => -3, 7224 => -4, 7225 => -5, 7211 => 1, 7212 => 2, 7213 => 3, 7214 => 4, 7215 => 5);
$aug = simplexml_load_file('data/augmentation_skillmap.xml');
$augSkills = array();
foreach ($aug->augmentation as $augmentation)
{
$augSkills[intval($augmentation['id'])] = array(intval($augmentation->skillId['val']), intval($augmentation->skillLevel['val']));
}
unset($aug);
$craft = simplexml_load_file('data/recipes.xml');
$commonCraft = array();
foreach ($craft->item as $item)
{
if (strval($item['type']) == 'common') $commonCraft[intval($item['id'])] = true;
}
unset($craft);
$paperdollSlots = array('ST_right_hand' => 9, 'ST_left_hand' => 10, 'ST_gloves' => 11, 'ST_chest' => 12, 'ST_legs' => 13, 'ST_feet' => 14, 'ST_both_hand' => 16);
defineOffset('char', 0x10000000);
defineOffset('clan', CHAR_OFFSET + $ms->selectCell('SELECT MAX(char_id) FROM user_data'));
defineOffset('item', CLAN_OFFSET + $ms->selectCell('SELECT MAX(pledge_id) FROM Pledge'));
try
{
$insert = new FastInsert($my);
$insert->addTable('items', array('owner_id', 'object_id', 'item_id', 'count', 'enchant_level', 'loc', 'loc_data', 'time_of_use', 'custom_type1', 'custom_type2', 'mana_left', 'time'), 'dddddsdddddd');
$insert->addTable('character_skills', array('charId', 'skill_id', 'skill_level', 'class_index'), 'dddd');
$insert->addTable('character_recipebook', array('charId', 'id', 'classIndex', 'type'), 'dddd');
$insert->addTable('clan_skills', array('clan_id', 'skill_id', 'skill_level', 'skill_name'), 'ddds');
$insert->addTable('clan_wars', array('clan1', 'clan2', 'wantspeace1', 'wantspeace2'), 'dddd');
$insert->addTable('clan_subpledges', array('clan_id', 'sub_pledge_id', 'name', 'leader_id'), 'ddsd');
$insert->addTable('pets', array('item_obj_id', 'name', 'level', 'curHp', 'curMp', 'exp', 'sp', 'fed', 'weapon', 'armor', 'jewel'), 'dsdddsddddd');
$insert->addTable('character_quest_global_data', array('charId', 'var', 'value'), 'dss');
$insert->addTable('character_quests', array('charId', 'name', 'var', 'value', 'class_index'), 'dsssd');
$insert->addTable('heroes', array('charId', 'class_id', 'count', 'played', 'message'), 'dddds');
$insert->addTable('heroes_diary', array('charId', 'time', 'action', 'param'), 'dsdd');
$insert->addTable('olympiad_data', array('id', 'current_cycle', 'period', 'olympiad_end', 'validation_end', 'next_weekly_change'), 'dddsss');
$insert->addTable('olympiad_fights', array('charOneId', 'charTwoId', 'charOneClass', 'charTwoClass', 'winner', 'start', 'time', 'classed'), 'dddddsdd');
$insert->addTable('olympiad_nobles', array('charId', 'class_id', 'olympiad_points', 'competitions_done', 'competitions_won', 'competitions_lost', 'competitions_drawn'), 'ddddddd');
$insert->addTable('olympiad_nobles_eom', array('charId', 'class_id', 'olympiad_points', 'competitions_done', 'competitions_won', 'competitions_lost', 'competitions_drawn'), 'ddddddd');
$insert->truncate();
$my->query('TRUNCATE characters');
$my->query('TRUNCATE character_subclasses');
$my->query('TRUNCATE clan_data');
$my->query('TRUNCATE character_hennas');
$my->query('TRUNCATE item_attributes');
$progress->setText('lin2world.user_data');
$res = mssql_query('SELECT * FROM user_data', $db);
//$res = mssql_query('SELECT * FROM user_data WHERE char_id = 153106', $db);
$progress->setMax(mssql_num_rows($res));
$students = array();
while ($char = mssql_fetch_array($res))
{
$progress->next();
if ($char['account_id'] <= 0) continue; // deleted
$row = $ms->selectRow('SELECT account FROM lin2db.dbo.user_account WHERE uid = ?d', $char['account_id']);
if (!is_array($row) || !isset($row['account'])) throw new Exception('Account not found!');
$account = strtolower(trim($row['account']));
if (strlen($account) == 0) throw new Exception('Invalid account!');
$charId = intval($char['char_id']);
$charIdEx = $charId + CHAR_OFFSET;
// Items
$items = $ms->select('SELECT * FROM user_item WHERE char_id = ?d AND warehouse IN (0, 1)', $charId);
$equipment = array();
if ($char['ST_legs'] && $char['ST_chest'] == $char['ST_legs']) $char['ST_legs'] = 0;
foreach ($char as $key => $value)
{
if (strpos($key, 'ST_') === 0 && $value > 0) $equipment[$value] = isset($paperdollSlots[$key]) ? $paperdollSlots[$key] : true;
}
$varkaKetraAlly = 0;
foreach ($items as $item)
{
if (isset($varkaKetraItems[$item['item_type']])) $varkaKetraAlly = $varkaKetraItems[$item['item_type']];
$item['bless'] = intval($item['bless']);
$item['eroded'] = intval($item['eroded']);
if ($item['bless'] < 0) continue; // shadow
$slotType = $item['warehouse'] == 0 ? (isset($equipment[$item['item_id']]) ? 'PAPERDOLL' : 'INVENTORY') : 'WAREHOUSE';
$slotIndex = $slotType == 'PAPERDOLL' && is_int($equipment[$item['item_id']]) ? $equipment[$item['item_id']] : 0;
$insert->add('items', array($charIdEx, $item['item_id'] + ITEM_OFFSET, $item['item_type'], $item['amount'], $item['enchant'], $slotType, $slotIndex, null, 0, 0, -1, -1));
insertExtItemData($item['item_id'] + ITEM_OFFSET, $item['bless'], $item['eroded']);
}
// Character
if ($char['subjob_id'] == 0)
{
$level = $char['Lev'];
$exp = $char['Exp'];
$HP = $char['HP'];
$MP = $char['MP'];
$SP = $char['SP'];
$baseClass = $char['class'];
$excludeSub = false;
}
else
{
$tmp = $ms->selectRow('SELECT * FROM user_subjob WHERE char_id = ?d AND subjob_id = 0', $charId);
if (!is_array($tmp) || !$tmp) throw new Exception('Can\'t find base class in user_subjob for char_id #' . $charId);
$level = $tmp['level'];
$exp = $tmp['exp'];
$HP = $tmp['hp'];
$MP = $tmp['mp'];
$SP = $tmp['sp'];
$baseClass = $char['subjob0_class'];
$excludeSub = $char['subjob_id'];
$my->query('INSERT INTO character_subclasses SET charId = ?d, class_id = ?d, exp = ?, sp = ?, level = ?d, class_index = ?d',
$charIdEx, $char['class'], $char['Exp'], $char['SP'], $char['Lev'], $char['subjob_id']);
}
$row = $ms->selectRow('SELECT * FROM user_henna WHERE char_id = ?d', $charId);
if (is_array($row) && $row)
{
for ($i = 1; $i <= 3; $i++)
{
$henna = $row['henna_' . $i];
if ($henna > 0)
{
$my->query('INSERT INTO character_hennas SET charId = ?d, symbol_id = ?d, slot = ?d, class_index = ?d',
$charIdEx, $henna, $i, $char['subjob_id']);
}
}
}
$subjobs = false;
for ($i = 1; $i <= 3; $i++)
{
if ($char['subjob' . $i . '_class'] != -1)
{
$subjobs = true;
break;
}
}
if ($subjobs)
{
$rows = $ms->select('SELECT * FROM user_subjob WHERE char_id = ?d', $charId);
if (!is_array($rows) || !$rows) throw new Exception('Can\'t find subclasses!');
foreach ($rows as $row)
{
$subjob = $char['subjob' . $row['subjob_id'] . '_class'];
if ($subjob <= 0) throw new Exception('Invalid subjob!');
if ($row['subjob_id'] == $excludeSub) continue;
if (is_null($row['level'])) continue;
for ($i = 1; $i <= 3; $i++)
{
$henna = $row['henna_' . $i];
if ($henna > 0)
{
$my->query('INSERT INTO character_hennas SET charId = ?d, symbol_id = ?d, slot = ?d, class_index = ?d',
$charIdEx, $henna, $i, $row['subjob_id']);
}
}
if ($row['subjob_id'] == 0) continue;
$my->query('INSERT INTO character_subclasses SET charId = ?d, class_id = ?d, exp = ?, sp = ?, level = ?d, class_index = ?d',
$charIdEx, $subjob, $row['exp'], $row['sp'], $row['level'], $row['subjob_id']);
}
}
$tmp = $ms->selectRow('SELECT * FROM user_nobless WHERE char_id = ?d', $charId);
$nobless = is_array($tmp) && $tmp ? 1 : 0;
// Sponsor and apprentice
$sponsor = 0;
$apprentice = 0;
if ($char['pledge_academy_sponsor_id'] > 0)
{
$tmp = $char['pledge_academy_sponsor_id'] + CHAR_OFFSET;
if ($char['pledge_subunit_type'] == -1)
{
$sponsor = $tmp;
}
else
{
$apprentice = $tmp;
}
}
$new = array();
$new['account_name'] = $account;
$new['charId'] = $charIdEx;
$new['char_name'] = $char['char_name'];
$new['level'] = $level;
$new['maxHp'] = round($char['max_hp']);
$new['curHp'] = round($HP);
$new['maxCp'] = round($char['max_cp']);
$new['curCp'] = round($char['cp']);
$new['maxMp'] = round($char['max_mp']);
$new['curMp'] = round($MP);
$new['face'] = $char['face_index'];
$new['hairStyle'] = $char['hair_shape_index'];
$new['hairColor'] = $char['hair_color_index'];
$new['sex'] = $char['gender'];
$new['heading'] = 0;
$new['x'] = $char['xloc'];
$new['y'] = $char['yloc'];
$new['z'] = $char['zloc'];
$new['exp'] = $exp;
$new['expBeforeDeath'] = 0;
$new['sp'] = $SP;
$new['karma'] = $char['align'];
$new['fame'] = $char['fame'];
$new['pvpkills'] = $char['Duel'] < 50000 ? $char['Duel'] : 0;
$new['pkkills'] = $char['PK'];
$new['clanid'] = $char['pledge_id'] + CLAN_OFFSET;
$new['race'] = $char['race'];
$new['classid'] = $char['class'];
$new['base_class'] = $baseClass;
$new['transform_id'] = 0;
$new['deletetime'] = 0;
$new['cancraft'] = 0; // !!!
$new['title'] = !is_string($char['nickname']) || strlen($char['nickname']) > 16 ? '' : trim($char['nickname']);
$new['title_color'] = $char['title_color'] == 15530402 ? 16777079 : $char['title_color'];
$new['rec_have'] = 0;
$new['rec_left'] = 9;
$new['accesslevel'] = $char['builder'] == 1 ? 1 : 0;
$new['online'] = 0;
$new['onlinetime'] = $char['use_time'];
$new['newbie'] = 0;
$new['lastAccess'] = timeToJava($char['login']);
$new['clan_privs'] = 0;
$new['wantspeace'] = 0;
$new['isin7sdungeon'] = 0;
$new['punish_level'] = 0;
$new['punish_timer'] = 0;
$new['power_grade'] = $char['pledge_power_grade'];
$new['nobless'] = $nobless;
$new['subpledge'] = $char['pledge_subunit_type'];
$new['last_recom_date'] = 0;
$new['lvl_joined_academy'] = $char['level_join_academy'];
$new['apprentice'] = $apprentice;
$new['sponsor'] = $sponsor;
$new['varka_ketra_ally'] = $varkaKetraAlly; // [-5,-1] varka, 0 neutral, [1,5] ketra
$new['clan_join_expiry_time'] = 0;
$new['clan_create_expiry_time'] = 0;
$new['death_penalty_level'] = 0;
$new['bookmarkslot'] = 0;
$new['vitality_points'] = 1;
$new['createTime'] = timeToJava($char['create_date']);
$new['language'] = 'en';
$my->query('INSERT INTO characters(?#) VALUES(?a)', array_keys($new), array_values($new));
$skills = $ms->select('SELECT * FROM user_skill WHERE char_id = ?d', $charId);
foreach ($skills as $skill)
{
$insert->add('character_skills', array($charIdEx, $skill['skill_id'], $skill['skill_lev'], $skill['subjob_id']));
}
$recipes = $ms->select('SELECT * FROM user_recipe WHERE char_id = ?d', $charId);
foreach ($recipes as $recipe)
{
$type = isset($commonCraft[$recipe['recipe_id']]) ? 0 : 1;
$insert->add('character_recipebook', array($charIdEx, $recipe['recipe_id'], 0, $type));
}
// Quests
$completedQuests = array();
$bin = $char['quest_flag'];
for ($i = 0; $i < strlen($bin); $i++)
{
$d = ord($bin[$i]);
for ($j = 0; $j < 8; $j++)
{
$id = $i * 8 + $j;
$flag = (($d & 1) > 0);
if ($flag) $completedQuests[] = $id;
$d = $d >> 1;
}
}
foreach ($completedQuests as $questId)
{
if (!isset($questNames[$questId])) continue;
$name = $questNames[$questId];
$insert->add('character_quests', array($charIdEx, $name, '<state>', 'Completed', 0));
}
$quests = $ms->selectRow('SELECT * FROM quest WHERE char_id = ?d', $charId);
if (is_array($quests) && $quests)
{
for ($i = 1; $i < 100; $i++)
{
if (!isset($quests['q' . $i])) break;
$id = intval($quests['q' . $i]);
if (in_array($id, $completedQuests)) continue;
if (in_array($id, array(255))) continue;
if (!isset($questNames[$id])) continue;
$name = $questNames[$id];
$state = intval($quests['j' . $i]);
$cond = getQuestCondFromState($state);
$insert->add('character_quests', array($charIdEx, $name, '<state>', 'Started', 0));
$insert->add('character_quests', array($charIdEx, $name, 'cond', strval($cond), 0));
if ($state != 0 && $cond != $state)
{
$insert->add('character_quests', array($charIdEx, $name, '__compltdStateFlags', strval($state), 0));
}
}
}
}
$insert->process();
$progress->done();
//throw new Exception('Halt.');
// Pets
$progress->setText('lin2world.pet_data');
$res = mssql_query('SELECT * FROM pet_data', $db);
$progress->setMax(mssql_num_rows($res));
$pets = new Pets($my, 'data/petdata.txt', 'data/npcdata.txt');
$slots = array('slot1' => 'weapon', 'slot2' => 'armor');
while ($pet = mssql_fetch_array($res))
{
$progress->next();
$objectId = intval($pet['pet_id'] + ITEM_OFFSET);
$collar = $my->selectRow('SELECT * FROM items WHERE object_id = ?d', $objectId);
if (!is_array($collar) || !$collar) continue;
$level = intval($collar['enchant_level']);
if ($level <= 0) throw new Exception('Invalid level!');
$name = trim($pet['nick_name']);
if ($name == '') $name = null;
$stats = $pets->getStatsByLevel($pet['npc_class_id'] - 1000000, $level + 1);
$items = array();
foreach ($slots as $old => $new)
{
$items[$new] = 0;
if ($pet[$old] > 0)
{
$row = $my->selectRow('SELECT item_id FROM items WHERE object_id = ?d', $pet[$old] + ITEM_OFFSET);
if (is_array($row) && $row) $items[$new] = $row['item_id'];
}
}
// item_obj_id, name, level, curHp, curMp, exp, sp, fed, weapon, armor, jewel
$insert->add('pets', array($objectId, $name, $stats['level'], $stats['hpMax'], $stats['mpMax'], $stats['expMax'], $pet['sp'], $stats['feedMax'], $items['weapon'], $items['armor'], 0));
if ($level != $stats['level'])
{
$my->query('UPDATE items SET enchant_level = ?d WHERE object_id = ?d LIMIT 1', $stats['level'], $objectId);
}
}
$insert->process();
$progress->done();
//throw new Exception('Halt.');
$progress->setText('lin2world.alliance');
$rows = $ms->select('SELECT * FROM Alliance');
$progress->setMax(count($rows));
$alliances = array();
foreach ($rows as $row)
{
$progress->next();
$alliances[$row['id']] = $row;
}
$progress->done();
$progress->setText('lin2world.pledge');
$res = mssql_query('SELECT * FROM Pledge', $db);
$progress->setMax(mssql_num_rows($res));
while ($clan = mssql_fetch_array($res))
{
$progress->next();
if ($clan['alliance_id'] > 0)
{
if (isset($alliances[$clan['alliance_id']]))
{
$ally = $alliances[$clan['alliance_id']];
}
else
{
throw new Exception('Alliance not found!');
}
}
else
{
$ally = false;
}
$new = array();
$new['clan_id'] = $clan['pledge_id'] + CLAN_OFFSET;
$new['clan_name'] = $clan['name'];
$new['clan_level'] = $clan['skill_level'];
$new['reputation_score'] = $clan['reputation_point'];
$new['hasCastle'] = $clan['castle_id'];
$new['ally_id'] = $ally ? $ally['master_pledge_id'] + CLAN_OFFSET : 0;
if ($ally && $ally['master_pledge_id'] == $clan['pledge_id']) $new['ally_name'] = $ally['name'];
$new['leader_id'] = $clan['ruler_id'] + CHAR_OFFSET;
$new['crest_id'] = 0;
$new['crest_large_id'] = 0;
$new['ally_crest_id'] = 0;
$new['auction_bid_at'] = 0;
$new['ally_penalty_expiry_time'] = 0;
$new['ally_penalty_type'] = 0;
$new['char_penalty_expiry_time'] = 0;
$new['dissolving_expiry_time'] = 0;
$my->query('INSERT INTO clan_data(?#) VALUES(?a)', array_keys($new), array_values($new));
$items = $ms->select('SELECT * FROM user_item WHERE char_id = ?d AND warehouse = 2', $clan['pledge_id']);
$slotType = 'CLANWH';
$slotIndex = 0;
foreach ($items as $item)
{
$insert->add('items', array($clan['pledge_id'] + CLAN_OFFSET, $item['item_id'] + ITEM_OFFSET, $item['item_type'], $item['amount'], $item['enchant'], $slotType, $slotIndex, null, 0, 0, -1, -1));
insertExtItemData($item['item_id'] + ITEM_OFFSET, $item['bless'], $item['eroded'], false);
}
$skills = $ms->select('SELECT * FROM pledge_skill WHERE pledge_id = ?d', $clan['pledge_id']);
foreach ($skills as $skill)
{
$insert->add('clan_skills', array($clan['pledge_id'] + CLAN_OFFSET, $skill['skill_id'], $skill['skill_lev'], 'Unknown'));
}
}
$wars = $ms->select('SELECT * FROM war_declare');
foreach ($wars as $war)
{
$insert->add('clan_wars', array($war['challenger'] + CLAN_OFFSET, $war['challengee'] + CLAN_OFFSET, 0, 0));
}
unset($wars);
$subunits = $ms->select('SELECT * FROM pledge_subunit');
foreach ($subunits as $subunit)
{
$insert->add('clan_subpledges', array($subunit['pledge_id'] + CLAN_OFFSET, $subunit['subunit_type'], $subunit['subunit_name'], $subunit['subunit_master_id'] + CHAR_OFFSET));
}
unset($subunits);
// Castles
$castles = $my->select('SELECT * FROM castle');
$siegeDate = intval(strtotime('next Sunday') + 3600 * 24 * 7 + 3600 * 16);
$n = intval(count($castles) / 2);
foreach ($castles as $castle)
{
if ($n-- == 0)
{
$siegeDate += 3600 * 4;
}
$my->query('UPDATE castle SET taxPercent = ?d, treasury = ?d, siegeDate = ?, regTimeOver = ?, regTimeEnd = ?, showNpcCrest = ? WHERE id = ?d',
0, 0, timeToJava($siegeDate), 'true', timeToJava($siegeDate - 3600 * 24 * 13), 'false', $castle['id']);
}
unset($castles);
// Clan halls
$my->query('UPDATE clanhall SET ownerId = 0, paidUntil = 0, paid = 0');
$my->query('TRUNCATE clanhall_functions');
$agits = $ms->select('SELECT * FROM agit');
$paidUntil = timeToJava(strtotime('next Monday') + 3600 * 20);
foreach ($agits as $agit)
{
if ($agit['pledge_id'] <= 0) continue;
$row = $my->selectRow('SELECT * FROM clanhall WHERE id = ?d', $agit['id']);
if (!is_array($row) || !$row) continue;
$siege = $row['lease'] == 0;
$my->query('UPDATE clanhall SET ownerId = ?d, paid = ?d, paidUntil = ? WHERE id = ?d', $agit['pledge_id'] + CLAN_OFFSET, $siege ? 0 : 1, $siege ? 0 : $paidUntil, $agit['id']);
}
unset($agits);
$progress->setText('Olympiad');
$progress->setMax(3);
$tmp = $ms->selectRow('SELECT MAX(season) AS season FROM olympiad_result');
if (!is_array($tmp) || !$tmp) throw new Exception('Empty olympiad_result!');
$lastSeason = $tmp['season'];
$tmp = $ms->selectRow('SELECT MAX(season) AS season FROM olympiad');
if (!is_array($tmp) || !$tmp) throw new Exception('Empty olympiad!');
$season = $tmp['season'];
$progress->next();
$heroes = $ms->select('SELECT * FROM user_nobless N LEFT JOIN user_data U ON N.char_id = U.char_id WHERE hero_type = 2');
foreach ($heroes as $hero)
{
$tmp = $ms->selectRow('SELECT * FROM olympiad_result WHERE season = ?d AND char_id = ?d', $lastSeason, $hero['char_id']);
if (!is_array($tmp) || !$tmp) throw new Exception('Unknown hero!');
$class = intval($tmp['class']);
$insert->add('heroes', array($hero['char_id'] + CHAR_OFFSET, $class, $hero['win_count'], 1, ''));
}
$progress->next();
$rows = $ms->select('SELECT * FROM olympiad_result WHERE season = ?d', $lastSeason);
foreach ($rows as $row)
{
$drawn = max($row['match_count'] - $row['olympiad_win_count'] - $row['olympiad_lose_count'], 0);
$insert->add('olympiad_nobles_eom', array($row['char_id'] + CHAR_OFFSET, $row['class'], $row['point'], $row['match_count'], $row['olympiad_win_count'], $row['olympiad_lose_count'], $drawn));
}
$progress->next();
$rows = $ms->select('SELECT * FROM user_nobless WHERE match_count > 0');
foreach ($rows as $row)
{
$tmp = $ms->selectRow('SELECT TOP 1 * FROM olympiad_match WHERE char_id = ?d', $row['char_id']);
if (!is_array($tmp) || !$tmp) throw new Exception('Invalid nobless!');
$class = $tmp['class'];
$drawn = max($row['match_count'] - $row['olympiad_win_count'] - $row['olympiad_lose_count'], 0);
$insert->add('olympiad_nobles', array($row['char_id'] + CHAR_OFFSET, $class, $row['olympiad_point'], $row['match_count'], $row['olympiad_win_count'], $row['olympiad_lose_count'], $drawn));
}
$progress->done();
$progress->setText('Olympiad (matchs)');
$res = mssql_query('SELECT * FROM olympiad_match WHERE season > ' . ($lastSeason - 6) . ' AND is_winner = 1', $db);
$progress->setMax(mssql_num_rows($res));
while ($row = mssql_fetch_array($res))
{
$progress->next();
$rival = $ms->selectRow('SELECT TOP 1 * FROM olympiad_match WHERE match_time = ?d AND char_id = ?d AND rival_id = ?d AND is_winner = 0', $row['match_time'], $row['rival_id'], $row['char_id']);
if (!is_array($rival) || !$rival) continue;
$insert->add('olympiad_fights', array($row['char_id'] + CHAR_OFFSET, $row['rival_id'] + CHAR_OFFSET, $row['class'], $rival['class'], 1, timeToJava(intval($row['match_time'])), 60000, $row['class'] == $rival['class'] ? 1 : 0));
}
$insert->process();
// Other
$my->query('UPDATE items SET item_id = 9142 WHERE item_id = 5249');
$progress->done();
$progress->end();
}
catch (Exception $e)
{
$progress->error($e->getMessage());
}
?>