bool Algorithm::OnFindPath(std::shared_ptr<NetAvatar> player, std::shared_ptr<World> world, const CL_Vec2i& current_pos, const CL_Vec2i& future_pos) {
int start = current_pos.m_x + current_pos.m_y * world->GetSize().m_x;
int end = future_pos.m_x + future_pos.m_y * world->GetSize().m_x;
if (current_pos.m_x < 0 || current_pos.m_x >= world->GetSize().m_x || current_pos.m_y < 0 || current_pos.m_y >= world->GetSize().m_y)
return false;
if (future_pos.m_x < 0 || future_pos.m_x >= world->GetSize().m_x || future_pos.m_y < 0 || future_pos.m_y >= world->GetSize().m_y)
return false;
if (world->IsObstacle(player, current_pos) || world->IsObstacle(player, future_pos))
return false;
if (start == end)
return true;
for (auto& tile : world->GetTiles()) {
tile.m_path_parent = -1;
tile.m_visited = false;
tile.m_local = INFINITY;
tile.m_global = INFINITY;
}
auto get_distance = [&](int32_t a, int32_t b) {
return sqrtf(
(world->GetTile(a)->GetPosition().m_x - world->GetTile(b)->GetPosition().m_x) * (world->GetTile(a)->GetPosition().m_x - world->GetTile(b)->GetPosition().m_x) +
(world->GetTile(a)->GetPosition().m_y - world->GetTile(b)->GetPosition().m_y) * (world->GetTile(a)->GetPosition().m_y - world->GetTile(b)->GetPosition().m_y)
);
};
int current = start;
world->GetTile(start)->m_local = 0.0f;
world->GetTile(start)->m_global = get_distance(start, end);
std::list<int> not_tested;
not_tested.emplace_back(start);
while(!not_tested.empty() && current != end) {
not_tested.sort([&](const int lhs, const int rhs) {
return world->GetTile(lhs)->m_global < world->GetTile(rhs)->m_global;
});
while(!not_tested.empty() && world->GetTile(not_tested.front())->m_visited)
not_tested.pop_front();
if (not_tested.empty())
break;
current = not_tested.front();
world->GetTile(current)->m_visited = true;
int x = world->GetTile(current)->GetPosition().m_x, y = world->GetTile(current)->GetPosition().m_y;
if (y + 1 < world->GetSize().m_y) {
int index = world->GetTile(x + (y + 1) * world->GetSize().m_x)->GetPosition().m_x + world->GetTile(x + (y + 1) * world->GetSize().m_x)->GetPosition().m_y * world->GetSize().m_x;
if (!world->GetTile(index)->m_visited && world->IsObstacle(player, { world->GetTile(index)->GetPosition().m_x, world->GetTile(index)->GetPosition().m_y }) == false)
not_tested.emplace_back(index);
float distance = world->GetTile(current)->m_local + get_distance(current, index);
if (distance < world->GetTile(index)->m_local) {
world->GetTile(index)->m_path_parent = current;
world->GetTile(index)->m_local = distance;
world->GetTile(index)->m_global = world->GetTile(index)->m_local + get_distance(index, end);
}
}
if (x + 1 < world->GetSize().m_x) {
int index = world->GetTile((x + 1) + y * world->GetSize().m_x)->GetPosition().m_x + world->GetTile((x + 1) + y * world->GetSize().m_x)->GetPosition().m_y * world->GetSize().m_x;
if (!world->GetTile(index)->m_visited && world->IsObstacle(player, { world->GetTile(index)->GetPosition().m_x, world->GetTile(index)->GetPosition().m_y }) == false)
not_tested.emplace_back(index);
float distance = world->GetTile(current)->m_local + get_distance(current, index);
if (distance < world->GetTile(index)->m_local) {
world->GetTile(index)->m_path_parent = current;
world->GetTile(index)->m_local = distance;
world->GetTile(index)->m_global = world->GetTile(index)->m_local + get_distance(index, end);
}
}
if (y - 1 >= 0) {
int index = world->GetTile(x + (y - 1) * world->GetSize().m_x)->GetPosition().m_x + world->GetTile(x + (y - 1) * world->GetSize().m_x)->GetPosition().m_y * world->GetSize().m_x;
if (!world->GetTile(index)->m_visited && world->IsObstacle(player, { world->GetTile(index)->GetPosition().m_x, world->GetTile(index)->GetPosition().m_y }) == false)
not_tested.emplace_back(index);
float distance = world->GetTile(current)->m_local + get_distance(current, index);
if (distance < world->GetTile(index)->m_local) {
world->GetTile(index)->m_path_parent = current;
world->GetTile(index)->m_local = distance;
world->GetTile(index)->m_global = world->GetTile(index)->m_local + get_distance(index, end);
}
}
if (x - 1 >= 0) {
int index = world->GetTile((x - 1) + y * world->GetSize().m_x)->GetPosition().m_x + world->GetTile((x - 1) + y * world->GetSize().m_x)->GetPosition().m_y * world->GetSize().m_x;
if (!world->GetTile(index)->m_visited && world->IsObstacle(player, { world->GetTile(index)->GetPosition().m_x, world->GetTile(index)->GetPosition().m_y }) == false)
not_tested.emplace_back(index);
float distance = world->GetTile(current)->m_local + get_distance(current, index);
if (distance < world->GetTile(index)->m_local) {
world->GetTile(index)->m_path_parent = current;
world->GetTile(index)->m_local = distance;
world->GetTile(index)->m_global = world->GetTile(index)->m_local + get_distance(index, end);
}
}
}
if (end != -1) {
int p = end;
if (p < 0 || p >= world->GetSize().m_x * world->GetSize().m_y)
return false;
while (world->GetTile(p)->m_path_parent != -1) {
if (world->GetTile(p)->m_path_parent == p)
return false;
if (p < 0 || p >= world->GetSize().m_x * world->GetSize().m_y)
return false;
p = world->GetTile(p)->m_path_parent;
}
if (p == start)
return true;
}
return false;
}
bool ar_turi_noclipa(World* world_, int x, int y, WorldBlock* target_, ENetPeer* p_) {
//try {
vector<int> new_tiles{};
if (items[world_->blocks[(int)x / 32 + ((int)y / 32 * 100)].fg].collisionType != 1 or items[world_->blocks[(int)x / 32 + ((int)y / 32 * 100)].fg].entrance or items[world_->blocks[(int)x / 32 + ((int)y / 32 * 100)].fg].toggleable or items[world_->blocks[(int)x / 32 + ((int)y / 32 * 100)].fg].vipentrance) {
if (items[world_->blocks[(int)x / 32 + ((int)y / 32 * 100)].fg].vipentrance and not world_->blocks[(int)x / 32 + ((int)y / 32 * 100)].limit_admins and world_->owner_name != pInfo(p_)->tankIDName and not world_->owner_name.empty() and find(world_->blocks[(int)x / 32 + ((int)y / 32 * 100)].admins.begin(), world_->blocks[(int)x / 32 + ((int)y / 32 * 100)].admins.end(), pInfo(p_)->tankIDName) == world_->blocks[(int)x / 32 + ((int)y / 32 * 100)].admins.end()) {
}
else if (items[world_->blocks[(int)x / 32 + ((int)y / 32 * 100)].fg].entrance and is_false_state(world_->blocks[(int)x / 32 + ((int)y / 32 * 100)], 0x00800000) and world_->owner_name != pInfo(p_)->tankIDName and not world_->open_to_public and not world_->owner_name.empty() and !guild_access(p_, world_->guild_id) and find(world_->admins.begin(), world_->admins.end(), pInfo(p_)->tankIDName) == world_->admins.end()) {
}
else if (items[world_->blocks[(int)x / 32 + ((int)y / 32 * 100)].fg].toggleable and is_false_state(world_->blocks[(int)x / 32 + ((int)y / 32 * 100)], 0x00400000)) {
}
else {
new_tiles.push_back((int)x / 32 + ((int)y / 32 * 100));
}
} int ySize = world_->blocks.size() / 100, xSize = world_->blocks.size() / ySize;
vector<WorldBlock> shadow_copy = world_->blocks;
for (int i2 = 0; i2 < new_tiles.size(); i2++) {
int x_ = new_tiles[i2] % 100, y_ = new_tiles[i2] / 100;
/*if (abs(x_ - x) >= 10 and abs(y_ - y) >= 10) {
return true;
}*/
if (&world_->blocks[x_ + (y_ * 100)] == target_ and items[shadow_copy[x_ + (y_ * 100)].fg].collisionType != 1) {
return false;
} if (x_ < 99 and items[shadow_copy[x_ + 1 + (y_ * 100)].fg].collisionType != 1 or x_ < 99 and items[shadow_copy[x_ + 1 + (y_ * 100)].fg].entrance or x_ < 99 and items[shadow_copy[x_ + 1 + (y_ * 100)].fg].toggleable) {
if (items[shadow_copy[x_ + 1 + (y_ * 100)].fg].vipentrance and not shadow_copy[x_ + 1 + (y_ * 100)].limit_admins and world_->owner_name != pInfo(p_)->tankIDName and not world_->owner_name.empty() and find(shadow_copy[x_ + 1 + (y_ * 100)].admins.begin(), shadow_copy[x_ + 1 + (y_ * 100)].admins.end(), pInfo(p_)->tankIDName) == shadow_copy[x_ + 1 + (y_ * 100)].admins.end()) {
}
else if (items[shadow_copy[x_ + 1 + (y_ * 100)].fg].entrance and is_false_state(shadow_copy[x_ + 1 + (y_ * 100)], 0x00800000) and world_->owner_name != pInfo(p_)->tankIDName and not world_->open_to_public and not world_->owner_name.empty() and !guild_access(p_, world_->guild_id) and find(world_->admins.begin(), world_->admins.end(), pInfo(p_)->tankIDName) == world_->admins.end()) {
}
else if (items[shadow_copy[x_ + 1 + (y_ * 100)].fg].toggleable and is_false_state(shadow_copy[x_ + 1 + (y_ * 100)], 0x00400000)) {
}
else {
if (not shadow_copy[x_ + 1 + (y_ * 100)].scanned) {
shadow_copy[x_ + 1 + (y_ * 100)].scanned = true;
new_tiles.push_back(x_ + 1 + (y_ * 100));
}
}
} if (x_ > 0 and items[shadow_copy[x_ - 1 + (y_ * 100)].fg].collisionType != 1 or x_ > 0 and items[shadow_copy[x_ - 1 + (y_ * 100)].fg].entrance or x_ > 0 and items[shadow_copy[x_ - 1 + (y_ * 100)].fg].toggleable) {
if (items[shadow_copy[x_ - 1 + (y_ * 100)].fg].vipentrance and not shadow_copy[x_ - 1 + (y_ * 100)].limit_admins and world_->owner_name != pInfo(p_)->tankIDName and not world_->owner_name.empty() and find(shadow_copy[x_ - 1 + (y_ * 100)].admins.begin(), shadow_copy[x_ - 1 + (y_ * 100)].admins.end(), pInfo(p_)->tankIDName) == shadow_copy[x_ - 1 + (y_ * 100)].admins.end()) {
}
else if (items[shadow_copy[x_ - 1 + (y_ * 100)].fg].entrance and is_false_state(shadow_copy[x_ - 1 + (y_ * 100)], 0x00800000) and world_->owner_name != pInfo(p_)->tankIDName and not world_->open_to_public and not world_->owner_name.empty() and !guild_access(p_, world_->guild_id) and find(world_->admins.begin(), world_->admins.end(), pInfo(p_)->tankIDName) == world_->admins.end()) {
}
else if (items[shadow_copy[x_ - 1 + (y_ * 100)].fg].toggleable and is_false_state(shadow_copy[x_ - 1 + (y_ * 100)], 0x00400000)) {
}
else {
if (not shadow_copy[x_ - 1 + (y_ * 100)].scanned) {
shadow_copy[x_ - 1 + (y_ * 100)].scanned = true;
new_tiles.push_back(x_ - 1 + (y_ * 100));
}
}
} if (y_ < 59 and items[shadow_copy[x_ + ((y_ + 1) * 100)].fg].collisionType != 1 or y_ < 59 and items[shadow_copy[x_ + ((y_ + 1) * 100)].fg].entrance or y_ < 59 and items[shadow_copy[x_ + ((y_ + 1) * 100)].fg].toggleable) {
if (items[shadow_copy[x_ + ((y_ + 1) * 100)].fg].vipentrance and not shadow_copy[x_ + ((y_ + 1) * 100)].limit_admins and world_->owner_name != pInfo(p_)->tankIDName and not world_->owner_name.empty() and find(shadow_copy[x_ + ((y_ + 1) * 100)].admins.begin(), shadow_copy[x_ + ((y_ + 1) * 100)].admins.end(), pInfo(p_)->tankIDName) == shadow_copy[x_ + ((y_ + 1) * 100)].admins.end()) {
}
else if (items[shadow_copy[x_ + ((y_ + 1) * 100)].fg].entrance and is_false_state(shadow_copy[x_ + ((y_ + 1) * 100)], 0x00800000) and world_->owner_name != pInfo(p_)->tankIDName and not world_->open_to_public and not world_->owner_name.empty() and !guild_access(p_, world_->guild_id) and find(world_->admins.begin(), world_->admins.end(), pInfo(p_)->tankIDName) == world_->admins.end()) {
}
else if (items[shadow_copy[x_ + ((y_ + 1) * 100)].fg].toggleable and is_false_state(shadow_copy[x_ + ((y_ + 1) * 100)], 0x00400000)) {
}
else {
if (not shadow_copy[x_ + ((y_ + 1) * 100)].scanned) {
shadow_copy[x_ + ((y_ + 1) * 100)].scanned = true;
new_tiles.push_back(x_ + ((y_ + 1) * 100));
}
}
} if (y_ > 0 and items[shadow_copy[x_ + ((y_ - 1) * 100)].fg].collisionType != 1 or y_ > 0 and items[shadow_copy[x_ + 1 + ((y_ - 1) * 100)].fg].entrance or y_ > 0 and items[shadow_copy[x_ + 1 + ((y_ - 1) * 100)].fg].toggleable) {
if (items[shadow_copy[x_ + ((y_ - 1) * 100)].fg].vipentrance and not shadow_copy[x_ + ((y_ - 1) * 100)].limit_admins and world_->owner_name != pInfo(p_)->tankIDName and not world_->owner_name.empty() and find(shadow_copy[x_ + ((y_ - 1) * 100)].admins.begin(), shadow_copy[x_ + ((y_ - 1) * 100)].admins.end(), pInfo(p_)->tankIDName) == shadow_copy[x_ + ((y_ - 1) * 100)].admins.end()) {
}
else if (items[shadow_copy[x_ + ((y_ - 1) * 100)].fg].entrance and is_false_state(shadow_copy[x_ + ((y_ - 1) * 100)], 0x00800000) and world_->owner_name != pInfo(p_)->tankIDName and not world_->open_to_public and not world_->owner_name.empty() and !guild_access(p_, world_->guild_id) and find(world_->admins.begin(), world_->admins.end(), pInfo(p_)->tankIDName) == world_->admins.end()) {
}
else if (items[shadow_copy[x_ + ((y_ - 1) * 100)].fg].toggleable and is_false_state(shadow_copy[x_ + ((y_ - 1) * 100)], 0x00400000)) {
}
else {
if (not shadow_copy[x_ + ((y_ - 1) * 100)].scanned) {
shadow_copy[x_ + ((y_ - 1) * 100)].scanned = true;
new_tiles.push_back(x_ + ((y_ - 1) * 100));
}
}
}
}
return true;
//}
//catch (out_of_range) {
//return false;
//}
}