Replacing the terrain transition code by something entirely in WML.

Made forests and hills always overlay terrain on their northern (top)
side.  [building_rule] tag is now called [terrain_graphics] A few
changes in the terrain graphics WML element
This commit is contained in:
Philippe Plantier 2004-05-31 22:25:37 +00:00
parent ef1048d187
commit bd2866fb61
13 changed files with 1130 additions and 216 deletions

View file

@ -1,85 +1,632 @@
[building_rule]
map="
C
C
!KC"
image_background="castle-bg-concave-$R"
image_foreground="castle-fg-concave-$R"
rotations=ne,e,se,sw,w,nw
[/building_rule]
[building_rule]
#define TERRAIN_TYPES
"KCDuWFfmHhVSvtgrRd\/|YwipZcs~ "
#enddef
#define TERRAIN_BASE_PROBABILITY LETTER IMAGE PROBABILITY
[terrain_graphics]
[tile]
x=0
y=0
type="{LETTER}"
[image]
z_index=-99
name={IMAGE}
[/image]
[/tile]
probability={PROBABILITY}
no_flag="terrain-{LETTER}"
set_flag="terrain-{LETTER}"
[/terrain_graphics]
#enddef
#define TERRAIN_BASE LETTER IMAGE
{TERRAIN_BASE_PROBABILITY ({LETTER}) {IMAGE} 100}
#enddef
#define TERRAIN_ADJACENT_4 LETTERS IMAGE
[terrain_graphics]
map="
2
. 3
1
. 4
5
"
[tile]
pos=1
type=!{LETTERS}
[no_flag]
name=transition-@R0
[/no_flag]
[no_flag]
name=transition-@R1
[/no_flag]
[no_flag]
name=transition-@R2
[/no_flag]
[no_flag]
name=transition-@R3
[/no_flag]
[set_flag]
name=transition-@R0
[/set_flag]
[set_flag]
name=transition-@R1
[/set_flag]
[set_flag]
name=transition-@R2
[/set_flag]
[set_flag]
name=transition-@R3
[/set_flag]
[image]
z_index=-98
name={IMAGE}-@R0-@R1-@R2-@R3
[/image]
[/tile]
[tile]
pos=2
type={LETTERS}
no_flag=transition-@R3
set_flag=transition-@R3
[/tile]
[tile]
pos=3
type={LETTERS}
no_flag=transition-@R4
set_flag=transition-@R4
[/tile]
[tile]
pos=4
type={LETTERS}
no_flag=transition-@R5
set_flag=transition-@R5
[/tile]
[tile]
pos=5
type={LETTERS}
no_flag=transition-@R0
set_flag=transition-@R0
[/tile]
rotations=n,ne,se,s,sw,nw
[/terrain_graphics]
#enddef
#define TERRAIN_ADJACENT_3 LETTERS IMAGE
[terrain_graphics]
map="
2
. 3
1
. 4
.
"
[tile]
pos=1
type=!{LETTERS}
[no_flag]
name=transition-@R0
[/no_flag]
[no_flag]
name=transition-@R1
[/no_flag]
[no_flag]
name=transition-@R2
[/no_flag]
[set_flag]
name=transition-@R0
[/set_flag]
[set_flag]
name=transition-@R1
[/set_flag]
[set_flag]
name=transition-@R2
[/set_flag]
[image]
z_index=-98
name={IMAGE}-@R0-@R1-@R2
[/image]
[/tile]
[tile]
pos=2
type={LETTERS}
no_flag=transition-@R3
set_flag=transition-@R3
[/tile]
[tile]
pos=3
type={LETTERS}
no_flag=transition-@R4
set_flag=transition-@R4
[/tile]
[tile]
pos=4
type={LETTERS}
no_flag=transition-@R5
set_flag=transition-@R5
[/tile]
rotations=n,ne,se,s,sw,nw
[/terrain_graphics]
#enddef
#define TERRAIN_ADJACENT_2 LETTERS IMAGE
[terrain_graphics]
map="
2
. 3
1
. .
.
"
[tile]
pos=1
type=!{LETTERS}
[no_flag]
name=transition-@R0
[/no_flag]
[no_flag]
name=transition-@R1
[/no_flag]
[set_flag]
name=transition-@R0
[/set_flag]
[set_flag]
name=transition-@R1
[/set_flag]
[image]
z_index=-98
name={IMAGE}-@R0-@R1
[/image]
[/tile]
[tile]
pos=2
type={LETTERS}
no_flag=transition-@R3
set_flag=transition-@R3
[/tile]
[tile]
pos=3
type={LETTERS}
no_flag=transition-@R4
set_flag=transition-@R4
[/tile]
rotations=n,ne,se,s,sw,nw
[/terrain_graphics]
#enddef
#define TERRAIN_ADJACENT_1 LETTERS IMAGE
[terrain_graphics]
map="
2
. .
1
. .
.
"
[tile]
pos=1
type=!{LETTERS}
[no_flag]
name=transition-@R0
[/no_flag]
[set_flag]
name=transition-@R0
[/set_flag]
[image]
z_index=-98
name={IMAGE}-@R0
[/image]
[/tile]
[tile]
pos=2
type={LETTERS}
no_flag=transition-@R3
set_flag=transition-@R3
[/tile]
rotations=n,ne,se,s,sw,nw
[/terrain_graphics]
#enddef
#define TERRAIN_ADJACENT_1234 LETTERS IMAGE
{TERRAIN_ADJACENT_4 ({LETTERS}) {IMAGE}}
{TERRAIN_ADJACENT_3 ({LETTERS}) {IMAGE}}
{TERRAIN_ADJACENT_2 ({LETTERS}) {IMAGE}}
{TERRAIN_ADJACENT_1 ({LETTERS}) {IMAGE}}
#enddef
#define TERRAIN_ADJACENT_123 LETTERS IMAGE
{TERRAIN_ADJACENT_3 ({LETTERS}) {IMAGE}}
{TERRAIN_ADJACENT_2 ({LETTERS}) {IMAGE}}
{TERRAIN_ADJACENT_1 ({LETTERS}) {IMAGE}}
#enddef
#define TERRAIN_ADJACENT_12 LETTERS IMAGE
{TERRAIN_ADJACENT_2 ({LETTERS}) {IMAGE}}
{TERRAIN_ADJACENT_1 ({LETTERS}) {IMAGE}}
#enddef
#define TERRAIN_ADJACENT_NORTH LETTERS IMAGE
[terrain_graphics]
map="
2
. .
1
"
[tile]
pos=2
type=!{LETTERS}
no_flag=transition-s
set_flag=transition-s
[image]
z_index=-99
name={IMAGE}-s
[/image]
[/tile]
[tile]
no_flag=transition-n
set_flag=transition-n
pos=1
type={LETTERS}
[/tile]
[/terrain_graphics]
[terrain_graphics]
map="
.
2 .
1
"
[tile]
pos=2
type=!{LETTERS}
no_flag=transition-se
set_flag=transition-se
[image]
z_index=-99
name={IMAGE}-se
[/image]
[/tile]
[tile]
no_flag=transition-nw
set_flag=transition-nw
pos=1
type={LETTERS}
[/tile]
[/terrain_graphics]
[terrain_graphics]
map="
.
. 2
1
"
[tile]
pos=2
type=!{LETTERS}
no_flag=transition-sw
set_flag=transition-sw
[image]
z_index=-99
name={IMAGE}-sw
[/image]
[/tile]
[tile]
no_flag=transition-ne
set_flag=transition-ne
pos=1
type={LETTERS}
[/tile]
[/terrain_graphics]
#enddef
#define DISABLE_TRANSITIONS LETTER
[terrain_graphics]
map="
1
6 2
7
5 3
4
"
[tile]
pos=1
set_flag=transition-s
[/tile]
[tile]
pos=2
set_flag=transition-sw
[/tile]
[tile]
pos=3
set_flag=transition-nw
[/tile]
[tile]
pos=4
set_flag=transition-n
[/tile]
[tile]
pos=5
set_flag=transition-ne
[/tile]
[tile]
pos=6
set_flag=transition-se
[/tile]
[tile]
pos=7
type={LETTER}
[/tile]
[/terrain_graphics]
#enddef
#define CASTLE_WALLS CASTLE NOTCASTLE IMAGE
{DISABLE_TRANSITIONS {CASTLE}}
[terrain_graphics]
map="
2
2
1"
[tile]
pos=1
type={NOTCASTLE}
[/tile]
[tile]
pos=2
type={CASTLE}
[/tile]
[image]
z_index=-1
name="{IMAGE}-bg-concave-@R0"
[/image]
[image]
z_index=1
name="{IMAGE}-fg-concave-@R0"
[/image]
rotations=ne,e,se,sw,w,nw
[/terrain_graphics]
[terrain_graphics]
map="
1
1
C"
2"
[tile]
pos=1
type=!KC
type={NOTCASTLE}
[/tile]
[tile]
pos=2
type={CASTLE}
[/tile]
image_background="castle-bg-convex-$R"
image_foreground="castle-fg-convex-$R"
rotations=ne,e,se,sw,w,nw
[/building_rule]
[building_rule]
[image]
z_index=-1
name="{IMAGE}-bg-convex-@R0"
[/image]
[image]
z_index=1
name="{IMAGE}-fg-convex-@R0"
[/image]
rotations=ne,e,se,sw,w,nw
[/terrain_graphics]
#enddef
#define CASTLE_AND_KEEP CASTLE KEEP CASTLE_IMAGE KEEP_IMAGE
{CASTLE_WALLS {CASTLE} !{CASTLE}{KEEP} {CASTLE_IMAGE}}
{DISABLE_TRANSITIONS {KEEP}}
[terrain_graphics]
map="
C
C
2
2
1"
[tile]
# Using anchors for demonstrations's sake
pos=1
type=K
type={KEEP}
[/tile]
image_background="keep-bg-inside-$R"
image_foreground="keep-fg-inside-$R"
rotations=ne,e,se,sw,w,nw
[/building_rule]
[building_rule]
map="
!KC
K"
[tile]
# Using [tile] element just for demonstration's sake
x=1
y=0
type=!KC
pos=2
type={CASTLE}
[/tile]
image_background="keep-bg-wall-$R"
image_foreground="keep-fg-wall-$R"
rotations=ne,e,se,sw,w,nw
[/building_rule]
[building_rule]
[image]
z_index=-1
name="{KEEP_IMAGE}-bg-inside-@R0"
[/image]
[image]
z_index=1
name="{KEEP_IMAGE}-fg-inside-@R0"
[/image]
rotations=ne,e,se,sw,w,nw
[/terrain_graphics]
[terrain_graphics]
map="
C
!KC
K"
3
3
1"
[tile]
pos=1
type={KEEP}
[/tile]
[tile]
pos=3
type=!{CASTLE}{KEEP}
[/tile]
image_background="keep-bg-wall-0-$R"
image_foreground="keep-fg-wall-0-$R"
[image]
z_index=-1
name="{KEEP_IMAGE}-bg-wall-@R0"
[/image]
[image]
z_index=1
name="{KEEP_IMAGE}-fg-wall-@R0"
[/image]
rotations=ne,e,se,sw,w,nw
[/building_rule]
[/terrain_graphics]
[building_rule]
[terrain_graphics]
map="
!KC
C
K"
2
3
1"
image_background="keep-bg-wall-1-$R"
image_foreground="keep-fg-wall-1-$R"
[tile]
pos=1
type={KEEP}
[/tile]
[tile]
pos=2
type={CASTLE}
[/tile]
[tile]
pos=3
type=!{CASTLE}{KEEP}
[/tile]
[image]
z_index=-1
name="{KEEP_IMAGE}-bg-wall-0-@R0"
[/image]
[image]
z_index=1
name="{KEEP_IMAGE}-fg-wall-0-@R0"
[/image]
rotations=ne,e,se,sw,w,nw
[/building_rule]
[/terrain_graphics]
[terrain_graphics]
map="
3
2
1"
[tile]
pos=1
type={KEEP}
[/tile]
[tile]
pos=2
type={CASTLE}
[/tile]
[tile]
pos=3
type=!{CASTLE}{KEEP}
[/tile]
[image]
z_index=-1
name="{KEEP_IMAGE}-bg-wall-1-@R0"
[/image]
[image]
z_index=1
name="{KEEP_IMAGE}-fg-wall-1-@R0"
[/image]
rotations=ne,e,se,sw,w,nw
[/terrain_graphics]
#enddef
#
# Attachs graphics to each known terrain types
#
{TERRAIN_BASE K keep}
{TERRAIN_BASE C castle}
{TERRAIN_BASE D flag-cave-neutral}
{TERRAIN_BASE u cave}
{TERRAIN_BASE W cavewall}
{TERRAIN_BASE F snow-forest}
{TERRAIN_BASE f forest}
{TERRAIN_BASE m mountains}
{TERRAIN_BASE H snow-hills}
{TERRAIN_BASE_PROBABILITY h hills-variation1 15}
{TERRAIN_BASE_PROBABILITY h hills-variation2 15}
{TERRAIN_BASE_PROBABILITY h hills-variation3 30}
{TERRAIN_BASE h hills}
{TERRAIN_BASE_PROBABILITY S snow2 30}
{TERRAIN_BASE_PROBABILITY S snow3 30}
{TERRAIN_BASE S snow}
{TERRAIN_BASE V flag-snow-neutral}
{TERRAIN_BASE v human-village}
{TERRAIN_BASE t flag-neutral}
{TERRAIN_BASE_PROBABILITY g grassland-rocks 4}
{TERRAIN_BASE_PROBABILITY g grassland-flowers 8}
{TERRAIN_BASE g grassland}
{TERRAIN_BASE r dirt}
{TERRAIN_BASE R road}
{TERRAIN_BASE_PROBABILITY d desert-plant 10}
{TERRAIN_BASE d desert}
{TERRAIN_BASE \ bridge-se-nw}
{TERRAIN_BASE / bridge-ne-sw}
{TERRAIN_BASE | bridge-n-s}
{TERRAIN_BASE Y flag-swampwater-neutral}
{TERRAIN_BASE_PROBABILITY w swampwater2 30}
{TERRAIN_BASE_PROBABILITY w swampwater3 30}
{TERRAIN_BASE w swampwater}
{TERRAIN_BASE i ice}
{TERRAIN_BASE p pier}
{TERRAIN_BASE c coast}
{TERRAIN_BASE s ocean}
{TERRAIN_BASE Z flag-coast-neutral}
{TERRAIN_BASE ~ fog}
{TERRAIN_BASE ( ) void}
#
# Transition between terrains
#
# Special transitions go first
# Castle and keeps
{CASTLE_AND_KEEP C K castle keep}
# Forest, hills and mountains should always overlay on northern sides
{TERRAIN_ADJACENT_NORTH m mountains}
{TERRAIN_ADJACENT_NORTH H snow-hills}
{TERRAIN_ADJACENT_NORTH h hills}
{TERRAIN_ADJACENT_NORTH F snow-forest}
{TERRAIN_ADJACENT_NORTH f forest}
# Then, standard transitions
{TERRAIN_ADJACENT_1234 uD cave}
{TERRAIN_ADJACENT_1 F snow-forest}
{TERRAIN_ADJACENT_1 f forest}
{TERRAIN_ADJACENT_1 m mountains}
{TERRAIN_ADJACENT_12 H snow-hills}
{TERRAIN_ADJACENT_12 h hills}
{TERRAIN_ADJACENT_1234 SV snow}
{TERRAIN_ADJACENT_1234 tvg grassland}
{TERRAIN_ADJACENT_1 r dirt}
{TERRAIN_ADJACENT_1 R road} # Graphics do not seem to be here
{TERRAIN_ADJACENT_1 d desert}
{TERRAIN_ADJACENT_1 Yw swampwater}
{TERRAIN_ADJACENT_1 i ice}
{TERRAIN_ADJACENT_1 cZp\|/ coast}
{TERRAIN_ADJACENT_1 s ocean}
{TERRAIN_ADJACENT_1234 ~ fog}
{TERRAIN_ADJACENT_1234 ( ) void}
# Some test cases
#[building_rule]
#[terrain_graphics]
# map="
#. 1
# .
@ -98,24 +645,51 @@ K"
# set_flag="built-m"
#
# image_background="mountains-test"
#[/building_rule]
#
#[building_rule]
#[/terrain_graphics]
#[terrain_graphics]
# [tile]
# x=0
# y=0
# type=m
# [image]
# z_index=-1
# name="mountains-test-2"
# [/image]
# [/tile]
# probability=20
# # probability=20
# no_flag="built-m"
# set_flag="built-m"
# image_background="mountains-test-2"
#[/building_rule]
# # image_background="mountains-test-2"
#
# precedence=2
#[/terrain_graphics]
#
#
#[terrain_graphics]
# terrains=mgcw
#
# [tile]
# x=0
# y=0
# type="@"
# [/tile]
# [tile]
# x=1
# y=1
# type="po@ual"
# [/tile]
#
# no_flag="built-@T"
# set_flag="built-@T"
#
# precedence=3
#[/terrain_graphics]
# A stupid test case, just to demonstrate the has_flag condition
#[building_rule]
#[terrain_graphics]
#
# [tile]
# x=0
@ -124,9 +698,9 @@ K"
# set_flag=moo
# [/tile]
#
#[/building_rule]
#[/terrain_graphics]
#
#[building_rule]
#[terrain_graphics]
# [tile]
# x=0
# y=0
@ -139,4 +713,4 @@ K"
# has_flag="moo"
# [/tile]
# image_background=schmurgle
#[/building_rule]
#[/terrain_graphics]

