_tableName = 'planets'; $this->_idFieldName = 'id'; $this->_builder = new Legacies_Empire_Model_Planet_Builder($this, $this->getUser()); } public function _afterLoad() { parent::_afterLoad(); $this->_builder->init(); return $this; } public function getLastUpdate() { return $this->getData('last_update'); } public function setLastUpdate($time) { return $this->setData('last_update', $time); } public function updateStorages($time = null) { Math::setPrecision(50); $resources = Legacies_Empire_Model_Game_Resources::getSingleton(); foreach ($resources->getAllDatas() as $resource => $resourceData) { if (!isset($resourceData['storage_field']) || $resourceData['storage_field'] === null) { continue; } $officerEnhancement = (.5 * $this->getUser()->getData('rpg_stockeur')) + 1; $storageEnhancementFactor = Math::floor(Math::pow(1.6, $this[Legacies_Empire::getFieldName($resourceData['storage'])])); $storageEnhancement = Math::mul(BASE_STORAGE_SIZE / 2, $storageEnhancementFactor); $value = Math::mul(MAX_OVERFLOW, Math::mul($officerEnhancement, Math::add(BASE_STORAGE_SIZE, $storageEnhancement))); $this->setData($resourceData['storage_field'], Math::floor($value)); } Math::setPrecision(); return $this; } public function updateBuildingFields() { $types = Legacies_Empire_Model_Game_Types::getSingleton(); if ($this->isPlanet()) { $filter = Legacies_Empire::TYPE_BUILDING_PLANET; } else if ($this->isMoon()) { $filter = Legacies_Empire::TYPE_BUILDING_MOON; } else { return $this; } $usedFields = 0; foreach ($types[$filter] as $buildingId) { $usedFields += $this->getElement($buildingId); } $this->setData('field_current', $usedFields); return $this; } public function updateResourceProduction($time = null) { $types = Legacies_Empire_Model_Game_Types::getSingleton(); $resources = Legacies_Empire_Model_Game_Resources::getSingleton(); $production = Legacies_Empire_Model_Game_Production::getSingleton(); if ($time === null) { $time = Legacies::now(); } if (!$this->isPlanet()) { return $this; } /* * Compute resources consumers and resources producers */ $resourcesTotals = array(); $resourcesProductionTotals = array(); $resourcesConsumptionTotals = array(); $resourcesProducers = array(); $resourcesConsumers = array(); $productionRatios = array(); foreach ($resources->getAllDatas() as $resource => $resourceData) { foreach ($resourceData['production'] as $productionUnit => $ratioField) { if (!in_array($productionUnit, $types['prod'])) { continue; } $level = $this->getData(Legacies_Empire::getFieldName($productionUnit)); $ratio = $this->getData($ratioField); $element = self::getProductionElementInstance($productionUnit); $productionRatios[$productionUnit] = $element->getProductionRatios($level, $ratio, $this, $this->getUser()); foreach ($productionRatios[$productionUnit] as $resourceId => $resourceProduction) { $comp = Math::comp($resourceProduction, 0); if ($comp < 0) { if (!isset($resourcesConsumers[$resourceId])) { $resourcesConsumers[$resourceId] = array(); } $resourcesConsumers[$resourceId][] = $productionUnit; if (!isset($resourcesConsumptionTotals[$resourceId])) { $resourcesConsumptionTotals[$resourceId] = 0; } $resourcesConsumptionTotals[$resourceId] = Math::add($resourcesConsumptionTotals[$resourceId], $resourceProduction); if (!isset($resourcesTotals[$resourceId])) { $resourcesTotals[$resourceId] = 0; } $resourcesTotals[$resourceId] = Math::add($resourcesTotals[$resourceId], $resourceProduction); } else if ($comp > 0) { if (!isset($resourcesProducers[$resourceId])) { $resourcesProducers[$resourceId] = array(); } $resourcesProducers[$resourceId][] = $productionUnit; if (!isset($resourcesProductionTotals[$resourceId])) { $resourcesProductionTotals[$resourceId] = 0; } $resourcesProductionTotals[$resourceId] = Math::add($resourcesProductionTotals[$resourceId], $resourceProduction); if (!isset($resourcesTotals[$resourceId])) { $resourcesTotals[$resourceId] = 0; } $resourcesTotals[$resourceId] = Math::add($resourcesTotals[$resourceId], $resourceProduction); } } } } /* * Compute resource consumption */ $actualProduction = $resourcesTotals; foreach ($resourcesTotals as $resource => $total) { if (Math::isPositiveOrZero($total, 0)) { continue; } $productionRatio = 0; if (isset($resourcesProductionTotals[$resource]) && Math::isPositive($resourcesProductionTotals[$resource])) { $consumptions = Math::mul(-1, $resourcesConsumptionTotals[$resource]); Math::setPrecision(50); $productionRatio = Math::div($resourcesProductionTotals[$resource], $consumptions); Math::setPrecision(); } foreach ($resourcesConsumers[$resource] as $consumer) { foreach ($productionRatios[$consumer] as $resourceId => $ratio) { Math::setPrecision(50); $productionOverhead = Math::mul(Math::sub(1, $productionRatio), $ratio); Math::setPrecision(); $actualProduction[$resourceId] = Math::sub($actualProduction[$resourceId], $productionOverhead); } } } foreach ($actualProduction as $resource => $production) { $this->setData($resources[$resource]['production_field'], $production); } return $this; } public function updateResources($time = null) { $resources = Legacies_Empire_Model_Game_Resources::getSingleton(); if ($time === null) { $time = Legacies::now(); } $timeDiff = ($time - $this->getLastUpdate()) / 3600; foreach ($resources->getAllDatas() as $resourceId => $resourceConfig) { $production = Math::mul($this->getData($resourceConfig['production_field']), $timeDiff); $resourceValue = Math::add($this->getData($resourceConfig['field']), $production); $this->setData($resourceConfig['field'], Math::min($resourceValue, $this->getData($resourceConfig['storage_field']))); } $this->setLastUpdate($time); return $this; } public static function getProductionElementInstance($buildingId) { $production = Legacies_Empire_Model_Game_Production::getSingleton(); if (!isset(self::$_productionInstances[$buildingId])) { if (!isset($production[$buildingId])) { return null; } $class = $production[$buildingId][Legacies_Empire::RESOURCE_CLASS]; $reflection = new ReflectionClass($class); self::$_productionInstances[$buildingId] = $reflection->newInstance(); } return self::$_productionInstances[$buildingId]; } public function getFleetCollection($time = null) { $firstCollection = new Legacies_Core_Collection(array('fleet' => 'fleets')); $firstCollection ->column('*') ->where('fleet.fleet_start_galaxy = :galaxy') ->where('fleet.fleet_start_system = :system') ->where('fleet.fleet_start_planet = :position') ->where('fleet.fleet_start_type = :planet_type') ; $backCollection = new Legacies_Core_Collection(array('fleet' => 'fleets')); $backCollection ->column('*') ->where('fleet.fleet_end_galaxy = :galaxy') ->where('fleet.fleet_end_system = :system') ->where('fleet.fleet_end_planet = :position') ->where('fleet.fleet_end_type = :planet_type') ; $options = array( 'galaxy' => $this->getSystem(), 'system' => $this->getSystem(), 'position' => $this->getPosition(), 'planet_type' => $this->getType() ); if ($time !== null) { $options['now'] = $time; $firstCollection->where('fleet_start_time <= :now'); $backCollection->where('fleet_end_time <= :now'); } $collection = new Legacies_Core_Collection(); $collection ->setEntityClassName('Legacies_Empire_Model_Fleet') ->union($firstCollection) ->union($backCollection) ->load($options) ; return $collection; } public function getUser() { if ($this->_user === null) { $this->_user = Legacies_Empire_Model_User::factory($this->getData('id_owner')); } return $this->_user; } public function setUser(Legacies_Empire_Model_User $user) { $this->_user = $user; return $this; } public function getShipyard() { if ($this->_shipyard === null) { $this->_shipyard = new Legacies_Empire_Model_Planet_Building_Shipyard($this, $this->getUser()); } return $this->_shipyard; } public function setShipyard(Legacies_Empire_Model_Planet_Building_Shipyard $shipyard) { $this->_shipyard = $shipyard; return $this; } public function isPlanet() { return (bool) ($this->getData('planet_type') == self::TYPE_PLANET); } public function isDebris() { return (bool) ($this->getData('planet_type') == self::TYPE_DEBRIS); } public function isMoon() { return (bool) ($this->getData('planet_type') == self::TYPE_MOON); } public function getMoon() { static $statement = null; if ($this->isMoon()) { return null; } if ($this->_moon === null) { if ($statement === null) { $statement = new Legacies_Core_Collection(array('planet' => 'planets'), get_class($this)); $statement ->where('galaxy=:galaxy') ->where('system=:system') ->where('planet=:position') ->where('planet_type=' . strval(self::TYPE_MOON)) ; } $statement->load(array( 'galaxy' => $this->getGalaxy(), 'system' => $this->getSystem(), 'position' => $this->getPosition() )); $this->_moon = $statement->current(); } return $this->_moon; } public function setGalaxy($galaxy) { $this->setData('galaxy', $galaxy); return $this; } public function getGalaxy() { return (int) $this->getData('galaxy'); } public function setSystem($system) { $this->setData('system', $system); return $this; } public function getSystem() { return (int) $this->getData('system'); } public function setPosition($position) { $this->setData('planet', $position); return $this; } public function getPosition() { return (int) $this->getData('planet'); } public function setType($type) { $this->setData('planet_type', $type); return $this; } public function getType() { return (int) $this->getData('planet_type'); } public function getElement($elementId) { $fields = Legacies_Empire_Model_Game_FieldsAlias::getSingleton(); return $this->getData($fields[$elementId]); } public function setElement($elementId, $level) { $fields = Legacies_Empire_Model_Game_FieldsAlias::getSingleton(); return $this->setData($fields[$elementId], $level); } public function hasElement($elementId, $levelRequired = 0) { $fields = Legacies_Empire_Model_Game_FieldsAlias::getSingleton(); return $this->hasData($fields[$elementId]) && Math::comp($this->getElement($elementId), $levelRequired) > 0; } public function appendBuildingQueue($buildingId, $destroy = false, $time = null) { $types = Legacies_Empire_Model_Game_Types::getSingleton(); $prices = Legacies_Empire_Model_Game_Prices::getSingleton(); if ($time === null) { $time = Legacies::now(); } if (!$types->is($buildingId, Legacies_Empire::TYPE_BUILDING)) { return $this; } if ($destroy === false && !$this->checkAvailability($buildingId)) { return $this; } // Dispatch 'planet.building.append-queue.before' event Legacies::dispatchEvent($this->_eventPrefix . 'building.append-queue.before', array( 'bulding_id' => $buildingId, 'level' => $this->getElement($buildingId), 'planet' => $this, 'user' => $this->getUser(), 'destroy' => $destroy )); if ($destroy === false) { $level = $this->getElement($buildingId) + 1; } else { $level = max($this->getElement($buildingId) - 1, 0); } $this->_builder->appendQueue($buildingId, $level, $time); // Dispatch 'planet.shipyard.append-queue.after' event Legacies::dispatchEvent($this->_eventPrefix . 'building.append-queue.after', array( 'bulding_id' => $buildingId, 'level' => $this->getElement($buildingId), 'planet' => $this, 'user' => $this->getUser(), 'destroy' => $destroy )); return $this; } public function updateBuildingQueue($time = null) { if ($time === null) { $time = Legacies::now(); } // Dispatch event Legacies::dispatchEvent($this->_eventPrefix . 'update-queue.before', array( 'time' => &$time, 'planet' => $this->_currentPlanet, 'user' => $this->_currentUser )); $this->_builder->updateQueue($time); // Dispatch event Legacies::dispatchEvent($this->_eventPrefix . 'update-queue.after', array( 'time' => $time, 'shipyard' => $this, 'planet' => $this->_currentPlanet, 'user' => $this->_currentUser )); return $this; } public function getBuildingQueue() { return $this->_builder; } /** * Check if a building is actually buildable on the current planet, * depending on the technology and buildings requirements. * * @param int $buildingId * @return bool */ public function checkAvailability($buildingId) { $this->_builder->checkAvailability($buildingId); try { // Dispatch event. Throw an exception to break the avaliability. Legacies::dispatchEvent($this->_eventPrefix . 'check-availability', array( 'ship_id' => $buildingId, 'shipyard' => $this, 'planet' => $this->_currentPlanet, 'user' => $this->_currentUser )); } catch (Exception $e) { return false; } return true; } /** * Get the resources needed to build a specific building * * @param int $buildingId * @return bool */ public function getResourcesNeeded($buildingId, $level) { return $this->_builder->getResourcesNeeded($buildingId, $level); } /** * Get the time needed to build a specific building * * @param int $buildingId * @return bool */ public function getBuildingTime($buildingId, $level) { return $this->_builder->getBuildingTime($buildingId, $level); } public static function registrationListener($eventData) { if (isset($eventData['user'])) { $user = $eventData['user']; $request = $eventData['request']; if ($user === null || !$user instanceof Legacies_Empire_Model_User || $user->getId()) { return; } if ($request === null || !$request instanceof Legacies_Core_Controller_Request) { return; } $collection = new Legacies_Core_Collection('planets'); $collection ->column(array( 'galaxy' => 'planet.galaxy', 'system' => 'planet.system', 'count' => 'COUNT(planet.id)' )) ->group('planet.galaxy') ->group('planet.system') ->where('planet.planet_type=1') ->order('COUNT(planet.id)', 'ASC') ->order('RAND()', 'ASC') ->limit(1) ; $params = array(); $galaxy = $request->getParam('system'); if ($galaxy !== null) { $collection->where('planet.galaxy=:galaxy'); $params['galaxy'] = $galaxy; $systems = explode(',', $request->getParam('system')); if (is_array($systems) && count($systems) == 2 && is_int($systems[0]) && is_int($systems[1])) { $collection->where('planet.system IN(' . implode(', ', range($systems[0], $systems[1])) . ')'); } } $collection->load($params); if ($collection->count() == 0) { throw new Exception('No planet to colonize there!'); // FIXME } $systemInfo = $collection->current(); if ($systemInfo->getData('count') >= MAX_PLANET_IN_SYSTEM) { throw new Exception('No planet to colonize there!'); // FIXME } $system = $systemInfo->getData('system'); $galaxy = $systemInfo->getData('galaxy'); $collection = new Legacies_Core_Collection('planets'); $collection ->column(array('position' => 'planet.position')) ->where('planet.planet_type=1') ->where('planet.planet_type=:system') ->load() ; $positions = range(1, MAX_PLANET_IN_SYSTEM); foreach ($collection as $planet) { $key = array_search($planet->getData('position'), $positions); if ($key !== false) { unset($positions[$key]); } } $key = array_rand($positions, 1); $finalPosition = $positions[$key]; $planet = new self(); $planet ->setData('id_owner', $user->getId()) ->setData('name', $request->getParam('planet')) ->setData('galaxy', $galaxy) ->setData('system', $system) ->setData('position', $finalPosition) ->setData('planet_type', 1) ; Legacies::dispatchEvent('planet.init', array( 'planet' => $planet, 'user' => $user )); $planet ->setData('field_max', 163) ->setData('field_current', 0) ->save() ; $user ->setData('id_planet', $planet->getId()) ->setData('current_planet', $planet->getId()) ; } } public static function planetUpdateListener($eventData) { if (isset($eventData['planet'])) { $planet = $eventData['planet']; if (isset($eventData['time'])) { $time = $eventData['time']; } else { $time = time(); } if ($planet === null || !$planet instanceof Legacies_Empire_Model_Planet) { return; } $planet->updateBuildingQueue($time); $planet->updateResources($time); $planet->getShipyard()->updateQueue($time); $planet->setLastUpdate($time); } } }