| 100 | } |
| 101 | |
| 102 | bool placeRandomTree(const World::Pos2& pos, std::optional<uint8_t> treeType) |
| 103 | { |
| 104 | GameCommands::TreePlacementArgs args; |
| 105 | args.quadrant = World::getQuadrantFromPos(pos); |
| 106 | args.pos = World::Pos2(pos.x & 0xFFE0, pos.y & 0xFFE0); |
| 107 | // Note: this is not the same as the randomDirection above as it is the trees rotation |
| 108 | args.rotation = gPrng1().randNext(3); |
| 109 | args.colour = Colour::black; |
| 110 | |
| 111 | // If not set by the caller then a random tree type is selected based on the surface type |
| 112 | std::optional<uint8_t> randTreeType = treeType; |
| 113 | if (!randTreeType.has_value()) |
| 114 | { |
| 115 | randTreeType = getRandomTreeTypeFromSurface(World::toTileSpace(args.pos), false); |
| 116 | // It is possible that there are no valid tree types for the surface |
| 117 | if (!randTreeType.has_value()) |
| 118 | { |
| 119 | return false; |
| 120 | } |
| 121 | } |
| 122 | args.type = *randTreeType; |
| 123 | args.buildImmediately = true; |
| 124 | args.requiresFullClearance = true; |
| 125 | |
| 126 | // First query if we can place a tree at this location; skip if we can't. |
| 127 | auto queryRes = doCommand(args, 0); |
| 128 | if (queryRes == GameCommands::kFailure) |
| 129 | { |
| 130 | return false; |
| 131 | } |
| 132 | |
| 133 | // Actually place the tree |
| 134 | doCommand(args, GameCommands::Flags::apply); |
| 135 | return true; |
| 136 | } |
| 137 | |
| 138 | // 0x004BDC67 (when treeType is nullopt) & 0x004BDDC6 (when treeType is set) |
| 139 | bool placeTreeCluster(const World::TilePos2& centreLoc, const uint16_t range, const uint16_t density, const std::optional<uint8_t> treeType) |
no test coverage detected