val('style', 'header' );
$header =~ s/VAR_TITLE/$title/g;
$header =~ s/VAR_SUMMARY/$summary/g;
return $header;
}
sub format_name {
# make "shield_level_1" => "Shield Level 1"
my ( $name ) = @_;
$name =~ s/_/ /g;
$name =~ s/(.)/\u$1/;
$name =~ s/( )(.)/$1\u$2/g;
return $name;
}
sub get_value {
my ( $xpath, $location ) = @_;
my $nodeset = $xpath->find("$location");
print "doing location $location\n";
my ($node) = $nodeset->get_nodelist;
my $value;
if ( $node ) {
my $attribute = XML::XPath::XMLParser::as_string( $node );
# get only the value of an attribute, XML::Xpath returns f.e. regeneration="3", we want just 3
if ( $attribute =~ /(?, $building, $upgrade\n";
push @{ $c_nodes{"$faction"} }, "$unit:$unit_pretty:$url:".($building || "").":".($upgrade || "");
if ( $building ) {
$graph_all -> add_node($unit, shape => 'house', color=> 'red', label => $unit_pretty, URL => $url, fontcolor => $svg_fontcolor );
$graph_buildings_units-> add_node($unit, shape => 'house', color=> 'red', label => $unit_pretty, URL => $url, fontcolor => $svg_fontcolor );
$graph_buildings -> add_node($unit, shape => 'house', color=> 'red', label => $unit_pretty, URL => $url, fontcolor => $svg_fontcolor );
}
elsif ( $upgrade ) {
$graph_all -> add_node($unit, shape => 'parallelogram', color=> 'green' , label => $unit_pretty, URL => $url, fontcolor => $svg_fontcolor);
##$graph_buildings_units -> add_node($unit, shape => 'parallelogram', color=> 'green' , label => $unit_pretty, URL => $url, fontcolor => $svg_fontcolor);
##$graph_buildings -> add_node($unit, shape => 'parallelogram', color=> 'green' , label => $unit_pretty, URL => $url, fontcolor => $svg_fontcolor);
}
# combat or work unit
else {
$graph_all -> add_node($unit, color => 'magenta', label => $unit_pretty, URL => $url, fontcolor => $svg_fontcolor);
$graph_buildings_units -> add_node($unit, color => 'magenta', label => $unit_pretty, URL => $url, fontcolor => $svg_fontcolor);
##$graph_buildings -> add_node($unit, color => 'magenta', label => $unit_pretty, URL => $url, fontcolor => $svg_fontcolor);
}
}
sub g_add_edge {
my ( $faction, $unit_from, $unit_to, $style, $relation ) = @_;
push @{ $c_edges{"$faction"} }, "$unit_from:$unit_to:$style:$relation";
push @{ $c_edges_from{"$faction:$unit_from"} }, "$unit_from:$unit_to:$style:$relation";
$edges_relation{"$faction:$unit_from:$unit_to:$relation"}=1;
}
sub check_multi_hops {
my ( $faction ) = @_;
# loop over all edges and check each
foreach my $edge ( @{$c_edges{"$faction"}} ) {
my ( $unit_from, $unit_to, $style, $relation ) = split(/:/, $edge );
print "#################edge_check1: $unit_from -> $unit_to\n";
# only check for Requirement and Upgrade-Requirement
if ( $relation =~ /Requirement/i ) {
# do recursion in check_edges:
if ( &check_edges( $faction, $unit_from, $unit_to, 0 ) ) {
$multi_hop{"$faction:$unit_from:$unit_to"}=1;
print "edge_check5: $faction:$unit_from:$unit_to =1\n";
}
}
# find multihop from building via upgrade to building to include in graphs without upgrades
# f.e. techndrome via advanced architecture to defense tower
elsif (
$relation eq "Upgrade" &&
$building{"$faction:$unit_from"}
) {
# in our example, check all edges from advanced architecture for links to buildings
REC: foreach my $edge ( @{$c_edges_from{"$faction:$unit_to"}} ) {
my ( $o_unit_from, $o_unit_to, $o_style, $o_relation ) = split(/:/, $edge );
if ( $building{ "$faction:$o_unit_to"} ) {
print "upgrade-multihop: $unit_from to $o_unit_to\n";
$multi_hop_upgrade{"$faction:$unit_from:$o_unit_to"}=1;
}
}
}
}
}
sub check_edges {
# recursive function to walk thru the branch of the tree and find a multi_hop
my ( $faction, $unit_from, $unit_to, $recursion_depth ) = @_;
$recursion_depth++;
my $found_multihop=0;
print "edge_check2: $faction, $unit_from, $unit_to, $recursion_depth\n";
REC: foreach my $edge ( @{$c_edges_from{"$faction:$unit_from"}} ) {
my ( $o_unit_from, $o_unit_to, $o_style, $o_relation ) = split(/:/, $edge );
print "edge_check3: $o_unit_from -> $o_unit_to\n";
if (
$unit_to eq $o_unit_to &&
# skip the record we're just checking
$recursion_depth > 1
) {
$found_multihop=1;
print "edge_check4: found an end at $o_unit_from to $unit_to\n";
last REC;
}
else {
# here &check_edges() recursivly calls itself until it finds something or $recursion_depth ==4:
if ( $recursion_depth < 4 ) {
$found_multihop = &check_edges( $faction, $o_unit_to, $unit_to, $recursion_depth );
}
}
last REC if ( $found_multihop );
}
return $found_multihop;
}
sub export_graphs {
my ( $faction ) = @_;
my ( @as_functions ) = split(/;/, $cfg->val('all', 'export_graph'));
foreach my $as_function ( @as_functions ) {
my $extension = $as_function;
if ( $extension =~ s/^as_// ) {
# all
my $graph_file ="$out_path/$images_path/$faction/${faction}_techtree_graph_all.$extension";
$graph_files{ "$faction:$extension:all" } = $graph_file;
open (OUTGRAPH, "> $graph_file") || die "cant write graph-file: $graph_file\n";
print OUTGRAPH $graph_all->$as_function;
close OUTGRAPH;
# buildings & units
$graph_file ="$out_path/$images_path/$faction/${faction}_techtree_graph_buildings.$extension";
$graph_files{ "$faction:$extension:buildings" } = $graph_file;
open (OUTGRAPH, "> $graph_file") || die "cant write graph-file: $graph_file\n";
print OUTGRAPH $graph_buildings->$as_function;
close OUTGRAPH;
# buildings
$graph_file ="$out_path/$images_path/$faction/${faction}_techtree_graph_buildings_units.$extension";
$graph_files{ "$faction:$extension:buildings_units" } = $graph_file;
open (OUTGRAPH, "> $graph_file") || die "cant write graph-file: $graph_file\n";
print OUTGRAPH $graph_buildings_units->$as_function;
close OUTGRAPH;
}
else {
die "ERROR: wrong function in ini-files: export_graph: $as_function\n\n";
}
}
}
sub build_clickable_map {
my ( $faction ) = @_;
my %cmapx;
$cmapx{'all'} = $graph_all->as_cmapx;
$cmapx{'buildings'} = $graph_buildings->as_cmapx;
$cmapx{'buildings_units'} = $graph_buildings_units->as_cmapx;
foreach my $map ('buildings', 'buildings_units', 'all') {
my $png = $graph_files{"$faction:png:map"};
my $graph_file = "$out_path/${faction}_techtree_clickable_map_${map}.html";
$graph_files{ "$faction:click_map:${map}" } = $graph_file;
open (OUTHTML, "> $graph_file") || die "cant write graph-file: $graph_file\n";
my $title = "Clickable Techtree Diagram for ".&format_name($faction)." - ".&format_name( $map );
push @all_html_pages, $graph_file;
$h_all_html_pages{"$faction:$map"} = "$graph_file:$title";
print OUTHTML &header($title);
print OUTHTML &choose_faction_html( $faction )."\n";
print OUTHTML &diagram_links_html( $faction )."
\n";
print OUTHTML "\n";
print OUTHTML $cmapx{$map};
print OUTHTML $map_legend;
close OUTHTML;
}
}
sub calc_cost_of_unit {
# calculate amount for morphed units, f.e. battemachine morphed from technician
# technician costs 150 gold
# battlemachine costs 150 gold, 300 wood with 40% discount = 90 gold + 180 wood
# = 240 gold + 180 wood total (food = 1 from battlemachine because technician is gone)
# note: the "discount" is actually a refund, you pay 150 gold at morphing to the battlemachine and get 60 back when it's done
my ( $u, $created_by_u, $method, $discount, $ignore_food ) = @_;
print "\ncalc_cost_of_unit: $u\n";
my ( $faction, $unit ) = split(/:/, $u );
my ( $cost, $cost_icon, $cost_icon_overview );
my ( $morph_cost, $morph_cost_icon, $morph_cost_icon_overview );
my $cost_icon_discount;
my %morph_cost_resource;
if ( $method eq "morph" ) {
foreach my $created_by_unit_tmp ( @{$created_by_unit{ "$faction:$created_by_u" }} ) {
my ( $o_created_by_u, $o_method, $o_discount ) = split(/:/, $created_by_unit_tmp );
# here calc_cost_of_unit recusivly calls itself:
( $morph_cost, $morph_cost_icon, $morph_cost_icon_overview ) = &calc_cost_of_unit("$faction:$created_by_u", $o_created_by_u, $o_method, $o_discount, "ignore_food" );
my (@res_amounts) = split(/,/, $morph_cost );
foreach my $res_amount ( @res_amounts ) {
my ( $res, $amount ) = split(/:/, $res_amount );
$morph_cost_resource{ $res } = $amount;
print "morph_cost_resource of $u res: $res = $amount\n";
}
}
}
# loop over @resource_order to get it in the proper order (medival programmig ;)
foreach my $resource_now ( @resource_order ) {
# part 1: stupid fix for thortotem (250 stone )+ thor (gold + wood) so loop again over all resources ( @resource_order )
foreach my $resource_requirement ( @{$c_resource_requirement{$u}}, @resource_order ) {
my ( $resource, $amount ) = split(/:/, $resource_requirement );
# ignore food, housing, energy if i have to calculate the cost of a unit morphed from
if (
!$ignore_food ||
$ignore_food && (
$resource eq "gold" ||
$resource eq "wood" ||
$resource eq "stone"
)
) {
my ($amount_with_discount, $amount_total);
# part 2: stupid fix for thortotem + thor: add cost of stone in this case:
if (
!$amount &&
$resource eq $resource_now
) {
if (
$morph_cost_resource{ $resource } &&
# and check it's not in @{c_resource_requirement}, this is really stupid but i don't come up with a good solution at this
# time of the day ;)
( join(":", @{$c_resource_requirement{$u}} ) !~ /$resource/ )
) {
$amount_total = $morph_cost_resource{ $resource_now };
my ( $cost_tmp, $cost_icon_tmp, $cost_icon_overview_tmp ) = &add_costs( $resource, $amount_total );
$cost .= $cost_tmp;
$cost_icon .= $cost_icon_tmp;
$cost_icon_overview .= $cost_icon_overview_tmp;
}
}
elsif ( $resource eq $resource_now ) {
# oly use 1st letter in uppercase
my $resource_char = $resource;
$resource_char =~ s/^(.).+/\u$1/;
if ( $method && $method eq "morph" ) {
# get discount/refund and add cost of unit morphed from
if ( $resource eq "gold" || $resource eq "wood" || $resource eq "stone" ) {
$amount_with_discount = int($amount * (100-$discount)/100);
}
else {
# no discount for food, energy, housing, ...
$amount_with_discount = $amount;
}
$amount_total = $amount_with_discount + ($morph_cost_resource{ $resource } || 0 );
$cost_icon_discount .= &html_icon_resource($resource, 16)." $amount_with_discount ";
}
else {
$amount_total = $amount;
}
my ( $cost_tmp, $cost_icon_tmp, $cost_icon_overview_tmp ) = &add_costs( $resource, $amount_total );
$cost .= $cost_tmp;
$cost_icon .= $cost_icon_tmp;
$cost_icon_overview .= $cost_icon_overview_tmp;
}
}
}
# handle f.e. thor where
if ( $morph_cost_resource{ $resource_now } ) {
}
}
# remove trailing ","
chop $cost;
my $cost_icon_total;
if ( $method && $method eq "morph" ) {
$cost_icon_total = "$cost_icon
(Cost for ".&format_name($unit);
if ( $discount ) {
$cost_icon_total .= " with $discount % discount = $cost_icon_discount";
}
else {
$cost_icon_total .= " = $cost_icon_discount";
}
$cost_icon_total .= "
+ cost for ".&link_unit($faction, $created_by_u)." = $morph_cost_icon )";
}
else {
$cost_icon_total= $cost_icon;
}
print "cost for $u: $cost\n";
return ( $cost, $cost_icon_total, $cost_icon_overview );
}
sub add_costs {
my ( $resource, $amount_total ) = @_;
print "amount_total: $resource: $amount_total \n";
my $cost .= "$resource:$amount_total,";
my $add_nbsp = "";
if ( $amount_total < 100 && ( $resource eq "gold" || $resource eq "wood" || $resource eq "stone" ) ) {
$add_nbsp = " ";
}
my $cost_icon .= "".&html_icon_resource($resource, 16)."$amount_total ";
my $cost_icon_overview .= "".&html_icon_resource($resource, 16)."$add_nbsp$amount_total ";
return ( $cost, $cost_icon, $cost_icon_overview );
}
sub html_icon {
my ( $u, $size ) = @_;
my ( $faction, $unit ) = split(/:/, $u );
return "";
}
sub html_icon_png {
my ( $u, $width, $height ) = @_;
my ( $faction, $unit ) = split(/:/, $u );
my $full_png = $icon{$u};
$full_png=~ s/\.[^.]+$//;
$full_png = $full_png."-full.png";
#print("==================> USING G3D image [$unit_full_image]\n");
return "";
#return "";
}
sub html_icon_command {
my ( $c, $size ) = @_;
my ( $faction, $unit, $command ) = split(/:/, $c );
if ( !$command_icon{$c} ) {
print "WARNING: no command icon for $c\n";
}
return "";
}
sub link_unit {
# create HTML-link to a unit
my ($faction, $unit, $link_text, $link_to_single_units, $file_only ) = @_;
# default to pretty unit name if no link_text passed
if ( !$link_text ) {
$link_text = &format_name($unit);
}
my $link;
if (
$cfg->val('all', 'link_to_single_units') ||
$link_to_single_units
) {
my $file = "${faction}_${unit}_full.html";
if ( $file_only ) {
$link = $file;
}
else {
$link = "$link_text";
}
}
else {
my $file = "${faction}_techtree.html#${unit}_full";
if ( $file_only ) {
$link = $file;
}
else {
$link = "$link_text";
}
}
return $link;
}
sub link_attack_and_armor_types {
my ( $link_to ) = @_;
my $html = "".&format_name($link_to)."" if ( $link_to );
return $html;
}
sub show_attack {
my ( $c, $max_strength_vs_land, $max_strength_vs_land_var, $max_strength_vs_air, $max_strength_vs_air_var, $max_range, $max_move_speed, $skill_on_hold_position ) = @_;
my ( $faction, $unit, $command ) = split(/:/, $c );
my $command_pretty = &format_name( $command );
my $used_on_hold_position=0;
my $target;
my $full_attack_tmp = "
Attack Command: $command_pretty ".&html_icon_command( $c, 32 )." | \n";
my $skill = $attack_skill{ $c };
# attacks have own move_skills (charge)
my $move_skill = $move_skill{ $c };
my $s = "$faction:$unit:$skill";
my $ms = "$faction:$unit:$move_skill" if ( $move_skill);
my $skill_short = $skill;
$skill_short =~ s/_skill$//;
my $skill_pretty = &format_name( $skill_short );
if ( $attack_land{ $s } ) {
if ( $attack_strenght{ $s } > $max_strength_vs_land ) {
$max_strength_vs_land = $attack_strenght{ $s };
$max_strength_vs_land_var = $attack_var{ $s };
}
}
if ( $attack_air{ $s } ) {
if ( $attack_strenght{ $s } > $max_strength_vs_air ) {
$max_strength_vs_air = $attack_strenght{ $s };
$max_strength_vs_air_var = $attack_var{ $s };
}
}
if (
$attack_land{ $s } &&
$attack_air{ $s }
) {
$target .= "Ground and air";
$full_attack_tmp .= "Target: $target units \n";
}
elsif (
$attack_air{ $s }
) {
$target .= "Only air";
$full_attack_tmp .= "Target: $target units \n";
}
elsif (
$attack_land{ $s }
) {
$target .= "Only ground";
$full_attack_tmp .= "Target: $target units \n";
}
if ( $attack_range{ $s } > $max_range ) {
$max_range = $attack_range{ $s };
}
$full_attack_tmp .= "Strength: $attack_strenght{ $s }+-$attack_var{ $s } \n";
# show attack as range ( 100-200)
#$full_attack_tmp .= "Strength: ".($attack_strenght{ $s }-$attack_var{ $s })."-".($attack_strenght{ $s }+$attack_var{ $s })." \n";
#$full_attack_tmp .= "Strength-Variance: ".$attack_var{ $s }." \n";
#$full_attack_tmp .= "Strength: ".$attack_strenght{ $s }." \n";
#$full_attack_tmp .= "Strength-Variance: ".$attack_var{ $s }." \n";
$full_attack_tmp .= "Range: ".$attack_range{ $s }." \n";
if ( $splash{ $s } ) {
$full_attack_tmp .= "Splash-Radius: $splash_radius{ $s } \n";
$full_attack_tmp .= "Splash also damages own units! \n" if ($splash_damage_all{ $s });
}
$full_attack_tmp .= "Type: ".&link_attack_and_armor_types($attack_type{ $s })." \n";
$full_attack_tmp .= "Attack Speed: ".$speed{ $s }." \n";
$full_attack_tmp .= "Start Time: ".$attack_start_time{ $s }." \n";
$full_attack_tmp .= "Energy-Cost: ".$ep_cost{ $s }." \n" if ( $ep_cost{ $s });
if ( $skill_on_hold_position ) {
my ( $s, $requirement ) = split(/;/, $skill_on_hold_position );
if ( $skill eq $s ) {
$used_on_hold_position="true";
$full_attack_tmp .= "This Attack Skill is used on \"Hold Position\" \n";
$full_attack_tmp .= "(\"Hold Position\" requires ".&link_unit($faction, $requirement).") \n" if ( $requirement);
}
}
if ( $ms) {
print "speed: $speed{ $ms } of $ms\n" ;
if ( $speed{ $ms } > $max_move_speed ) {
$max_move_speed = $speed{ $ms };
$full_attack_tmp .= "Special Move Speed: ".$speed{ $ms }." (".&format_name( $move_skill).") \n";
}
}
$full_attack_tmp .= " |
\n";
return (
$full_attack_tmp,
$max_strength_vs_land,
$max_strength_vs_land_var,
$max_strength_vs_air,
$max_strength_vs_air_var,
$max_range,
$max_move_speed,
$attack_strenght{ $s },
$attack_var{ $s },
$attack_range{ $s },
$attack_type{ $s },
$speed{ $s },
$attack_start_time{ $s },
$ep_cost{ $s },
$used_on_hold_position,
$target,
);
}
sub html_icon_resource {
# return for resource (gold, wood, stone, ...)
my ($resource, $size) = @_;
return "";
}
sub load_tip_files {
foreach my $faction_path ( @factions ) {
my $faction = $faction_path;
$faction =~ s/.+\///;
my $faction_pretty = &format_name( $faction );
my $tip_file = "$faction_path/lang/${faction}_en.lng";
print "tip-file: $tip_file\n";
open (TIPS, "< $tip_file") || die "can't read tip-file: $tip_file\n";
while (my $line =) {
next if ( $line =~ /^;/ );
if ( $line =~ /(.+)=(.+)/ ) {
my $name = $1;
my $key = $2;
$tips{ $name } = $key;
}
}
close TIPS;
}
}
sub choose_faction_html {
my ( $faction ) = @_;
my $tmp_links = $all_faction_links_overview;
if ( $faction ) {
my $faction_pretty = &format_name( $faction );
$tmp_links =~ s/>($faction_pretty)>$1<\/I>;
}
return "Choose faction: $tmp_links
\n";
}
sub diagram_links_html {
my ( $faction ) = @_;
my $graph_file;
my $html="
Techtree Diagrams: ";
for my $type ('buildings', 'buildings_units', 'all') {
#if ( $graph_files{ "$faction:click_map:$type" } ) {
if ( $cfg->val('all', 'build_clickable_map') ) {
$graph_file = "${faction}_techtree_clickable_map_${type}.html";
#$graph_file = $graph_files{ "$faction:click_map:$type" };
}
elsif ( $graph_files{ "$faction:svg:$type" } ) {
$graph_file = "${faction}_techtree_graph_${type}.svg";
}
$graph_file =~ s/.+\///;
$html .= "".&format_name($type)." |\n";
}
chop $html;
chop $html;
chop $html;
$html .="
\n";
return $html;
}
sub create_armor_vs_attack {
my ( $pack_file ) = @_;
my $xpath = XML::XPath->new( $pack_file );
my $armor_types_xml = $xpath->find("/tech-tree/armor-types/armor-type");
foreach my $armor_type ( $armor_types_xml->get_nodelist ) {
XML::XPath::XMLParser::as_string( $armor_type ) =~ /name=\"(.+?)\"/;
my $armor_type_tmp = $1;
push @armor_types, $armor_type_tmp;
print "armor-type: $armor_type_tmp\n";
}
my $attack_types_xml = $xpath->find("/tech-tree/attack-types/attack-type");
foreach my $attack_type ( $attack_types_xml->get_nodelist ) {
XML::XPath::XMLParser::as_string( $attack_type ) =~ /name=\"(.+?)\"/;
my $attack_type_tmp = $1;
push @attack_types, $attack_type_tmp;
print "attack-type: $attack_type_tmp\n";
}
my $damage_multipliers_xml = $xpath->find("/tech-tree/damage-multipliers/damage-multiplier");
foreach my $damage_multiplier_tmp ( $damage_multipliers_xml->get_nodelist ) {
XML::XPath::XMLParser::as_string( $damage_multiplier_tmp ) =~ /attack=\"(.+?)\" armor=\"(.+?)\" value=\"(.+?)\"/;
my $attack = $1;
my $armor = $2;
my $value = $3;
$damage_multiplier{"$attack:$armor"} = $value;
print "damage_multiplier for $attack vs $armor = $value\n";
}
my $table = "";
$table .= " | \n";
foreach my $armor ( @armor_types ) {
$table .= " ".format_name($armor)." | \n";
}
$table .= "
\n";
foreach my $attack ( @attack_types ) {
$table .= " ".&format_name( $attack)." | \n";
foreach my $armor ( @armor_types ) {
my $mul = ($damage_multiplier{"$attack:$armor"} || 1);
if ( $mul > 1 ) {
#$table .= "";
$table .= " | ";
}
elsif ( $mul < 1 ) {
#$table .= " | ";
$table .= " | ";
}
else {
$table .= " | ";
}
$table .= " ".$mul;
$table .= " | ";
}
$table .= "
\n";
}
$table .= "
\n";
my $html_page = "attack_and_armor_types.html";
my $outfile = "$out_path/$html_page";
open (HTML, "> $outfile") || die "can't write outfile: $outfile\n";
my $title = "Damage Multipliers for Attack Types versus Armor Types";
push @special_html_pages, "$html_page;$title";
print HTML &header($title);
print HTML "Values larger than 1 mean more damage, smaller than 1 less damage.
\n";
print HTML $table;
my $pack_file_short = $pack_file;
$pack_file =~ s/.+\///;
print HTML "
This information is extracted from $pack_file.
\n";
print HTML $footer;
close HTML;
}
sub do_air_ground {
# show if unit is on field air,ground or both
my ( $u ) = @_;
my $overview_tmp .= "
";
my $full_tmp .= " | Movement Type: | ";
# air + land means land (f.e. tech archer)
# units can't be both, although that would seem ok for the genie
if (
$land_unit{ $u } ||
(
$air_unit{ $u } &&
$land_unit{ $u }
)
) {
$overview_tmp .= "Ground";
$full_tmp .= "Ground Unit";
}
elsif ( $air_unit{ $u } ) {
$overview_tmp .= "Air";
$full_tmp .= "Air Unit";
}
else {
print "WARNING: unit neither air nor ground: $u\n";
}
$overview_tmp .= " | \n";
$full_tmp .= "\n";
return ( $overview_tmp, $full_tmp );
}
sub show_special_pages {
return "$special_pages
";
}
sub do_upgrade_benefits {
# show the benefit of an upgrade
my ( $u ) = @_;
my $upgrade_benefits="";
my $upgrade_benefits_html="";
$upgrade_benefits_html .= "
Increase Hitpoints: | +".$max_hp{$u}." |
\n" if ( $max_hp{$u} );
$upgrade_benefits_html .= "Increase Energy-Points: | +".$max_ep{$u}." |
\n" if ( $max_ep{$u} );
$upgrade_benefits_html .= "Increase Sight: | +".$sight{$u}." |
\n" if ( $sight{$u} );
$upgrade_benefits_html .= "Increase Attack Strength: | +".$attack_strenght{$u}." |
\n" if ( $attack_strenght{$u} );
$upgrade_benefits_html .= "Increase Attack Range: | +".$attack_range{$u}." |
\n" if ( $attack_range{$u} );
$upgrade_benefits_html .= "Increase Armor: | +".$armor{$u}." |
\n" if ( $armor{$u} );
$upgrade_benefits_html .= "Increase Move: | +".$move_speed{$u}." |
\n" if ( $move_speed{$u} );
$upgrade_benefits_html .= "Increase Production Speed: | +".$production_speed{$u}." |
\n" if ( $production_speed{$u} );
$upgrade_benefits = $upgrade_benefits_html;
# for overview remove HTML-tags
$upgrade_benefits =~ s/<\/?TD>//gi;
$upgrade_benefits =~ s///gi;
$upgrade_benefits =~ s/<\/TR>/, /gi;
$upgrade_benefits =~ s/Increase //gi;
# remove last coma
$upgrade_benefits =~ s/, $//g;
# remove trailing whitespace
$upgrade_benefits =~ s/\s+$//g;
return ( $upgrade_benefits, $upgrade_benefits_html );
}