View file

@ -117,5 +117,5 @@ ggggggggggggggggggggggggggggggggggggg
letter=C
[/terrain]
[/event]
[/test]

View file

@ -443,4 +443,5 @@ recruitment_ignore_bad_combat=yes
message="There can be no looking back. We must go quickly!"
[/message]
[/event]
[/scenario]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 706 B

After

Width:  |  Height:  |  Size: 714 B

View file

@ -56,6 +56,7 @@ terrain_builder::terrain_builder(const config& cfg, const gamemap& gmap) :
{
parse_config(cfg);
build_terrains();
//rebuild_terrain(gamemap::location(0,0));
}
const std::vector<image::locator> *terrain_builder::get_terrain_at(const gamemap::location &loc,
@ -108,25 +109,64 @@ terrain_builder::terrain_constraint terrain_builder::rotate(const terrain_builde
return ret;
}
void terrain_builder::replace_rotation(std::string &s, const std::string &replacement)
void terrain_builder::replace_token(std::string &s, const std::string &token, const std::string &replacement)
{
int pos;
while((pos = s.find("$R")) != std::string::npos) {
s.replace(pos, 2, replacement);
if(token.empty()) {
std::cerr << "Error: empty token in replace_token\n";
return;
}
while((pos = s.find(token)) != std::string::npos) {
s.replace(pos, token.size(), replacement);
}
}
void terrain_builder::replace_token(terrain_builder::imagelist &list, const std::string &token, const std::string &replacement)
{
for(imagelist::iterator itor = list.begin(); itor != list.end(); ++itor) {
replace_token(itor->second, token, replacement);
replace_token(itor->second, token, replacement);
}
}
void terrain_builder::replace_token(terrain_builder::building_rule &rule, const std::string &token, const std::string& replacement)
{
constraint_set::iterator cons;
for(cons = rule.constraints.begin(); cons != rule.constraints.end(); ++cons) {
//Transforms attributes
std::vector<std::string>::iterator flag;
for(flag = cons->second.set_flag.begin(); flag != cons->second.set_flag.end(); flag++) {
replace_token(*flag, token, replacement);
}
for(flag = cons->second.no_flag.begin(); flag != cons->second.no_flag.end(); flag++) {
replace_token(*flag, token, replacement);
}
for(flag = cons->second.has_flag.begin(); flag != cons->second.has_flag.end(); flag++) {
replace_token(*flag, token, replacement);
}
replace_token(cons->second.images, token, replacement);
}
replace_token(rule.images, token, replacement);
}
terrain_builder::building_rule terrain_builder::rotate_rule(const terrain_builder::building_rule &rule,
int angle, const std::string &angle_name)
int angle, const std::vector<std::string>& rot)
{
building_rule ret;
ret.image_foreground = rule.image_foreground;
ret.image_background = rule.image_background;
if(rot.size() != 6) {
std::cerr << "Error: invalid rotations\n";
return ret;
}
ret.images = rule.images;
ret.location_constraints = rule.location_constraints;
ret.probability = rule.probability;
ret.precedence = rule.precedence;
building_rule::constraint_set::const_iterator cons;
constraint_set::const_iterator cons;
for(cons = rule.constraints.begin(); cons != rule.constraints.end(); ++cons) {
const terrain_constraint &rcons = rotate(cons->second, angle);
ret.constraints[rcons.loc] = rcons;
@ -136,7 +176,7 @@ terrain_builder::building_rule terrain_builder::rotate_rule(const terrain_builde
int minx = INT_MAX;
int miny = INT_MAX;
building_rule::constraint_set::iterator cons2;
constraint_set::iterator cons2;
for(cons2 = ret.constraints.begin(); cons2 != ret.constraints.end(); ++cons2) {
minx = minimum<int>(cons2->second.loc.x, minx);
miny = minimum<int>(2*cons2->second.loc.y + (cons2->second.loc.x & 1), miny);
@ -150,31 +190,42 @@ terrain_builder::building_rule terrain_builder::rotate_rule(const terrain_builde
for(cons2 = ret.constraints.begin(); cons2 != ret.constraints.end(); ++cons2) {
//Adjusts positions
cons2->second.loc += gamemap::location(-minx, -((miny-1)/2));
//Transforms attributes
std::vector<std::string>::iterator flag;
for(flag = cons2->second.set_flag.begin(); flag != cons2->second.set_flag.end(); flag++) {
replace_rotation(*flag, angle_name);
}
for(flag = cons2->second.no_flag.begin(); flag != cons2->second.no_flag.end(); flag++) {
replace_rotation(*flag, angle_name);
}
for(flag = cons2->second.has_flag.begin(); flag != cons2->second.has_flag.end(); flag++) {
replace_rotation(*flag, angle_name);
}
}
replace_rotation(ret.image_foreground, angle_name);
replace_rotation(ret.image_background, angle_name);
for(int i = 0; i < 6; ++i) {
int a = (angle+i) % 6;
std::string token = "@R";
token.push_back('0' + i);
replace_token(ret, token, rot[a]);
}
return ret;
}
void terrain_builder::add_constraint_item(std::vector<std::string> &list, const std::string &item)
terrain_builder::building_rule terrain_builder::rule_from_terrain_template(const terrain_builder::building_rule&tpl, const gamemap::TERRAIN terrain)
{
if(!item.empty())
list.push_back(item);
terrain_builder::building_rule ret = tpl;
std::string ter(1, terrain);
constraint_set::iterator cons;
for(cons = ret.constraints.begin(); cons != ret.constraints.end(); ++cons) {
replace_token(cons->second.terrain_types, "@", ter);
}
replace_token(ret, "@T", map_.get_terrain_info(terrain).default_image());
return ret;
}
void terrain_builder::add_images_from_config(imagelist& images, const config &cfg)
{
const config::child_list& cimages = cfg.get_children("image");
for(config::child_list::const_iterator itor = cimages.begin(); itor != cimages.end(); ++itor) {
const int z_index = atoi((**itor)["z_index"].c_str());
const std::string &name = (**itor)["name"];
images.insert(std::pair<int, std::string>(z_index, name));
}
}
void terrain_builder::add_constraints(std::map<gamemap::location, terrain_builder::terrain_constraint> & constraints,
@ -185,18 +236,34 @@ void terrain_builder::add_constraints(std::map<gamemap::location, terrain_builde
constraints[loc] = terrain_constraint(loc);
}
if(type.size())
if(!type.empty())
constraints[loc].terrain_types = type;
}
void terrain_builder::add_constraints(std::map<gamemap::location, terrain_builder::terrain_constraint> &constraints,
const gamemap::location& loc, const config& cfg)
void terrain_builder::add_constraint_item(std::vector<std::string> &list, const config& cfg, const std::string &item)
{
if(!cfg[item].empty())
list.push_back(cfg[item]);
const config::child_list& items = cfg.get_children(item);
for(config::child_list::const_iterator itor = items.begin(); itor != items.end(); ++itor) {
if(!(**itor)["name"].empty())
list.push_back((**itor)["name"]);
}
}
void terrain_builder::add_constraints(terrain_builder::constraint_set &constraints, const gamemap::location& loc, const config& cfg)
{
add_constraints(constraints, loc, cfg["type"]);
add_constraint_item(constraints[loc].set_flag, cfg["set_flag"]);
add_constraint_item(constraints[loc].has_flag, cfg["has_flag"]);
add_constraint_item(constraints[loc].no_flag, cfg["no_flag"]);
terrain_constraint& constraint = constraints[loc];
add_constraint_item(constraint.set_flag, cfg, "set_flag");
add_constraint_item(constraint.has_flag, cfg, "has_flag");
add_constraint_item(constraint.no_flag, cfg, "no_flag");
add_images_from_config(constraint.images, cfg);
}
void terrain_builder::parse_mapstring(const std::string &mapstring, struct building_rule &br,
@ -262,22 +329,39 @@ void terrain_builder::parse_mapstring(const std::string &mapstring, struct build
}
void terrain_builder::add_rotated_rules(building_ruleset& rules, const building_rule& tpl, const std::string &rotations)
{
if(rotations.empty()) {
// Adds the parsed built terrain to the list
building_rules_.insert(std::pair<int, building_rule>(tpl.precedence, tpl));
} else {
const std::vector<std::string>& rot = config::split(rotations, ',');
for(int angle = 0; angle < rot.size(); angle++) {
building_rules_.insert(std::pair<int, building_rule>(tpl.precedence,
rotate_rule(tpl, angle, rot)));
}
}
}
void terrain_builder::parse_config(const config &cfg)
{
log_scope("terrain_builder::parse_config");
//Parses the list of building rules (BRs)
config::child_list brs(cfg.get_children("building_rule"));
const config::child_list& brs = cfg.get_children("terrain_graphics");
for(config::child_list::const_iterator br = brs.begin(); br != brs.end(); ++br) {
building_rule pbr; // Parsed Building rule
pbr.image_foreground = (**br)["image_foreground"];
pbr.image_background = (**br)["image_background"];
add_images_from_config(pbr.images, **br);
if(!((**br)["x"].empty() || (**br)["y"].empty()))
pbr.location_constraints = gamemap::location(atoi((**br)["x"].c_str()), atoi((**br)["y"].c_str()));
pbr.probability = (**br)["probability"].empty() ? -1 : atoi((**br)["probability"].c_str());
pbr.precedence = (**br)["precedence"].empty() ? 0 : atoi((**br)["precedence"].c_str());
//Mapping anchor indices to anchor locations.
anchormap anchors;
@ -322,7 +406,7 @@ void terrain_builder::parse_config(const config &cfg)
const std::string global_no_flag = (**br)["no_flag"];
const std::string global_has_flag = (**br)["has_flag"];
for(building_rule::constraint_set::iterator constraint = pbr.constraints.begin(); constraint != pbr.constraints.end();
for(constraint_set::iterator constraint = pbr.constraints.begin(); constraint != pbr.constraints.end();
constraint++) {
if(global_set_flag.size())
@ -338,25 +422,29 @@ void terrain_builder::parse_config(const config &cfg)
// Handles rotations
const std::string rotations = (**br)["rotations"];
if(rotations.size()) {
const std::vector<std::string>& rot = config::split(rotations, ',');
for(int angle = 0; angle < rot.size(); angle++) {
building_rules_.push_back(rotate_rule(pbr, angle, rot[angle]));
}
const std::string terrains = (**br)["terrains"];
if(terrains.empty()) {
add_rotated_rules(building_rules_, pbr, rotations);
} else {
// Adds the parsed built terrain to the list
building_rules_.push_back(pbr);
for(std::string::const_iterator terrain = terrains.begin();
terrain != terrains.end(); ++terrain) {
const building_rule r = rule_from_terrain_template(pbr, *terrain);
add_rotated_rules(building_rules_, r, rotations);
}
}
}
#if 0
std::cerr << "Built terrain rules: \n";
building_ruleset::const_iterator rule;
for(rule = building_rules_.begin(); rule != building_rules_.end(); ++rule) {
std::cerr << ">> New rule: image_background = " << rule->image_background << " , image_foreground = "<< rule->image_foreground << "\n";
for(building_rule::constraint_set::const_iterator constraint = rule->constraints.begin();
constraint != rule->constraints.end(); ++constraint) {
std::cerr << ">> New rule: image_background = " /* << rule->second.image_background << " , image_foreground = "<< rule->second.image_foreground */ << "\n";
for(constraint_set::const_iterator constraint = rule->second.constraints.begin();
constraint != rule->second.constraints.end(); ++constraint) {
std::cerr << ">>>> New constraint: location = (" << constraint->second.loc.x << ", " << constraint->second.loc.y << "), terrain types = " << constraint->second.terrain_types << "\n";
@ -372,6 +460,7 @@ void terrain_builder::parse_config(const config &cfg)
}
}
#endif
}
@ -388,7 +477,7 @@ bool terrain_builder::rule_matches(const terrain_builder::building_rule &rule, c
return false;
}
for(building_rule::constraint_set::const_iterator cons = rule.constraints.begin();
for(constraint_set::const_iterator cons = rule.constraints.begin();
cons != rule.constraints.end(); ++cons) {
// translated location
@ -399,9 +488,11 @@ bool terrain_builder::rule_matches(const terrain_builder::building_rule &rule, c
const tile& btile = tile_map_[tloc];
if(!map_.get_terrain_info(tloc).matches(cons->second.terrain_types))
return false;
if(!cons->second.terrain_types.empty()) {
if(!map_.get_terrain_info(tloc).matches(cons->second.terrain_types))
return false;
}
std::vector<std::string>::const_iterator itor;
for(itor = cons->second.no_flag.begin(); itor != cons->second.no_flag.end(); ++itor) {
@ -422,7 +513,7 @@ bool terrain_builder::rule_matches(const terrain_builder::building_rule &rule, c
void terrain_builder::apply_rule(const terrain_builder::building_rule &rule, const gamemap::location &loc)
{
for(building_rule::constraint_set::const_iterator constraint = rule.constraints.begin();
for(constraint_set::const_iterator constraint = rule.constraints.begin();
constraint != rule.constraints.end(); ++constraint) {
const gamemap::location tloc = loc + constraint->second.loc;
@ -431,17 +522,28 @@ void terrain_builder::apply_rule(const terrain_builder::building_rule &rule, con
tile& btile = tile_map_[tloc];
if(rule.image_foreground.size()) {
image::locator th(rule.image_foreground, constraint->second.loc);
btile.images_foreground.push_back(th);
std::multimap<int, std::string>::const_iterator img;
for(img = rule.images.begin(); img != rule.images.end(); ++img) {
image::locator th(img->second, constraint->second.loc);
if(img->first < 0) {
btile.images_background.push_back(th);
} else {
btile.images_foreground.push_back(th);
}
}
if(rule.image_background.size()) {
image::locator th(rule.image_background, constraint->second.loc);
btile.images_background.push_back(th);
for(img = constraint->second.images.begin(); img != constraint->second.images.end(); ++img) {
image::locator th(img->second);
if(img->first < 0) {
btile.images_background.push_back(th);
} else {
btile.images_foreground.push_back(th);
}
}
// Sets flags
for(std::vector<std::string>::const_iterator itor = constraint->second.set_flag.begin();
itor != constraint->second.set_flag.end(); itor++) {
btile.flags.insert(*itor);
@ -468,36 +570,79 @@ void terrain_builder::build_terrains()
building_ruleset::const_iterator rule;
for(rule = building_rules_.begin(); rule != building_rules_.end(); ++rule) {
//if the rule has no constraints, it is invalid
if(rule->second.constraints.empty())
continue;
//find a constraint that contains an unique terrain type on the current
//rule
building_rule::constraint_set::const_iterator constraint;
for(constraint = rule->constraints.begin();
constraint != rule->constraints.end(); ++constraint) {
if(constraint->second.terrain_types.size() == 1 && (constraint->second.terrain_types[0] != '*')) {
break;
//checks if all the images referenced by the current rule are valid.
//if not, this rule will not match.
bool absent_image = false;
imagelist::const_iterator image;
constraint_set::const_iterator constraint;
for(image = rule->second.images.begin();
!absent_image && (image != rule->second.images.end()); ++image) {
if(!image::exists("terrain/" + image->second + ".png"))
absent_image = true;
}
for(constraint = rule->second.constraints.begin();
constraint != rule->second.constraints.end(); ++constraint) {
for(image = constraint->second.images.begin();
!absent_image && (image != constraint->second.images.end());
++image) {
if(!image::exists("terrain/" + image->second + ".png"))
absent_image = true;
}
}
if(constraint != rule->constraints.end()) {
gamemap::TERRAIN c = constraint->second.terrain_types[0];
gamemap::location loc = constraint->second.loc;
const std::vector<gamemap::location>& locations = terrain_by_type_[c];
if(absent_image)
continue;
//find the constraint that contains the less terrain of all terrain rules
constraint_set::const_iterator smallest_constraint;
int smallest_constraint_size = INT_MAX;
for(constraint = rule->second.constraints.begin();
constraint != rule->second.constraints.end(); ++constraint) {
const std::string &types = constraint->second.terrain_types;
for(std::vector<gamemap::location>::const_iterator itor = locations.begin();
itor != locations.end(); ++itor) {
if(types.empty())
continue;
if(types[0] == '!')
continue;
if(types.find('*') != std::string::npos)
continue;
if(types.size() >= smallest_constraint_size)
continue;
smallest_constraint_size = types.size();
smallest_constraint = constraint;
}
if(smallest_constraint_size != INT_MAX) {
const std::string &types = smallest_constraint->second.terrain_types;
const gamemap::location loc = smallest_constraint->second.loc;
for(std::string::const_iterator c = types.begin(); c != types.end(); ++c) {
const std::vector<gamemap::location>& locations = terrain_by_type_[*c];
for(std::vector<gamemap::location>::const_iterator itor = locations.begin();
itor != locations.end(); ++itor) {
if(rule_matches(*rule, *itor - loc, rule_index)) {
apply_rule(*rule, *itor - loc);
if(rule_matches(rule->second, *itor - loc, rule_index)) {
apply_rule(rule->second, *itor - loc);
}
}
}
} else {
for(int x = -5; x <= map_.x() + 4; ++x) {
for(int y = 51; y <= map_.y() + 4; ++y) {
for(int x = -1; x <= map_.x(); ++x) {
for(int y = -1; y <= map_.y(); ++y) {
const gamemap::location loc(x,y);
if(rule_matches(*rule, loc, rule_index))
apply_rule(*rule, loc);
if(rule_matches(rule->second, loc, rule_index))
apply_rule(rule->second, loc);
}
}
}

View file

@ -33,10 +33,14 @@ public:
//built content for this tile.
//Returns NULL if there is no built content for this tile.
const std::vector<image::locator> *get_terrain_at(const gamemap::location &loc,
ADJACENT_TERRAIN_TYPE terrain_type) const;
ADJACENT_TERRAIN_TYPE terrain_type) const;
// regenerate the generated content at the given location.
void rebuild_terrain(const gamemap::location &loc);
typedef std::multimap<int, std::string> imagelist;
struct terrain_constraint
{
terrain_constraint() : loc() {};
@ -48,8 +52,10 @@ public:
std::vector<std::string> set_flag;
std::vector<std::string> no_flag;
std::vector<std::string> has_flag;
};
imagelist images;
};
struct tile
{
std::set<std::string> flags;
@ -60,16 +66,17 @@ public:
};
private:
typedef std::map<gamemap::location, terrain_constraint> constraint_set;
struct building_rule
{
typedef std::map<gamemap::location, terrain_constraint> constraint_set;
constraint_set constraints;
gamemap::location location_constraints;
int probability;
std::string image_foreground;
std::string image_background;
int precedence;
imagelist images;
};
struct tilemap
@ -88,21 +95,28 @@ private:
int y_;
};
typedef std::multimap<int, building_rule> building_ruleset;
terrain_constraint rotate(const terrain_constraint &constraint, int angle);
void replace_rotation(std::string &s, const std::string &replacement);
void replace_token(std::string &, const std::string &token, const std::string& replacement);
void replace_token(imagelist &, const std::string &token, const std::string& replacement);
void replace_token(building_rule &s, const std::string &token, const std::string& replacement);
building_rule rotate_rule(const building_rule &rule, int angle, const std::string &angle_name);
building_rule rotate_rule(const building_rule &rule, int angle, const std::vector<std::string>& angle_name);
void add_rotated_rules(building_ruleset& rules, const building_rule& tpl, const std::string &rotations);
void add_constraint_item(std::vector<std::string> &list, const config& cfg, const std::string &item);
void terrain_builder::add_images_from_config(imagelist &images, const config &cfg);
void add_constraint_item(std::vector<std::string> &list, const std::string &item);
void add_constraints(std::map<gamemap::location, terrain_constraint>& constraints,
const gamemap::location &loc, const std::string& type);
void add_constraints(std::map<gamemap::location, terrain_constraint>& constraints, const gamemap::location &loc,
const config &cfg);
typedef std::multimap<int, gamemap::location> anchormap;
void parse_mapstring(const std::string &mapstring, struct building_rule &br,
anchormap& anchors);
terrain_builder::building_rule rule_from_terrain_template(const terrain_builder::building_rule &tpl, const gamemap::TERRAIN terrain);
void parse_config(const config &cfg);
bool rule_matches(const building_rule &rule, const gamemap::location &loc, int rule_index);
void apply_rule(const building_rule &rule, const gamemap::location &loc);
@ -113,8 +127,7 @@ private:
typedef std::map<unsigned char, std::vector<gamemap::location> > terrain_by_type_map;
terrain_by_type_map terrain_by_type_;
typedef std::vector<building_rule> building_ruleset;
building_ruleset building_rules_;
};

View file

@ -912,7 +912,7 @@ void display::draw_unit_details(int x, int y, const gamemap::location& loc,
void display::draw_minimap(int x, int y, int w, int h)
{
const scoped_sdl_surface surface(getMinimap(w,h));
const scoped_sdl_surface surface(get_minimap(w,h));
if(surface == NULL)
return;
@ -957,6 +957,7 @@ void display::draw_minimap(int x, int y, int w, int h)
update_rect(minimap_location);
}
#if 0
void display::draw_terrain_palette(int x, int y, gamemap::TERRAIN selected)
{
const int max_h = 35;
@ -971,7 +972,7 @@ void display::draw_terrain_palette(int x, int y, gamemap::TERRAIN selected)
std::vector<gamemap::TERRAIN> terrains = map_.get_terrain_precedence();
for(std::vector<gamemap::TERRAIN>::const_iterator i = terrains.begin();
i != terrains.end(); ++i) {
const scoped_sdl_surface image(getTerrain(*i,image::SCALED,-1,-1));
const scoped_sdl_surface image(get_terrain(*i,image::SCALED,-1,-1));
if(image == NULL) {
std::cerr << "image for terrain '" << *i << "' not found\n";
return;
@ -1004,6 +1005,7 @@ void display::draw_terrain_palette(int x, int y, gamemap::TERRAIN selected)
invalid_rect.h = y - invalid_rect.y;
update_rect(invalid_rect);
}
#endif
gamemap::TERRAIN display::get_terrain_on(int palx, int paly, int x, int y)
{
@ -1265,7 +1267,7 @@ void display::draw_bar(const std::string& image, int xpos, int ypos, size_t heig
blit_surface(xpos,ypos,surf,&top);
blit_surface(xpos,ypos+top.h,surf,&bot);
const size_t unfilled = height*(1.0 - filled);
const size_t unfilled = (const size_t)(height*(1.0 - filled));
if(unfilled < height && alpha >= 0.3) {
SDL_Rect filled_area = {xpos+bar_loc.x,ypos+bar_loc.y+unfilled,bar_loc.w,height-unfilled};
@ -1274,6 +1276,7 @@ void display::draw_bar(const std::string& image, int xpos, int ypos, size_t heig
}
}
#if 0
void display::draw_tile_adjacent(int x, int y, image::TYPE image_type, ADJACENT_TERRAIN_TYPE type)
{
const gamemap::location loc(x,y);
@ -1306,6 +1309,34 @@ void display::draw_tile_adjacent(int x, int y, image::TYPE image_type, ADJACENT_
SDL_BlitSurface(*i,NULL,dst,&dstrect);
}
}
#endif
void display::draw_terrain_on_tile(int x, int y, image::TYPE image_type, ADJACENT_TERRAIN_TYPE type)
{
const gamemap::location loc(x,y);
int xpos = int(get_location_x(loc));
int ypos = int(get_location_y(loc));
SDL_Rect clip_rect = map_area();
if(xpos > clip_rect.x + clip_rect.w || ypos > clip_rect.y + clip_rect.h ||
xpos + zoom_ < clip_rect.x || ypos + zoom_ < clip_rect.y) {
return;
}
SDL_Surface* const dst = screen_.getSurface();
clip_rect_setter set_clip_rect(dst,clip_rect);
const std::vector<shared_sdl_surface>& images = get_terrain_images(x,y,image_type,type);
std::vector<shared_sdl_surface>::const_iterator itor;
for(itor = images.begin(); itor != images.end(); ++itor) {
SDL_Rect dstrect = { xpos, ypos, 0, 0 };
SDL_BlitSurface(*itor,NULL,dst,&dstrect);
}
}
void display::draw_tile(int x, int y, SDL_Surface* unit_image, double alpha, Uint32 blend_to)
{
@ -1363,7 +1394,8 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image, double alpha, Uin
image_type = image::SEMI_BRIGHTENED;
}
scoped_sdl_surface surface(getTerrain(terrain,image_type,x,y));
#if 0
scoped_sdl_surface surface(get_terrain(terrain,image_type,x,y));
if(surface == NULL) {
std::cerr << "Could not get terrain surface\n";
@ -1376,16 +1408,17 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image, double alpha, Uin
//initialized to pass to each call to SDL_BlitSurface
SDL_Rect dstrect = { xpos, ypos, 0, 0 };
SDL_BlitSurface(surface,NULL,dst,&dstrect);
#endif
if(!is_shrouded) {
scoped_sdl_surface flag(getFlag(terrain,x,y));
draw_terrain_on_tile(x,y,image_type,ADJACENT_BACKGROUND);
scoped_sdl_surface flag(get_flag(terrain,x,y));
if(flag != NULL) {
SDL_Rect dstrect = { xpos, ypos, 0, 0 };
SDL_BlitSurface(flag,NULL,dst,&dstrect);
}
draw_tile_adjacent(x,y,image_type,ADJACENT_BACKGROUND);
typedef std::multimap<gamemap::location,std::string>::const_iterator Itor;
for(std::pair<Itor,Itor> overlays = overlays_.equal_range(loc);
@ -1393,15 +1426,26 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image, double alpha, Uin
scoped_sdl_surface overlay_surface(image::get_image(overlays.first->second));
//note that dstrect can be changed by SDL_BlitSurface and so a
//new instance should be initialized to pass to each call to
//SDL_BlitSurface
if(overlay_surface != NULL) {
SDL_Rect dstrect = { xpos, ypos, 0, 0 };
SDL_BlitSurface(overlay_surface,NULL,dst,&dstrect);
}
}
}
if(!is_shrouded) {
draw_footstep(loc,xpos,ypos);
} else {
//FIXME: shouldn't void.png and fog.png be in the program configuration?
scoped_sdl_surface surface(image::get_image("terrain/void.png"));
if(surface == NULL) {
std::cerr << "Could not get void surface!\n";
return;
}
SDL_Rect dstrect = { xpos, ypos, 0, 0 };
SDL_BlitSurface(surface,NULL,dst,&dstrect);
}
if(fogged(x,y)) {
@ -1415,7 +1459,7 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image, double alpha, Uin
draw_unit_on_tile(x,y,unit_image,alpha,blend_to);
if(!shrouded(x,y)) {
draw_tile_adjacent(x,y,image_type,ADJACENT_FOREGROUND);
draw_terrain_on_tile(x,y,image_type,ADJACENT_FOREGROUND);
}
//draw the time-of-day mask on top of the hex
@ -1450,6 +1494,8 @@ void display::draw_tile(int x, int y, SDL_Surface* unit_image, double alpha, Uin
if(cross != NULL)
draw_unit(xpos,ypos,cross,false,debugHighlights_[loc],0);
}
update_rect(xpos,ypos,zoom_,zoom_);
}
void display::draw_footstep(const gamemap::location& loc, int xloc, int yloc)
@ -1544,6 +1590,7 @@ const std::string& get_direction(size_t n)
const static std::string dirs[6] = {"-n","-ne","-se","-s","-sw","-nw"};
return dirs[n >= sizeof(dirs)/sizeof(*dirs) ? 0 : n];
}
}
bool angle_is_northern(size_t n)
@ -1557,7 +1604,7 @@ const std::string& get_angle_direction(size_t n)
const static std::string dirs[6] = {"-ne","-e","-se","-sw","-w","-nw"};
return dirs[n >= sizeof(dirs)/sizeof(*dirs) ? 0 : n];
}
#if 0
std::vector<shared_sdl_surface> display::getAdjacentTerrain(int x, int y, image::TYPE image_type, ADJACENT_TERRAIN_TYPE terrain_type)
{
std::vector<shared_sdl_surface> res;
@ -1618,7 +1665,7 @@ std::vector<shared_sdl_surface> display::getAdjacentTerrain(int x, int y, image:
for(int n = 0; *terrain == tiles[i] && n != 6; i = (i+1)%6, ++n) {
stream << get_direction(i);
const shared_sdl_surface new_surface(getTerrain(
const shared_sdl_surface new_surface(get_terrain(
*terrain,image_type,x,y,stream.str()));
if(new_surface == NULL) {
@ -1642,8 +1689,79 @@ std::vector<shared_sdl_surface> display::getAdjacentTerrain(int x, int y, image:
return res;
}
#endif
std::vector<shared_sdl_surface> display::getBuiltTerrain(int x, int y, image::TYPE image_type, ADJACENT_TERRAIN_TYPE terrain_type)
std::vector<std::string> display::get_fog_shroud_graphics(const gamemap::location& loc)
{
std::vector<std::string> res;
gamemap::location adjacent[6];
bool transition_done[6];
get_adjacent_tiles(loc,adjacent);
int tiles[6];
static const int terrain_types[] = { gamemap::VOID_TERRAIN, gamemap::FOGGED, 0 };
for(int i = 0; i != 6; ++i) {
if(shrouded(adjacent[i].x,adjacent[i].y))
tiles[i] = gamemap::VOID_TERRAIN;
else if(!fogged(loc.x,loc.y) && fogged(adjacent[i].x,adjacent[i].y))
tiles[i] = gamemap::FOGGED;
else
tiles[i] = 0;
}
for(const int * terrain = terrain_types; *terrain != 0; terrain ++) {
//find somewhere that doesn't have overlap to use as a starting point
int start;
for(start = 0; start != 6; ++start) {
if(tiles[start] != *terrain)
break;
}
if(start == 6) {
start = 0;
}
//find all the directions overlap occurs from
for(int i = (start+1)%6, n = 0; i != start && n != 6; ++n) {
if(tiles[i] == *terrain) {
std::ostringstream stream;
std::string name;
// if(*terrain == gamemap::VOID_TERRAIN)
// stream << "void";
//else
// stream << "fog";
stream << map_.get_terrain_info(*terrain).default_image();
for(int n = 0; *terrain == tiles[i] && n != 6; i = (i+1)%6, ++n) {
stream << get_direction(i);
if(!image::exists("terrain/" + stream.str() + ".png")) {
//if we don't have any surface at all,
//then move onto the next overlapped area
if(name.empty())
i = (i+1)%6;
break;
} else {
name = stream.str();
}
}
if(!name.empty()) {
res.push_back(name);
}
} else {
i = (i+1)%6;
}
}
}
return res;
}
std::vector<shared_sdl_surface> display::get_terrain_images(int x, int y, image::TYPE image_type, ADJACENT_TERRAIN_TYPE terrain_type)
{
std::vector<shared_sdl_surface> res;
gamemap::location loc(x,y);
@ -1658,17 +1776,34 @@ std::vector<shared_sdl_surface> display::getBuiltTerrain(int x, int y, image::TY
image::locator image = *it;
image.filename = "terrain/" + it->filename;
const shared_sdl_surface surface(getTerrain(image,image_type,x,y,true));
const shared_sdl_surface surface(get_terrain(image,image_type,x,y,true));
if(surface != NULL) {
res.push_back(surface);
}
}
}
if(terrain_type == ADJACENT_FOREGROUND) {
const std::vector<std::string> fog_shroud = get_fog_shroud_graphics(gamemap::location(x,y));
if(!fog_shroud.empty()) {
for(std::vector<std::string>::const_iterator it = fog_shroud.begin(); it != fog_shroud.end(); ++it) {
image::locator image(*it);
image.filename = "terrain/" + *it;
const shared_sdl_surface surface(get_terrain(image,image_type,x,y,true));
if(surface != NULL) {
res.push_back(surface);
}
}
}
}
return res;
}
SDL_Surface* display::getTerrain(const image::locator& image, image::TYPE image_type,
SDL_Surface* display::get_terrain(const image::locator& image, image::TYPE image_type,
int x, int y, bool search_tod)
{
SDL_Surface* im = NULL;
@ -1700,18 +1835,18 @@ SDL_Surface* display::getTerrain(const image::locator& image, image::TYPE image_
const int radj = tod_at.red - tod.red;
const int gadj = tod_at.green - tod.green;
const int badj = tod_at.blue - tod.blue;
if((radj|gadj|badj) != 0 && im != NULL) {
const scoped_sdl_surface backup(im);
im = adjust_surface_colour(im,radj,gadj,badj);
if(im == NULL)
std::cerr << "could not adjust surface..\n";
}
return im;
}
SDL_Surface* display::getTerrain(gamemap::TERRAIN terrain, image::TYPE image_type,
#if 0
SDL_Surface* display::get_terrain(gamemap::TERRAIN terrain, image::TYPE image_type,
int x, int y, const std::string& direction)
{
std::string image = "terrain/" + (direction.empty() ?
@ -1720,7 +1855,7 @@ SDL_Surface* display::getTerrain(gamemap::TERRAIN terrain, image::TYPE image_typ
image += direction;
SDL_Surface* im = getTerrain(image, image_type, x, y, direction.empty());
SDL_Surface* im = get_terrain(image, image_type, x, y, direction.empty());
if(im == NULL && direction.empty()) {
im = image::get_image("terrain/" +
@ -1729,8 +1864,8 @@ SDL_Surface* display::getTerrain(gamemap::TERRAIN terrain, image::TYPE image_typ
return im;
}
SDL_Surface* display::getFlag(gamemap::TERRAIN terrain, int x, int y)
#endif
SDL_Surface* display::get_flag(gamemap::TERRAIN terrain, int x, int y)
{
const bool village = map_.is_village(terrain);
if(!village)
@ -1762,7 +1897,7 @@ void display::blit_surface(int x, int y, SDL_Surface* surface, SDL_Rect* srcrect
}
}
SDL_Surface* display::getMinimap(int w, int h)
SDL_Surface* display::get_minimap(int w, int h)
{
if(minimap_ == NULL) {
minimap_ = image::getMinimap(w,h,map_,
@ -1820,8 +1955,8 @@ void display::float_label(const gamemap::location& loc, const std::string& text,
}
void display::draw_unit(int x, int y, SDL_Surface* image,
bool upside_down, double alpha, Uint32 blendto, double submerged,
SDL_Surface* ellipse_back, SDL_Surface* ellipse_front)
bool upside_down, double alpha, Uint32 blendto, double submerged,
SDL_Surface* ellipse_back, SDL_Surface* ellipse_front)
{
//calculate the y position of the ellipse. It should be the same as the y position of the image, unless
//the image is partially submerged, in which case the ellipse should appear to float 'on top of' the water

View file

@ -175,13 +175,17 @@ public:
int red, int green, int blue);
private:
enum ADJACENT_TERRAIN_TYPE { ADJACENT_BACKGROUND, ADJACENT_FOREGROUND };
//composes and draws the terrains on a tile
void draw_terrain_on_tile(int x, int y, image::TYPE image_type, ADJACENT_TERRAIN_TYPE type);
void draw_unit_on_tile(int x, int y, SDL_Surface* unit_image=NULL,
double alpha=1.0, Uint32 blend_to=0);
void draw_halo_on_tile(int x, int y);
enum ADJACENT_TERRAIN_TYPE { ADJACENT_BACKGROUND, ADJACENT_FOREGROUND };
void draw_tile_adjacent(int x, int y, image::TYPE image_type, ADJACENT_TERRAIN_TYPE type);
// void draw_tile_adjacent(int x, int y, image::TYPE image_type, ADJACENT_TERRAIN_TYPE type);
public:
@ -239,7 +243,7 @@ public:
void update_display();
//functions used in the editor.
void draw_terrain_palette(int x, int y, gamemap::TERRAIN selected);
//void draw_terrain_palette(int x, int y, gamemap::TERRAIN selected);
gamemap::TERRAIN get_terrain_on(int palx, int paly, int x, int y);
//set_team sets the team controlled by the player using the computer,
@ -351,21 +355,23 @@ private:
void bounds_check_position();
std::vector<shared_sdl_surface> getAdjacentTerrain(int x, int y, image::TYPE type, ADJACENT_TERRAIN_TYPE terrain_type);
std::vector<shared_sdl_surface> getBuiltTerrain(int x, int y, image::TYPE type, ADJACENT_TERRAIN_TYPE terrain_type);
// std::vector<shared_sdl_surface> getAdjacentTerrain(int x, int y, image::TYPE type, ADJACENT_TERRAIN_TYPE terrain_type);
std::vector<shared_sdl_surface> get_terrain_images(int x, int y, image::TYPE type, ADJACENT_TERRAIN_TYPE terrain_type);
std::vector<std::string> get_fog_shroud_graphics(const gamemap::location& loc);
//this surface must be freed by the caller
SDL_Surface* getTerrain(gamemap::TERRAIN, image::TYPE type,
int x, int y, const std::string& dir="");
//SDL_Surface* get_terrain(gamemap::TERRAIN, image::TYPE type,
// int x, int y, const std::string& dir="");
//this surface must be freed by the caller
SDL_Surface* getTerrain(const image::locator &image, image::TYPE type,
SDL_Surface* get_terrain(const image::locator &image, image::TYPE type,
int x, int y, bool search_tod);
//this surface must be freed by the caller
SDL_Surface* getFlag(gamemap::TERRAIN, int x, int y);
SDL_Surface* get_flag(gamemap::TERRAIN, int x, int y);
//this surface must be freed by the caller
SDL_Surface* getMinimap(int w, int h);
SDL_Surface* get_minimap(int w, int h);
CVideo& screen_;
mutable CKey keys_;

View file

@ -22,6 +22,8 @@ typedef std::map<image::locator,SDL_Surface*> image_map;
image_map images_,scaledImages_,unmaskedImages_,greyedImages_;
image_map brightenedImages_,semiBrightenedImages_;
std::map<image::locator,bool> image_existance_map;
std::map<SDL_Surface*,SDL_Surface*> reversedImages_;
int red_adjust = 0, green_adjust = 0, blue_adjust = 0;
@ -95,31 +97,41 @@ void flush_cache()
clear_surfaces(reversedImages_);
}
std::vector<std::string> get_search_locations(const std::string &file)
{
std::vector<std::string> ret;
static const std::string images_path = "images/";
const std::string image_filename = images_path + file;
if(!game_config::path.empty()) {
ret.push_back(game_config::path + "/" + image_filename);
}
ret.push_back(image_filename);
ret.push_back(get_user_data_dir() + "/" + image_filename);
return ret;
}
SDL_Surface* load_image_file(image::locator i_locator)
{
SDL_Surface* surf = NULL;
static const std::string images_path = "images/";
const std::string images_filename = images_path + i_locator.filename;
const std::vector<std::string>& locations = get_search_locations(i_locator.filename);
for(std::vector<std::string>::const_iterator itor = locations.begin();
itor != locations.end(); ++itor) {
if(game_config::path.empty() == false) {
const std::string& fullpath = game_config::path + "/" +
images_filename;
surf = IMG_Load(fullpath.c_str());
}
if(surf == NULL) {
surf = IMG_Load(images_filename.c_str());
}
if(surf == NULL) {
const std::string user_image = get_user_data_dir() + "/" + images_filename;
surf = IMG_Load(user_image.c_str());
surf = IMG_Load(itor->c_str());
if(surf != NULL)
return surf;
}
return surf;
}
SDL_Surface * load_image_sub_file(image::locator i_locator)
{
SDL_Surface *surf = NULL;
@ -434,6 +446,29 @@ void register_image(const std::string &id, SDL_Surface* surf)
register_image(locator(id), surf);
}
bool exists(const image::locator& i_locator)
{
bool ret=false;
if(i_locator.type != image::locator::FILE &&
i_locator.type != image::locator::SUB_FILE)
return false;
if(image_existance_map.find(i_locator) != image_existance_map.end())
return image_existance_map[i_locator];
const std::vector<std::string>& locations = get_search_locations(i_locator.filename);
for(std::vector<std::string>::const_iterator itor = locations.begin();
itor != locations.end(); ++itor) {
if(file_exists(*itor))
ret = true;
}
image_existance_map[i_locator] = ret;
return ret;
}
SDL_Surface* getMinimap(int w, int h, const gamemap& map,
int lawful_bonus, const team* tm)
{

View file

@ -100,6 +100,9 @@ namespace image {
///and replaced with this image.
void register_image(const locator& i_locator, SDL_Surface* surf);
//returns true if the given image actually exists, without loading it.
bool exists(const locator& i_locator);
///function to create the minimap for a given map
///the surface returned must be freed by the user
SDL_Surface* getMinimap(int w, int h, const gamemap& map_, int lawful_bonus, const team* tm=NULL);

View file

@ -626,7 +626,8 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
const std::string& team_name = (*child)["team_name"];
if(team_name == "" || teams[disp.viewing_team()].team_name() == team_name) {
if(preferences::message_bell()) {
sound::play_sound(game_config::sounds::receive_message);
if(!replayer.skipping())
sound::play_sound(game_config::sounds::receive_message);
}
const int side = lexical_cast_default<int>((*child)["side"].c_str());

View file

@ -59,16 +59,17 @@ terrain_type::terrain_type(const config& cfg)
castle_ = cfg["recruit_onto"] == "true";
keep_ = cfg["recruit_from"] == "true";
}
#if 0
const std::string& terrain_type::image(int x, int y) const
{
assert(!images_.empty());
return images_[(((x<<8)^3413402)+y^34984 + x*y)%images_.size()];
//return images_[(((x<<8)^3413402)+y^34984 + x*y)%images_.size()];
return default_image();
}
#endif
const std::string& terrain_type::default_image() const
{
//static const std::string ret = "void";
assert(!images_.empty());
return images_.front();
}

View file

@ -24,7 +24,7 @@ public:
terrain_type();
terrain_type(const config& cfg);
const std::string& image(int x, int y) const;
//const std::string& image(int x, int y) const;
const std::string& default_image() const;
const std::string& adjacent_image() const;
const std::string& name() const;