void ResourcePool::Update() { //DebugLogger() << "ResourcePool::Update for type " << boost::lexical_cast<std::string>(m_type); // sum production from all ResourceCenters in each group, for resource point type appropriate for this pool MeterType meter_type = ResourceToMeter(m_type); MeterType target_meter_type = ResourceToTargetMeter(m_type); if (INVALID_METER_TYPE == meter_type || INVALID_METER_TYPE == target_meter_type) ErrorLogger() << "ResourcePool::Update() called when m_type can't be converted to a valid MeterType"; // zero to start... m_connected_object_groups_resource_output.clear(); m_connected_object_groups_resource_target_output.clear(); // temporary storage: indexed by group of systems, which objects // are located in that system group? std::map<std::set<int>, std::set<std::shared_ptr<const UniverseObject>>> system_groups_to_object_groups; // for every object, find if a connected system group contains the object's // system. If a group does, place the object into that system group's set // of objects. If no group contains the object, place the object in its own // single-object group. for (std::shared_ptr<const UniverseObject> obj : Objects().FindObjects<const UniverseObject>(m_object_ids)) { int object_id = obj->ID(); int object_system_id = obj->SystemID(); // can't generate resources when not in a system if (object_system_id == INVALID_OBJECT_ID) continue; // is object's system in a system group? std::set<int> object_system_group; for (const std::set<int>& sys_group : m_connected_system_groups) { if (sys_group.find(object_system_id) != sys_group.end()) { object_system_group = sys_group; break; } } // if object's system is not in a system group, add it as its // own entry in m_connected_object_groups_resource_output and m_connected_object_groups_resource_target_output // this will allow the object to use its own locally produced // resource when, for instance, distributing pp if (object_system_group.empty()) { object_system_group.insert(object_id); // just use this already-available set to store the object id, even though it is not likely actually a system float obj_output = obj->GetMeter(meter_type) ? obj->CurrentMeterValue(meter_type) : 0.0f; m_connected_object_groups_resource_output[object_system_group] = obj_output; float obj_target_output = obj->GetMeter(target_meter_type) ? obj->CurrentMeterValue(target_meter_type) : 0.0f; m_connected_object_groups_resource_target_output[object_system_group] = obj_target_output; continue; } // if resource center's system is in a system group, record which system // group that is for later system_groups_to_object_groups[object_system_group].insert(obj); } // sum the resource production for object groups, and store the total // group production, indexed by group of object ids for (std::map<std::set<int>, std::set<std::shared_ptr<const UniverseObject>>>::value_type& entry : system_groups_to_object_groups) { const std::set<std::shared_ptr<const UniverseObject>>& object_group = entry.second; std::set<int> object_group_ids; float total_group_output = 0.0f; float total_group_target_output = 0.0f; for (std::shared_ptr<const UniverseObject> obj : object_group) { if (obj->GetMeter(meter_type)) total_group_output += obj->CurrentMeterValue(meter_type); if (obj->GetMeter(target_meter_type)) total_group_target_output += obj->CurrentMeterValue(target_meter_type); object_group_ids.insert(obj->ID()); } m_connected_object_groups_resource_output[object_group_ids] = total_group_output; m_connected_object_groups_resource_target_output[object_group_ids] = total_group_target_output; } ChangedSignal(); }
void SupplyManager::Update() { m_supply_starlane_traversals.clear(); m_supply_starlane_obstructed_traversals.clear(); m_fleet_supplyable_system_ids.clear(); m_resource_supply_groups.clear(); m_propagated_supply_ranges.clear(); // for each empire, need to get a set of sets of systems that can exchange // resources. some sets may be just one system, in which resources can be // exchanged between UniverseObjects producing or consuming them, but which // can't exchange with any other systems. // which systems can share resources depends on system supply ranges, which // systems have obstructions to supply propagation for reach empire, and // the ranges and obstructions of other empires' supply, as only one empire // can supply each system or propagate along each starlane. one empire's // propagating supply can push back another's, if the pusher's range is // larger. // map from empire id to map from system id to range (in starlane jumps) // that supply can be propagated out of that system by that empire. std::map<int, std::map<int, float>> empire_system_supply_ranges; // map from empire id to which systems are obstructed for it for supply // propagation std::map<int, std::set<int>> empire_supply_unobstructed_systems; // map from empire id to map from system id to sum of supply source ranges // owned by empire in that in system std::map<int, std::map<int, float>> empire_system_supply_range_sums; for (const std::map<int, Empire*>::value_type& entry : Empires()) { const Empire* empire = entry.second; empire_system_supply_ranges[entry.first] = empire->SystemSupplyRanges(); empire_supply_unobstructed_systems[entry.first] = empire->SupplyUnobstructedSystems(); //std::stringstream ss; //for (int system_id : empire_supply_unobstructed_systems[entry.first]) //{ ss << system_id << ", "; } //DebugLogger() << "Empire " << empire->EmpireID() << " unobstructed systems: " << ss.str(); } for (auto empire_id_pair : empire_system_supply_ranges) { for (auto sys_id_pair : empire_id_pair.second) { empire_system_supply_range_sums[empire_id_pair.first][sys_id_pair.first] = EmpireTotalSupplyRangeSumInSystem(empire_id_pair.first, sys_id_pair.first); } } ///// // probably temporary: additional restriction here for supply propagation // but not for general system obstruction as determind within Empire::UpdateSupplyUnobstructedSystems ///// const std::vector<std::shared_ptr<Fleet>> fleets = GetUniverse().Objects().FindObjects<Fleet>(); for (const std::map<int, Empire*>::value_type& entry : Empires()) { int empire_id = entry.first; const std::set<int>& known_destroyed_objects = GetUniverse().EmpireKnownDestroyedObjectIDs(empire_id); std::set<int> systems_containing_friendly_fleets; for (std::shared_ptr<const Fleet> fleet : fleets) { int system_id = fleet->SystemID(); if (system_id == INVALID_OBJECT_ID) { continue; // not in a system, so can't affect system obstruction } else if (known_destroyed_objects.find(fleet->ID()) != known_destroyed_objects.end()) { continue; //known to be destroyed so can't affect supply, important just in case being updated on client side } if ((fleet->HasArmedShips() || fleet->HasFighterShips()) && fleet->Aggressive()) { if (fleet->OwnedBy(empire_id)) { if (fleet->NextSystemID() == INVALID_OBJECT_ID || fleet->NextSystemID() == fleet->SystemID()) { systems_containing_friendly_fleets.insert(system_id); } } } } std::set<int> systems_where_others_have_supply_sources_and_current_empire_doesnt; // add all systems where others have supply for (std::map<int, std::map<int, float>>::value_type& empire_supply : empire_system_supply_ranges) { if (empire_supply.first == empire_id || empire_supply.first == ALL_EMPIRES) continue; for (const std::map<int, float>::value_type& supply_range : empire_supply.second) { if (supply_range.second <= 0.0f) continue; systems_where_others_have_supply_sources_and_current_empire_doesnt.insert(supply_range.first); } } // remove systems were this empire has supply std::map<int, std::map<int, float>>::const_iterator it = empire_system_supply_ranges.find(empire_id); if (it != empire_system_supply_ranges.end()) { for (const std::map<int, float>::value_type& supply_range : it->second) { if (supply_range.second <= 0.0f) continue; systems_where_others_have_supply_sources_and_current_empire_doesnt.erase(supply_range.first); } } // for systems where others have supply sources and this empire doesn't // and where this empire has no fleets... // supply is obstructed for (int system_id : systems_where_others_have_supply_sources_and_current_empire_doesnt) { if (systems_containing_friendly_fleets.find(system_id) == systems_containing_friendly_fleets.end()) empire_supply_unobstructed_systems[empire_id].erase(system_id); } } ///// // end probably temporary... ///// // system connections each empire can see / use for supply propagation std::map<int, std::map<int, std::set<int>>> empire_visible_starlanes; for (std::map<int, Empire*>::value_type& entry : Empires()) { const Empire* empire = entry.second; empire_visible_starlanes[entry.first] = empire->KnownStarlanes();// VisibleStarlanes(); } std::set<int> systems_with_supply_in_them; // store (supply range in jumps, and distance to supply source) of all // unobstructed systems before propagation, and add to list of systems // to propagate from. std::map<int, std::map<int, std::pair<float, float>>> empire_propagating_supply_ranges; float max_range = 0.0f; for (const auto& empire_supply : empire_system_supply_ranges) { int empire_id = empire_supply.first; const std::set<int>& unobstructed_systems = empire_supply_unobstructed_systems[empire_id]; for (const std::map<int, float>::value_type& supply_range : empire_supply.second) { int system_id = supply_range.first; if (unobstructed_systems.find(system_id) != unobstructed_systems.end()) { // stored: first -> source supply range. second -> distance to source (0 for the source itself) empire_propagating_supply_ranges[empire_id][system_id] = {supply_range.second, 0.0f}; if (supply_range.second > max_range) max_range = supply_range.second; systems_with_supply_in_them.insert(system_id); } } } // spread supply out from sources by "diffusion" like process, along unobstructed // starlanes, until the range is exhausted. for (float range_to_spread = max_range; range_to_spread >= 0; range_to_spread -= 1.0f) { //DebugLogger() << "!!!! Reduced spreading range to " << range_to_spread; // update systems that have supply in them for (const auto& empire_supply : empire_propagating_supply_ranges) { for (const std::map<int, std::pair<float, float>>::value_type& supply_range : empire_supply.second) { systems_with_supply_in_them.insert(supply_range.first); } } // resolve supply fights between multiple empires in one system. // pass over all empire-supplied systems, removing supply for all // but the empire with the highest supply range in each system for (int sys_id : systems_with_supply_in_them) { // sort empires by range in this system std::map<float, std::set<int>> empire_ranges_here; for (auto& empire_supply : empire_propagating_supply_ranges) { int empire_id = empire_supply.first; std::map<int, std::pair<float, float>>::const_iterator empire_supply_it = empire_supply.second.find(sys_id); // does this empire have any range in this system? if so, store it if (empire_supply_it == empire_supply.second.end()) continue; // stuff to break ties... float bonus = 0.0f; // empires with planets in system bool has_outpost = false, has_colony = false; if (std::shared_ptr<const System> sys = GetSystem(sys_id)) { std::vector<int> obj_ids; std::copy(sys->ContainedObjectIDs().begin(), sys->ContainedObjectIDs().end(), std::back_inserter(obj_ids)); for (std::shared_ptr<UniverseObject> obj : Objects().FindObjects(obj_ids)) { if (!obj) continue; if (!obj->OwnedBy(empire_id)) continue; if (obj->ObjectType() == OBJ_PLANET) { if (std::shared_ptr<Planet> planet = std::dynamic_pointer_cast<Planet>(obj)) { if (!planet->SpeciesName().empty()) has_colony = true; else has_outpost = true; continue; } } } } if (has_colony) bonus += 0.5f; else if (has_outpost) bonus += 0.3f; // sum of all supply sources in this system bonus += empire_system_supply_range_sums[empire_id][sys_id] / 1000.0f; // distance to supply source from here float propagated_distance_to_supply_source = std::max(1.0f, empire_supply_it->second.second); bonus += 0.0001f / propagated_distance_to_supply_source; // store ids of empires indexed by adjusted propgated range, in order to sort by range float propagated_range = empire_supply_it->second.first; empire_ranges_here[propagated_range + bonus].insert(empire_id); } if (empire_ranges_here.empty()) continue; // no empire has supply here? if (empire_ranges_here.size() == 1 && empire_ranges_here.begin()->second.size() < 2) continue; // only one empire has supply here // at least two empires have supply sources here... // check if one is stronger // remove supply for all empires except the top-ranged empire here // if there is a tie for top-ranged, remove all std::map<float, std::set<int>>::reverse_iterator range_empire_it = empire_ranges_here.rbegin(); int top_range_empire_id = ALL_EMPIRES; if (range_empire_it->second.size() == 1) { // if just one empire has the most range, it is the top empire top_range_empire_id = *(range_empire_it->second.begin()); } //DebugLogger() << "top ranged empire here: " << top_range_empire_id; // remove range entries and traversals for all but the top empire // (or all empires if there is no single top empire) for (auto& empire_supply : empire_propagating_supply_ranges) { int empire_id = empire_supply.first; if (empire_id == top_range_empire_id) continue; // this is the top empire, so leave as the sole empire supplying here // remove from range entry... std::map<int, std::pair<float, float>>& empire_ranges = empire_supply.second; empire_ranges.erase(sys_id); //DebugLogger() << "... removed empire " << empire_id << " system " << sys_id << " supply."; // Remove from unobstructed systems empire_supply_unobstructed_systems[empire_id].erase(sys_id); std::set<std::pair<int, int>>& lane_traversals = m_supply_starlane_traversals[empire_id]; std::set<std::pair<int, int>> lane_traversals_initial = lane_traversals; std::set<std::pair<int, int>>& obstructed_traversals = m_supply_starlane_obstructed_traversals[empire_id]; std::set<std::pair<int, int>> obstrcuted_traversals_initial = obstructed_traversals; // remove from traversals departing from or going to this system for this empire, // and set any traversals going to this system as obstructed for (const auto& lane : lane_traversals_initial) { if (lane.first == sys_id) { lane_traversals.erase(std::make_pair(sys_id, lane.second)); } if (lane.second == sys_id) { lane_traversals.erase(std::make_pair(lane.first, sys_id)); obstructed_traversals.insert(std::make_pair(lane.first, sys_id)); } } // remove obstructed traverals departing from this system for (const auto& lane : obstrcuted_traversals_initial) { if (lane.first == sys_id) obstructed_traversals.erase(std::make_pair(lane.first, lane.second)); } } //// DEBUG //DebugLogger() << "after culling empires ranges at system " << sys_id << ":"; //for (std::map<int, std::map<int, float>>::value_type& empire_supply : empire_propagating_supply_ranges) { // std::map<int, float>& system_ranges = empire_supply.second; // std::map<int, float>::iterator range_it = system_ranges.find(sys_id); // if (range_it != system_ranges.end()) // DebugLogger() << empire_supply.first << " : " << range_it->second; //} //// END DEBUG } if (range_to_spread <= 0) break; // initialize next iteration with current supply distribution auto empire_propagating_supply_ranges_next = empire_propagating_supply_ranges; // for sources of supply of at least the minimum range for this // iteration that are in the current map, give adjacent systems one // less supply in the next iteration (unless as much or more is already // there) for (const auto& empire_supply : empire_propagating_supply_ranges) { int empire_id = empire_supply.first; //DebugLogger() << ">-< Doing supply propagation for empire " << empire_id << " >-<"; const std::map<int, std::pair<float, float>>& prev_sys_ranges = empire_supply.second; const std::set<int>& unobstructed_systems = empire_supply_unobstructed_systems[empire_id]; for (const std::map<int, std::pair<float, float>>::value_type& supply_range : empire_supply.second) { // does the source system have enough supply range to propagate outwards? float range = supply_range.second.first; if (range != range_to_spread) continue; float range_after_one_more_jump = range - 1.0f; // what to set adjacent systems' ranges to (at least) // how far is this system from a source of supply for this empire? float distance_to_supply_source = supply_range.second.second; // what starlanes can be used to propagate supply? int system_id = supply_range.first; //DebugLogger() << "propagating from system " << system_id << " which has range: " << range << " and distance: " << distance_to_supply_source; // attempt to propagate to all adjacent systems... for (int lane_end_sys_id : empire_visible_starlanes[empire_id][system_id]) { // is propagation to the adjacent system obstructed? if (unobstructed_systems.find(lane_end_sys_id) == unobstructed_systems.end()) { // propagation obstructed! //DebugLogger() << "Added obstructed traversal from " << system_id << " to " << lane_end_sys_id << " due to not being on unobstructed systems"; m_supply_starlane_obstructed_traversals[empire_id].insert({system_id, lane_end_sys_id}); continue; } // propagation not obstructed. // does another empire already have as much or more supply here from a previous iteration? float other_empire_biggest_range = -10000.0f; // arbitrary big numbeer for (const std::map<int, std::map<int, std::pair<float, float>>>::value_type& other_empire_supply : empire_propagating_supply_ranges) { int other_empire_id = other_empire_supply.first; if (other_empire_id == empire_id) continue; const std::map<int, std::pair<float, float>>& prev_other_empire_sys_ranges = other_empire_supply.second; std::map<int, std::pair<float, float>>::const_iterator prev_other_empire_range_it = prev_other_empire_sys_ranges.find(lane_end_sys_id); if (prev_other_empire_range_it == prev_other_empire_sys_ranges.end()) continue; if (prev_other_empire_range_it->second.first > other_empire_biggest_range) other_empire_biggest_range = prev_other_empire_range_it->second.first; } // if so, add a blocked traversal and continue if (range_after_one_more_jump <= other_empire_biggest_range) { m_supply_starlane_obstructed_traversals[empire_id].insert(std::make_pair(system_id, lane_end_sys_id)); //DebugLogger() << "Added obstructed traversal from " << system_id << " to " << lane_end_sys_id << " due to other empire biggest range being " << other_empire_biggest_range; continue; } // otherwise, propagate into system... float lane_length = DistanceBetweenObjects(system_id, lane_end_sys_id); float distance_to_supply_source_after_next_lane = lane_length + distance_to_supply_source; //DebugLogger() << "Attempting to propagate into system: " << lane_end_sys_id << " the new range: " << range_after_one_more_jump << " and distance: " << distance_to_supply_source_after_next_lane; // if propagating supply would increase the range of the adjacent system, // or decrease the distance to the adjacent system from a supply source... std::map<int, std::pair<float, float>>::const_iterator prev_range_it = prev_sys_ranges.find(lane_end_sys_id); if (prev_range_it == prev_sys_ranges.end()) { empire_propagating_supply_ranges_next[empire_id][lane_end_sys_id] = {range_after_one_more_jump, distance_to_supply_source_after_next_lane}; //DebugLogger() << " ... default case: no previous entry."; } else { //DebugLogger() << " ... previous entry values: " << prev_range_it->second.first << " and " << prev_range_it->second.second; if (range_after_one_more_jump > prev_range_it->second.first) { empire_propagating_supply_ranges_next[empire_id][lane_end_sys_id].first = range_after_one_more_jump; //DebugLogger() << " ... range increased!"; } if (distance_to_supply_source_after_next_lane < prev_range_it->second.second) { empire_propagating_supply_ranges_next[empire_id][lane_end_sys_id].second = distance_to_supply_source_after_next_lane; //DebugLogger() << " ... distance decreased!"; } } // always record a traversal, so connectivity is calculated properly m_supply_starlane_traversals[empire_id].insert({system_id, lane_end_sys_id}); //DebugLogger() << "Added traversal from " << system_id << " to " << lane_end_sys_id; // erase any previous obstructed traversal that just succeeded if (m_supply_starlane_obstructed_traversals[empire_id].find(std::make_pair(system_id, lane_end_sys_id)) != m_supply_starlane_obstructed_traversals[empire_id].end()) { //DebugLogger() << "Removed obstructed traversal from " << system_id << " to " << lane_end_sys_id; m_supply_starlane_obstructed_traversals[empire_id].erase(std::make_pair(system_id, lane_end_sys_id)); } if (m_supply_starlane_obstructed_traversals[empire_id].find(std::make_pair(lane_end_sys_id, system_id)) != m_supply_starlane_obstructed_traversals[empire_id].end()) { //DebugLogger() << "Removed obstructed traversal from " << lane_end_sys_id << " to " << system_id; m_supply_starlane_obstructed_traversals[empire_id].erase(std::make_pair(lane_end_sys_id, system_id)); } } } } // save propagated results for next iteration empire_propagating_supply_ranges = empire_propagating_supply_ranges_next; } //// DEBUG //DebugLogger() << "SuppolyManager::Update: after removing conflicts, empires can provide supply to the following system ids:"; //for (std::map<int, std::map<int, float>>::value_type& empire_supply : empire_propagating_supply_ranges) { // int empire_id = empire_supply.first; // std::stringstream ss; // for (std::map<int, float>::value_type& supply_range : empire_supply.second) { // ss << supply_range.first << " (" << supply_range.second << "), "; // } // DebugLogger() << "empire: " << empire_id << ": " << ss.str(); //} //// END DEBUG // record which systems are fleet supplyable by each empire (after resolving conflicts in each system) for (const auto& empire_supply : empire_propagating_supply_ranges) { int empire_id = empire_supply.first; for (const auto& supply_range : empire_supply.second) { if (supply_range.second.first < 0.0f) continue; // negative supply doesn't count... zero does (it just reaches) m_fleet_supplyable_system_ids[empire_id].insert(supply_range.first); // should be only one empire per system at this point, but use max just to be safe... m_propagated_supply_ranges[supply_range.first] = std::max(supply_range.second.first, m_propagated_supply_ranges[supply_range.first]); m_empire_propagated_supply_ranges[empire_id][supply_range.first] = m_propagated_supply_ranges[supply_range.first]; // should be only one empire per system at this point, but use max just to be safe... m_propagated_supply_distances[supply_range.first] = std::max(supply_range.second.second, m_propagated_supply_distances[supply_range.first]); m_empire_propagated_supply_distances[empire_id][supply_range.first] = m_propagated_supply_distances[supply_range.first]; } //DebugLogger() << "For empire: " << empire_id << " system supply distances: "; //for (auto entry : m_empire_propagated_supply_distances[empire_id]) { // DebugLogger() << entry.first << " : " << entry.second; //} } // TEST STUFF FOR INTER-EMPIRE-MERGING std::map<int, std::set<std::pair<int, int>>> ally_merged_supply_starlane_traversals = m_supply_starlane_traversals; // add connections into allied empire systems when their obstructed lane // traversals originate on either end of a starlane for (auto& empire_set : m_supply_starlane_obstructed_traversals) { // input: const std::set<std::pair<int, int>>& empire_obstructed_traversals = empire_set.second; // output: std::set<std::pair<int, int>>& empire_supply_traversals = ally_merged_supply_starlane_traversals[empire_set.first]; std::set<int> allies_of_empire = Empires().GetEmpireIDsWithDiplomaticStatusWithEmpire(empire_set.first, DIPLO_ALLIED); for (int ally_id : allies_of_empire) { // input: auto const& ally_obstructed_traversals = m_supply_starlane_obstructed_traversals[ally_id]; // find cases where outer loop empire has an obstructed traversal from A to B // and inner loop empire has an obstructed traversal from B to A for (auto const& empire_trav : empire_obstructed_traversals) { for (auto const& ally_trav : ally_obstructed_traversals) { if (empire_trav.first == ally_trav.second && empire_trav.second == ally_trav.first) { empire_supply_traversals.insert({empire_trav.first, empire_trav.second}); empire_supply_traversals.insert({empire_trav.second, empire_trav.first}); } } } } } // add allied supply starlane traversals to empires' traversals, so that // allies can use eachothers' supply networks for (auto& empire_set : ally_merged_supply_starlane_traversals) { std::set<std::pair<int, int>>& output_empire_traversals = empire_set.second; for (int ally_id : Empires().GetEmpireIDsWithDiplomaticStatusWithEmpire(empire_set.first, DIPLO_ALLIED)) { // copy ally traversals into the output empire traversals set for (const auto& traversal_pair : m_supply_starlane_traversals[ally_id]) output_empire_traversals.insert(traversal_pair); } } // same for fleet supplyable system ids, as these are added to supplyable // groups in following code auto ally_merged_fleet_supplyable_system_ids = m_fleet_supplyable_system_ids; for (auto& empire_set : ally_merged_fleet_supplyable_system_ids) { std::set<int>& output_empire_ids = empire_set.second; for (int ally_id : Empires().GetEmpireIDsWithDiplomaticStatusWithEmpire(empire_set.first, DIPLO_ALLIED)) { // copy ally traversals into the output empire traversals set for (int sys_id : m_fleet_supplyable_system_ids[ally_id]) output_empire_ids.insert(sys_id); } } // END TEST STUFF FOR INTER-EMPIRE-MERGING // determine supply-connected groups of systems for each empire. // need to merge interconnected supply groups into as few sets of mutually- // supply-exchanging systems as possible. This requires finding the // connected components of an undirected graph, where the node // adjacency are the directly-connected systems determined above. for (const auto& empire_supply : empire_propagating_supply_ranges) { int empire_id = empire_supply.first; // assemble all direct connections between systems from remaining traversals std::map<int, std::set<int>> supply_groups_map; for (auto const& lane : ally_merged_supply_starlane_traversals[empire_id]) { supply_groups_map[lane.first].insert(lane.second); supply_groups_map[lane.second].insert(lane.first); } // also add connections from all fleet-supplyable systems to themselves, so that // any fleet supply able system with no connection to another system can still // have resource sharing within tiself for (int system_id : ally_merged_fleet_supplyable_system_ids[empire_id]) supply_groups_map[system_id].insert(system_id); if (supply_groups_map.empty()) continue; //DebugLogger() << "Empire " << empire_id << " supply groups map:"; //for (auto const& q : supply_groups_map) { // int source_id = q.first; // std::stringstream other_ids; // for (auto const& r : q.second) // { other_ids << r << ", "; } // DebugLogger() << " ... src: " << source_id << " to: " << other_ids.str(); //} // create graph boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS> graph; // boost expects vertex labels to range from 0 to num vertices - 1, so need // to map from system id to graph id and back when accessing vertices std::vector<int> graph_id_to_sys_id; graph_id_to_sys_id.reserve(supply_groups_map.size()); std::map<int, int> sys_id_to_graph_id; int graph_id = 0; for (std::map<int, std::set<int>>::value_type& supply_group : supply_groups_map) { int sys_id = supply_group.first; boost::add_vertex(graph); // should add with index = graph_id graph_id_to_sys_id.push_back(sys_id); sys_id_to_graph_id[sys_id] = graph_id; ++graph_id; } // add edges for all direct connections between systems // and add edges from fleet supplyable systems to themselves for (std::map<int, std::set<int>>::value_type& supply_group : supply_groups_map) { int start_graph_id = sys_id_to_graph_id[supply_group.first]; for (int system_id : supply_group.second) { int end_graph_id = sys_id_to_graph_id[system_id]; boost::add_edge(start_graph_id, end_graph_id, graph); } } // declare storage and fill with the component id (group id of connected systems) // for each graph vertex std::vector<int> components(boost::num_vertices(graph)); boost::connected_components(graph, &components[0]); // convert results back from graph id to system id, and into desired output format // output: std::map<int, std::set<std::set<int>>>& m_resource_supply_groups // first, sort into a map from component id to set of system ids in component std::map<int, std::set<int>> component_sets_map; for (std::size_t comp_graph_id = 0; comp_graph_id != components.size(); ++comp_graph_id) { int label = components[comp_graph_id]; int sys_id = graph_id_to_sys_id[comp_graph_id]; component_sets_map[label].insert(sys_id); } // copy sets in map into set of sets for (std::map<int, std::set<int>>::value_type& component_set : component_sets_map) m_resource_supply_groups[empire_id].insert(component_set.second); } }
void GenerateStarlanes(int max_jumps_between_systems, int max_starlane_length) { int num_systems, s1, s2, s3; // numbers of systems, indices in vec_sys int n; // loop counter std::vector<int> triVerts; // indices of stars that form vertices of a triangle // array of set to store final, included starlanes for each star std::vector<std::set<int> > laneSetArray; // array of set to store possible starlanes for each star, as extracted form triangulation std::vector<std::set<int> > potential_lane_set_array; // iterators for traversing lists of starlanes std::set<int>::iterator laneSetIter, laneSetEnd, laneSetIter2, laneSetEnd2; // get systems std::vector<TemporaryPtr<System> > sys_vec = Objects().FindObjects<System>(); num_systems = sys_vec.size(); // (actually = number of systems + 1) // pass systems to Delauney Triangulation routine, getting array of triangles back std::list<Delauney::DTTriangle>* triangle_list = Delauney::DelauneyTriangulate(sys_vec); if (!triangle_list ||triangle_list->empty()) { ErrorLogger() << "Got no list or blank list of triangles from Triangulation."; return; } Delauney::DTTriangle tri; // initialize arrays... potential_lane_set_array.resize(num_systems); for (n = 0; n < num_systems; n++) { potential_lane_set_array[n].clear(); } laneSetArray.resize(num_systems); for (n = 0; n < num_systems; n++) { laneSetArray[n].clear(); } // extract triangles from list, add edges to sets of potential starlanes for each star (in array) while (!triangle_list->empty()) { tri = triangle_list->front(); triVerts = tri.Verts(); s1 = triVerts[0]; s2 = triVerts[1]; s3 = triVerts[2]; // add starlanes to list of potential starlanes for each star, making sure each pair involves // only stars that actually exist. triangle generation uses three extra points which don't // represent actual systems and which need to be weeded out here. if ((s1 >= 0) && (s2 >= 0) && (s3 >= 0)) { if ((s1 < num_systems) && (s2 < num_systems)) { potential_lane_set_array[s1].insert(s2); potential_lane_set_array[s2].insert(s1); } if ((s1 < num_systems) && (s3 < num_systems)) { potential_lane_set_array[s1].insert(s3); potential_lane_set_array[s3].insert(s1); } if ((s2 < num_systems) && (s3 < num_systems)) { potential_lane_set_array[s2].insert(s3); potential_lane_set_array[s3].insert(s2); } } triangle_list->pop_front(); } // cleanup delete triangle_list; //DebugLogger() << "Extracted Potential Starlanes from Triangulation"; CullTooLongLanes(max_starlane_length, potential_lane_set_array, sys_vec); CullAngularlyTooCloseLanes(0.98, potential_lane_set_array, sys_vec); //DebugLogger() << "Culled Agularly Too Close Lanes"; laneSetArray = potential_lane_set_array; // attempt removing lanes, but don't do so if it would make the systems // the lane connects too far apart for (n = 0; n < num_systems; ++n) { laneSetIter = potential_lane_set_array[n].begin(); while (laneSetIter != potential_lane_set_array[n].end()) { s1 = *laneSetIter; // try removing lane laneSetArray[n].erase(s1); laneSetArray[s1].erase(n); if (!ConnectedWithin(n, s1, max_jumps_between_systems, laneSetArray)) { // lane removal was a bad idea. restore it laneSetArray[n].insert(s1); laneSetArray[s1].insert(n); } ++laneSetIter; } // end while } // add the starlane to the stars for (n = 0; n < num_systems; ++n) { const std::set<int>& lanes = laneSetArray[n]; for (std::set<int>::const_iterator it = lanes.begin(); it != lanes.end(); ++it) sys_vec[n]->AddStarlane(sys_vec[*it]->ID()); // System::AddStarlane() expects a system ID } DebugLogger() << "Initializing System Graph"; GetUniverse().InitializeSystemGraph(); }
void CMine::MoveOn (char axis,INT32 inc) { int nSegment = Current ()->segment; int nSide = Current ()->side; int nPoint = Current ()->point; int nLine = Current ()->line; CDSegment *seg = Segments (nSegment); INT16 i; theApp.SetModified (TRUE); switch (m_selectMode) { case POINT_MODE: switch (axis) { case 'X': Vertices (seg->verts [side_vert [nSide][nPoint]])->x += inc; break; case 'Y': Vertices (seg->verts [side_vert [nSide][nPoint]])->y += inc; break; case 'Z': Vertices (seg->verts [side_vert [nSide][nPoint]])->z += inc; break; } break; case LINE_MODE: switch (axis) { case 'X': Vertices (seg->verts [line_vert [side_line [nSide][nLine]][0]])->x += inc; Vertices (seg->verts [line_vert [side_line [nSide][nLine]][1]])->x += inc; break; case 'Y': Vertices (seg->verts [line_vert [side_line [nSide][nLine]][0]])->y += inc; Vertices (seg->verts [line_vert [side_line [nSide][nLine]][1]])->y += inc; break; case 'Z': Vertices (seg->verts [line_vert [side_line [nSide][nLine]][0]])->z += inc; Vertices (seg->verts [line_vert [side_line [nSide][nLine]][1]])->z += inc; break; } break; case SIDE_MODE: switch (axis) { case 'X': for (i = 0; i < 4; i++) Vertices (seg->verts [side_vert [nSide][i]])->x += inc; break; case 'Y': for (i = 0; i < 4; i++) Vertices (seg->verts [side_vert [nSide][i]])->y += inc; break; case 'Z': for (i = 0; i < 4; i++) Vertices (seg->verts [side_vert [nSide][i]])->z += inc; break; } break; case CUBE_MODE: switch (axis) { case 'X': for (i = 0; i < 8; i++) Vertices (seg->verts [i])->x += inc; for (i = 0; i < GameInfo ().objects.count; i++) if (Objects (i)->segnum == nSegment) Objects (i)->pos.x += inc; break; case 'Y': for (i = 0; i < 8; i++) Vertices (seg->verts [i])->y += inc; for (i = 0; i < GameInfo ().objects.count; i++) if (Objects (i)->segnum == nSegment) Objects (i)->pos.y += inc; break; case 'Z': for (i = 0; i < 8; i++) Vertices (seg->verts [i])->z += inc; for (i = 0; i < GameInfo ().objects.count; i++) if (Objects (i)->segnum == nSegment) Objects (i)->pos.z += inc; break; } break; case OBJECT_MODE: switch (axis) { case 'X': CurrObj ()->pos.x += inc; break; case 'Y': CurrObj ()->pos.y += inc; break; case 'Z': CurrObj ()->pos.z += inc; break; } break; case BLOCK_MODE: CDObject *obj = Objects (); switch (axis) { case 'X': for (i = 0; i < MAX_VERTICES; i++) if (*VertStatus (i) & MARKED_MASK) Vertices (i)->x += inc; for (i = GameInfo ().objects.count; i; i--, obj++) if (obj->segnum >= 0) if (Segments (obj->segnum)->wall_bitmask & MARKED_MASK) obj->pos.x += inc; break; case 'Y': for (i = 0; i < MAX_VERTICES; i++) if (*VertStatus (i) & MARKED_MASK) Vertices (i)->y += inc; for (i = GameInfo ().objects.count; i; i--, obj++) if (obj->segnum >= 0) if (Segments (obj->segnum)->wall_bitmask & MARKED_MASK) obj->pos.y += inc; break; case 'Z': for (i = 0; i < MAX_VERTICES; i++) if (*VertStatus (i) & MARKED_MASK) Vertices (i)->z += inc; for (i = GameInfo ().objects.count; i; i--, obj++) if (obj->segnum >= 0) if (Segments (obj->segnum)->wall_bitmask & MARKED_MASK) obj->pos.z += inc; break; } break; } }
void CMine::SpinSelection(double angle) { int nSegment = Current ()->segment; int nSide = Current ()->side; CDSegment *seg = Segments (nSegment); CDObject *obj; vms_vector center,opp_center; INT16 i; #ifdef SPIN_RELATIVE double xspin,yspin,zspin; vms_vector rel [3]; #endif /* calculate segment pointer */ switch (m_selectMode) { case POINT_MODE: ErrorMsg ("Cannot spin a point"); break; /* can't spin a point */ case LINE_MODE: ErrorMsg ("Cannot spin a line"); break; /* line spinning not supported */ case SIDE_MODE: // spin side around its center in the plane of the side // calculate center of current side theApp.SetModified (TRUE); center.x = center.y = center.z = 0; for (i = 0; i < 4; i++) { center.x += Vertices (seg->verts [side_vert [nSide][i]])->x; center.y += Vertices (seg->verts [side_vert [nSide][i]])->y; center.z += Vertices (seg->verts [side_vert [nSide][i]])->z; } center.x /= 4; center.y /= 4; center.z /= 4; // calculate orthogonal vector from lines which intersect point 0 // |x y z | // AxB = |ax ay az| = x(aybz-azby), y(azbx-axbz), z(axby-aybx) // |bx by bz| struct vector {double x,y,z;}; struct vector a,b,c; double length; INT16 vertnum1,vertnum2; vertnum1 = seg->verts [side_vert [nSide][0]]; vertnum2 = seg->verts [side_vert [nSide][1]]; a.x = (double)(Vertices (vertnum2)->x - Vertices (vertnum1)->x); a.y = (double)(Vertices (vertnum2)->y - Vertices (vertnum1)->y); a.z = (double)(Vertices (vertnum2)->z - Vertices (vertnum1)->z); vertnum1 = seg->verts [side_vert [nSide][0]]; vertnum2 = seg->verts [side_vert [nSide][3]]; b.x = (double)(Vertices (vertnum2)->x - Vertices (vertnum1)->x); b.y = (double)(Vertices (vertnum2)->y - Vertices (vertnum1)->y); b.z = (double)(Vertices (vertnum2)->z - Vertices (vertnum1)->z); c.x = a.y*b.z - a.z*b.y; c.y = a.z*b.x - a.x*b.z; c.z = a.x*b.y - a.y*b.x; // normalize the vector length = sqrt(c.x*c.x + c.y*c.y + c.z*c.z); c.x /= length; c.y /= length; c.z /= length; // set sign (since vert numbers for most sides don't follow right-handed convention) if (nSide!=1 && nSide!=5) { c.x = -c.x; c.y = -c.y; c.z = -c.z; } // set opposite center opp_center.x = center.x + (FIX)(0x10000L*c.x); opp_center.y = center.y + (FIX)(0x10000L*c.y); opp_center.z = center.z + (FIX)(0x10000L*c.z); /* rotate points around a line */ for (i = 0; i < 4; i++) { RotateVertex(Vertices (seg->verts [side_vert [nSide][i]]), ¢er,&opp_center,angle); } break; case CUBE_MODE: // spin cube around the center of the cube using screen's perspective // calculate center of current cube theApp.SetModified (TRUE); center.x = center.y = center.z = 0; for (i = 0; i < 8; i++) { center.x += Vertices (seg->verts [i])->x; center.y += Vertices (seg->verts [i])->y; center.z += Vertices (seg->verts [i])->z; } center.x /= 8; center.y /= 8; center.z /= 8; // calculate center of oppisite current side opp_center.x = opp_center.y = opp_center.z = 0; for (i = 0; i < 4; i++) { opp_center.x += Vertices (seg->verts [opp_side_vert [nSide][i]])->x; opp_center.y += Vertices (seg->verts [opp_side_vert [nSide][i]])->y; opp_center.z += Vertices (seg->verts [opp_side_vert [nSide][i]])->z; } opp_center.x /= 4; opp_center.y /= 4; opp_center.z /= 4; // rotate points about a point for (i = 0; i < 8; i++) RotateVertex(Vertices (seg->verts [i]),¢er,&opp_center,angle); break; case OBJECT_MODE: // spin object vector theApp.SetModified (TRUE); vms_matrix *orient; orient = (Current ()->object == GameInfo ().objects.count) ? &SecretOrient () : &CurrObj ()->orient; switch (nSide) { case 0: RotateVmsMatrix(orient,angle,'x'); break; case 2: RotateVmsMatrix(orient,-angle,'x'); break; case 1: RotateVmsMatrix(orient,-angle,'y'); break; case 3: RotateVmsMatrix(orient,angle,'y'); break; case 4: RotateVmsMatrix(orient,angle,'z'); break; case 5: RotateVmsMatrix(orient,-angle,'z'); break; } #ifdef SPIN_RELATIVE // calculate angles to spin the side into the x-y plane // use points 0,1, and 2 of the side // make point0 the origin // and get coordinates of points 1 and 2 relative to point 0 for (i=0;i<3;i++) { rel [i].x = vertices [seg->verts [side_vert [nSide][i]]].x - vertices [seg->verts [side_vert [nSide][0]]].x; rel [i].y = vertices [seg->verts [side_vert [nSide][i]]].y - vertices [seg->verts [side_vert [nSide][0]]].y; rel [i].z = vertices [seg->verts [side_vert [nSide][i]]].z - vertices [seg->verts [side_vert [nSide][0]]].z; } // calculate z-axis spin angle to rotate point1 so it lies in x-y plane zspin = (rel [1].x==rel [1].y) ? PI/4 : atan2(rel [1].y,rel [1].x); // spin all 3 points on z axis for (i=0;i<3;i++) RotateVmsVector(&rel [i],zspin,'z'); // calculate y-axis spin angle to rotate point1 so it lies on x axis yspin = (rel [1].z==rel [1].x) ? PI/4 : atan2(rel [1].z,rel [1].x); // spin points 1 and 2 on y axis (don't need to spin point 0 since it is at 0,0,0) for (i=1;i<=2;i++) RotateVmsVector(&rel [i],yspin,'y'); // calculate x-axis spin angle to rotate point2 so it lies in x-y plane xspin = (rel [2].z==rel [2].y) ? PI/4 : atan2(rel [2].z,rel [2].y); // spin points 2 on x axis (don't need to spin point 1 since it is on the x-axis RotateVmsVector(&rel [2],xspin,'x'); RotateVmsMatrix(&obj->orient,zspin,'z'); RotateVmsMatrix(&obj->orient,yspin,'y'); RotateVmsMatrix(&obj->orient,xspin,'x'); RotateVmsMatrix(&obj->orient,-xspin,'x'); RotateVmsMatrix(&obj->orient,-yspin,'y'); RotateVmsMatrix(&obj->orient,-zspin,'z'); #endif //SPIN_RELATIVE break; case BLOCK_MODE: theApp.SetModified (TRUE); // calculate center of current cube center.x = center.y = center.z = 0; for (i = 0; i < 8; i++) { center.x += Vertices (seg->verts [i])->x; center.y += Vertices (seg->verts [i])->y; center.z += Vertices (seg->verts [i])->z; } center.x /= 8; center.y /= 8; center.z /= 8; // calculate center of oppisite current side opp_center.x = opp_center.y = opp_center.z = 0; for (i = 0; i < 4; i++) { opp_center.x += Vertices (seg->verts [opp_side_vert [nSide][i]])->x; opp_center.y += Vertices (seg->verts [opp_side_vert [nSide][i]])->y; opp_center.z += Vertices (seg->verts [opp_side_vert [nSide][i]])->z; } opp_center.x /= 4; opp_center.y /= 4; opp_center.z /= 4; // rotate points about a point for (i=0;i<VertCount ();i++) if (*VertStatus (i) & MARKED_MASK) RotateVertex(Vertices (i),¢er,&opp_center,angle); // rotate Objects () within marked cubes obj = Objects (); for (i = GameInfo ().objects.count; i; i--, obj++) if (Segments (obj->segnum)->wall_bitmask & MARKED_MASK) RotateVertex(&obj->pos, ¢er, &opp_center, angle); break; } }
bool Planet::Colonize(int empire_id, const std::string& species_name, double population) { const Species* species = 0; // if desired pop > 0, we want a colony, not an outpost, so we need to do some checks if (population > 0.0) { // check if specified species exists and get reference species = GetSpecies(species_name); if (!species) { ErrorLogger() << "Planet::Colonize couldn't get species already on planet with name: " << species_name; return false; } // check if specified species can colonize this planet if (EnvironmentForSpecies(species_name) < PE_HOSTILE) { ErrorLogger() << "Planet::Colonize: can't colonize planet already populated by species " << species_name; return false; } } // reset the planet to unowned/unpopulated if (!OwnedBy(empire_id)) { Reset(); } else { PopCenter::Reset(); for (std::set<int>::const_iterator it = m_buildings.begin(); it != m_buildings.end(); ++it) if (TemporaryPtr<Building> building = GetBuilding(*it)) building->Reset(); m_just_conquered = false; m_is_about_to_be_colonized = false; m_is_about_to_be_invaded = false; m_is_about_to_be_bombarded = false; SetOwner(ALL_EMPIRES); } // if desired pop > 0, we want a colony, not an outpost, so we have to set the colony species if (population > 0.0) SetSpecies(species_name); // find a default focus. use first defined available focus. // AvailableFoci function should return a vector of all names of // available foci. std::vector<std::string> available_foci = AvailableFoci(); if (species && !available_foci.empty()) { bool found_preference = false; for (std::vector<std::string>::const_iterator it = available_foci.begin(); it != available_foci.end(); ++it) { if (!it->empty() && *it == species->PreferredFocus()) { SetFocus(*it); found_preference = true; break; } } if (!found_preference) SetFocus(*available_foci.begin()); } else { DebugLogger() << "Planet::Colonize unable to find a focus to set for species " << species_name; } // set colony population GetMeter(METER_POPULATION)->SetCurrent(population); GetMeter(METER_TARGET_POPULATION)->SetCurrent(population); BackPropagateMeters(); // set specified empire as owner SetOwner(empire_id); // if there are buildings on the planet, set the specified empire as their owner too std::vector<TemporaryPtr<Building> > buildings = Objects().FindObjects<Building>(BuildingIDs()); for (std::vector<TemporaryPtr<Building> >::iterator building_it = buildings.begin(); building_it != buildings.end(); ++building_it) { (*building_it)->SetOwner(empire_id); } return true; }
void RoadPositionSystem::Update(float dt) { for(auto o : Objects()) { PositionChanged(o); } }
void FleetTransferOrder::ExecuteImpl() const { ValidateEmpireID(); // look up the destination fleet TemporaryPtr<Fleet> target_fleet = GetFleet(DestinationFleet()); if (!target_fleet) { ErrorLogger() << "Empire attempted to move ships to a nonexistant fleet"; return; } // check that destination fleet is owned by empire if (!target_fleet->OwnedBy(EmpireID())) { ErrorLogger() << "Empire attempted to move ships to a fleet it does not own"; return; } // verify that fleet is in a system if (target_fleet->SystemID() == INVALID_OBJECT_ID) { ErrorLogger() << "Empire attempted to transfer ships to/from fleet(s) not in a system"; return; } // check that all ships are in the same system std::vector<TemporaryPtr<Ship> > ships = Objects().FindObjects<Ship>(m_add_ships); std::vector<TemporaryPtr<Ship> > validated_ships; validated_ships.reserve(m_add_ships.size()); std::vector<int> validated_ship_ids; validated_ship_ids.reserve(m_add_ships.size()); for (std::vector<TemporaryPtr<Ship> >::const_iterator it = ships.begin(); it != ships.end(); ++it) { TemporaryPtr<Ship> ship = *it; if (!ship->OwnedBy(EmpireID())) continue; if (ship->SystemID() != target_fleet->SystemID()) continue; if (ship->FleetID() == target_fleet->ID()) continue; validated_ships.push_back(ship); validated_ship_ids.push_back(ship->ID()); } if (validated_ships.empty()) return; GetUniverse().InhibitUniverseObjectSignals(true); // remove from old fleet(s) std::set<TemporaryPtr<Fleet> > modified_fleets; for (std::vector<TemporaryPtr<Ship> >::iterator it = validated_ships.begin(); it != validated_ships.end(); ++it) { TemporaryPtr<Ship> ship = *it; if (TemporaryPtr<Fleet> source_fleet = GetFleet(ship->FleetID())) { source_fleet->RemoveShip(ship->ID()); modified_fleets.insert(source_fleet); } ship->SetFleetID(target_fleet->ID()); } // add to new fleet target_fleet->AddShips(validated_ship_ids); GetUniverse().InhibitUniverseObjectSignals(false); // signal change to fleet states modified_fleets.insert(target_fleet); for (std::set<TemporaryPtr<Fleet> >::iterator it = modified_fleets.begin(); it != modified_fleets.end(); ++it) { TemporaryPtr<Fleet> modified_fleet = *it; if (!modified_fleet->Empty()) modified_fleet->StateChangedSignal(); // if modified fleet is empty, it should be immently destroyed, so that updating it now is redundant } }
CombatInfo::CombatInfo(int system_id_, int turn_) : turn(turn_), system_id(system_id_) { TemporaryPtr<System> system = ::GetSystem(system_id); if (!system) { Logger().errorStream() << "CombatInfo constructed with invalid system id: " << system_id; return; } // add system to full / complete objects in combat - NOTE: changed from copy of system objects.Insert(system); // find ships and their owners in system std::vector<TemporaryPtr<Ship> > ships = Objects().FindObjects<Ship>(system->ShipIDs()); for (std::vector<TemporaryPtr<Ship> >::const_iterator ship_it = ships.begin(); ship_it != ships.end(); ++ship_it) { TemporaryPtr<Ship> ship = *ship_it; // add owner to empires that have assets in this battle empire_ids.insert(ship->Owner()); objects.Insert(ship); } // find planets and their owners in system std::vector<TemporaryPtr<Planet> > planets = Objects().FindObjects<Planet>(system->PlanetIDs()); for (std::vector<TemporaryPtr<Planet> >::const_iterator planet_it = planets.begin(); planet_it != planets.end(); ++planet_it) { TemporaryPtr<Planet> planet = *planet_it; // if planet is populated, add owner to empires that have assets in this battle if (planet->CurrentMeterValue(METER_POPULATION) > 0.0) empire_ids.insert(planet->Owner()); objects.Insert(planet); } // TODO: should buildings be considered separately? // now that all participants in the battle have been found, loop through // objects again to assemble each participant empire's latest // known information about all objects in this battle // system for (std::set<int>::const_iterator empire_it = empire_ids.begin(); empire_it != empire_ids.end(); ++empire_it) { int empire_id = *empire_it; if (empire_id == ALL_EMPIRES) continue; empire_known_objects[empire_id].Insert(GetEmpireKnownSystem(system->ID(), empire_id)); } // ships for (std::vector<TemporaryPtr<Ship> >::const_iterator it = ships.begin(); it != ships.end(); ++it) { TemporaryPtr<Ship> ship = *it; int ship_id = ship->ID(); TemporaryPtr<const Fleet> fleet = GetFleet(ship->FleetID()); if (!fleet) { Logger().errorStream() << "CombatInfo::CombatInfo couldn't get fleet with id " << ship->FleetID() << " in system " << system->Name() << " (" << system_id << ")"; continue; } for (std::set<int>::const_iterator empire_it = empire_ids.begin(); empire_it != empire_ids.end(); ++empire_it) { int empire_id = *empire_it; if (empire_id == ALL_EMPIRES) continue; if (GetUniverse().GetObjectVisibilityByEmpire(ship_id, empire_id) >= VIS_BASIC_VISIBILITY || (fleet->Aggressive() && (empire_id == ALL_EMPIRES || fleet->Unowned() || Empires().GetDiplomaticStatus(empire_id, fleet->Owner()) == DIPLO_WAR))) { empire_known_objects[empire_id].Insert(GetEmpireKnownShip(ship->ID(), empire_id));} } } // planets for (std::vector<TemporaryPtr<Planet> >::const_iterator it = planets.begin(); it != planets.end(); ++it) { TemporaryPtr<Planet> planet = *it; int planet_id = planet->ID(); for (std::set<int>::const_iterator empire_it = empire_ids.begin(); empire_it != empire_ids.end(); ++empire_it) { int empire_id = *empire_it; if (empire_id == ALL_EMPIRES) continue; if (GetUniverse().GetObjectVisibilityByEmpire(planet_id, empire_id) >= VIS_BASIC_VISIBILITY) { empire_known_objects[empire_id].Insert(GetEmpireKnownPlanet(planet->ID(), empire_id)); } } } // after battle is simulated, any changes to latest known or actual objects // will be copied back to the main Universe's ObjectMap and the Universe's // empire latest known objects ObjectMap - NOTE: Using the real thing now }
void HydralicMeshSystem::Update(float dt) { for (GameObject* object : Objects()) { const Atlas::Node& housing = object->GetComponent<Atlas>()->GetNode("HydralicHousing"); const Atlas::Node& cylinder = object->GetComponent<Atlas>()->GetNode("HydralicMetal"); auto& mesh = object->GetComponent<Mesh>()->GetMesh<Vertex>(); Spring* spring = object->GetComponent<Spring>(); float houseWidth = object->GetComponent<Hydralic>()->minLength; float houseEdgeWidth = 0.02f; float houseThickness = 1.2f; float houseTex = 0.05f; float cylinderEdgeWidth = 0.02f; float cylinderWidth = spring->length - houseWidth; float cylinderThickness = 0.80f; float cylinderTex = 0.05f; mesh.vertices.resize(6 + 8); mesh.vertices[0].Position = {cylinderThickness, houseWidth,0}; mesh.vertices[0].TextureCoords = {cylinder.outer.left +cylinderTex,cylinder.outer.top}; mesh.vertices[1].Position = {-cylinderThickness, houseWidth,0}; mesh.vertices[1].TextureCoords = {cylinder.outer.left +cylinderTex,cylinder.outer.bottom}; mesh.vertices[2].Position = {cylinderThickness, houseWidth+cylinderWidth-cylinderEdgeWidth,0}; mesh.vertices[2].TextureCoords = {cylinder.outer.right - cylinderTex, cylinder.outer.top}; mesh.vertices[3].Position = {-cylinderThickness,houseWidth+cylinderWidth-cylinderEdgeWidth,0}; mesh.vertices[3].TextureCoords = {cylinder.outer.right - cylinderTex, cylinder.outer.bottom}; mesh.vertices[4].Position = {cylinderThickness,houseWidth+cylinderWidth,0}; mesh.vertices[4].TextureCoords = {cylinder.outer.right, cylinder.outer.top}; mesh.vertices[5].Position = {-cylinderThickness,houseWidth+cylinderWidth,0}; mesh.vertices[5].TextureCoords = {cylinder.outer.right, cylinder.outer.bottom}; mesh.triangles.clear(); for (int i=0; i<2; i++) { int index = i * 2; mesh.triangles.push_back(index + 0); mesh.triangles.push_back(index + 2); mesh.triangles.push_back(index + 3); mesh.triangles.push_back(index + 0); mesh.triangles.push_back(index + 3); mesh.triangles.push_back(index + 1); } mesh.vertices[6].Position = {houseThickness,0,0}; mesh.vertices[6].TextureCoords = {housing.outer.left, housing.outer.top}; mesh.vertices[7].Position = {-houseThickness,0,0}; mesh.vertices[7].TextureCoords = {housing.outer.left, housing.outer.bottom}; mesh.vertices[8].Position = {houseThickness,houseEdgeWidth,0}; mesh.vertices[8].TextureCoords = {housing.outer.left+houseTex, housing.outer.top}; mesh.vertices[9].Position = {-houseThickness, houseEdgeWidth,0}; mesh.vertices[9].TextureCoords = {housing.outer.left+houseTex, housing.outer.bottom}; mesh.vertices[10].Position = {houseThickness, houseWidth - houseEdgeWidth,0}; mesh.vertices[10].TextureCoords = {housing.outer.right-houseTex, housing.outer.top}; mesh.vertices[11].Position = {-houseThickness,houseWidth - houseEdgeWidth,0}; mesh.vertices[11].TextureCoords = {housing.outer.right-houseTex, housing.outer.bottom}; mesh.vertices[12].Position = {houseThickness, houseWidth,0}; mesh.vertices[12].TextureCoords = {housing.outer.right, housing.outer.top}; mesh.vertices[13].Position = {-houseThickness, houseWidth,0}; mesh.vertices[13].TextureCoords = {housing.outer.right, housing.outer.bottom}; for (int i=0; i<3; i++) { int index = 6 + i * 2; mesh.triangles.push_back(index + 0); mesh.triangles.push_back(index + 2); mesh.triangles.push_back(index + 3); mesh.triangles.push_back(index + 0); mesh.triangles.push_back(index + 3); mesh.triangles.push_back(index + 1); } } }
void CreateWorld() { Objects TownUpObjects[9] = {Objects(375, 300, 50, 150), Objects(185, 325, 80, 130), Objects(85, 195, 50, 155), Objects(0, -1, 101, 210), Objects(100, -1, 135, 185), Objects(245, -1, 75, 100), Objects(310, -1, 50, 150), Objects(380, -1, 100, 150), Objects(400, -1, 100, 175)}; places.InsertTop("TownUP.bmp", NULL, NULL, NULL, 9, TownUpObjects, 0, NULL, 0, NULL); Objects TownExitObjects[11] = {Objects(-1, -1, 140, 100), Objects(85, -1, 50, 155), Objects(160, -1, 40, 155), Objects(240, -1, 90, 155), Objects(340, -1, 150, 155), Objects(370, -1, 175, 175), Objects(-1, 360, 125, 150), Objects(315, 300, 300, 300), Objects(400, 240, 100, 100), Objects(30, 210, 50, 50), Objects(270, 210, 50, 50)}; places.InsertBottom("TownExit.bmp", NULL, NULL, NULL, 11, TownExitObjects, 0, NULL, 2, NPCs); Objects TownLeftObjects[9] = {Objects(240, 290, 75, 85), Objects(-1, -1, 100, 175), Objects(90, -1, 50, 210), Objects(150, 0, 90, 210), Objects(210, 0, 30, 260), Objects(-1, 290, 70, 200), Objects(210, 0, 50, 75), Objects(285, 0, 177, 75), Objects(400, 75, 60, 125)}; places.InsertLeft("TownLeft.bmp", NULL, NULL, NULL, 9, TownLeftObjects, 0, NULL, 0, NULL); currentLocation = currentLocation->left; Objects LeftUpObjects[8] = {Objects(0, 0, 235, 210), Objects(0, 209, 100, 200), Objects(0, 280, 230, 200), Objects(170, 250, 50, 200), Objects(245, 0, 200, 210), Objects(365, 209, 100, 200), Objects(250, 290, 300, 160), Objects(250, 250, 60, 100)}; currentLocation->InsertTop("TownLeftUp.bmp", NULL, NULL, NULL, 8, LeftUpObjects, 0, NULL, 0, NULL); currentLocation = places.bottom; Objects FirstForest[9] = {Objects(0, 0, 190, 275), Objects(0, 199, 165, 100), Objects(0, 298, 110, 150), Objects(0, 370, 140, 75), Objects(190, 270, 75, 180), Objects(250, 0, 250, 150), Objects(280, 0, 250, 200), Objects(330, 189, 250, 150), Objects(380, 300, 100, 150)}; currentLocation->InsertBottom("FirstForest.bmp", NULL, NULL, NULL, 9, FirstForest, 0, NULL, 0, NULL); currentLocation = currentLocation->bottom; Objects SecondForest[6] = {Objects(0, 0, 170, 200), Objects(215, 0, 85, 200), Objects(170, 120, 45, 160), Objects(330, 0, 100, 465), Objects(220, 250, 45, 160), Objects(0, 300, 250, 250)}; currentLocation->InsertBottom("SecondForest.bmp", NULL, NULL, NULL, 6, SecondForest, 0, NULL, 0, NULL); currentLocation = currentLocation->bottom; Objects caveObjects[4] = {Objects(-1, -1, 200, 500), Objects(100, 200, 130, 500), Objects(300, -1, 500, 500), Objects(250, 200, 500, 500)}; Interior Cave[1] = {Interior(new Location("FirstCave.bmp", NULL, NULL, NULL, NULL, 4, caveObjects, 0, NULL, 0, NULL), 215, 150, 240, 60, SetFront)}; Objects ThirdForest[5] = {Objects(0, 0, 200, 500), Objects(230, -1, 220, 200), Objects(250, 199, 140, 160), Objects(390, 300, 50, 150), Objects(199, 325, 35, 30)}; currentLocation->InsertLeft("ThirdForest.bmp", NULL, NULL, NULL, 5, ThirdForest, 1, Cave, 0, NULL); currentLocation = currentLocation->left; Objects SecondCaveObjects[5] = {Objects(-1, -1, 200, 300), Objects(-1, -1, 231, 200), Objects(0, 298, 255, 200), Objects(250, -1, 500, 200), Objects(280, 100, 500, 500)}; currentLocation->interiors[0].getLocation()->InsertBottom("SecondCave.bmp", NULL, NULL, NULL, 5, SecondCaveObjects, 0, NULL, 0, NULL); currentLocation = &places; }
int current_frame=0; bool w = false, a = false, s = false, d = false, InInterior = false, InMenu = false, topInterior = false, text1 = false, text2 = false; void *font2; float color[3]; CTimer StopTime; int last_time, StoppedTime, currentInterior, walkTimer; CTimer *Timer=new CTimer(); Inventory inventory; CObject *NPCs = NULL; CObject Textbox; Character Gerad; BMPClass background; CBaseSprite *mario1sprite=NULL, *InventorySprite=NULL, *NPC1Sprite = NULL, *NPC2Sprite = NULL, *TextboxSprite = NULL; Objects objects[9] = {Objects(0, 190, 40, 300), Objects(0, 0, 50, 100), Objects(0, 260, 200, 215), Objects(240, 390, 215, 215), Objects(285, 350, 45, 50), Objects(80, 150, 60, 300), Objects(375, 300, 200, 200), Objects(250, 0, 75, 110), Objects(435, 0, 75,50)}; Location places("StartingPoint.bmp", NULL, NULL, NULL, NULL, 9, objects, 0, NULL, 0, NULL); Location *currentLocation = &places; Location *exitLocation = NULL; void CreateObjects() { int x=50, y=250, xspeed=-4, yspeed=0; Gerad.person.create(x, y, xspeed, yspeed, mario1sprite, Timer); inventory.box.create(50, 50, 0, 0, InventorySprite, Timer); NPCs = new CObject[2]; NPCs[0].create(x, y, xspeed, yspeed, NPC1Sprite, Timer); NPCs[1].create(x + 250, y, xspeed, yspeed, NPC2Sprite, Timer); Textbox.create(50, 50, 0, 0, TextboxSprite, Timer);