/** * eco_bld_handle_que.php * Handles building in hangar * * @oldname HandleElementBuildingQueue.php * @package economic * @version 2 * * Revision History * ================ * 2 - copyright (c) 2010 by Gorlum for http://supernova.ws * [!] Full rewrite * [%] Fixed stupid bug that allows to build several fast-build * units utilizing build-time of slow-build units upper in que * [~] Some optimizations and speedups * [~] Complies with PCG1 * * 1 - copyright 2008 By Chlorel for XNova */ function eco_bld_handle_que($user, &$planet, $production_time) { global $sn_data; $quest_rewards = array(); if ($planet['b_hangar_id'] != 0) { $hangar_time = $planet['b_hangar'] + $production_time; $que = explode(';', $planet['b_hangar_id']); $quest_list = qst_get_quests($user['id']); $quest_triggers = qst_active_triggers($quest_list); $built = array(); $new_hangar = ''; $skip_rest = false; foreach ($que as $que_string) { if ($que_string) { $que_data = explode(',', $que_string); $unit_id = $que_data[0]; $count = $que_data[1]; $build_time = GetBuildingTime($user, $planet, $unit_id); if (!$skip_rest) { $unit_db_name = $sn_data[$unit_id]['name']; $planet_unit = $planet[$unit_db_name]; while ($hangar_time >= $build_time && $count > 0) { $hangar_time -= $build_time; $count--; $built[$unit_id]++; $planet_unit++; } $planet[$unit_db_name] = $planet_unit; // TODO: Check mutiply condition quests $quest_trigger_list = array_keys($quest_triggers, $unit_id); foreach ($quest_trigger_list as $quest_id) { if ($quest_list[$quest_id]['quest_unit_amount'] <= $planet[$unit_db_name] && $quest_list[$quest_id]['quest_status_status'] != QUEST_STATUS_COMPLETE) { $quest_rewards[$quest_id] = $quest_list[$quest_id]['quest_rewards']; $quest_list[$quest_id]['quest_status_status'] = QUEST_STATUS_COMPLETE; } } if ($count) { $skip_rest = true; } } if ($count > 0) { $new_hangar .= "{$unit_id},{$count};"; } } } if (!$new_hangar) { $hangar_time = 0; } $planet['b_hangar'] = $hangar_time; $planet['b_hangar_id'] = $new_hangar; } else { $built = ''; $planet['b_hangar'] = 0; } return array('built' => $built, 'rewards' => $quest_rewards); }
function HandleTechnologieBuild(&$user, &$planetrow) { global $sn_data, $time_now, $lang; if ($user['b_tech_planet']) { if ($user['b_tech_planet'] != $planetrow['id']) { $planet = doquery("SELECT * FROM `{{planets}}` WHERE `id` = '{$user['b_tech_planet']}' LIMIT 1;", '', true); } else { $planet = $planetrow; } if ($planet['b_tech'] && $planet['b_tech_id'] && $planet['b_tech'] <= $time_now) { $unit_id = $planet['b_tech_id']; $unit_db_name = $sn_data[$unit_id]['name']; $user[$unit_db_name]++; msg_send_simple_message($user['id'], 0, $time_now, MSG_TYPE_QUE, $lang['msg_que_research_from'], $lang['msg_que_research_subject'], sprintf($lang['msg_que_research_message'], $lang['tech'][$planet['b_tech_id']], $user[$unit_db_name])); $quest_list = qst_get_quests($user['id']); $quest_triggers = qst_active_triggers($quest_list); $quest_rewards = array(); // TODO: Check mutiply condition quests $quest_trigger_list = array_keys($quest_triggers, $unit_id); foreach ($quest_trigger_list as $quest_id) { if ($quest_list[$quest_id]['quest_unit_amount'] <= $user[$unit_db_name] && $quest_list[$quest_id]['quest_status_status'] != QUEST_STATUS_COMPLETE) { $quest_rewards[$quest_id] = $quest_list[$quest_id]['quest_rewards']; $quest_list[$quest_id]['quest_status_status'] = QUEST_STATUS_COMPLETE; } } qst_reward($user, $planet, $quest_rewards, $quest_list); doquery("UPDATE `{{planets}}` SET `b_tech` = '0', `b_tech_id` = '0' WHERE `id` = '{$planet['id']}' LIMIT 1;"); doquery("UPDATE `{{users}}` SET `{$unit_db_name}` = `{$unit_db_name}` + 1, `b_tech_planet` = '0' WHERE `id` = '{$user['id']}' LIMIT 1;"); $planet["b_tech_id"] = 0; } elseif ($planet["b_tech_id"] == 0) { // Il n'y a rien a l'ouest ... // Pas de Technologie en cours devait y avoir un bug lors de la derniere connexion // On met l'enregistrement informant d'une techno en cours de recherche a jours doquery("UPDATE `{{users}}` SET `b_tech_planet` = '0' WHERE `id` = '{$user['id']}' LIMIT 1;"); } } }
function que_process(&$user, $planet = null, $on_time = SN_TIME_NOW) { sn_db_transaction_check(true); $que = array(); // Блокируем пользователя. Собственно, запись о нём нам не нужна - будем использовать старую $user = db_user_by_id($user['id'], true); $time_left[$user['id']][0] = max(0, $on_time - $user['que_processed']); if ($planet === null && !$time_left[$user['id']][0]) { // TODO return $que; } // Определяем, какие очереди нам нужны и получаем их $que_type_id = $planet === null ? QUE_RESEARCH : false; $planet = intval(is_array($planet) ? $planet['id'] : $planet); // В $planet у нас теперь только её ID или шаблон null/0/false $que = que_get($user['id'], $planet, $que_type_id, true); //pdump($que); if (empty($que['items'])) { return $que; } $planet_list = array(); if ($planet !== null) { // Если нужно изменять данные на планетах - блокируем планеты и получаем данные о них // TODO - от них не надо ничего, кроме ID и que_processed // $planet_query = db_planet_list_by_user_or_planet($user['id'], $planet); // foreach($planet_query as $planet_row) $planet_row = db_planet_list_by_user_or_planet($user['id'], $planet); $planet_list[$planet_row['id']] = $planet_row; $time_left[$planet_row['id_owner']][$planet_row['id']] = max(0, $on_time - $planet_row['que_processed']); } // pdump($time_left); // Теперь в $time_left лежит время обсчета всех очередей по каждой из планеты if (array_sum($time_left[$user['id']]) == 0) { return $que; } // pdump($que); $db_changeset = array(); $unit_changes = array(); foreach ($que['items'] as &$que_item) { $que_player_id =& $que_item['que_player_id']; $que_planet_id = intval($que_item['que_planet_id']); // $que_type = &$que_item['que_type']; $que_time_left =& $que['time_left'][$que_player_id][$que_planet_id][$que_item['que_type']]; if (!isset($que_time_left)) { $que_time_left = $time_left[$que_player_id][$que_planet_id]; } if ($que_time_left <= 0 || $que_item['que_unit_amount'] <= 0) { continue; } // Дальше мы идем, если только осталось время в очереди И юниты к постройке // Вычисляем, сколько целых юнитов будет построено - от 0 до количества юнитов в очереди $unit_processed = min($que_item['que_unit_amount'] - 1, floor($que_time_left / $que_item['que_unit_time'])); // Вычитаем это время из остатков $que_time_left -= $unit_processed * $que_item['que_unit_time']; // Теперь работаем с остатком времени на юните. Оно не может быть равно или меньше нуля // Если времени в очереди осталось не меньше, чем время текущего юнита - значит мы достроили юнит if ($que_time_left >= $que_item['que_time_left']) { // Увеличиваем количество отстроенных юнитов $unit_processed++; // Вычитаем из времени очереди потраченное на постройку время $que_time_left -= $que_item['que_time_left']; // Полное время юнита равно времени нового юнита $que_item['que_time_left'] = $que_item['que_unit_time']; // Тут у нас может остатся время очереди - если постройка была не последняя } // Изменяем количество оставшихся юнитов $que_item['que_unit_amount'] -= $unit_processed; // Если еще остались юниты - значит ВСЁ оставшееся время приходится на достройку следующего юнита if ($que_item['que_unit_amount'] > 0) { $que_item['que_time_left'] = $que_item['que_time_left'] - $que_time_left; $que_time_left = 0; } if ($que_item['que_unit_amount'] <= 0) { $db_changeset['que'][] = array('action' => SQL_OP_DELETE, P_VERSION => 1, 'where' => array("que_id" => $que_item['que_id'])); } else { $db_changeset['que'][] = array('action' => SQL_OP_UPDATE, P_VERSION => 1, 'where' => array("que_id" => $que_item['que_id']), 'fields' => array('que_unit_amount' => array('delta' => -$unit_processed), 'que_time_left' => array('set' => $que_item['que_time_left']))); } if ($unit_processed) { $unit_processed_delta = $unit_processed * ($que_item['que_unit_mode'] == BUILD_CREATE ? 1 : -1); $unit_changes[$que_player_id][$que_planet_id][$que_item['que_unit_id']] += $unit_processed_delta; } } foreach ($time_left as $player_id => $planet_data) { foreach ($planet_data as $planet_id => $time_on_planet) { $table = $planet_id ? 'planets' : 'users'; $id = $planet_id ? $planet_id : $player_id; $db_changeset[$table][] = array('action' => SQL_OP_UPDATE, P_VERSION => 1, 'where' => array("id" => $id), 'fields' => array('que_processed' => array('set' => $on_time))); if (is_array($unit_changes[$player_id][$planet_id])) { foreach ($unit_changes[$player_id][$planet_id] as $unit_id => $unit_amount) { $db_changeset['unit'][] = sn_db_unit_changeset_prepare($unit_id, $unit_amount, $user, $planet_id ? $planet_id : null); } } } } //pdump($db_changeset, '$db_changeset'); $que = que_recalculate($que); //pdump($que, '$que'); // TODO: Re-enable quests for Alliances if (!empty($unit_changes) && !$user['user_as_ally']) { $quest_list = qst_get_quests($user['id']); $quest_triggers = qst_active_triggers($quest_list); $quest_rewards = array(); $xp_incoming = array(); foreach ($unit_changes as $user_id => $planet_changes) { foreach ($planet_changes as $planet_id => $changes) { $planet_this = $planet_id ? classSupernova::db_get_record_by_id(LOC_PLANET, $planet_id) : array(); foreach ($changes as $unit_id => $unit_value) { $que_id = que_get_unit_que($unit_id); $unit_level_new = mrc_get_level($user, $planet_this, $unit_id, false, true) + $unit_value; if ($que_id == QUE_STRUCTURES || $que_id == QUE_RESEARCH) { $build_data = eco_get_build_data($user, $planet_this, $unit_id, $unit_level_new - 1); $build_data = $build_data[BUILD_CREATE]; foreach (sn_get_groups('resources_loot') as $resource_id) { $xp_incoming[$que_id] += $build_data[$resource_id]; // TODO - добавить конверсию рейтов обмена } } if (is_array($quest_triggers)) { // TODO: Check mutiply condition quests $quest_trigger_list = array_keys($quest_triggers, $unit_id); if (is_array($quest_trigger_list)) { foreach ($quest_trigger_list as $quest_id) { if ($quest_list[$quest_id]['quest_status_status'] != QUEST_STATUS_COMPLETE && $quest_list[$quest_id]['quest_unit_amount'] <= $unit_level_new) { $quest_rewards[$quest_id][$user_id][$planet_id] = $quest_list[$quest_id]['quest_rewards_list']; $quest_list[$quest_id]['quest_status_status'] = QUEST_STATUS_COMPLETE; } } } } } } } // TODO: Изменить начисление награды за квесты на ту планету, на которой происходил ресеч qst_reward($user, $quest_rewards, $quest_list); foreach ($xp_incoming as $que_id => $xp) { rpg_level_up($user, $que_id == QUE_RESEARCH ? RPG_TECH : RPG_STRUCTURE, $xp / 1000); } } db_changeset_apply($db_changeset); // TODO Сообщения о постройке // $user = db_user_by_id($user['id'], true); return $que; /* // $local_que['time_left'][QUE_RESEARCH][0] = $time_left[QUE_RESEARCH][0]; //pdump($user_time_left, '$user_time_left'); print('1'); //foreach($local_que as $que_id => &$que_data) //{ // if(!intval($que_id))continue; foreach(sn_get_groups('que') as $que_id => $que_info) { if(!isset($que['ques'][$que_id]))continue; foreach($que_data as $owner_id => &$que_items) { foreach($que_items as &$que_item) { // Вычисляем, сколько целых юнитов будет построено - от 0 до количества юнитов в очереди $unit_processed = min($que_item['que_unit_amount'] - 1, floor($local_que['time_left'][$que_id][$owner_id] / $que_item['que_unit_time'])); // Вычитаем это время из остатков $local_que['time_left'][$que_id][$owner_id] -= $unit_processed * $que_item['que_unit_time']; // Теперь работаем с остатком времени на юните. Оно не может быть равно или меньше нуля // Вычитаем остаток времени работы очереди с времени постройки юнита if($que_item['que_time_left'] <= $local_que['time_left'][$que_id][$owner_id]) { // Если время постройки - неположительное, значит мы достроили юнит // Увеличиваем количество отстроенных юнитов $unit_processed++; // Вычитаем из времени очереди потраченное на постройку время $local_que['time_left'][$que_id][$owner_id] -= $que_item['que_time_left']; $que_item['que_time_left'] = $que_item['que_unit_time']; // Тут у нас может остатся время очереди - если постройка была не последняя } // Изменяем количество оставшихся юнитов $que_item['que_unit_amount'] -= $unit_processed; if($que_item['que_unit_amount']) { $que_item['que_time_left'] = $que_item['que_time_left'] - $local_que['time_left'][$que_id][$owner_id]; $local_que['time_left'][$que_id][$owner_id] = 0; } if(!$que_item['que_unit_amount']) { $db_changeset['que'][$que_item['que_id']] = array( 'action' => SQL_OP_DELETE, 'where' => array( "`que_id` = {$que_item['que_id']}", ), ); } else { $db_changeset['que'][$que_item['que_id']] = array( 'action' => SQL_OP_UPDATE, 'where' => array( "`que_id` = {$que_item['que_id']}", ), 'fields' => array( 'que_unit_amount' => array( 'delta' => -$unit_processed ), 'que_time_left' => array( 'set' => $que_item['que_time_left'] ), ), ); } if($unit_processed) { $unit_processed_delta = $unit_processed * ($que_item['que_unit_mode'] == BUILD_CREATE ? 1 : -1); $unit_changes[$owner_id][$que_item['que_unit_id']] += $unit_processed_delta; } // Если на очереди времени не осталось - выходим if(!$local_que['time_left'][$que_id][$owner_id]) { break; } } } } die(); // TODO: Re-enable quests for Alliances if(!empty($unit_changes) && !$user['user_as_ally'] && $user['id_planet']) { $planet = db_planet_by_id($user['id_planet'], true); $quest_list = qst_get_quests($user['id']); $quest_triggers = qst_active_triggers($quest_list); } else { $planet = array(); } $quest_rewards = array(); $xp_incoming = 0; foreach($unit_changes as $owner_id => $changes) { // $user_id_sql = $owner_id ? $owner_id : $user['id']; $planet_id_sql = $owner_id ? $owner_id : null; foreach($changes as $unit_id => $unit_value) { $db_changeset['unit'][] = sn_db_unit_changeset_prepare($unit_id, $unit_value, $user, $planet_id_sql); // TODO: Изменить согласно типу очереди $unit_level_new = mrc_get_level($user, array(), $unit_id, false, true) + $unit_value; $build_data = eco_get_build_data($user, array(), $unit_id, $unit_level_new - 1); $build_data = $build_data[BUILD_CREATE]; foreach(sn_get_groups('resources_loot') as $resource_id) { $xp_incoming += $build_data[$resource_id]; } if($planet['id']) { // TODO: Check mutiply condition quests $quest_trigger_list = array_keys($quest_triggers, $unit_id); foreach($quest_trigger_list as $quest_id) { if($quest_list[$quest_id]['quest_status_status'] != QUEST_STATUS_COMPLETE && $quest_list[$quest_id]['quest_unit_amount'] <= $unit_level_new) { $quest_rewards[$quest_id] = $quest_list[$quest_id]['quest_rewards']; $quest_list[$quest_id]['quest_status_status'] = QUEST_STATUS_COMPLETE; } } } } } // TODO: Изменить согласно типу очереди rpg_level_up($user, RPG_TECH, $xp_incoming / 1000); // TODO: Изменить начисление награды за квесты на ту планету, на которой происходил ресеч qst_reward($user, $planet, $quest_rewards, $quest_list); db_changeset_apply($db_changeset); // Сообщения о постройке $user = db_user_by_id($user['id'], true); // TODO Так же пересчитывать планеты // sn_db_transaction_commit(); // TODO поменять que_processed у планеты и юзера return $local_que; */ }
function get_quest_amount_complete($user_id) { // TODO: Make it faster - rewrite SQL? return count(qst_get_quests($user_id, QUEST_STATUS_COMPLETE)); }
function eco_que_process($user, &$planet, $time_left) { global $lang; $sn_data =& $GLOBALS['sn_data']; $quest_list = qst_get_quests($user['id']); $quest_triggers = qst_active_triggers($quest_list); $quest_rewards = array(); $que = array(); $built = array(); $xp = array(); $que_amounts = array(); $in_que = array(); $in_que_abs = array(); $query_string = ''; $query = ''; if ($planet['que']) { $que_types = $sn_data['groups']['ques']; foreach ($que_types as $que_type_id => &$que_type_data) { $que_type_data['time_left'] = $time_left; $que_type_data['unit_place'] = 0; $que_type_data['que_changed'] = false; } $que_types[QUE_STRUCTURES]['unit_list'] = $sn_data['groups']['build_allow'][$planet['planet_type']]; $que_strings = explode(';', $planet['que']); foreach ($que_strings as $que_item_string) { //start processing $que_strings // skipping empty que lines if (!$que_item_string) { continue; } //pdump($que_item_string); $que_item = explode(',', $que_item_string); // Skipping invalid negative values for unit_amount if ((int) $que_item[1] < 1) { continue; } $unit_id = $que_item[0]; $que_item = array('ID' => $que_item[0], 'AMOUNT' => $que_item[1] > 0 ? $que_item[1] : 0, 'TIME' => $que_item[2] > 0 ? $que_item[2] : 0, 'TIME_FULL' => $que_item[2] > 0 ? $que_item[2] : 0, 'MODE' => $que_item[3], 'QUE' => $que_item[4], 'NAME' => $lang['tech'][$unit_id], 'STRING' => "{$que_item_string};"); $que_id = $que_item['QUE']; $que_data =& $que_types[$que_id]; if (!in_array($unit_id, $que_data['unit_list'])) { // Unit is in wrong que. It can't happens in normal circuimctances - hacked? // We will not proceed such units continue; } $que_unit_place =& $que_data['unit_place']; $time_left =& $que_data['time_left']; $unit_db_name = $sn_data[$unit_id]['name']; $build_mode = $que_item['MODE'] == BUILD_CREATE ? 1 : -1; $amount_change = $build_mode * $que_item['AMOUNT']; $unit_level = ($planet[$unit_db_name] ? $planet[$unit_db_name] : 0) + $in_que[$unit_id]; $build_data = eco_get_build_data($user, $planet, $unit_id, $unit_level); $build_data = $build_data[$que_item['MODE']]; if ($que_unit_place) { $que_item['TIME'] = $build_data[RES_TIME]; } $que_item['TIME_FULL'] = $build_data[RES_TIME]; $que_unit_place++; if ($time_left > 0) { // begin processing que with time left on it $build_time = $que_item['TIME']; $amount_to_build = min($que_item['AMOUNT'], floor($time_left / $build_time)); if ($amount_to_build > 0) { // This Is Building! // Do not 'optimize' by deleting this IF! It will be need later if ($que_id == QUE_STRUCTURES) { $que_item['AMOUNT'] -= $amount_to_build; $time_left -= min($time_left, $amount_to_build * $build_time); // prevents negative times and cycling $amount_to_build *= $build_mode; $built[$unit_id] += $amount_to_build; $xp_incoming = 0; foreach ($sn_data['groups']['resources_loot'] as $resource_id) { $xp_incoming += $build_data[$resource_id] * $amount_to_build; } $xp[RPG_STRUCTURE] += round(($xp_incoming > 0 ? $xp_incoming : 0) / 1000); $planet[$unit_db_name] += $amount_to_build; $query .= "`{$unit_db_name}` = `{$unit_db_name}` + '{$amount_to_build}',"; $que_type_data['que_changed'] = true; // TODO: Check mutiply condition quests $quest_trigger_list = array_keys($quest_triggers, $unit_id); foreach ($quest_trigger_list as $quest_id) { if ($quest_list[$quest_id]['quest_unit_amount'] <= $planet[$unit_db_name] && $quest_list[$quest_id]['quest_status_status'] != QUEST_STATUS_COMPLETE) { $quest_rewards[$quest_id] = $quest_list[$quest_id]['quest_rewards']; $quest_list[$quest_id]['quest_status_status'] = QUEST_STATUS_COMPLETE; } } } } if ($que_item['AMOUNT'] > 0) { $que_item['TIME'] -= $time_left; $que_item['STRING'] = "{$unit_id},{$que_item['AMOUNT']},{$que_item['TIME']},{$que_item['MODE']},{$que_item['QUE']};"; $time_left = 0; } } else { $time_left = 0; } if ($que_item['AMOUNT'] > 0) { $query_string .= $que_item['STRING']; $que_amounts[$que_id] += $amount_change; $in_que[$unit_id] += $amount_change; $in_que_abs[$unit_id] += $que_item['AMOUNT']; $que_item['LEVEL'] = ($planet[$unit_db_name] ? $planet[$unit_db_name] : 0) + $in_que[$unit_id] + $built[$unit_id]; $que_item['CHANGE'] = $in_que[$unit_id] + $built[$unit_id]; $que[$que_id][] = $que_item; } } // end processing $que_strings } // end if($planet['que']) $planet['que'] = $query_string; $query .= "`que` = '{$query_string}'"; return array('que' => $que, 'built' => $built, 'xp' => $xp, 'amounts' => $que_amounts, 'in_que' => $in_que, 'in_que_abs' => $in_que_abs, 'string' => $query_string, 'query' => $query, 'rewards' => $quest_rewards, 'quests' => $quest_list, 'processed' => true); }