diff --git .editorconfig .editorconfig index f3a6b01da..3bfe70220 100644 --- .editorconfig +++ .editorconfig @@ -22,3 +22,7 @@ indent_size = 2 [Makefile,*.mk] indent_style = space indent_size = 2 + +[{*.vcxitems,*.vcxproj}] +insert_final_newline = false +indent_style = space diff --git Makefile Makefile index 4ded87ec7..b97245d3d 100644 --- Makefile +++ Makefile @@ -257,6 +257,7 @@ SOURCES += bauer/fabrikbauer.cc SOURCES += bauer/goods_manager.cc SOURCES += bauer/hausbauer.cc SOURCES += bauer/tunnelbauer.cc +SOURCES += bauer/tree_builder.cc SOURCES += bauer/vehikelbauer.cc SOURCES += bauer/wegbauer.cc SOURCES += boden/boden.cc diff --git Simutrans-Main.vcxitems Simutrans-Main.vcxitems index 140bb9e05..3fd2fd5a3 100644 --- Simutrans-Main.vcxitems +++ Simutrans-Main.vcxitems @@ -47,6 +47,7 @@ + @@ -392,6 +393,7 @@ + diff --git bauer/tree_builder.cc bauer/tree_builder.cc new file mode 100644 index 000000000..2944136c2 --- /dev/null +++ bauer/tree_builder.cc @@ -0,0 +1,345 @@ +/* + * This file is part of the Simutrans project under the Artistic License. + * (see LICENSE.txt) + */ + +#include "tree_builder.h" + +#include "../dataobj/settings.h" +#include "../obj/baum.h" +#include "../obj/groundobj.h" +#include "../simworld.h" +#include "../utils/simrandom.h" + +#include + + +static karte_ptr_t welt; + + +static const uint8 tree_age_index[(baum_t::AGE_LIMIT >> 6) + 1] = +{ + 0,1,2,3,3,3,3,3,3,4,4,4 +}; + + +vector_tpl tree_builder_t::tree_list(0); +weighted_vector_tpl tree_builder_t::tree_list_per_climate[MAX_CLIMATES]; +stringhashtable_tpl tree_builder_t::desc_table; + + +/// Quick lookup of an image, assuring always five seasons and five ages. +/// Missing images just have identical entries. +/// Seasons are: 0=summer, 1=autumn, 2=winter, 3=spring, 4=snow +/// Snow image is used if tree is above snow line, or for arctic climate +static image_id tree_id_to_image[256][5*5]; + + +image_id tree_builder_t::get_tree_image(uint8 tree_id, uint32 age, uint8 season) +{ + const uint8 tree_age_idx = tree_age_index[min(age>>6, 11u)]; + assert(tree_age_idx < 5); + return tree_id_to_image[ tree_id ][ season*5 + tree_age_idx ]; +} + + +const tree_desc_t *tree_builder_t::find_tree(const char *tree_name) +{ + return tree_list.empty() ? NULL : desc_table.get(tree_name); +} + + +uint8 tree_builder_t::plant_tree_on_coordinate(koord pos, const uint8 maximum_count, const uint8 count) +{ + grund_t *gr = welt->lookup_kartenboden(pos); + if( gr ) { + if( has_trees_for_climate( welt->get_climate(pos) ) && gr->ist_natur() && gr->get_top() < maximum_count ) { + obj_t *obj = gr->obj_bei(0); + if(obj) { + switch(obj->get_typ()) { + case obj_t::wolke: + case obj_t::air_vehicle: + case obj_t::baum: + case obj_t::leitung: + case obj_t::label: + case obj_t::zeiger: + // ok to build here + break; + case obj_t::groundobj: + if(((groundobj_t *)obj)->get_desc()->can_build_trees_here()) { + break; + } + /* FALLTHROUGH */ + // leave these (and all other empty) + default: + return 0; + } + } + + const uint8 count_planted = min( maximum_count - gr->get_top(), count); + for (uint8 i=0; iobj_add( new baum_t(gr->get_pos()) ); //plants the tree(s) + } + + return count_planted; + } + } + + return 0; +} + + +bool tree_builder_t::plant_tree_on_coordinate(koord pos, const tree_desc_t *desc, const bool check_climate, const bool random_age) +{ + // none there + if( desc_table.empty() ) { + return false; + } + + grund_t *gr = welt->lookup_kartenboden(pos); + if( gr ) { + if( gr->ist_natur() && gr->get_top() < welt->get_settings().get_max_no_of_trees_on_square() && (!check_climate || desc->is_allowed_climate( welt->get_climate(pos) )) ) { + if( gr->get_top() > 0 ) { + switch(gr->obj_bei(0)->get_typ()) { + case obj_t::wolke: + case obj_t::air_vehicle: + case obj_t::baum: + case obj_t::leitung: + case obj_t::label: + case obj_t::zeiger: + // ok to built here + break; + case obj_t::groundobj: + if(((groundobj_t *)(gr->obj_bei(0)))->get_desc()->can_build_trees_here()) { + break; + } + /* FALLTHROUGH */ + // leave these (and all other empty) + default: + return false; + } + } + + baum_t *b = new baum_t(gr->get_pos(), desc); //plants the tree + if( random_age ) { + b->geburt = welt->get_current_month() - simrand(baum_t::AGE_LIMIT-1); + b->calc_off( welt->lookup( b->get_pos() )->get_grund_hang() ); + } + + gr->obj_add( b ); + return true; //tree was planted - currently unused value is not checked + } + } + + return false; +} + + +uint32 tree_builder_t::create_forest(koord new_center, koord wh, sint16 xtop, sint16 ytop, sint16 xbottom, sint16 ybottom) +{ + // none there + if( desc_table.empty() ) { + return 0; + } + + const sint16 xpos_f = new_center.x; + const sint16 ypos_f = new_center.y; + uint32 number_of_new_trees = 0; + + for( sint16 j = 0; j < wh.x; j++) { + for( sint16 i = 0; i < wh.y; i++) { + + const sint32 x_tree_pos = (j-(wh.x>>1)); + const sint32 y_tree_pos = (i-(wh.y>>1)); + + if( xtop > (xpos_f + x_tree_pos) || (xpos_f + x_tree_pos) >= xbottom ) { + continue; + } + if( ytop > (ypos_f + y_tree_pos) || (ypos_f + y_tree_pos) >= ybottom ) { + continue; + } + + const uint64 distance = 1 + sqrt_i64( ((uint64)x_tree_pos*x_tree_pos*(wh.y*wh.y) + (uint64)y_tree_pos*y_tree_pos*(wh.x*wh.x))); + const uint32 tree_probability = (uint32)( ( 8 * (uint32)((wh.x*wh.x)+(wh.y*wh.y)) ) / distance ); + + if (tree_probability < 38) { + continue; + } + + uint8 number_to_plant = 0; + uint8 const max_trees_here = min(welt->get_settings().get_max_no_of_trees_on_square(), (tree_probability - 38 + 1) / 2); + + for (uint8 c2 = 0 ; c2get_settings().get_max_no_of_trees_on_square(); + + number_of_new_trees += plant_tree_on_coordinate(tree_pos, max_trees_per_square, number_to_plant); + } + } + + return number_of_new_trees; +} + + +void tree_builder_t::fill_trees(int dichte, sint16 xtop, sint16 ytop, sint16 xbottom, sint16 ybottom ) +{ + // none there + if( desc_table.empty() ) { + return; + } + + DBG_MESSAGE("tree_builder_t::fill_trees", "distributing single trees"); + koord pos; + + for( pos.y=ytop; pos.ylookup_kartenboden(pos); + if(gr->get_top() == 0 && gr->get_typ() == grund_t::boden) { + // plant spare trees, (those with low preffered density) or in an entirely tree climate + const uint16 cl = 1 << welt->get_climate(pos); + const settings_t &s = welt->get_settings(); + + if ((cl & s.get_no_tree_climates()) == 0 && ((cl & s.get_tree_climates()) != 0 || simrand(s.get_forest_inverse_spare_tree_density() * dichte) < 100)) { + plant_tree_on_coordinate(pos, 1, 1); + } + } + } + } +} + + +static bool compare_tree_desc(const tree_desc_t *a, const tree_desc_t *b) +{ + // same level - we do an artificial but unique sorting by (untranslated) name + return strcmp(a->get_name(), b->get_name())<0; +} + + +bool tree_builder_t::successfully_loaded() +{ + if( desc_table.empty() ) { + DBG_MESSAGE("tree_builder_t::successfully_loaded", "No trees found - feature disabled"); + } + + FOR(stringhashtable_tpl, const& i, desc_table) { + tree_list.insert_ordered(i.value, compare_tree_desc); + if( tree_list.get_count()==255 ) { + dbg->error( "tree_builder_t::successfully_loaded", "Maximum tree count exceeded! (%u > 255)", desc_table.get_count() ); + break; + } + } + + tree_list.append( NULL ); + + // clear cache + memset( tree_id_to_image, -1, sizeof(tree_id_to_image) ); + + // now register all trees for all fitting climates + for( uint32 typ=0; typis_allowed_climate((climate)j) ) { + assert(typ <= 255); + tree_list_per_climate[j].append((uint8)typ, tree_list[typ]->get_distribution_weight()); + } + } + + // create cache images + for( uint8 season = 0; season < 5; season++ ) { + uint8 use_season = 0; + const sint16 seasons = tree_list[typ]->get_seasons(); + + if( seasons > 1 ) { + use_season = season; + // three possibilities + if( seasons < 4 ) { + // only summer and winter => season 4 with winter image + use_season = (season == 4); + } + else if( seasons == 4 ) { + // all there, but the snowy special image missing + if( season == 4 ) { + // take spring image (gave best results with pak64, pak.german) ////// but season 2 is winter???? + use_season = 2; + } + } + } + + for( uint8 age_idx = 0; age_idx < 5; age_idx++ ) { + tree_id_to_image[typ][season * 5 + age_idx] = tree_list[typ]->get_image_id( use_season, age_idx ); + } + } + } + + return true; +} + + +bool tree_builder_t::register_desc(const tree_desc_t *desc) +{ + // avoid duplicates with same name + if( desc_table.remove(desc->get_name()) ) { + dbg->doubled( "baum_t", desc->get_name() ); + } + + desc_table.put(desc->get_name(), desc ); + return true; +} + + +void tree_builder_t::distribute_trees(int dichte, sint16 xtop, sint16 ytop, sint16 xbottom, sint16 ybottom) +{ + // now we can proceed to tree planting routine itself + // best forests results are produced if forest size is tied to map size - + // but there is some nonlinearity to ensure good forests on small maps + settings_t const& s = welt->get_settings(); + sint32 const x = welt->get_size().x; + sint32 const y = welt->get_size().y; + unsigned const t_forest_size = (unsigned)pow(((double)x * (double)y), 0.25) * s.get_forest_base_size() / 11 + (x + y) / (2 * s.get_forest_map_size_divisor()); + uint8 const c_forest_count = (unsigned)pow(((double)x * (double)y), 0.5) / s.get_forest_count_divisor(); + + DBG_MESSAGE("tree_builder_t::distribute_trees", "Creating %i forests", c_forest_count); + + for (uint8 c1 = 0 ; c1 < c_forest_count ; c1++) { + // to have same execution order for simrand + koord const start = koord::koord_random(x, y); + koord const size = koord(t_forest_size,t_forest_size) + koord::koord_random(t_forest_size, t_forest_size); + + create_forest( start, size, xtop, ytop, xbottom, ybottom ); + } + + fill_trees( dichte, xtop, ytop, xbottom, ybottom ); +} + + +const tree_desc_t *tree_builder_t::random_tree_for_climate(climate cl) +{ + const uint16 b = random_tree_id_for_climate(cl); + return b!=0xFFFF ? tree_list[b] : NULL; +} + + +uint16 tree_builder_t::random_tree_id_for_climate(climate cl) +{ + // now weight their distribution + weighted_vector_tpl const &t = tree_list_per_climate[cl]; + return t.empty() ? 0xFFFF : pick_any_weighted(t); +} + + +bool tree_builder_t::spawn_tree_near(const baum_t *tree, int radius) +{ + // to have same execution order for simrand + const sint16 sx = simrand(2*radius + 1)-radius; + const sint16 sy = simrand(2*radius + 1)-radius; + const koord k = tree->get_pos().get_2d() + koord(sx,sy); + + return plant_tree_on_coordinate(k, tree->get_desc(), true, false); +} + diff --git bauer/tree_builder.h bauer/tree_builder.h new file mode 100644 index 000000000..2ef39943f --- /dev/null +++ bauer/tree_builder.h @@ -0,0 +1,76 @@ +/* + * This file is part of the Simutrans project under the Artistic License. + * (see LICENSE.txt) + */ + +#ifndef BAUER_TREE_BUILDER_H +#define BAUER_TREE_BUILDER_H + + +#include "../tpl/stringhashtable_tpl.h" +#include "../tpl/weighted_vector_tpl.h" +#include "../tpl/vector_tpl.h" + +#include "../dataobj/koord.h" +#include "../display/simimg.h" + + +class tree_desc_t; +class baum_t; + + +/// Handles desc management and distribution of trees. +class tree_builder_t +{ +private: + static stringhashtable_tpl desc_table; ///< Mapping desc_name -> desc + static vector_tpl tree_list; ///< Mapping tree_id -> desc + static weighted_vector_tpl tree_list_per_climate[MAX_CLIMATES]; ///< index vector into tree_list, accessible per climate + +public: + static const tree_desc_t *get_desc_by_name(const char * tree_name) { return desc_table.get(tree_name); } + static const tree_desc_t *get_desc_by_id(uint8 tree_id) { return tree_id < get_num_trees() ? tree_list[tree_id] : NULL; } + static uint8 get_id_by_desc(const tree_desc_t *desc) { return tree_list.index_of(desc); } + + static image_id get_tree_image(uint8 idx, uint32 age, uint8 season); + + static bool has_trees() { return get_num_trees() > 0; } + static bool has_trees_for_climate(climate cl) { return !tree_list_per_climate[cl].empty(); } + + static sint32 get_num_trees() { return tree_list.get_count()-1; } + + /// Fill rectangular region with trees. + static void fill_trees(int dichte, sint16 xtop, sint16 ytop, sint16 xbottom, sint16 ybottom); + + static bool register_desc(const tree_desc_t *desc); + static bool successfully_loaded(); + + /// @returns list of all registered descriptors + static const vector_tpl &get_all_desc() { return tree_list; } + + /// Plant a new tree in a (2n+1) * (2n+1) square around @p tree. + static bool spawn_tree_near(const baum_t *tree, int radius = 3); + + static uint32 create_forest(koord center, koord size, sint16 xtop, sint16 ytop, sint16 xbottom, sint16 ybottom); + +public: + /// distributes trees in a rectangular region of the map + static void distribute_trees(int dichte, sint16 xtop, sint16 ytop, sint16 xbottom, sint16 ybottom); + + /// tree planting function - it takes care of checking suitability of area + static bool plant_tree_on_coordinate(koord pos, const tree_desc_t *desc, const bool check_climate, const bool random_age); + + /// tree planting function - it takes care of checking suitability of area + static uint8 plant_tree_on_coordinate(koord pos, const uint8 maximum_count, const uint8 count); + + static const tree_desc_t *find_tree( const char *tree_name ); + + static const tree_desc_t *random_tree_for_climate(climate cl); + + /// also checks for distribution values + /// @returns the tree_i, or 0xFFFF if no trees exist for the requested climate. + static uint16 random_tree_id_for_climate(climate cl); +}; + + +#endif diff --git boden/boden.cc boden/boden.cc index 820f61551..265aafbb1 100644 --- boden/boden.cc +++ boden/boden.cc @@ -29,7 +29,7 @@ boden_t::boden_t(loadsave_t *file, koord pos ) : grund_t( koord3d(pos,0) ) sint32 age; file->rdwr_long( age ); // check, if we still have this tree ... (if there are not trees, the first index is NULL!) - if (id < baum_t::get_count() && baum_t::get_all_desc()[id]) { + if (tree_builder_t::get_desc_by_id(id) != NULL) { baum_t *tree = new baum_t( get_pos(), (uint8)id, age, slope ); objlist.add( tree ); } diff --git boden/grund.h boden/grund.h index d3e25b8d4..8f170d8c1 100644 --- boden/grund.h +++ boden/grund.h @@ -275,7 +275,14 @@ public: * Updates snowline dependent grund_t (and derivatives) - none are season dependent * Updates season and or snowline dependent objects */ - void check_season_snowline(const bool season_change, const bool snowline_change) { if( snowline_change ) { calc_image_internal( snowline_change ); } objlist.check_season( season_change && !snowline_change ); } + void check_season_snowline(const bool season_change, const bool snowline_change) + { + if( snowline_change ) { + calc_image_internal( snowline_change ); + } + + objlist.check_season( season_change && !snowline_change ); + } /** * Updates images after change of underground mode. diff --git dataobj/objlist.cc dataobj/objlist.cc index 9835ec31b..5aaae69dc 100644 --- dataobj/objlist.cc +++ dataobj/objlist.cc @@ -952,7 +952,7 @@ void objlist_t::rdwr(loadsave_t *file, koord3d current_pos) baum_t *b = new baum_t(file); if( !b->get_desc() ) { // is there a replacement possible - if( const tree_desc_t *desc = baum_t::random_tree_for_climate( world()->get_climate_at_height(current_pos.z) ) ) { + if( const tree_desc_t *desc = tree_builder_t::random_tree_for_climate( world()->get_climate_at_height(current_pos.z) ) ) { b->set_desc( desc ); } else { diff --git descriptor/reader/tree_reader.cc descriptor/reader/tree_reader.cc index e945cb215..2e7eea3c0 100644 --- descriptor/reader/tree_reader.cc +++ descriptor/reader/tree_reader.cc @@ -19,7 +19,7 @@ void tree_reader_t::register_obj(obj_desc_t *&data) { tree_desc_t *desc = static_cast(data); - baum_t::register_desc(desc); + tree_builder_t::register_desc(desc); checksum_t *chk = new checksum_t(); desc->calc_checksum(chk); pakset_info_t::append(desc->get_name(), get_type(), chk); @@ -28,7 +28,7 @@ void tree_reader_t::register_obj(obj_desc_t *&data) bool tree_reader_t::successfully_loaded() const { - return baum_t::successfully_loaded(); + return tree_builder_t::successfully_loaded(); } diff --git gui/baum_edit.cc gui/baum_edit.cc index b08f262b9..5c843fd01 100644 --- gui/baum_edit.cc +++ gui/baum_edit.cc @@ -81,7 +81,7 @@ void baum_edit_frame_t::fill_list() { tree_list.clear(); const bool is_sortedbyname = get_sortedby()==gui_sorting_item_t::BY_NAME_TRANSLATED; - FOR(vector_tpl, const i, baum_t::get_all_desc()) { + FOR(vector_tpl, const i, tree_builder_t::get_all_desc()) { if ( i && (i->get_allowed_climate_bits() & get_climate()) ) { tree_list.insert_ordered(i, is_sortedbyname ? compare_tree_desc_name : compare_tree_desc); } diff --git obj/baum.cc obj/baum.cc index f33f1af86..7a7533150 100644 --- obj/baum.cc +++ obj/baum.cc @@ -3,369 +3,158 @@ * (see LICENSE.txt) */ -#include -#include -#include +#include "baum.h" -#include "../simdebug.h" -#include "../simworld.h" -#include "simobj.h" -#include "../display/simimg.h" -#include "../player/simplay.h" -#include "../simtypes.h" +#include "groundobj.h" #include "../boden/grund.h" - +#include "../dataobj/environment.h" +#include "../dataobj/freelist.h" +#include "../dataobj/loadsave.h" +#include "../dataobj/translator.h" #include "../descriptor/tree_desc.h" - -#include "groundobj.h" - +#include "../display/simimg.h" +#include "../player/simplay.h" +#include "../simdebug.h" +#include "../simtypes.h" +#include "../simworld.h" #include "../utils/cbuffer_t.h" #include "../utils/simrandom.h" -#include "../dataobj/loadsave.h" -#include "../dataobj/translator.h" -#include "../dataobj/environment.h" -#include "../dataobj/freelist.h" - - -#include "baum.h" +#include +#include +#include -static const uint8 tree_age_index[12] = -{ - 0,1,2,3,3,3,3,3,3,4,4,4 -}; FLAGGED_PIXVAL baum_t::outline_color = 0; -// quick lookup of an image, assuring always five seasons and five ages -// missing images just have identical entries -// seasons are: 0=summer, 1=autumn, 2=winter, 3=spring, 4=snow -// snow image is used if tree is above snow line, or for arctic climate -static image_id tree_id_to_image[256][5*5]; - -// distributes trees on a map -void baum_t::distribute_trees(int dichte, sint16 xtop, sint16 ytop, sint16 xbottom, sint16 ybottom ) +baum_t::baum_t(loadsave_t *file) : + obj_t(), + geburt(welt->get_current_month()), + tree_id(0), + season(0) { - // now we can proceed to tree planting routine itself - // best forests results are produced if forest size is tied to map size - - // but there is some nonlinearity to ensure good forests on small maps - settings_t const& s = welt->get_settings(); - sint32 const x = welt->get_size().x; - sint32 const y = welt->get_size().y; - unsigned const t_forest_size = (unsigned)pow(((double)x * (double)y), 0.25) * s.get_forest_base_size() / 11 + (x + y) / (2 * s.get_forest_map_size_divisor()); - uint8 const c_forest_count = (unsigned)pow(((double)x * (double)y), 0.5) / s.get_forest_count_divisor(); - -DBG_MESSAGE("verteile_baeume()","creating %i forest",c_forest_count); - for (uint8 c1 = 0 ; c1 < c_forest_count ; c1++) { - // to have same execution order for simrand - koord const start = koord::koord_random(x, y); - koord const size = koord(t_forest_size,t_forest_size) + koord::koord_random(t_forest_size, t_forest_size); - create_forest( start, size, xtop, ytop, xbottom, ybottom ); - } - - fill_trees( dichte, xtop, ytop, xbottom, ybottom ); + rdwr(file); } -/*************************** first the static function for the baum_t and tree_desc_t administration ***************/ - -/* - * Diese Tabelle ermoeglicht das Auffinden dient zur Auswahl eines Baumtypen - */ -vector_tpl baum_t::tree_list(0); - -// index vector into tree_idn, accessible per climate -weighted_vector_tpl* baum_t::tree_list_per_climate = NULL; - -/* - * Diese Tabelle ermoeglicht das Auffinden einer Description durch ihren Namen - */ -stringhashtable_tpl baum_t::desc_table; - - -// total number of trees -// the same for a certain climate -int baum_t::get_count(climate cl) +baum_t::baum_t(koord3d pos) : + obj_t(pos), + geburt(welt->get_current_month() - simrand(baum_t::AGE_LIMIT-1)), // generate aged trees, might underflow + season(0) { - return tree_list_per_climate[cl].get_count(); + tree_id = (uint8)tree_builder_t::random_tree_id_for_climate( welt->get_climate( pos.get_2d() ) ); + + calc_off( welt->lookup( get_pos())->get_grund_hang() ); + calc_image(); } -/** - * tree planting function - it takes care of checking suitability of area - */ -uint8 baum_t::plant_tree_on_coordinate(koord pos, const uint8 maximum_count, const uint8 count) +baum_t::baum_t(koord3d pos, uint8 type, sint32 age, uint8 slope ) : + obj_t(pos), + geburt(welt->get_current_month() - age), // might underflow + tree_id(type), + season(0) { - grund_t * gr = welt->lookup_kartenboden(pos); - if( gr ) { - if( get_count( welt->get_climate(pos) ) > 0 && gr->ist_natur() && gr->get_top() < maximum_count ) { - obj_t *obj = gr->obj_bei(0); - if(obj) { - switch(obj->get_typ()) { - case obj_t::wolke: - case obj_t::air_vehicle: - case obj_t::baum: - case obj_t::leitung: - case obj_t::label: - case obj_t::zeiger: - // ok to built here - break; - case obj_t::groundobj: - if(((groundobj_t *)obj)->get_desc()->can_build_trees_here()) { - break; - } - /* FALLTHROUGH */ - // leave these (and all other empty) - default: - return 0; - } - } - const uint8 count_planted = min( maximum_count - gr->get_top(), count); - for (uint8 i=0; iobj_add( new baum_t(gr->get_pos()) ); //plants the tree(s) - } - return count_planted; - } - } - return 0; + calc_off( slope ); + calc_image(); } -/** - * tree planting function - it takes care of checking suitability of area - */ -bool baum_t::plant_tree_on_coordinate(koord pos, const tree_desc_t *desc, const bool check_climate, const bool random_age ) +baum_t::baum_t(koord3d pos, const tree_desc_t *desc) : + obj_t(pos), + geburt(welt->get_current_month()), + tree_id(tree_builder_t::get_id_by_desc(desc)), + season(0) { - // none there - if( desc_table.empty() ) { - return false; - } - grund_t *gr = welt->lookup_kartenboden(pos); - if( gr ) { - if( gr->ist_natur() && gr->get_top() < welt->get_settings().get_max_no_of_trees_on_square() && (!check_climate || desc->is_allowed_climate( welt->get_climate(pos) )) ) { - if( gr->get_top() > 0 ) { - switch(gr->obj_bei(0)->get_typ()) { - case obj_t::wolke: - case obj_t::air_vehicle: - case obj_t::baum: - case obj_t::leitung: - case obj_t::label: - case obj_t::zeiger: - // ok to built here - break; - case obj_t::groundobj: - if(((groundobj_t *)(gr->obj_bei(0)))->get_desc()->can_build_trees_here()) { - break; - } - /* FALLTHROUGH */ - // leave these (and all other empty) - default: - return false; - } - } - baum_t *b = new baum_t(gr->get_pos(), desc); //plants the tree - if( random_age ) { - b->geburt = welt->get_current_month() - simrand(703); - b->calc_off( welt->lookup( b->get_pos() )->get_grund_hang() ); - } - gr->obj_add( b ); - return true; //tree was planted - currently unused value is not checked - } - } - return false; + + calc_off( welt->lookup( get_pos())->get_grund_hang() ); + calc_image(); } -uint32 baum_t::create_forest(koord new_center, koord wh, sint16 xtop, sint16 ytop, sint16 xbottom, sint16 ybottom ) +void baum_t::rdwr(loadsave_t *file) { - // none there - if( desc_table.empty() ) { - return 0; - } - const sint16 xpos_f = new_center.x; - const sint16 ypos_f = new_center.y; - uint32 number_of_new_trees = 0; - for( sint16 j = 0; j < wh.x; j++) { - for( sint16 i = 0; i < wh.y; i++) { - - const sint32 x_tree_pos = (j-(wh.x>>1)); - const sint32 y_tree_pos = (i-(wh.y>>1)); + xml_tag_t d( file, "baum_t" ); - if( xtop > (xpos_f + x_tree_pos) || (xpos_f + x_tree_pos) >= xbottom ) { - continue; - } - if( ytop > (ypos_f + y_tree_pos) || (ypos_f + y_tree_pos) >= ybottom ) { - continue; - } + obj_t::rdwr(file); - const uint64 distance = 1 + sqrt_i64( ((uint64)x_tree_pos*x_tree_pos*(wh.y*wh.y) + (uint64)y_tree_pos*y_tree_pos*(wh.x*wh.x))); - const uint32 tree_probability = (uint32)( ( 8 * (uint32)((wh.x*wh.x)+(wh.y*wh.y)) ) / distance ); + sint32 alter = (welt->get_current_month() - geburt)<<18; + file->rdwr_long(alter); - if (tree_probability < 38) { - continue; - } + // after loading, calculate new + geburt = welt->get_current_month() - (alter>>18); - uint8 number_to_plant = 0; - uint8 const max_trees_here = min(welt->get_settings().get_max_no_of_trees_on_square(), (tree_probability - 38 + 1) / 2); - for (uint8 c2 = 0 ; c2is_loading()) { + char buf[128]; + file->rdwr_str(buf, lengthof(buf)); - number_of_new_trees += baum_t::plant_tree_on_coordinate(koord((sint16)(xpos_f + x_tree_pos), (sint16)(ypos_f + y_tree_pos)), welt->get_settings().get_max_no_of_trees_on_square(), number_to_plant); + const tree_desc_t *desc = tree_builder_t::get_desc_by_name( buf ); + if( !desc ) { + desc = tree_builder_t::get_desc_by_name( translator::compatibility_name(buf) ); } - } - return number_of_new_trees; -} - -void baum_t::fill_trees(int dichte, sint16 xtop, sint16 ytop, sint16 xbottom, sint16 ybottom ) -{ - // none there - if( desc_table.empty() ) { - return; - } -DBG_MESSAGE("verteile_baeume()","distributing single trees"); - koord pos; - for( pos.y=ytop; pos.ylookup_kartenboden(pos); - if(gr->get_top() == 0 && gr->get_typ() == grund_t::boden) { - // plant spare trees, (those with low preffered density) or in an entirely tree climate - uint16 cl = 1 << welt->get_climate(pos); - settings_t const& s = welt->get_settings(); - if ((cl & s.get_no_tree_climates()) == 0 && ((cl & s.get_tree_climates()) != 0 || simrand(s.get_forest_inverse_spare_tree_density() * dichte) < 100)) { - plant_tree_on_coordinate(pos, 1, 1); - } - } + if( desc ) { + tree_id = tree_builder_t::get_id_by_desc( desc ); + } + else { + // not a tree + tree_id = tree_builder_t::get_num_trees(); } } -} - - -static bool compare_tree_desc(const tree_desc_t* a, const tree_desc_t* b) -{ - // same level - we do an artificial but unique sorting by (untranslated) name - return strcmp(a->get_name(), b->get_name())<0; -} - - -bool baum_t::successfully_loaded() -{ - if( desc_table.empty() ) { - DBG_MESSAGE("baum_t", "No trees found - feature disabled"); + else { + const char *c = get_desc()->get_name(); + file->rdwr_str(c); } - FOR(stringhashtable_tpl, const& i, desc_table) { - tree_list.insert_ordered(i.value, compare_tree_desc); - if( tree_list.get_count()==255 ) { - dbg->error( "baum_t::successfully_loaded()", "Maximum tree count exceeded! (max 255 instead of %i)", desc_table.get_count() ); - break; - } + // z-offset + if(file->is_version_atleast(111, 1)) { + uint8 zoff_ = zoff; + file->rdwr_byte(zoff_); + zoff = zoff_; } - tree_list.append( NULL ); - - delete [] tree_list_per_climate; - tree_list_per_climate = new weighted_vector_tpl[MAX_CLIMATES]; - - // clear cache - memset( tree_id_to_image, -1, sizeof(tree_id_to_image) ); - // now register all trees for all fitting climates - for( uint32 typ=0; typis_allowed_climate((climate)j) ) { - tree_list_per_climate[j].append(typ, tree_list[typ]->get_distribution_weight()); - } - } - // create cache images - for( uint8 season = 0; season < 5; season++ ) { - uint8 use_season = 0; - const sint16 seasons = tree_list[typ]->get_seasons(); - if( seasons > 1 ) { - use_season = season; - // three possibilities - if( seasons < 4 ) { - // only summer and winter => season 4 with winter image - use_season = (season == 4); - } - else if( seasons == 4 ) { - // all there, but the snowy special image missing - if( season == 4 ) { - // take spring image (gave best results with pak64, pak.german) ////// but season 2 is winter???? - use_season = 2; - } - } - } - for( uint8 age = 0; age < 5; age++ ) { - tree_id_to_image[typ][season * 5 + age] = tree_list[typ]->get_image_id( use_season, age ); - } + else { + // correct z-offset + if(file->is_loading()) { + // this will trigger recalculation of offset in finish_rd() + // we cant call calc_off() since this->pos is still invalid + set_xoff(-128); } } - return true; } -bool baum_t::register_desc(tree_desc_t *desc) +void baum_t::finish_rd() { - // avoid duplicates with same name - if( desc_table.remove(desc->get_name()) ) { - dbg->doubled( "baum_t", desc->get_name() ); + if(get_xoff()==-128) { + calc_off(welt->lookup( get_pos())->get_grund_hang()); } - desc_table.put(desc->get_name(), desc ); - return true; } -// calculates tree position on a tile -// takes care of slopes -void baum_t::calc_off(uint8 slope, sint8 x_, sint8 y_) +image_id baum_t::get_image() const { - sint16 random = (sint16)( get_pos().x + get_pos().y + get_pos().z + slope + (sint16)(intptr_t)this ); - // point on tile (imaginary origin at sw corner, x axis: north, y axis: east - sint16 x = x_==-128 ? (random + tree_id) & 31 : x_; - sint16 y = y_==-128 ? (random + get_age()) & 31 : y_; - - // the last bit has to be the same - y = y ^ (x&1); - - // bilinear interpolation of tile height - uint32 zoff_ = ((corner_ne(slope)*x*y + corner_nw(slope)*x*(32-y) - + corner_se(slope)*(32-x)*y + corner_sw(slope)*(32-x)*(32-y)) * TILE_HEIGHT_STEP) / (32*32); - // now zoff between 0 and TILE_HEIGHT_STEP-1 - zoff = zoff_ < (uint32)TILE_HEIGHT_STEP ? zoff_ : TILE_HEIGHT_STEP-1u; - - // xoff must be even - set_xoff( x + y - 32 ); - set_yoff( (y - x)/2 - zoff); -} - + if( env_t::hide_trees ) { + if( env_t::hide_with_transparency ) { + // we need the real age for transparency or real image + return IMG_EMPTY; + } + else { + return tree_builder_t::get_tree_image(tree_id, 0, season); + } + } -void baum_t::recalc_off() -{ - // reconstruct position on tile - const sint8 xoff = get_xoff() + 32; // = x+y - const sint8 yoff = 2*(get_yoff() + zoff); // = y-x - sint8 x = (xoff - yoff) / 2; - sint8 y = (xoff + yoff) / 2; - calc_off(welt->lookup( get_pos())->get_grund_hang(), x, y); + return tree_builder_t::get_tree_image(tree_id, get_age(), season); + // return get_desc()->get_image_id( season, baum_alter ); } -void baum_t::rotate90() +// image which transparent outline is used +image_id baum_t::get_outline_image() const { - // cant use obj_t::rotate90 to rotate offsets as it rotates them only if xoff!=0 - sint8 old_yoff = get_yoff() + zoff; - sint8 old_xoff = get_xoff(); - // rotate position - obj_t::rotate90(); - // .. and the offsets - set_xoff( -2 * old_yoff ); - set_yoff( old_xoff/2 - zoff); + return tree_builder_t::get_tree_image(tree_id, get_age(), season); + // return get_desc()->get_image_id( season, baum_alter ); } @@ -386,106 +175,17 @@ void baum_t::calc_image() } -image_id baum_t::get_image() const -{ - if( env_t::hide_trees ) { - if( env_t::hide_with_transparency ) { - // we need the real age for transparency or real image - return IMG_EMPTY; - } - else { - return tree_id_to_image[ tree_id ][ season*5 ]; - } - } - const uint8 baum_alter = tree_age_index[min(get_age()>>6, 11u)]; - return tree_id_to_image[ tree_id ][ season*5 + baum_alter ]; -// return get_desc()->get_image_id( season, baum_alter ); -} - - -// image which transparent outline is used -image_id baum_t::get_outline_image() const -{ - const uint8 baum_alter = tree_age_index[min(get_age()>>6, 11u)]; - return tree_id_to_image[ tree_id ][ season*5 + baum_alter ]; -// return get_desc()->get_image_id( season, baum_alter ); -} - - -uint32 baum_t::get_age() const -{ - sint32 age = welt->get_current_month() - geburt; - if (age<0) { - // correct underflow, geburt is 16bit - age += 1 << 16; - } - return age; -} - - -/** - * also checks for distribution values - */ -uint16 baum_t::random_tree_for_climate_intern(climate cl) -{ - // now weight their distribution - weighted_vector_tpl const& t = tree_list_per_climate[cl]; - return t.empty() ? 0xFFFF : pick_any_weighted(t); -} - - -baum_t::baum_t(loadsave_t *file) : obj_t() -{ - season = 0; - geburt = welt->get_current_month(); - tree_id = 0; - rdwr(file); -} - -baum_t::baum_t(koord3d pos) : obj_t(pos) +FLAGGED_PIXVAL baum_t::get_outline_colour() const { - // generate aged trees - // might underflow - geburt = welt->get_current_month() - simrand(703); - tree_id = (uint8)random_tree_for_climate_intern( welt->get_climate( pos.get_2d() ) ); - season = 0; - calc_off( welt->lookup( get_pos())->get_grund_hang() ); - calc_image(); + return outline_color; } -baum_t::baum_t(koord3d pos, uint8 type, sint32 age, uint8 slope ) : obj_t(pos) +void baum_t::recalc_outline_color() { - geburt = welt->get_current_month()-age; // might underflow - tree_id = type; - season = 0; - calc_off( slope ); - calc_image(); -} - - -baum_t::baum_t(koord3d pos, const tree_desc_t *desc) : obj_t(pos) -{ - geburt = welt->get_current_month(); - tree_id = tree_list.index_of(desc); - season = 0; - calc_off( welt->lookup( get_pos())->get_grund_hang() ); - calc_image(); -} - - -bool baum_t::saee_baum() -{ - // spawn a new tree in an area 3x3 tiles around - // the area for normal new tree planting is slightly more restricted, square of 9x9 was too much - - // to have same execution order for simrand - const sint16 sx = simrand(5)-2; - const sint16 sy = simrand(5)-2; - const koord k = get_pos().get_2d() + koord(sx,sy); - - return plant_tree_on_coordinate(k, tree_list[tree_id], true, false); + outline_color = (env_t::hide_trees && env_t::hide_with_transparency) ? + (TRANSPARENT25_FLAG | OUTLINE_FLAG | color_idx_to_rgb(COL_BLACK)) : 0; } @@ -500,23 +200,25 @@ bool baum_t::check_season(const bool) age += 1 << 16; } - if( age >= 512 && age <= 515 ) { + if( age >= baum_t::SPAWN_PERIOD_START && age < baum_t::SPAWN_PERIOD_START + baum_t::SPAWN_PERIOD_LENGTH ) { // only in this month a tree can span new trees // only 1-3 trees will be planted.... uint8 const c_plant_tree_max = 1 + simrand( welt->get_settings().get_max_no_of_trees_on_square() ); - uint retrys = 0; - for( uint8 c_temp = 0; c_temp < c_plant_tree_max && retrys < c_plant_tree_max; c_temp++ ) { - if( !saee_baum() ) { - retrys++; + uint retries = 0; + + for( uint8 c_temp = 0; c_temp < c_plant_tree_max && retries < c_plant_tree_max; c_temp++ ) { + if( !tree_builder_t::spawn_tree_near(this) ) { + retries++; c_temp--; } } + // we make the tree four months older to avoid second spawning - geburt = geburt - 4; + geburt -= baum_t::SPAWN_PERIOD_LENGTH; } - // tree will die after 704 month (i.e. 58 years 8 month) - if( age >= 704 ) { + // tree will die after 704 months (i.e. 58 years 8 months) + if( age >= baum_t::AGE_LIMIT ) { mark_image_dirty( get_image(), 0 ); return false; } @@ -532,60 +234,61 @@ bool baum_t::check_season(const bool) } -void baum_t::rdwr(loadsave_t *file) +void baum_t::rotate90() { - xml_tag_t d( file, "baum_t" ); + // cant use obj_t::rotate90 to rotate offsets as it rotates them only if xoff!=0 + sint8 old_yoff = get_yoff() + zoff; + sint8 old_xoff = get_xoff(); - obj_t::rdwr(file); + // rotate position + obj_t::rotate90(); - sint32 alter = (welt->get_current_month() - geburt)<<18; - file->rdwr_long(alter); + // .. and the offsets + set_xoff( -2 * old_yoff ); + set_yoff( old_xoff/2 - zoff); +} - // after loading, calculate new - geburt = welt->get_current_month() - (alter>>18); - if(file->is_loading()) { - char buf[128]; - file->rdwr_str(buf, lengthof(buf)); - const tree_desc_t *desc = desc_table.get( buf ); - if( !tree_list.is_contained(desc) ) { - desc = desc_table.get( translator::compatibility_name(buf) ); - } - if( tree_list.is_contained(desc) ) { - tree_id = tree_list.index_of( desc ); - } - else { - // not a tree - tree_id = tree_list.get_count()-1; - } - } - else { - const char *c = get_desc()->get_name(); - file->rdwr_str(c); - } - // z-offset - if(file->is_version_atleast(111, 1)) { - uint8 zoff_ = zoff; - file->rdwr_byte(zoff_); - zoff = zoff_; - } - else { - // correct z-offset - if(file->is_loading()) { - // this will trigger recalculation of offset in finish_rd() - // we cant call calc_off() since this->pos is still invalid - set_xoff(-128); - } - } +void baum_t::recalc_off() +{ + // reconstruct position on tile + const sint8 xoff = get_xoff() + 32; // = x+y + const sint8 yoff = 2*(get_yoff() + zoff); // = y-x + sint8 x = (xoff - yoff) / 2; + sint8 y = (xoff + yoff) / 2; + + calc_off(welt->lookup( get_pos())->get_grund_hang(), x, y); } -void baum_t::finish_rd() +// calculates tree position on a tile +// takes care of slopes +void baum_t::calc_off(uint8 slope, sint8 x_, sint8 y_) { - if(get_xoff()==-128) { - calc_off(welt->lookup( get_pos())->get_grund_hang()); - } + const sint16 random = (sint16)( get_pos().x + get_pos().y + get_pos().z + slope + (sint16)(intptr_t)this ); + + // point on tile (imaginary origin at sw corner, x axis: north, y axis: east + sint16 x = x_==-128 ? (random + tree_id) & 31 : x_; + sint16 y = y_==-128 ? (random + get_age()) & 31 : y_; + + // the last bit has to be the same + y ^= x&1; + + // bilinear interpolation of tile height + const uint32 zoff_ = + ((corner_ne(slope) * x * y + + corner_nw(slope) * x * (32-y) + + corner_se(slope) * (32-x) * y + + corner_sw(slope) * (32-x) * (32-y)) + * TILE_HEIGHT_STEP) / (32*32); + + // now zoff between 0 and TILE_HEIGHT_STEP-1 + zoff = zoff_ < (uint32)TILE_HEIGHT_STEP ? zoff_ : TILE_HEIGHT_STEP-1u; + + // xoff must be even + set_xoff( x + y - 32 ); + set_yoff( (y - x)/2 - zoff); } @@ -597,13 +300,14 @@ void baum_t::show_info() } -void baum_t::info(cbuffer_t & buf) const +void baum_t::info(cbuffer_t &buf) const { obj_t::info(buf); buf.append( translator::translate(get_desc()->get_name()) ); buf.append( "\n" ); - uint32 age = get_age(); + + const uint32 age = get_age(); buf.printf( translator::translate("%i years %i months old."), age/12, (age%12) ); if (char const* const maker = get_desc()->get_copyright()) { @@ -620,6 +324,17 @@ void baum_t::cleanup(player_t *player) } +uint32 baum_t::get_age() const +{ + sint32 age = welt->get_current_month() - geburt; + if (age<0) { + // correct underflow, geburt is 16bit + age += 1 << 16; + } + return age; +} + + void *baum_t::operator new(size_t /*s*/) { return freelist_t::gimme_node(sizeof(baum_t)); diff --git obj/baum.h obj/baum.h index f37edae4b..8518f9a85 100644 --- obj/baum.h +++ obj/baum.h @@ -9,6 +9,7 @@ #include "simobj.h" +#include "../bauer/tree_builder.h" #include "../tpl/stringhashtable_tpl.h" #include "../tpl/vector_tpl.h" #include "../tpl/weighted_vector_tpl.h" @@ -24,122 +25,99 @@ */ class baum_t : public obj_t { + friend class tree_builder_t; + +public: + static const uint16 AGE_LIMIT = 704; // in months (58 years 8 months) + static const uint16 SPAWN_PERIOD_START = 512; + static const uint16 SPAWN_PERIOD_LENGTH = 4; + private: static FLAGGED_PIXVAL outline_color; - /** month of birth */ + /// month of birth uint16 geburt; - /** type of tree (was 9 but for more compact saves now only 254 different tree types are allowed) */ + /// type of tree (was 9 but for more compact saves now only 254 different tree types are allowed) uint8 tree_id; uint8 season:3; - /** z-offset, max TILE_HEIGHT_STEP ie 4 bits */ + /// z-offset, max TILE_HEIGHT_STEP ie 4 bits uint8 zoff:4; // one bit free ;) - // static for administration - static stringhashtable_tpl desc_table; - static vector_tpl tree_list; - static weighted_vector_tpl* tree_list_per_climate; - - bool saee_baum(); - - /** - * calculate offsets for new trees - */ - void calc_off(uint8 slope, sint8 x=-128, sint8 y=-128); - - static uint16 random_tree_for_climate_intern(climate cl); - public: - /** - * Only the load save constructor should be called outside - * otherwise I suggest use the plant tree function (see below) - */ + /// Only the load save constructor should be called outside. + /// Otherwise I suggest use the plant tree function (@see tree_builder_t) baum_t(loadsave_t *file); baum_t(koord3d pos); - baum_t(koord3d pos, uint8 type, sint32 age, uint8 slope ); + baum_t(koord3d pos, uint8 type, sint32 age, uint8 slope); baum_t(koord3d pos, const tree_desc_t *desc); +public: + /// @copydoc obj_t::get_name + const char *get_name() const OVERRIDE { return "Baum"; } + + /// @copydoc obj_t::get_typ + typ get_typ() const OVERRIDE { return baum; } + + /// @copydoc obj_t::rdwr void rdwr(loadsave_t *file) OVERRIDE; + /// @copydoc obj_t::finish_rd void finish_rd() OVERRIDE; + /// @copydoc obj_t::get_image image_id get_image() const OVERRIDE; - /** - * hide trees eventually with transparency - */ - FLAGGED_PIXVAL get_outline_colour() const OVERRIDE { return outline_color; } + /// @copydoc obj_t::get_outline_image image_id get_outline_image() const OVERRIDE; - static void recalc_outline_color() { outline_color = (env_t::hide_trees && env_t::hide_with_transparency) ? (TRANSPARENT25_FLAG | OUTLINE_FLAG | color_idx_to_rgb(COL_BLACK)) : 0; } - - /** - * Calculates tree image dependent on tree age - */ + /// @copydoc obj_t::calc_image + /// Calculates tree image dependent on tree age void calc_image() OVERRIDE; - /** - * Called whenever the season or snowline height changes - * return false and the obj_t will be deleted - */ + /// @copydoc obj_t::get_outline_colour + /// hide trees eventually with transparency + FLAGGED_PIXVAL get_outline_colour() const OVERRIDE; + + static void recalc_outline_color(); + + /// @copydoc obj_t::check_season bool check_season(const bool) OVERRIDE; + /// @copydoc obj_t::rotate90 void rotate90() OVERRIDE; - /** - * re-calculate z-offset if slope of the tile has changed - */ + /// re-calculate z-offset if slope of the tile has changed void recalc_off(); - const char *get_name() const OVERRIDE {return "Baum";} - typ get_typ() const OVERRIDE { return baum; } - + /// @copydoc obj_t::show_info void show_info() OVERRIDE; + /// @copydoc obj-t::info void info(cbuffer_t & buf) const OVERRIDE; + /// @copydoc obj_t::cleanup void cleanup(player_t *player) OVERRIDE; - void * operator new(size_t s); - void operator delete(void *p); - - const tree_desc_t* get_desc() const { return tree_list[tree_id]; } - void set_desc( const tree_desc_t *b ) { tree_id = tree_list.index_of(b); } +public: + const tree_desc_t *get_desc() const { return tree_builder_t::get_desc_by_id(tree_id); } + void set_desc(const tree_desc_t *desc) { tree_id = tree_builder_t::get_id_by_desc(desc); } uint16 get_desc_id() const { return tree_id; } + /// @returns the age of the tree, in months. uint32 get_age() const; - // static functions to handle trees - - // distributes trees on a map - static void distribute_trees(int dichte, sint16 xtop, sint16 ytop, sint16 xbottom, sint16 ybottom ); - - static void fill_trees(int dichte, sint16 xtop, sint16 ytop, sint16 xbottom, sint16 ybottom ); - - static uint32 create_forest(koord center, koord size, sint16 xtop, sint16 ytop, sint16 xbottom, sint16 ybottom ); - - static bool plant_tree_on_coordinate(koord pos, const tree_desc_t *desc, const bool check_climate, const bool random_age ); - - static uint8 plant_tree_on_coordinate(koord pos, const uint8 maximum_count, const uint8 count); - - static bool register_desc(tree_desc_t *desc); - static bool successfully_loaded(); - - // return list to descriptors - static vector_tpl const& get_all_desc() { return tree_list; } - - static const tree_desc_t *random_tree_for_climate(climate cl) { uint16 b = random_tree_for_climate_intern(cl); return b!=0xFFFF ? tree_list[b] : NULL; } - - static const tree_desc_t *find_tree( const char *tree_name ) { return tree_list.empty() ? NULL : desc_table.get(tree_name); } - - static int get_count() { return tree_list.get_count()-1; } - static int get_count(climate cl); +public: + void *operator new(size_t s); + void operator delete(void *p); +private: + /// calculate offsets for new trees + void calc_off(uint8 slope, sint8 x=-128, sint8 y=-128); }; #endif diff --git script/api/api_obj_desc_base.cc script/api/api_obj_desc_base.cc index ae37bd00a..6a873cdd0 100644 --- script/api/api_obj_desc_base.cc +++ script/api/api_obj_desc_base.cc @@ -29,7 +29,7 @@ static const way_desc_t *my_get_desc(const char *name) return way_builder_t::get_desc(name); } -implement_desc_param(tree_desc_t, "tree_desc_x", &baum_t::find_tree); +implement_desc_param(tree_desc_t, "tree_desc_x", &tree_builder_t::find_tree); implement_desc_param(building_desc_t, "building_desc_x", &hausbauer_t::get_desc); implement_desc_param(goods_desc_t, "good_desc_x", (const goods_desc_t* (*)(const char*))(&goods_manager_t::get_info) ); implement_desc_param(way_desc_t, "way_desc_x", &my_get_desc); diff --git simtool-dialogs.h simtool-dialogs.h index 529d3849c..dd53c303d 100644 --- simtool-dialogs.h +++ simtool-dialogs.h @@ -509,10 +509,10 @@ class dialog_edit_tree_t : public tool_t { public: dialog_edit_tree_t() : tool_t(DIALOG_EDIT_TREE | DIALOGE_TOOL) {} char const* get_tooltip(player_t const*) const OVERRIDE{ return translator::translate("baum builder"); } - image_id get_icon(player_t *) const OVERRIDE { return baum_t::get_count() > 0 ? icon : IMG_EMPTY; } + image_id get_icon(player_t *) const OVERRIDE { return tree_builder_t::has_trees() ? icon : IMG_EMPTY; } bool is_selected() const OVERRIDE{ return win_get_magic(magic_edit_tree); } bool init(player_t* player) OVERRIDE{ - if (baum_t::get_count() > 0 && !is_selected()) { + if (tree_builder_t::has_trees() > 0 && !is_selected()) { create_win(new baum_edit_frame_t(player), w_info, magic_edit_tree); } return false; diff --git simtool.cc simtool.cc index 6246d32e1..8317bfabd 100644 --- simtool.cc +++ simtool.cc @@ -2151,18 +2151,20 @@ const char *tool_plant_tree_t::work( player_t *player, koord3d pos ) bool check_climates = true; bool random_age = false; if(default_param==NULL || strlen(default_param)==0) { - desc = baum_t::random_tree_for_climate( welt->get_climate( k ) ); + desc = tree_builder_t::random_tree_for_climate( welt->get_climate( k ) ); } else { // parse default_param: bbdesc_nr b=1 ignore climate b=1 random age check_climates = default_param[0]=='0'; random_age = default_param[1]=='1'; - desc = baum_t::find_tree(default_param+3); + desc = tree_builder_t::find_tree(default_param+3); } - if(desc && baum_t::plant_tree_on_coordinate( k, desc, check_climates, random_age ) ) { + + if(desc && tree_builder_t::plant_tree_on_coordinate( k, desc, check_climates, random_age ) ) { player_t::book_construction_costs(player, cost, k, ignore_wt); return NULL; } + return ""; } return NULL; @@ -6116,7 +6118,7 @@ const char *tool_forest_t::do_work( player_t *player, const koord3d &start, cons nw.x = min(start.x, end.x)+(wh.x/2); nw.y = min(start.y, end.y)+(wh.y/2); - sint64 costs = baum_t::create_forest( nw, wh, 0, 0, welt->get_size().x, welt->get_size().y ); + sint64 costs = tree_builder_t::create_forest( nw, wh, 0, 0, welt->get_size().x, welt->get_size().y ); player_t::book_construction_costs(player, costs * welt->get_settings().cst_remove_tree, end.get_2d(), ignore_wt); return NULL; diff --git simtool.h simtool.h index 3c93ccf91..64c000f96 100644 --- simtool.h +++ simtool.h @@ -237,9 +237,9 @@ private: class tool_plant_tree_t : public kartenboden_tool_t { public: tool_plant_tree_t() : kartenboden_tool_t(TOOL_PLANT_TREE | GENERAL_TOOL) {} - image_id get_icon(player_t *) const OVERRIDE { return baum_t::get_count() > 0 ? icon : IMG_EMPTY; } + image_id get_icon(player_t *) const OVERRIDE { return tree_builder_t::get_num_trees() > 0 ? icon : IMG_EMPTY; } char const* get_tooltip(player_t const*) const OVERRIDE { return translator::translate( "Plant tree" ); } - bool init(player_t*) OVERRIDE { return baum_t::get_count() > 0; } + bool init(player_t*) OVERRIDE { return tree_builder_t::has_trees(); } char const* move(player_t* const player, uint16 const b, koord3d const k) OVERRIDE; bool move_has_effects() const OVERRIDE { return true; } char const* work(player_t*, koord3d) OVERRIDE; @@ -589,9 +589,9 @@ public: class tool_forest_t : public two_click_tool_t { public: tool_forest_t() : two_click_tool_t(TOOL_FOREST | GENERAL_TOOL) {} - image_id get_icon(player_t *) const OVERRIDE { return baum_t::get_count() > 0 ? icon : IMG_EMPTY; } + image_id get_icon(player_t *) const OVERRIDE { return tree_builder_t::has_trees() ? icon : IMG_EMPTY; } char const* get_tooltip(player_t const*) const OVERRIDE { return translator::translate("Add forest"); } - bool init( player_t *player) OVERRIDE { return baum_t::get_count() > 0 && two_click_tool_t::init(player); } + bool init( player_t *player) OVERRIDE { return tree_builder_t::has_trees() && two_click_tool_t::init(player); } private: char const* do_work(player_t*, koord3d const&, koord3d const&) OVERRIDE; void mark_tiles(player_t*, koord3d const&, koord3d const&) OVERRIDE; @@ -924,10 +924,10 @@ class tool_fill_trees_t : public tool_t { public: tool_fill_trees_t() : tool_t(TOOL_FILL_TREES | SIMPLE_TOOL) {} char const* get_tooltip(player_t const*) const OVERRIDE { return translator::translate("Fill trees"); } - image_id get_icon(player_t *) const OVERRIDE { return baum_t::get_count() > 0 ? icon : IMG_EMPTY; } + image_id get_icon(player_t *) const OVERRIDE { return tree_builder_t::has_trees() ? icon : IMG_EMPTY; } bool init(player_t * ) OVERRIDE { - if( baum_t::get_count() > 0 && default_param ) { - baum_t::fill_trees( atoi(default_param), 0, 0, welt->get_size().x, welt->get_size().y ); + if( tree_builder_t::has_trees() && default_param ) { + tree_builder_t::fill_trees( atoi(default_param), 0, 0, welt->get_size().x, welt->get_size().y ); } return false; } diff --git simworld.cc simworld.cc index 7ea5784d2..609c04382 100644 --- simworld.cc +++ simworld.cc @@ -1739,26 +1739,26 @@ void karte_t::distribute_trees_region( sint16 xtop, sint16 ytop, sint16 xbottom, number_to_plant++; } } - baum_t::plant_tree_on_coordinate(pos, get_settings().get_max_no_of_trees_on_square(), number_to_plant); + + tree_builder_t::plant_tree_on_coordinate(pos, get_settings().get_max_no_of_trees_on_square(), number_to_plant); } else if(humidity_map.at(pos.x,pos.y)>75) { // plant spare trees, (those with low preffered density) or in an entirely tree climate uint16 cl = 1 << get_climate(pos); settings_t const& s = get_settings(); if ((cl & s.get_no_tree_climates()) == 0 && ((cl & s.get_tree_climates()) != 0 || simrand(s.get_forest_inverse_spare_tree_density() * /*dichte*/3) < 100)) { - baum_t::plant_tree_on_coordinate(pos, 1, 1); + tree_builder_t::plant_tree_on_coordinate(pos, 1, 1); } } } } - } break; } // fall-through case 1: // no humidity data or on request - baum_t::distribute_trees(3, xtop, ytop, xbottom, ybottom ); + tree_builder_t::distribute_trees(3, xtop, ytop, xbottom, ybottom ); break; case 0: // no trees