mirror of
https://github.com/glest/glest-source.git
synced 2025-02-24 19:52:25 +01:00
2708 lines
92 KiB
Perl
Executable File
2708 lines
92 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
|
|
# script to create HTML-pages and diagrams from the glest-factions techtree
|
|
# 20110120, bugs & feedback to olaus@rupp.de
|
|
# Copyright 2011 olaus
|
|
# Copyright 2012-2016 olaus & MegaGlest Team
|
|
# license: GPLv3 or newer
|
|
|
|
our $version = "0.8.1 beta";
|
|
|
|
# This tool requires jquery and the jquery dataTables plugin (run setupDeps.sh which uses curl to try to download these into the media folder).
|
|
# These are NOT required to run the script but are used to display the resulting html.
|
|
|
|
# general comments for running:
|
|
# - developed on ubuntu linux 10.04 and with modules from ubuntu (install with "apt-get install libgraphviz-perl libconfig-inifiles-perl libxml-xpath-perl perlmagick")
|
|
# - on non-ubuntu systems install "graphviz" using your package manager and try to also find the right perl modules with it.
|
|
# - if the package manager doesn't work install the needed perl modules using "cpan" on the command line: (untested):
|
|
# cpan> install XML::XPath;
|
|
# cpan> install GraphViz;
|
|
# cpan> install Config::IniFiles;
|
|
#
|
|
# - adjust the paths in the .ini-file to your system and run with f.e. "convert_faction_xml2html.pl mg.ini"
|
|
# - won't work on windows without adjustments (search for "system", at least ... ) and i guess some of the modules used aren't easily available for active-state-perl (graphviz also runs on windows).
|
|
|
|
# general comments for changing the code:
|
|
# - as far as possible i used "pidgin-perl" and tried to avoid complicated functions and data-structures. so hopefully anybody with bare programming skills can adopt this code to his needs
|
|
# - it runs with "use strict" and -w without any warnings. this makes coding a bit more complicated but saves lots of time in the long run, get used to it ;)
|
|
# - watch out for singular & plural in the variable-names, $harvested_resources{} ne $harvested_resource
|
|
# - if you need to read some new stuff from the XML-files, google the xpath-documentation. check if it's single- or multi-valued. use xpath.pl to check the location.
|
|
# - if you want to rewrite this in your favorite language i recommend your local xpath-module, then you can reuse the xpath-locations from this script
|
|
# - uses jquery.com and datatables.net for table sorting and searching. i recommend the firefox add-onswebdeveloper and firebug if touching these
|
|
|
|
# TODO:
|
|
# - requirement page per faction with all buildings and producing units and the units they produce (footnotes for requirements) (collect in $production{ $u } and $production_units{ $u }
|
|
|
|
# DONE:
|
|
# 0.8
|
|
# - bugfix: missing requirements in building & units diagrams
|
|
# - included all needed files in media-directory
|
|
# - reworker directory-structure in generated html-directory (best to delete the old one before upgrading!)
|
|
# - changed mg.ini and style.css to mg-webdesign (doesn't work with the wide tables because tiles are just made for narrow content in the middle)
|
|
# 0.7
|
|
# - big all and everything-table
|
|
# 0.6:
|
|
# - add png images rendered by g3d_viewer (by softcoder, thanks)
|
|
# 0.5:
|
|
# - allow relative & absolut path at the same time (relative can't start with / )
|
|
# - show what levels (f.e. elite after x kills) add to sight, armor, ...
|
|
# - show what available upgrades add to stats in each unit
|
|
# 0.4:
|
|
# - show updates available for each unit
|
|
# - fix paths with spaces
|
|
# 0.3
|
|
# - @all_html_pages with with page-title, sort by faction, special pages (keys & armor/attack)
|
|
# - fixed morph cost of thor/thortotem
|
|
# - pass http://validator.w3.org
|
|
# - images path per unit for romans (5 times guard.bmp with different content)
|
|
# - <NOBR> in cost
|
|
# - included levels
|
|
|
|
# maybe someday ...
|
|
# - compare units like http://www.imaging-resource.com/IMCOMP/COMPS01.HTM
|
|
# - support GAE skills (patrol, guard)
|
|
# - units commands in seperate table
|
|
# - links to XML-files
|
|
# - print -> &log
|
|
# - generate some descriptive text for each unit, like "this is the unit with the most hitpoints/damage to air units/armor/movement speed/... of the tech faction"
|
|
# - diff feature (CGI?) to show what changed in units if moving f.e. from vanila glest 3.2 to MG 3.4
|
|
# - make overview tables sortable (javascript?)
|
|
# - overview tables without border but different colors in odd/even rows
|
|
# - list of units this one is strong/weak against (via armor- and attack-types)
|
|
# - top-lists over all factions (units with most hit points, damage, ...)
|
|
# - calculate a "bang for the buck" for 10 units including all cost for upgrades, buildings, ...
|
|
# - multilanguage (use more icons, lng-files but unit names aren't multilanguage anyway)
|
|
# - import bitmap-icons in SVG (doesn't work with perls graphviz-module, would need to parse and change SVG)
|
|
# - map symbology below diagram
|
|
# - single pages for units with animated gif, link to XML, mini-diagram of techtree just for this unit
|
|
# - convert bmp-icons to png
|
|
# - create PDF-handbook of all units
|
|
|
|
# usefull for converting HTML-colors: http://www.yafla.com/yaflaColor/ColorRGBHSL.aspx
|
|
|
|
# strange stuff in the techtrees:
|
|
# - persian magician splash radius 0?
|
|
# - tech upgrades piercing/blade weapon don't work for battle machine?
|
|
# - f.e. battle machine with "hold" will only attack land units
|
|
# - workers are able to help a technician build an aerodrome faster. is that wanted?
|
|
|
|
####################################################################
|
|
|
|
our $cfg;
|
|
my $cfg_file;
|
|
|
|
if ( $cfg_file = shift @ARGV ) {
|
|
|
|
if ( ! -e $cfg_file ) {
|
|
die "cfg_file not existing: $cfg_file\n";
|
|
}
|
|
}
|
|
else {
|
|
$cfg_file ="megapack.ini";
|
|
}
|
|
|
|
if ( ! -e $cfg_file ) {
|
|
die "\nusage: $0 [megapack.ini]\n\n";
|
|
}
|
|
|
|
$cfg = new Config::IniFiles( -file => "./$cfg_file", -allowcontinue => 1 );
|
|
|
|
|
|
use strict;
|
|
use XML::XPath;
|
|
use XML::XPath::XMLParser;
|
|
use GraphViz;
|
|
use Config::IniFiles;
|
|
use FindBin;
|
|
use File::Spec;
|
|
use Cwd;
|
|
use File::Glob ':glob';
|
|
#use Image::Resize;
|
|
use Image::Magick;
|
|
|
|
BEGIN {
|
|
$ENV{APP_ROOT} = Cwd::realpath(File::Spec->rel2abs($FindBin::Bin)) ;
|
|
}
|
|
|
|
our $use_relative_paths = $cfg->val( 'all', 'relative_paths');
|
|
our $generate_g3d_images = $cfg->val( 'all', 'generate_g3d_images');
|
|
|
|
our $debug = $cfg->val( 'all', 'debug');
|
|
|
|
our $glest_version = $cfg->val( 'all', 'version');
|
|
|
|
our $factions_path=$cfg->val( 'files' , 'factions_path');
|
|
|
|
|
|
$factions_path = "$ENV{APP_ROOT}/$factions_path" if ( $use_relative_paths && $factions_path !~ /^\//);
|
|
our $g3dviewer_path=$cfg->val( 'files' , 'g3dviewer_path');
|
|
$g3dviewer_path = "$ENV{APP_ROOT}/$g3dviewer_path" if ( $use_relative_paths );
|
|
|
|
our $resources_path=$cfg->val( 'files' , 'resources_path');
|
|
$resources_path = "$ENV{APP_ROOT}/$resources_path" if ( $use_relative_paths && $resources_path !~ /^\// );
|
|
our $out_path=$cfg->val( 'files' , 'out_path');
|
|
$out_path = "$ENV{APP_ROOT}/$out_path" if ( $use_relative_paths && $out_path !~ /^\// );
|
|
|
|
our $pack_file=$cfg->val( 'files' , 'pack_file');
|
|
$pack_file = "$ENV{APP_ROOT}/$pack_file" if ( $use_relative_paths && $pack_file !~ /^\// );
|
|
|
|
|
|
our $units_path=$cfg->val( 'files' , 'units_path');
|
|
our $upgrades_path=$cfg->val( 'files' , 'upgrades_path');
|
|
our $images_path=$cfg->val( 'files' , 'images_path');
|
|
|
|
our $glestkeys=$cfg->val( 'files' , 'glestkeys');
|
|
$glestkeys = "$ENV{APP_ROOT}/$glestkeys" if ( $use_relative_paths && $glestkeys !~ /^\// );
|
|
|
|
our $summary = $cfg->val('files', 'summary');
|
|
|
|
our $svg_fontcolor = $cfg->val( 'style', 'svg_fontcolor');
|
|
|
|
our @armor_types;
|
|
our @attack_types;
|
|
|
|
our @resource_order = split(/:/, $cfg->val( 'style', 'resource_order') );
|
|
|
|
my $now_string = localtime;
|
|
my $me = $0;
|
|
$me =~ s/^.+\///;
|
|
|
|
our $footer=$cfg->val( 'style', 'footer');
|
|
our $map_legend = $cfg->val('style', 'map_legend');
|
|
|
|
#$footer =~ s/VAR_CREATED_BY/<I><A HREF=\"http:\/\/rupp.de\/glest\/\">$me<\/A><\/I>, version: <I>$version<\/I>, using config-file: <I>$cfg_file<\/I>, on: <I>$now_string<\/I> /;
|
|
# ^ timestamp should be in the one common footer
|
|
$footer =~ s/VAR_CREATED_BY/<I><A HREF=\"http:\/\/rupp.de\/glest\/\">$me<\/A><\/I>, version: <I>$version<\/I>, using config-file: <I>$cfg_file<\/I>/;
|
|
|
|
our $level_hp = $cfg->val('all', 'level_hp');
|
|
our $level_ep = $cfg->val('all', 'level_ep');
|
|
our $level_sight = $cfg->val('all', 'level_sight');
|
|
our $level_armor = $cfg->val('all', 'level_armor');
|
|
|
|
|
|
$|=1;
|
|
|
|
if ( ! -e $factions_path ) {
|
|
die "ERROR: cant find factions_path: $factions_path, check $cfg_file\n";
|
|
}
|
|
|
|
if ( ! -e $resources_path ) {
|
|
die "ERROR: cant find resources_path: $resources_path, check $cfg_file\n";
|
|
}
|
|
|
|
mkdir $out_path;
|
|
mkdir "$out_path/images";
|
|
if ( ! -w $out_path ) {
|
|
die "cant find out_path: $out_path or no write permission\n";
|
|
}
|
|
|
|
|
|
|
|
#our @factions = bsd_glob("$factions_path/magi*");
|
|
#our @factions = bsd_glob("$factions_path/norsemen");
|
|
#our @factions = bsd_glob("$factions_path/tec*");
|
|
#our @factions = bsd_glob("$factions_path/roma*");
|
|
#our @factions = bsd_glob("$factions_path/egy*");
|
|
our @factions = bsd_glob("$factions_path/*");
|
|
|
|
our @resources = bsd_glob( "$resources_path/*");
|
|
|
|
our @all_html_pages;
|
|
our %h_all_html_pages;
|
|
our @special_html_pages;
|
|
push @special_html_pages, "compare.html;Compare Units";
|
|
push @special_html_pages, "all.html;All Units of all Factions";
|
|
|
|
our %damage_multiplier;
|
|
|
|
our %icon;
|
|
our %max_hp;
|
|
our %max_ep;
|
|
our %regeneration;
|
|
our %regeneration_ep;
|
|
our %building;
|
|
our %armor;
|
|
our %armor_type;
|
|
our %sight;
|
|
our %time;
|
|
our %height;
|
|
|
|
our %upgrade;
|
|
our %upgrade_effects;
|
|
our %upgrades_for;
|
|
our %move_speed;
|
|
our %production_speed;
|
|
|
|
our %worker;
|
|
our %combat;
|
|
our %air_unit;
|
|
our %land_unit;
|
|
|
|
our %created_by_unit;
|
|
our %c_unit_allows;
|
|
our %c_unit_requires;
|
|
our %c_all;
|
|
our %c_resource_requirement;
|
|
our %c_resource_store;
|
|
our %c_harvested_resources;
|
|
our %max_load;
|
|
our %hits_per_unit;
|
|
our %c_unit_requirements;
|
|
our %c_upgrade_requirements;
|
|
|
|
our %u_levels;
|
|
|
|
our %graph_files;
|
|
our %c_nodes;
|
|
our %c_edges;
|
|
our %c_edges_from;
|
|
our %edges_relation;
|
|
our %multi_hop;
|
|
our %multi_hop_upgrade;
|
|
|
|
# for storing skills:
|
|
our %c_skill;
|
|
our %c_command;
|
|
our %speed;
|
|
our %ep_cost;
|
|
our %skill_type;
|
|
our %attack_range;
|
|
our %attack_strenght;
|
|
our %attack_var;
|
|
our %attack_type;
|
|
our %attack_start_time;
|
|
our %attack_land;
|
|
our %attack_air;
|
|
our %splash;
|
|
our %splash_radius;
|
|
our %splash_damage_all;
|
|
|
|
# for storing commands:
|
|
our %commands_of_unit;
|
|
our %command_type;
|
|
our %command_icon;
|
|
our %morph_skill;
|
|
our %morph_unit;
|
|
our %morph_discount;
|
|
|
|
our %move_skill;
|
|
our %move_loaded_skill;
|
|
our %attack_skill;
|
|
our %repair_skill;
|
|
our %build_skill;
|
|
our %produce_skill;
|
|
our %upgrade_skill;
|
|
our %harvest_skill;
|
|
|
|
our %produce_unit;
|
|
our %c_produced_units;
|
|
our %c_repaired_units;
|
|
|
|
our $graph_all;
|
|
our $graph_buildings;
|
|
our $graph_buildings_units;
|
|
|
|
our %tips;
|
|
|
|
# create page with all keys
|
|
if ( -f $glestkeys ) {
|
|
&create_glestkey_page();
|
|
}
|
|
|
|
if ( $cfg->val('files', 'load_tips') ) {
|
|
&load_tip_files();
|
|
}
|
|
|
|
if ( $pack_file ) {
|
|
&create_armor_vs_attack( $pack_file );
|
|
}
|
|
|
|
################################################
|
|
|
|
# built HTML for selecting faction
|
|
our $all_faction_links_overview ="";
|
|
foreach my $faction_path ( @factions ) {
|
|
my $faction = $faction_path;
|
|
$faction =~ s/.+\///;
|
|
my $faction_pretty = &format_name( $faction );
|
|
$all_faction_links_overview .= " <A HREF=${faction}_overview.html>$faction_pretty</a> | \n";
|
|
}
|
|
# remove last pipe
|
|
$all_faction_links_overview =~ s/ \| $//;
|
|
|
|
# built HTML-links for special pages:
|
|
our $special_pages ="Special Pages: ";
|
|
foreach my $page_tmp ( @special_html_pages ) {
|
|
my ( $page, $title ) = split(/;/, $page_tmp );
|
|
$page =~ s/$out_path\///;
|
|
$special_pages .= "<A HREF=\"$page\">$title</a> |\n";
|
|
}
|
|
# remove last pipe
|
|
chop $special_pages;
|
|
chop $special_pages;
|
|
chop $special_pages;
|
|
|
|
################################################
|
|
# copy resource images
|
|
mkdir "$out_path/images";
|
|
mkdir "$out_path/images/resources";
|
|
foreach my $resource_path ( @resources ) {
|
|
my $resource = $resource_path;
|
|
$resource =~ s/.+\///;
|
|
system "cp $resource_path/images/$resource.bmp $out_path/images/resources";
|
|
}
|
|
|
|
################################################
|
|
# read all units and draw graphs
|
|
foreach my $faction_path ( @factions ) {
|
|
|
|
my $faction = $faction_path;
|
|
$faction =~ s/.+\///;
|
|
my $faction_pretty = &format_name( $faction );
|
|
|
|
#my $graph = GraphViz->new( bgcolor => "0.5666,0,0.086", layout => "twopi" , overlap => "false");
|
|
#my $graph = GraphViz->new( bgcolor => "0.5666,0,0.086", layout => "fdp", concentrate => 1 , overlap => 0, epsilon => 0.01 );
|
|
|
|
$graph_all = GraphViz->new( bgcolor => "0.5666,0,0.086", layout => "dot", rankdir => 0 , overlap => 'false', concentrate => 1, epsilon => 0.01 );
|
|
# layout twopi, doesn't "bend" edges around nodes so the result doesn't look as good as it could
|
|
#$graph_all = GraphViz->new( bgcolor => "0.5666,0,0.086", layout => "twopi", rankdir => 0 , overlap => 'false', concentrate => 0, epsilon => 0.01 );
|
|
$graph_buildings = GraphViz->new( bgcolor => "0.5666,0,0.086", layout => "dot", rankdir => 0 , overlap => 'false', concentrate => 1, epsilon => 0.01 );
|
|
$graph_buildings_units = GraphViz->new( bgcolor => "0.5666,0,0.086", layout => "dot", rankdir => 0 , overlap => 'false', concentrate => 1, epsilon => 0.01 );
|
|
|
|
# good, from left to right:, not exactly 16:9 ;)
|
|
#my $graph = GraphViz->new( bgcolor => "0.5666,0,0.086", layout => "dot", rankdir => 1 , overlap => 0 );
|
|
|
|
|
|
|
|
print ("doing faction: $faction in path: <$faction_path>/<$units_path>\n") if ($debug);
|
|
|
|
mkdir ("$out_path/$images_path");
|
|
mkdir ("$out_path/$images_path/${faction}");
|
|
|
|
#system "cp $faction_path/loading_screen.jpg $out_path/$images_path/${faction}";
|
|
|
|
# read XML-files for all units
|
|
chdir ("$faction_path/$units_path");
|
|
opendir(UNITS, "." ) || die "cant open directory $faction_path/$units_path\n";
|
|
my @units = grep { !/\./ } readdir(UNITS);
|
|
closedir(UNITS);
|
|
|
|
foreach my $unit ( @units ) {
|
|
|
|
push @{ $c_all{"$faction"} }, $unit;
|
|
|
|
my $u = "$faction:$unit";
|
|
|
|
print "reading unit: $faction:$unit in $faction_path\n" if ( $debug );
|
|
my $unit_file ="$faction_path/$units_path/$unit/$unit.xml";
|
|
|
|
mkdir ("$out_path/$images_path/${faction}/$unit");
|
|
|
|
my ( $icon ) = &read_unit( $unit_file, $faction, $faction_path, $unit);
|
|
|
|
system "cp $faction_path/$units_path/$unit/images/$icon $out_path/$images_path/${faction}/$unit";
|
|
|
|
if ($generate_g3d_images == 1) {
|
|
my $full_png = $icon;
|
|
$full_png=~ s/\.[^.]+$//;
|
|
|
|
# use the height from the units XML-file for a rough guess on zooming the model to the right size
|
|
my $unit_height = $height{ $u };
|
|
# max to 6
|
|
$unit_height = 6 if ( $unit_height > 6 );
|
|
|
|
my $zoom = $cfg->val('style', 'unit_png_unit_zoom') - ( $unit_height * 0.15 );
|
|
|
|
# set buildings to config-value because some have just height=2 in XML
|
|
$zoom = $cfg->val('style', 'unit_png_building_zoom') if ( $building{ $u } );
|
|
|
|
my $save_as = "$out_path/$images_path/${faction}/$unit/$full_png-full.png";
|
|
|
|
if ( ! -e $save_as ) {
|
|
my $g3d_generate_cmd = "$g3dviewer_path --load-unit=$faction_path/$units_path/$unit,stop_skill,attack_skill --load-model-animation-value=0.5 --load-particle-loop-value=8 --zoom-value=$zoom --rotate-x-value=".$cfg->val('style', 'unit_png_rotate_x_value')." --rotate-y-value=".$cfg->val('style', 'unit_png_rotate_y_value')." --auto-screenshot=disable_grid,saveas-$save_as";
|
|
|
|
print "generating G3D using: [$g3d_generate_cmd]\n" if ( $debug );
|
|
my $ret = `$g3d_generate_cmd`;
|
|
print "g3d_generate said: $ret\n";
|
|
|
|
# if we need to resize the image the code below does it
|
|
#
|
|
my $image = new Image::Magick;
|
|
$image->Read($save_as);
|
|
#$image->Resize(
|
|
#width =>$cfg->val('style', 'unit_png_width'),
|
|
#height =>$cfg->val('style', 'unit_png_height')
|
|
#);
|
|
$image->Trim();
|
|
$image->Write($save_as);
|
|
#exit;
|
|
|
|
}
|
|
else {
|
|
print "g3d image already exist, skipping: $save_as\n";
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
# read XML-files for all upgrades
|
|
chdir ("$faction_path/$upgrades_path");
|
|
opendir(UPGRADES, "." ) || die "cant open directory $faction_path/$upgrades_path\n";
|
|
my @upgrades = grep { !/\./ } readdir(UPGRADES);
|
|
closedir(UPGRADES);
|
|
|
|
foreach my $upgrade ( @upgrades ) {
|
|
push @{ $c_all{"$faction"} }, $upgrade;
|
|
|
|
print "reading upgrade: $faction:$upgrade in $faction_path\n" if ( $debug );
|
|
my $upgrade_file ="$faction_path/$upgrades_path/$upgrade/$upgrade.xml";
|
|
|
|
mkdir ("$out_path/$images_path/${faction}/$upgrade");
|
|
|
|
my ( $icon ) = &read_unit( $upgrade_file, $faction, $faction_path, $upgrade );
|
|
|
|
system "cp $faction_path/$upgrades_path/$upgrade/images/$icon $out_path/$images_path/${faction}/$upgrade";
|
|
|
|
}
|
|
|
|
# don't clutter the diagram with direct links (mostly "requirement") if there's an indirect link with 2 hops.
|
|
# f.e. don't show a link that the technodrom is a requirement of the defense-tower because there's a link from
|
|
# technodrom to advanced architecture and a link from there to defense tower.
|
|
&check_multi_hops($faction);
|
|
|
|
# now the graphviz-nodes are set, do the edges
|
|
foreach my $edge ( @{$c_edges{"$faction"}} ) {
|
|
|
|
my ( $unit_from, $unit_to, $style, $relation ) = split(/:/, $edge );
|
|
|
|
print "dedge: deciding edge for $faction:$unit_from:$unit_to - $relation -style: $style\n";
|
|
|
|
|
|
# only show requirement-link of there's no build, morph or produce link
|
|
# otherwise graphviz would show a dotted line where a solid one makes more sense
|
|
if (
|
|
(
|
|
$relation eq "Requirement" ||
|
|
$relation eq "Upgrade-Requirement"
|
|
) && (
|
|
$edges_relation{"$faction:$unit_from:$unit_to:Build"} ||
|
|
$edges_relation{"$faction:$unit_from:$unit_to:Morph"} ||
|
|
$edges_relation{"$faction:$unit_from:$unit_to:Produce"}
|
|
)
|
|
) {
|
|
}
|
|
else {
|
|
|
|
my $dont_link_in_all=0;
|
|
if (
|
|
$multi_hop{"$faction:$unit_from:$unit_to"} &&
|
|
$relation ne "Build" &&
|
|
$relation ne "Morph" &&
|
|
$relation ne "Produce"
|
|
) {
|
|
$dont_link_in_all=1;
|
|
print "dedge: not showing edge $faction:$unit_from:$unit_to\n";
|
|
}
|
|
|
|
|
|
if ( $relation eq "Requirement" && $building{"$faction:$unit_to"} ) {
|
|
$graph_all -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor ) if (!$dont_link_in_all);
|
|
|
|
# only draw in the buildings-only-map if the requirement is also a building (f.e. in egypt a priest is needed for the obelisk)
|
|
if ( $building{"$faction:$unit_from"} ) {
|
|
$graph_buildings -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor );
|
|
}
|
|
}
|
|
elsif (
|
|
$relation eq "Requirement" ||
|
|
$relation eq "Upgrade-Requirement"
|
|
) {
|
|
$graph_all -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor ) if (!$dont_link_in_all);
|
|
print "dedge: SHOWING edge $faction:$unit_from:$unit_to\n";
|
|
|
|
if ( !$upgrade{"$faction:$unit_from"} ) {
|
|
$graph_buildings_units -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor );
|
|
}
|
|
}
|
|
elsif ( $relation eq "Build" ) {
|
|
$graph_all -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor ) if (!$dont_link_in_all);
|
|
$graph_buildings_units -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor );
|
|
#$graph_buildings -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor );
|
|
}
|
|
elsif ( $relation eq "Upgrade" ) {
|
|
$graph_all -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor ) if (!$dont_link_in_all);
|
|
##$graph_buildings_units -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor );
|
|
##$graph_buildings -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor );
|
|
}
|
|
elsif ( $relation eq "Morph" ) {
|
|
$graph_all -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor ) if (!$dont_link_in_all);
|
|
$graph_buildings_units -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor );
|
|
##$graph_buildings -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor );
|
|
}
|
|
elsif ( $relation eq "Produce" ) {
|
|
$graph_all -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor ) if (!$dont_link_in_all);
|
|
$graph_buildings_units -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor );
|
|
##$graph_buildings -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor );
|
|
}
|
|
else {
|
|
die "shouldnt happen, grep me 545454545: $relation\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
# create edges in diagrams which don't show the upgrades but go via an upgrade
|
|
# f.e. edge from technodrome to defense tower via advanced architecture
|
|
foreach my $multihop ( keys %multi_hop_upgrade ) {
|
|
my ( $faction_hop, $unit_from, $unit_to ) = split(/:/, $multihop );
|
|
|
|
if ( $faction eq $faction_hop ) {
|
|
print "found multihop from building to building $unit_from to $unit_to\n";
|
|
my $style="dotted";
|
|
$graph_buildings_units -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor );
|
|
$graph_buildings -> add_edge("$unit_from" => "$unit_to", style => $style, color => $svg_fontcolor );
|
|
}
|
|
}
|
|
|
|
&export_graphs($faction);
|
|
|
|
if (
|
|
$cfg->val('all', 'build_clickable_map') &&
|
|
$cfg->val('all', 'export_graph') =~ /as_png/ &&
|
|
$cfg->val('all', 'export_graph') =~ /as_cmapx/
|
|
) {
|
|
&build_clickable_map( $faction );
|
|
}
|
|
}
|
|
|
|
####################################################################################
|
|
# now that we have all the unit- and upgrade-requirements: export HTML
|
|
####################################################################################
|
|
|
|
# for all and everything table:
|
|
my $all_html_table="";
|
|
|
|
my $col_order_tmp = $cfg->val('style', 'columns_all_table');
|
|
$col_order_tmp =~ s/\s//g;
|
|
my ( @col_order ) =split(/,/, $col_order_tmp );
|
|
|
|
foreach my $faction_path ( @factions ) {
|
|
|
|
my $faction = $faction_path;
|
|
$faction =~ s/.+\///;
|
|
|
|
my $faction_pretty = &format_name( $faction );
|
|
|
|
|
|
my $full_all = "<P> <P><HR><H1>Unit Details for Faction $faction_pretty</H1>\n";
|
|
my $overview_all = "<TABLE BORDER=1 WIDTH=\"100%\"><TR> <TH> Name
|
|
<TH> Total Cost
|
|
<TH> Hit Points
|
|
<TH> Rege- nerate
|
|
<TH> Armor Strength
|
|
<TH> Armor Type
|
|
<TH> Sight Range
|
|
";
|
|
|
|
my $overview_combat = "<H3>Combat Units</H3> $overview_all
|
|
<TH> Move Speed
|
|
<TH> Air / Ground
|
|
<TH> Attack Strength Land
|
|
<TH> Attack Strength Air
|
|
<TH> Attack Range
|
|
";
|
|
|
|
my $overview_worker = "<H3>Worker Units</H3> $overview_all
|
|
<TH> Move Speed
|
|
<TH> Air / Ground
|
|
";
|
|
|
|
my $overview_building = "<H3>Buildings</H3> $overview_all
|
|
<TH>Storage
|
|
";
|
|
|
|
my $overview_upgrades = "<H3>Upgrades</H3><TABLE BORDER=1><TR> <TH WIDTH=200> Name
|
|
<TH> Cost
|
|
<TH> Increases
|
|
<TH> Affects
|
|
<TH> Enables to build
|
|
";
|
|
|
|
# now we have read all the XMLs, loop again over all units and export them to HTML
|
|
foreach my $unit ( sort @{$c_all{"$faction"}} ) {
|
|
|
|
my $full = "";
|
|
|
|
# collect all columns seperatly and build tables in the end as configured
|
|
my %col = ();
|
|
|
|
my $u = "$faction:$unit";
|
|
print "doing HTML for $u\n" if ( $debug );
|
|
|
|
my $full_tmp = "";
|
|
my $found = 0;
|
|
|
|
my $unit_pretty = &format_name( $unit );
|
|
|
|
$col{'name'} = $unit;
|
|
$col{'name_pretty'} = $unit_pretty;
|
|
$col{'name_link'} = &link_unit($faction, $unit);
|
|
$col{'faction'} = $faction;
|
|
$col{'faction_pretty'} = &format_name( $faction );
|
|
|
|
# FULL
|
|
$full .= "\n<TABLE BORDER=1>";
|
|
$full .= "<TR><TD WIDTH=250><A NAME=\"${unit}_full\"></A>".&html_icon( $u, 64 )."</TD><TD WIDTH=500> <B>$unit_pretty</B></TD></TR>\n";
|
|
|
|
if ($generate_g3d_images == 1) {
|
|
$full .= "<TR><TD COLSPAN=2 WIDTH=750><A NAME=\"${unit}_G3Dfull\"></A>".&html_icon_png( $u, $cfg->val('style', 'unit_png_width'), $cfg->val('style', 'unit_png_height') )."</TD></TR>\n";
|
|
}
|
|
|
|
if ( $upgrade{$u} ) {
|
|
$full .= "<TR><TD>Type:</TD><TD>Upgrade</TD></TR>\n";
|
|
$col{'type'} = "Upgrade";
|
|
}
|
|
elsif ( $building{$u} ) {
|
|
$full .= "<TR><TD>Type:</TD><TD>Building</TD></TR>\n";
|
|
$col{'type'} = "Building";
|
|
}
|
|
else {
|
|
|
|
$full .= "<TR><TD>Type:</TD><TD>";
|
|
if ( $worker{$u} ) {
|
|
$full .= "Worker Unit<br>\n";
|
|
$col{'type'} = "Worker Unit";
|
|
}
|
|
# a unit might fight and build so no elsif!
|
|
if ( $combat{$u} ) {
|
|
$full .= "Combat Unit\n";
|
|
$col{'type'} = "Combat Unit";
|
|
|
|
|
|
}
|
|
$full .= "</TD></TR>\n";
|
|
}
|
|
|
|
if ( $tips{ $unit } ) {
|
|
$full .= "<TR><TD>Description:</TD><TD> ".$tips{ "${unit}_info" }."</TD></TR>\n";
|
|
$col{'tip'} = $tips{ "${unit}_info" };
|
|
}
|
|
|
|
# put cost together
|
|
|
|
my $full_tmp_cost;
|
|
|
|
my ( $cost, $cost_icon, $cost_icon_overview );
|
|
# loop over creation-methods because f.e. guard might be produced in barracks or upgraded from swordman
|
|
|
|
my $num_creation_methods =@{$created_by_unit{ $u }};
|
|
my $num_method=0;
|
|
$full .= "<TR><TD>Creation:</TD><TD>";
|
|
|
|
foreach my $created_by_unit_tmp ( @{$created_by_unit{ $u }} ) {
|
|
|
|
$num_method++;
|
|
|
|
my ( $created_by_u, $method, $discount ) = split(/:/, $created_by_unit_tmp );
|
|
|
|
my ( $cost_tmp, $cost_icon_tmp, $cost_icon_overview_tmp ) = &calc_cost_of_unit( $u, $created_by_u, $method, $discount );
|
|
$cost_icon .= $cost_icon_tmp;
|
|
|
|
my %cost_hash;
|
|
my ( @cost_resources ) = split(/,/, $cost_tmp );
|
|
foreach my $cost_res ( @cost_resources ) {
|
|
my ( $resource, $amount ) = split(/:/, $cost_res );
|
|
$col{"${resource}_${num_method}"} = $amount;
|
|
$cost_hash{ $resource } = $amount;
|
|
}
|
|
|
|
|
|
my $created;
|
|
if ( $method eq "morph" ) {
|
|
$created = "upgraded from";
|
|
$full .= "Morphing from ".&link_unit($faction, ${created_by_u})."<BR>\n";
|
|
$col{"creation_${num_method}"} = "Morphed from ".&link_unit( $faction, ${created_by_u});
|
|
}
|
|
elsif ( $method eq "produce" ) {
|
|
$created = "produced by";
|
|
$full .= "Produced by ".&link_unit($faction, ${created_by_u})."<BR>\n";
|
|
$col{"creation_${num_method}"} = "Produced by ".&link_unit( $faction, ${created_by_u});
|
|
}
|
|
elsif ( $method eq "build" ) {
|
|
$created = "built by";
|
|
$full .= "Built by ".&link_unit($faction, ${created_by_u})."<BR>\n";
|
|
$col{"creation_${num_method}"} = "Built by ".&link_unit( $faction, ${created_by_u});
|
|
}
|
|
elsif ( $method eq "upgrade" ) {
|
|
$created = "upgraded by";
|
|
$full .= "Upgraded by ".&link_unit($faction, ${created_by_u})."<BR>\n";
|
|
$col{"creation_${num_method}"} = "Upgraded by ".&link_unit( $faction, ${created_by_u});
|
|
}
|
|
else {
|
|
print "method: $method for $u $created_by_u\n";
|
|
}
|
|
|
|
|
|
if ( $num_creation_methods == 1 ) {
|
|
$full_tmp_cost .= "<TR><TD>Total Cost: </TD><TD> $cost_icon_tmp\n";
|
|
}
|
|
else {
|
|
# f.e. guard might be produced in barracks or upgraded from swordman
|
|
$full_tmp_cost .= "<TR><TD>Total Cost when ${created} ".&format_name($created_by_u).": </TD><TD> $cost_icon_tmp\n";
|
|
}
|
|
|
|
# prefer cost for produce-method in overview if more than one method (guard) because that's less micromanagement for player
|
|
if (
|
|
$num_creation_methods == 1 ||
|
|
$num_creation_methods >= 2 &&
|
|
$method eq "produce"
|
|
) {
|
|
$cost_icon_overview = $cost_icon_overview_tmp;
|
|
}
|
|
}
|
|
|
|
$full .= "</TD></TR>\n";
|
|
|
|
|
|
# put storage of resources together
|
|
my $storage="";
|
|
my $storage_icon="";
|
|
foreach my $resource_stored ( @{$c_resource_store{"$faction:$unit"}} ) {
|
|
my ( $resource, $amount ) = split(/:/, $resource_stored );
|
|
|
|
$storage .= &format_name($resource).": $amount, ";
|
|
$storage_icon .= &html_icon_resource($resource, 16)." $amount ";
|
|
|
|
}
|
|
# remove trailing ", "
|
|
chop $storage;
|
|
chop $storage;
|
|
print "storage: $storage\n";
|
|
|
|
$col{"storage"} = $storage;
|
|
|
|
# do commands & skills
|
|
|
|
my $commands="";
|
|
|
|
my $full_attack_tmp="";
|
|
my $full_move_tmp="";
|
|
my $full_morph_tmp="";
|
|
my $full_repair_tmp="";
|
|
my $full_harvest_tmp="";
|
|
|
|
my $max_strength_vs_land = 0;
|
|
my $max_strength_vs_land_var = 0;
|
|
my $max_strength_vs_air = 0;
|
|
my $max_strength_vs_air_var = 0;
|
|
my $max_range = 0;
|
|
my $max_move_speed = 0;
|
|
|
|
my $num_move_command=0;
|
|
|
|
foreach my $c ( @{$commands_of_unit{"$u:move"}} ) {
|
|
$num_move_command++;
|
|
################################################################
|
|
# MOVE-command
|
|
################################################################
|
|
my ( $faction, $unit, $command ) = split(/:/, $c );
|
|
|
|
my $skill = $move_skill{ $c };
|
|
my $s = "$faction:$unit:$skill";
|
|
|
|
$full_move_tmp .= "<TR><TD> Move Command: ".&format_name($command)." </TD><TD> Speed: ".$speed{ $s }."</TD></TR>\n";
|
|
|
|
$col{"move_speed_${num_move_command}"} = $speed{ $s };
|
|
|
|
if ( $speed{ $s } > $max_move_speed ) {
|
|
$max_move_speed = $speed{ $s };
|
|
}
|
|
|
|
}
|
|
|
|
|
|
my $skill_on_hold_position="";
|
|
|
|
# don't ask me why this doesn't work ???????????
|
|
#$num_of_attacks = @{$commands_of_unit{"$u:attack"}};
|
|
# so do workaround:
|
|
my $num_of_attacks = 0;
|
|
foreach my $x ( @{$commands_of_unit{"$u:attack"}} ) {
|
|
$num_of_attacks++;
|
|
}
|
|
|
|
foreach my $c ( @{$commands_of_unit{"$u:attack_stopped"}} ) {
|
|
|
|
my ( $faction, $unit, $command ) = split(/:/, $c );
|
|
my $command_pretty = &format_name( $command );
|
|
|
|
$commands .= "$command_pretty, ";
|
|
|
|
# defensive-buildings like defense tower don't have an attack skill but just an attack_stopped skill
|
|
# so show this as main attack
|
|
if ( !$num_of_attacks ) {
|
|
my $full_attack_tmp_tmp;
|
|
|
|
( $full_attack_tmp_tmp, $max_strength_vs_land, $max_strength_vs_land_var, $max_strength_vs_air, $max_strength_vs_air_var, $max_range, $max_move_speed ) =
|
|
&show_attack( $c, $max_strength_vs_land, $max_strength_vs_land_var, $max_strength_vs_air, $max_strength_vs_air_var, $max_range, $max_move_speed );
|
|
|
|
$full_attack_tmp .= $full_attack_tmp_tmp;
|
|
}
|
|
else {
|
|
$skill_on_hold_position= $attack_skill{ $c };
|
|
if ( $c_upgrade_requirements{ $c } ) {
|
|
print "skill requires: $c_upgrade_requirements{ $c }\n";
|
|
$skill_on_hold_position .= ";$c_upgrade_requirements{ $c }";
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
# do all commands with <type value=attack>
|
|
my $num_attack=0;
|
|
foreach my $c ( @{$commands_of_unit{"$u:attack"}} ) {
|
|
|
|
my ( $faction, $unit, $command ) = split(/:/, $c );
|
|
my $command_pretty = &format_name( $command );
|
|
$commands .= "$command_pretty, ";
|
|
|
|
$num_move_command++;
|
|
$num_attack++;
|
|
|
|
my ($strength, $var, $range, $type, $speed, $start_time, $ep_cost ) ="";
|
|
|
|
my $full_attack_tmp_tmp;
|
|
|
|
(
|
|
$full_attack_tmp_tmp,
|
|
$max_strength_vs_land,
|
|
$max_strength_vs_land_var,
|
|
$max_strength_vs_air,
|
|
$max_strength_vs_air_var,
|
|
$max_range,
|
|
$max_move_speed,
|
|
$col{"attack_strength_$num_attack"},
|
|
$col{"attack_var_$num_attack"},
|
|
$col{"attack_range_$num_attack"},
|
|
$col{"attack_type_$num_attack"},
|
|
$col{"attack_speed_$num_attack"},
|
|
$col{"attack_start_time_$num_attack"},
|
|
$col{"attack_ep_cost_$num_attack"},
|
|
$col{"used_on_hold_position_$num_attack"},
|
|
$col{"target_$num_attack"},
|
|
) =
|
|
&show_attack( $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 );
|
|
|
|
|
|
$full_attack_tmp .= $full_attack_tmp_tmp;
|
|
|
|
my $move_skill = $move_skill{ $c };
|
|
if ( $move_skill) {
|
|
my $ms = "$faction:$unit:$move_skill";
|
|
$col{"move_speed_${num_move_command}"} = $speed{ $ms };
|
|
|
|
}
|
|
}
|
|
|
|
$col{"max_move_speed"} = $max_move_speed;
|
|
|
|
|
|
# show levels
|
|
if ( $u_levels{ $u } ) {
|
|
|
|
my $level_num = 0;
|
|
|
|
$full_attack_tmp .= "<TR><TD>Level(s):</TD><TD>\n";
|
|
|
|
|
|
foreach my $level ( @{ $u_levels{ $u }} ) {
|
|
$level_num++;
|
|
$col{"max_level"} = $level_num;
|
|
|
|
my ( $name, $kills ) = split(/:/, $level );
|
|
$full_attack_tmp .= "<B>".&format_name($name)."</b> at $kills kills<BR>\n";
|
|
|
|
# let do some mathz:
|
|
$full_attack_tmp .= "Hitpoints: ".int( $max_hp{ $u } * $level_hp ** ( $level_num - 1))." -> ". int( $max_hp{ $u } * ( $level_hp ** $level_num) )."<BR>\n";
|
|
|
|
if ( $max_ep{ $u } ) {
|
|
$full_attack_tmp .= "Energy Points: ".int( $max_ep{ $u } * $level_ep ** ( $level_num -1))." -> ".int( $max_ep{ $u } * $level_ep ** $level_num)."<BR>\n";
|
|
}
|
|
|
|
$full_attack_tmp .= "Armor Strength: ".int($armor{ $u } * $level_armor ** ($level_num-1))." -> ".int( $armor{ $u } * $level_armor ** $level_num )."<BR>\n";
|
|
$full_attack_tmp .= "Sight: ".int($sight{ $u } * $level_sight ** ( $level_num -1))." -> ".int( $sight{ $u } * $level_sight ** $level_num )."<BR>\n";
|
|
|
|
# as specified in the code, thanks titi for digging it out
|
|
#maxHp+= ut->getMaxHp()*50/100;
|
|
#maxEp+= ut->getMaxEp()*50/100;
|
|
#sight+= ut->getSight()*20/100;
|
|
#armor+= ut->getArmor()*50/100;
|
|
}
|
|
$full_attack_tmp .= "</TD></TR>\n";
|
|
}
|
|
|
|
# show available upgrades for this unit
|
|
if ( $upgrades_for{ $u } ) {
|
|
|
|
$full_attack_tmp .= "<TR><TD>Upgrades Available:</TD><TD>";
|
|
|
|
foreach my $upgrade_tmp ( @{ $upgrades_for{ $u }} ) {
|
|
my ( $u_faction, $u_upgrade ) = split(/:/, $upgrade_tmp );
|
|
|
|
my ( $upgrade_benefits, $upgrade_benefits_html ) = &do_upgrade_benefits( $upgrade_tmp );
|
|
|
|
my $str_tmp = &link_unit($faction, $u_upgrade);
|
|
$str_tmp .= " ($upgrade_benefits)" if ( $upgrade_benefits );
|
|
$str_tmp .= "<BR>\n";
|
|
$full_attack_tmp .= $str_tmp;
|
|
$col{"available_upgrades"} .= $str_tmp;
|
|
|
|
|
|
}
|
|
|
|
$full_attack_tmp .= "</TD></TR>\n";
|
|
}
|
|
|
|
# morphing
|
|
my $num_morph_skill=0;
|
|
foreach my $c ( @{$commands_of_unit{"$u:morph"}} ) {
|
|
|
|
my ( $faction, $unit, $command ) = split(/:/, $c );
|
|
|
|
my $skill = $morph_skill{ $c };
|
|
my $s = "$faction:$unit:$skill";
|
|
my $skill_short = $skill;
|
|
$skill_short =~ s/_skill$//;
|
|
|
|
print "morph_command: $command $c\n";
|
|
|
|
$full_morph_tmp .= "<TR><TD> Morph Skill: ".&format_name($skill_short)." </TD><TD>";
|
|
|
|
# since f.e. the technician can morph into different units, find the one for this skill
|
|
foreach my $command ( @{$c_command{ $u }} ) {
|
|
my $c = "$u:$command";
|
|
print "comparing command: $skill of $c\n";
|
|
if ( $morph_skill{ $c } && $morph_skill{ $c } eq $skill ) {
|
|
print "fitting morph_skill and command $skill of $c\n";
|
|
$full_morph_tmp .= "Morphing to: ".&link_unit($faction, $morph_unit{ $c }).&html_icon($faction.":".$morph_unit{ $c }, 64)."<BR>\n";
|
|
$full_morph_tmp .= "Refund (Discount): ".$morph_discount{ $c }." %<BR>\n";
|
|
$full_morph_tmp .="Morph Speed: ".$speed{ $s }."<BR>\n";
|
|
|
|
$num_morph_skill++;
|
|
$col{"morphing_to_$num_morph_skill"} = &link_unit($faction, $morph_unit{ $c });
|
|
$col{"morphing_discount_$num_morph_skill"} = $morph_discount{ $c }." %<BR>\n";
|
|
$col{"morphing_speed_$num_morph_skill"} = $speed{ $s }."<BR>\n";
|
|
|
|
}
|
|
}
|
|
$full_morph_tmp .= "</TD></TR>\n";
|
|
|
|
}
|
|
|
|
# repairing
|
|
my $num_heal=0;
|
|
foreach my $c ( @{$commands_of_unit{"$u:repair"}} ) {
|
|
$num_heal++;
|
|
my ( $faction, $unit, $command ) = split(/:/, $c );
|
|
|
|
my $skill = $repair_skill{ $c };
|
|
my $s = "$faction:$unit:$skill";
|
|
my $skill_short = $skill;
|
|
$skill_short =~ s/_skill$//;
|
|
|
|
print "repair_command: $command $c\n";
|
|
$full_repair_tmp .= "<TR><TD> Repair/Heal Skill: ".&format_name($skill_short)." </TD><TD>".&format_name($skill_short)."ing: ";
|
|
$col{"heal_skill_$num_heal"} = &format_name($skill_short);
|
|
|
|
foreach my $uu ( @{$c_repaired_units{$c}} ) {
|
|
$full_repair_tmp .= &link_unit($faction, $uu).", ";
|
|
$col{"heal_units_$num_heal"} .= &link_unit($faction, $uu).", ";
|
|
}
|
|
chop $full_repair_tmp;
|
|
chop $full_repair_tmp;
|
|
chop $col{"heal_units_$num_heal"};
|
|
chop $col{"heal_units_$num_heal"};
|
|
$full_repair_tmp .="<BR>\n";
|
|
|
|
$full_repair_tmp .="Repair/Heal Speed: ".$speed{ $s }."<BR>\n";
|
|
$full_repair_tmp .= "</TD></TR>\n";
|
|
$col{"heal_speed_$num_heal"} = $speed{ $s };
|
|
|
|
}
|
|
|
|
# harvesting/mining
|
|
my $num_mine=0;
|
|
foreach my $c ( @{$commands_of_unit{"$u:harvest"}} ) {
|
|
$num_mine++;
|
|
my ( $faction, $unit, $command ) = split(/:/, $c );
|
|
|
|
my $skill = $harvest_skill{ $c };
|
|
my $s = "$faction:$unit:$skill";
|
|
my $skill_short = $skill;
|
|
$skill_short =~ s/_skill$//;
|
|
|
|
print "harvest_command: $command $c\n";
|
|
$full_harvest_tmp .= "<TR><TD> Harvest/Mine Skill: ".&format_name($skill_short)." </TD><TD>";
|
|
$col{"mine_speed_$num_heal"} = $speed{ $s };
|
|
|
|
$col{"mine_resource_$num_mine"} = "";
|
|
foreach my $resource ( @{$c_harvested_resources{$c}} ) {
|
|
$full_harvest_tmp .= &html_icon_resource( $resource, 32 );
|
|
$col{"mine_resource_$num_mine"} .= &format_name( $resource ).", ";
|
|
}
|
|
chop $col{"mine_resource_$num_mine"};
|
|
chop $col{"mine_resource_$num_mine"};
|
|
|
|
$full_harvest_tmp .="<BR>\n";
|
|
|
|
$full_harvest_tmp .="Speed: ".$speed{ $s }."<BR>\n";
|
|
$full_harvest_tmp .="Max Load: ".$max_load{ $c }."<BR>\n";
|
|
$full_harvest_tmp .="Hits per Unit: ".$hits_per_unit{ $c }."<BR>\n";
|
|
$full_harvest_tmp .= "</TD></TR>\n";
|
|
|
|
$col{"mine_speed_$num_mine"} = $speed{ $s };
|
|
$col{"mine_max_load_$num_mine"} = $max_load{ $c };
|
|
$col{"mine_hits_per_unit_$num_mine"} = $hits_per_unit{ $c };
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# finnished with commands & skills
|
|
##########################################################
|
|
|
|
|
|
# first do name & costs, thats the same for all
|
|
my $overview_tmp = "<TR>";
|
|
$overview_tmp .= "<TD> ".&html_icon($u, 32).&link_unit($faction, $unit)."</TD>";
|
|
|
|
$overview_tmp .= "<TD>$cost_icon_overview\n";
|
|
$full .= $full_tmp_cost;
|
|
|
|
if ( $storage ) {
|
|
$full .= "<TR><TD>Storage:</TD><TD>$storage_icon\n";
|
|
|
|
if ( $storage =~ /wood/i && $storage !~ /gold/i ) {
|
|
$full .= "(Hint: This also means a worker can drop of his harvested wood into this building so it's useful to build it near trees.)";
|
|
|
|
}
|
|
$full .= "</TD></TR>\n";
|
|
}
|
|
|
|
$full .= "<TR><TD>Production Time:</TD><TD>".$time{$u}."</TD></TR>\n";
|
|
$col{"production_time"} = $time{$u};
|
|
|
|
if ( !$upgrade{$u} ) {
|
|
# OVERVIEW
|
|
$overview_tmp .= "<TD ALIGN=CENTER>".$max_hp{$u}."</TD>";
|
|
$overview_tmp .= "<TD ALIGN=CENTER>".( $regeneration{$u} || "-")."</TD>";
|
|
$overview_tmp .= "<TD ALIGN=CENTER>".( $armor{$u} || "-")."</TD>";
|
|
$overview_tmp .= "<TD ALIGN=CENTER>".( &link_attack_and_armor_types($armor_type{$u} ) )."</TD>";
|
|
$overview_tmp .= "<TD ALIGN=CENTER>".( $sight{$u} || "-")."</TD>";
|
|
|
|
$full .= "<TR><TD>Maximum Hitpoints:</TD><TD>".$max_hp{$u}."</TD></TR>\n";
|
|
$full .= "<TR><TD>Regeneration of Hitpoints:</TD><TD>".($regeneration{$u} || "-")."</TD></TR>\n";
|
|
$full .= "<TR><TD>Maximum Energy Points:</TD><TD>".$max_ep{$u}."</TD></TR>\n" if ( $max_ep{$u});
|
|
$full .= "<TR><TD>Regeneration Energy Points:</TD><TD>".$regeneration_ep{$u}."</TD></TR>\n" if ( $regeneration_ep{$u});
|
|
$full .= "<TR><TD>Armor-Strength:</TD><TD>".($armor{$u} || "-")."</TD></TR>\n";
|
|
$full .= "<TR><TD>Armor-Type:</TD><TD>".&link_attack_and_armor_types($armor_type{$u})."</TD></TR>\n";
|
|
$full .= "<TR><TD>Sight-Range:</TD><TD>".($sight{$u} || "-")."</TD></TR>\n";
|
|
|
|
$col{"max_hp"} = $max_hp{$u};
|
|
$col{"regeneration"} = $regeneration{$u};
|
|
$col{"max_ep"} = $max_ep{$u} if ( $max_ep{$u});
|
|
$col{"regeneration_ep"} = $regeneration_ep{$u} if ( $regeneration_ep{$u});
|
|
$col{"armor"} = $armor{$u};
|
|
$col{"armor_type"} = &link_attack_and_armor_types($armor_type{$u});
|
|
$col{"sight"} = $sight{$u};
|
|
|
|
}
|
|
else {
|
|
# handle upgrades
|
|
print "handling upgrade $u - $production_speed{$u} - $armor{$u}\n";
|
|
|
|
# do Increases:
|
|
my ( $upgrade_benefits, $upgrade_benefits_html ) = &do_upgrade_benefits( $u );
|
|
|
|
$full .= $upgrade_benefits_html;
|
|
|
|
|
|
|
|
$overview_tmp .= "<TD ALIGN=CENTER > ".$upgrade_benefits;
|
|
|
|
$overview_tmp .= "<TD ALIGN=CENTER> ";
|
|
|
|
$col{"upgrade_affects"} ="";
|
|
|
|
my $units="";
|
|
foreach my $unit_tmp ( @{$upgrade_effects{$u}} ) {
|
|
$units .= &link_unit($faction, $unit_tmp).", ";
|
|
$col{"upgrade_affects"} .= &link_unit($faction, $unit_tmp).", ";
|
|
}
|
|
chop ($units);
|
|
chop ($units);
|
|
chop $col{"upgrade_affects"};
|
|
chop $col{"upgrade_affects"};
|
|
$overview_tmp .= ($units || "")."\n";
|
|
|
|
$full .= "<TR><TD>Affects Units:</TD><TD> ".($units || "")."</TD></TR>\n" if ( $units );
|
|
}
|
|
|
|
# handle requirements. this won't go into $col for the all-table because that's not usefull in a 2D-sheet
|
|
my $req_overview_tmp;
|
|
for my $relation ('Build', 'Produce', 'Upgrade', 'Requirement', 'Upgrade-Requirement', 'Command' ) {
|
|
|
|
$found = 0;
|
|
|
|
if ( $relation =~ /Require/i ) {
|
|
$full_tmp = "<TR><TD>'$unit_pretty' is a $relation for:</TD><TD>";
|
|
}
|
|
elsif ( $relation =~ /Command/i ) {
|
|
$full_tmp = "<TR><TD>'$unit_pretty' enables commands:</TD><TD>";
|
|
}
|
|
else {
|
|
$full_tmp = "<TR><TD>'$unit_pretty' is able to $relation:</TD><TD>";
|
|
}
|
|
|
|
my $last_command="";
|
|
foreach my $unit_allows ( @{$c_unit_allows{"$faction:$unit:$relation"}} ) {
|
|
my ( $faction, $req_unit, $command ) = split(/:/, $unit_allows );
|
|
my $req_unit_pretty = &format_name( $req_unit );
|
|
$found = 1;
|
|
|
|
if ( $command ) {
|
|
$full_tmp .= &format_name($command)." : ".&link_unit($faction, $req_unit)."<br>\n";
|
|
if ( $command ne $last_command ) {
|
|
$req_overview_tmp .= "Enables command '<i>".&format_name($command)."</i>' for: ";
|
|
}
|
|
$req_overview_tmp .= &link_unit($faction, $req_unit).", ";
|
|
$last_command=$command;
|
|
}
|
|
else {
|
|
$full_tmp .= &link_unit($faction, $req_unit)."<br>\n";
|
|
$req_overview_tmp .= &link_unit($faction, $req_unit).", ";
|
|
}
|
|
}
|
|
|
|
$full_tmp .= "</TD></TR>\n";
|
|
|
|
if ( $found ) {
|
|
print "found enables for $u\n";
|
|
$full .= $full_tmp;
|
|
# detect unit & command in one cell
|
|
my $found_unit_command = grep /<A HREF=.*Enables command/, $req_overview_tmp;
|
|
if ( !$found_unit_command ) {
|
|
$req_overview_tmp = "<TD>$req_overview_tmp";
|
|
}
|
|
}
|
|
|
|
}
|
|
if ( defined $req_overview_tmp && length $req_overview_tmp ) {
|
|
chop $req_overview_tmp;
|
|
chop $req_overview_tmp;
|
|
}
|
|
$req_overview_tmp = $req_overview_tmp || "<TD> ";
|
|
|
|
|
|
|
|
# print what's needed to build this unit and what is enabled to built by this unit
|
|
$found = 0;
|
|
$full_tmp = "<TR><TD>Needed to build '$unit_pretty':</TD><TD>";
|
|
foreach my $unit_requirement ( @{$c_unit_requires{"$faction:$unit"}} ) {
|
|
my ( $faction, $req_unit ) = split(/:/, $unit_requirement );
|
|
my $req_unit_pretty = &format_name( $req_unit );
|
|
$full_tmp .= &link_unit($faction, $req_unit)."<br>\n";
|
|
$found = 1;
|
|
}
|
|
$full_tmp .= "</TD></TR>\n";
|
|
|
|
if ( $found ) {
|
|
$full .= $full_tmp;
|
|
}
|
|
|
|
|
|
if ( $building{$u} ) {
|
|
$overview_building .= $overview_tmp;
|
|
$overview_building .= "<TD>$storage_icon</TD>\n";
|
|
|
|
}
|
|
elsif ( $upgrade{$u} ) {
|
|
$overview_tmp .= $req_overview_tmp;
|
|
$overview_upgrades .= $overview_tmp;
|
|
}
|
|
|
|
if ( $worker{$u} ) {
|
|
$overview_worker .= $overview_tmp;
|
|
$overview_worker .= "<TD ALIGN=CENTER>".($max_move_speed || "--" )."</TD>\n";
|
|
my ( $o_tmp, $f_tmp ) = &do_air_ground( $u );
|
|
$overview_worker .= $o_tmp;
|
|
$col{"air_ground"} = $o_tmp;
|
|
$full .= $f_tmp;
|
|
}
|
|
|
|
if ( $combat{$u} ) {
|
|
$overview_combat .= $overview_tmp;
|
|
|
|
|
|
$overview_combat .= "<TD ALIGN=CENTER>".($max_move_speed || "--" )."\n";
|
|
my ( $o_tmp, $f_tmp ) = &do_air_ground( $u );
|
|
$overview_combat .= $o_tmp;
|
|
$col{"air_ground"} = $o_tmp;
|
|
|
|
# avoid writting the movement-type twice into technician (worker+combat unit)
|
|
if ( !$worker{$u} ) {
|
|
$full .= $f_tmp;
|
|
}
|
|
|
|
|
|
|
|
$overview_combat .= "<TD ALIGN=CENTER>";
|
|
if ($max_strength_vs_land ) {
|
|
# next line is showing damage as plus/minus, e.g. 300+-150 (which i prefer because otherwise everybody has to calculate the
|
|
# average to tell that 200-400 is stronger than 50-450)
|
|
$overview_combat .= "$max_strength_vs_land +- $max_strength_vs_land_var";
|
|
|
|
$col{"max_strength_vs_land"} = $max_strength_vs_land;
|
|
$col{"max_strength_vs_land_var"} = $max_strength_vs_land_var;
|
|
|
|
# next line is showing damage as range, e.g. 150-450
|
|
#$overview_combat .= ($max_strength_vs_land - $max_strength_vs_land_var )."-".($max_strength_vs_land + $max_strength_vs_land_var );
|
|
}
|
|
else {
|
|
$overview_combat .= "--\n";
|
|
}
|
|
$overview_combat .= "</TD>";
|
|
|
|
$overview_combat .= "<TD ALIGN=CENTER>";
|
|
if ($max_strength_vs_air ) {
|
|
$overview_combat .= "$max_strength_vs_air +- $max_strength_vs_air_var";
|
|
#$overview_combat .= ($max_strength_vs_air - $max_strength_vs_air_var )."-".($max_strength_vs_air + $max_strength_vs_air_var );
|
|
|
|
$col{"max_strength_vs_air"} = $max_strength_vs_air;
|
|
$col{"max_strength_vs_air_var"} = $max_strength_vs_air_var;
|
|
}
|
|
else {
|
|
$overview_combat .= "--\n";
|
|
}
|
|
$overview_combat .= "</TD>";
|
|
|
|
$overview_combat .= "<TD ALIGN=CENTER>".($max_range || "--" )."</TD>\n";
|
|
$col{"max_range"} = $max_range;
|
|
}
|
|
|
|
$full .= $full_move_tmp;
|
|
$full .= $full_morph_tmp;
|
|
$full .= $full_attack_tmp;
|
|
$full .= $full_repair_tmp;
|
|
$full .= $full_harvest_tmp;
|
|
$full .= "</TABLE><P>\n";
|
|
|
|
$full_all .= $full;
|
|
|
|
my $unit_html = "$out_path/${faction}_${unit}_full.html";
|
|
push @all_html_pages, $unit_html;
|
|
my $unit_title = &format_name( $unit )." - of the $faction_pretty Faction";
|
|
$h_all_html_pages{"$faction:units"} .= "$unit_html:$unit_title;";
|
|
|
|
open (UNIT, "> $unit_html") || die "cant write unit-html: $unit_html\n";
|
|
print UNIT &header($unit_title);
|
|
print UNIT &choose_faction_html( $faction )."<P>\n";
|
|
print UNIT $full;
|
|
print UNIT $footer;
|
|
close UNIT;
|
|
|
|
# do all all everything table
|
|
$all_html_table .= "<TR>\n";
|
|
foreach my $co ( @col_order ) {
|
|
|
|
# align everything centered except numbers
|
|
my $align ="CENTER";
|
|
if ( $col{"$co"} && $col{"$co"} =~ /^\d+$/ ) {
|
|
$align="RIGHT";
|
|
}
|
|
$all_html_table .= " <TD ALIGN=$align>".($col{"$co"} || "")."</TD>\n";
|
|
|
|
}
|
|
$all_html_table .= "</TR>\n";
|
|
}
|
|
|
|
$overview_combat .= "</TABLE>\n";
|
|
$overview_worker .= "</TABLE>\n";
|
|
$overview_building .= "</TABLE>\n";
|
|
$overview_upgrades .= "</TABLE>\n";
|
|
|
|
my $overview_html = "<H1>Overview for Faction: $faction_pretty</H1>\n\n";
|
|
$overview_html .= $overview_combat;
|
|
$overview_html .= $overview_worker;
|
|
$overview_html .= $overview_building;
|
|
$overview_html .= $overview_upgrades;
|
|
|
|
|
|
# create full-page for this faction
|
|
my $html_page = "${faction}_techtree.html";
|
|
my $outfile = "$out_path/$html_page";
|
|
open (HTML, "> $outfile") || die "can't write outfile: $outfile\n";
|
|
push @all_html_pages, $html_page;
|
|
my $title = "$faction_pretty Techtree of Glest - Version $version\n";
|
|
$h_all_html_pages{"$faction:techtree"} .= "$outfile:$title";
|
|
|
|
print HTML &header( $title, $faction );
|
|
print HTML &choose_faction_html( $faction )."<P>\n";
|
|
print HTML &diagram_links_html( $faction )."<P>\n";
|
|
|
|
print HTML $overview_html;
|
|
print HTML $full_all;
|
|
|
|
print HTML $footer;
|
|
close (HTML);
|
|
|
|
# create overview-page for this faction
|
|
$outfile = "$out_path/${faction}_overview.html";
|
|
open (HTML, "> $outfile") || die "can't write faction overview $outfile\n";
|
|
push @all_html_pages, $outfile;
|
|
|
|
$title = "$faction_pretty Overview\n";
|
|
|
|
$h_all_html_pages{"$faction:overview"} = "$outfile:$title";
|
|
|
|
print HTML &header( $title, $faction );
|
|
print HTML &choose_faction_html( $faction )."<P>\n";
|
|
print HTML &diagram_links_html( $faction )."<P>\n";
|
|
print HTML &show_special_pages()."<P>\n";
|
|
|
|
print HTML $overview_html;
|
|
print HTML $footer;
|
|
close (HTML);
|
|
|
|
}
|
|
|
|
print "creating all and everything table\n";
|
|
my $outfile = "$out_path/all.html";
|
|
open (HTML_ALL, "> $outfile") || die "can't write all table $outfile\n";
|
|
push @all_html_pages, $outfile;
|
|
|
|
my $title = "All Units of all Factions\n";
|
|
|
|
$h_all_html_pages{"all"} = "$outfile:$title";
|
|
|
|
print HTML_ALL &header( $title );
|
|
print HTML_ALL &choose_faction_html()."<P>\n";
|
|
print HTML_ALL &show_special_pages()."<P>\n";
|
|
|
|
print HTML_ALL "<TABLE BORDER=0 ID=table_all><THEAD><TR>";
|
|
|
|
# do table header
|
|
foreach my $co ( @col_order ) {
|
|
print HTML_ALL "<TH>".&format_name( $co )."</TH>";
|
|
}
|
|
|
|
print HTML_ALL "</THEAD><TBODY>";
|
|
print HTML_ALL $all_html_table;
|
|
print HTML_ALL "</TBODY></TABLE>\n";
|
|
|
|
print HTML_ALL $footer;
|
|
close (HTML_ALL);
|
|
|
|
print "creating global summary page\n";
|
|
|
|
$outfile = "$out_path/$summary";
|
|
|
|
open (HTML, "> $outfile") || die "can't write summary page $outfile\n";
|
|
|
|
print HTML &header("MegaGlest Techtree Summary");
|
|
print HTML &choose_faction_html()."<P>\n";
|
|
print HTML &show_special_pages()."<P>\n";
|
|
|
|
|
|
print HTML "<A NAME=factions></a><H2>Factions:</H2>\n";
|
|
|
|
foreach my $faction_path ( @factions ) {
|
|
my $faction = $faction_path;
|
|
$faction =~ s/.+\///;
|
|
|
|
my ( @units ) =split(/;/, $h_all_html_pages{"$faction:units"} );
|
|
|
|
print HTML "<A NAME=$faction></a>\n";
|
|
print HTML "<H3>".&format_name($faction).":</H3>\n";
|
|
|
|
|
|
my ( $overview_page, $overview_title ) = split(/:/, $h_all_html_pages{"$faction:overview"} );
|
|
$overview_page =~ s/$out_path\///;
|
|
print HTML "<B>Overview:</B> <a href=\"$overview_page\">$overview_title</a><BR>\n";
|
|
|
|
my ( $full_page, $full_title ) = split(/:/, $h_all_html_pages{"$faction:techtree"} );
|
|
$full_page =~ s/$out_path\///;
|
|
print HTML "<B>All in one Page:</B> <a href=\"$full_page\">$full_title</a><BR>\n";
|
|
|
|
print HTML "<H4>Techtree Diagrams:</H4>\n";
|
|
print HTML "<UL>\n";
|
|
|
|
foreach my $map ('all', 'buildings', 'buildings_units') {
|
|
if ( $cfg->val('all', 'build_clickable_map') ) {
|
|
my ( $page, $title ) = split(/:/, $h_all_html_pages{"$faction:$map"} );
|
|
$page =~ s/$out_path\///;
|
|
print HTML "<LI><a href=\"$page\">$title</a>\n";
|
|
}
|
|
else {
|
|
# do SVG-diagrams
|
|
my $page = $graph_files{ "$faction:svg:$map" };
|
|
$page =~ s/$out_path\///;
|
|
my $title = "Techtree Diagram for ".&format_name( $faction )." - ".&format_name($map) ;
|
|
print HTML "<LI><a href=\"$page\">$title</a>\n";
|
|
}
|
|
}
|
|
print HTML "</UL>\n";
|
|
|
|
|
|
print HTML "<H4>Units, Buildings & Upgrades:</H4>\n";
|
|
print HTML "<UL>\n";
|
|
|
|
foreach my $unit ( @units ) {
|
|
my ( $page, $title ) = split(/:/, $unit );
|
|
$page =~ s/$out_path\///;
|
|
print HTML "<LI><a href=\"$page\">$title</a>\n";
|
|
}
|
|
print HTML "</UL>\n";
|
|
|
|
}
|
|
print HTML $footer;
|
|
close HTML;
|
|
|
|
# copy static files to outpath
|
|
mkdir "$out_path/js";
|
|
mkdir "$out_path/css";
|
|
system "cp $ENV{APP_ROOT}/media/*.html $out_path";
|
|
system "cp $ENV{APP_ROOT}/media/*.ico $out_path";
|
|
system "cp $ENV{APP_ROOT}/media/*.css $out_path";
|
|
system "cp $ENV{APP_ROOT}/media/*.js $out_path/js";
|
|
system "cp -r $ENV{APP_ROOT}/media/datatables $out_path/images";
|
|
|
|
exit 0;
|
|
|
|
###############################################################################
|
|
# end of main(), now subs
|
|
###############################################################################
|
|
|
|
|
|
sub create_glestkey_page {
|
|
my $html_page = "glestkeys.html";
|
|
my $title = "Keyboard Assignment";
|
|
push @special_html_pages, "$html_page;$title";
|
|
my $outfile = "$out_path/$html_page";
|
|
open (HTML, "> $outfile") || die "can't write $outfile\n";
|
|
|
|
print HTML header($title);
|
|
print HTML "Note: Keyboard assignment can be changed in glestuserkeys.ini.<P>\n";
|
|
|
|
print HTML "<TABLE BORDER=1><TH>Name<TH>Key\n";
|
|
|
|
open (KEYS, "< $glestkeys") || die "can't read glestkeys: $glestkeys\n";
|
|
while (my $line =<KEYS>) {
|
|
next if ( $line =~ /^;/ );
|
|
if ( $line =~ /(.+)=(.+)/ ) {
|
|
my $name = $1;
|
|
my $key = $2;
|
|
|
|
$name =~ s/^hotkey//gi;
|
|
|
|
my $name_pretty = $name;
|
|
# make name pretty, e.g. CameraRotateUp => Camera Rotate Up
|
|
# spaces before uppercase-chars, expect if preceeded by uppercase, then it's an abbreviation like GUI
|
|
$name_pretty =~ s/(?<![[:upper:]])([[:upper:]])/ $1/g;
|
|
# SaveGUILayout => Save GUI Layout
|
|
$name_pretty =~ s/([[:upper:]])([[:upper:]])([[:upper:]])([[:lower:]])/$1$2 $3$4/g;
|
|
|
|
# space before numbers:
|
|
$name_pretty =~ s/(\d)/ $1/;
|
|
|
|
$key =~ s/^vk//;
|
|
$key =~ s/\'//g;
|
|
|
|
print HTML "<TR><TD>$name_pretty</TD><TD ALIGN=CENTER>$key</TD></TR>\n";
|
|
}
|
|
|
|
}
|
|
|
|
print HTML "</TABLE>\n";
|
|
print HTML $footer;
|
|
close HTML;
|
|
close KEYS;
|
|
}
|
|
|
|
sub read_unit {
|
|
|
|
my ($xml_file, $faction, $faction_path, $unit, $graph) = @_;
|
|
|
|
my $xpath = XML::XPath->new( $xml_file );
|
|
|
|
my $unit_pretty = &format_name ( $unit );
|
|
|
|
# index for all assoc arrays
|
|
my $u = "$faction:$unit";
|
|
print "reading XML for $u\n" if ( $debug );
|
|
|
|
$upgrade{$u} = get_value($xpath, "/upgrade");
|
|
|
|
my $resource_requirements = "";
|
|
|
|
if ( $upgrade{$u} ) {
|
|
$icon{$u} = get_value($xpath, "/upgrade/image/\@path");
|
|
# where to find resource-requirements, used below
|
|
$resource_requirements = $xpath->find("/upgrade/resource-requirements/resource");
|
|
|
|
# effects is a typo in the original glest-XML, i'll keep it in some variables
|
|
my $effects = $xpath->find("/upgrade/effects/unit");
|
|
foreach my $effected ( $effects->get_nodelist ) {
|
|
XML::XPath::XMLParser::as_string( $effected ) =~ /name=\"(.+?)\"/;
|
|
my $unit_tmp = $1;
|
|
push @{ $upgrade_effects{ $u } }, $unit_tmp;
|
|
push @{ $upgrades_for{ "$faction:$unit_tmp" } }, $u;
|
|
}
|
|
|
|
$max_hp{$u} = get_value($xpath, "/upgrade/max-hp" );
|
|
$max_ep{$u} = get_value($xpath, "/upgrade/max-ep" );
|
|
$sight{$u} = get_value($xpath, "/upgrade/sight" );
|
|
$attack_strenght{$u} = get_value($xpath, "/upgrade/attack-strenght" );
|
|
$attack_range{$u} = get_value($xpath, "/upgrade/attack-range" );
|
|
$armor{$u} = get_value($xpath, "/upgrade/armor" );
|
|
$move_speed{$u} = get_value($xpath, "/upgrade/move-speed" );
|
|
$production_speed{$u} = get_value($xpath, "/upgrade/production-speed" );
|
|
$time{$u} = get_value($xpath, "/upgrade/time/\@value");
|
|
|
|
}
|
|
else {
|
|
# do units and buildings ...
|
|
|
|
$icon{$u} = get_value($xpath, "/unit/parameters/image/\@path");
|
|
# where to find resource-requirements, used below
|
|
$resource_requirements = $xpath->find("/unit/parameters/resource-requirements/resource");
|
|
|
|
# basic unit stats:
|
|
$max_hp{$u} = get_value($xpath, "/unit/parameters/max-hp/\@value");
|
|
$regeneration{$u} = get_value($xpath, "/unit/parameters/max-hp/\@regeneration" );
|
|
$max_ep{$u} = get_value($xpath, "/unit/parameters/max-ep/\@value");
|
|
$regeneration_ep{$u} = get_value($xpath, "/unit/parameters/max-ep/\@regeneration" );
|
|
$armor{$u} = get_value($xpath, "/unit/parameters/armor/\@value");
|
|
$armor_type{$u} = get_value($xpath, "/unit/parameters/armor-type/\@value");
|
|
$sight{$u} = get_value($xpath, "/unit/parameters/sight/\@value");
|
|
$time{$u} = get_value($xpath, "/unit/parameters/time/\@value");
|
|
$height{$u} = get_value($xpath, "/unit/parameters/height/\@value");
|
|
|
|
if ( get_value($xpath, "/unit/parameters/fields/field[\@value='land']") ) {
|
|
$land_unit{ $u } = 1;
|
|
}
|
|
# no elsif because some units are land & air, f.e. genie
|
|
if ( get_value($xpath, "/unit/parameters/fields/field[\@value='air']") ) {
|
|
$air_unit{ $u } = 1;
|
|
}
|
|
|
|
# decide if it's a worker unit by checking if it can built something
|
|
$building{$u} = get_value($xpath, "/unit/skills/skill/name[\@value='be_built_skill']");
|
|
if ( get_value($xpath, "/unit/skills/skill/type[\@value='build']") ) {
|
|
$worker{ $u } = "1";
|
|
}
|
|
else {
|
|
$worker{ $u } = "0";
|
|
}
|
|
|
|
|
|
# now the multi-value stuff:
|
|
|
|
# skills:
|
|
my $skills_path = $xpath->find("/unit/skills/skill/name/\@value");
|
|
foreach my $skill_xml ( $skills_path->get_nodelist ) {
|
|
XML::XPath::XMLParser::as_string( $skill_xml ) =~ /value=\"(.+?)\"/;
|
|
my $skill = $1;
|
|
|
|
# ignore useless skills
|
|
if ( $skill !~ /stop/i && $skill !~ /die/i && $skill !~ /loaded/i && $skill !~ /be_built/i ) {
|
|
|
|
print "skill: $skill\n";
|
|
push @{ $c_skill{ $u } }, $skill;
|
|
|
|
# index-var for storing all skills:
|
|
my $s = "$u:$skill";
|
|
|
|
$speed{ $s } = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/speed/\@value");
|
|
$ep_cost{ $s } = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/ep-cost/\@value");
|
|
|
|
$skill_type{ $s } = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/type/\@value");
|
|
print "skill-type: <".$skill_type{ $s }.">\n";
|
|
if ( $skill_type{ $s } =~ /attack/i ) {
|
|
$combat{ $u } = 1;
|
|
$attack_range{ $s } = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/attack-range/\@value");
|
|
$attack_strenght{ $s } = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/attack-strenght/\@value");
|
|
$attack_var{ $s } = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/attack-var/\@value");
|
|
$attack_type{ $s } = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/attack-type/\@value");
|
|
$attack_start_time{ $s } = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/attack-start-time/\@value");
|
|
$attack_land{ $s } = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/attack-fields/field[\@value='land']");
|
|
$attack_air{ $s } = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/attack-fields/field[\@value='air']");
|
|
my $splash = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/splash/\@value");
|
|
$splash{ $s } = 1 if ( $splash =~ /true/ );
|
|
if ( $splash{ $s } ) {
|
|
$splash_radius{ $s } = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/splash/radius/\@value");
|
|
$splash_damage_all{ $s } = get_value($xpath, "/unit/skills/skill/name[\@value='$skill']/parent::*/splash/damage-all/\@value");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
##########################################
|
|
# COMMANDS:
|
|
##########################################
|
|
my $commands_path = $xpath->find("/unit/commands/command/name/\@value");
|
|
foreach my $command_xml ( $commands_path->get_nodelist ) {
|
|
XML::XPath::XMLParser::as_string( $command_xml ) =~ /value=\"(.+?)\"/;
|
|
my $command = $1;
|
|
|
|
print "command: $command\n";
|
|
push @{ $c_command{ $u } }, $command;
|
|
|
|
# index-var for storing all skills:
|
|
my $c = "$u:$command";
|
|
|
|
my $command_icon_tmp = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/image/\@path");
|
|
$command_icon{ $c } = $command_icon_tmp;
|
|
$command_icon{ $c } =~ s/.+\///;
|
|
if ( $command_icon{ $c }) {
|
|
print "command icon: ".$command_icon{ $c }." for $c\n" ;
|
|
# commented to save time, not used anyway yet
|
|
system "cp $faction_path/$units_path/$unit/$command_icon_tmp $out_path/$images_path/${faction}/$unit";
|
|
}
|
|
|
|
$move_skill{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/move-skill/\@value");
|
|
$move_loaded_skill{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/move-loaded-skill/\@value");
|
|
$attack_skill{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/attack-skill/\@value");
|
|
$repair_skill{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/repair-skill/\@value");
|
|
$build_skill{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/build-skill/\@value");
|
|
$upgrade_skill{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/upgrade-skill/\@value");
|
|
$harvest_skill{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/harvest-skill/\@value");
|
|
|
|
|
|
$command_type{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/type/\@value");
|
|
print "command-type: <".$command_type{ $c }.">\n";
|
|
|
|
push @{ $commands_of_unit{ "$u:$command_type{ $c }" } }, $c;
|
|
|
|
my $unit_requirements = $xpath->find("/unit/commands/command/name[\@value='$command']/parent::*/unit-requirements/*");
|
|
foreach my $unit_requirement ( $unit_requirements->get_nodelist ) {
|
|
print "req: ".XML::XPath::XMLParser::as_string( $unit_requirement ) . "\n";
|
|
XML::XPath::XMLParser::as_string( $unit_requirement ) =~ /name=\"(.+?)\"/;
|
|
my $req_name = $1;
|
|
print "FFF unit-req: $c of $u - $req_name\n";
|
|
|
|
# this can be multivalued, but not used yet so i'll be lazy
|
|
$c_unit_requirements{ $c } = $req_name;
|
|
}
|
|
|
|
my $upgrade_requirements = $xpath->find("/unit/commands/command/name[\@value='$command']/parent::*/upgrade-requirements/*");
|
|
foreach my $upgrade_requirement ( $upgrade_requirements->get_nodelist ) {
|
|
print "req: ".XML::XPath::XMLParser::as_string( $upgrade_requirement ) . "\n";
|
|
XML::XPath::XMLParser::as_string( $upgrade_requirement ) =~ /name=\"(.+?)\"/;
|
|
my $req_name = $1;
|
|
print "FFF-upgrade-req: $c of $u - $req_name\n";
|
|
|
|
# this can be multivalued, but not used yet so i'll be lazy
|
|
$c_upgrade_requirements{ $c } = $req_name;
|
|
push @{ $c_unit_allows{"$faction:$req_name:Command"} }, "$c";
|
|
}
|
|
|
|
|
|
if ( $command_type{ $c } =~ /morph/i ) {
|
|
print "found morph command: $command\n";
|
|
$morph_skill{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/morph-skill/\@value");
|
|
|
|
my $morph_to_unit = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/morph-unit/\@name");
|
|
$morph_unit{ $c } = $morph_to_unit;
|
|
|
|
$morph_discount{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/discount/\@value");
|
|
|
|
# a guard my be produced in a barrack and morphed from a swordman so %created_by_unit has to be multivalued for each unit
|
|
push @{$created_by_unit{ "$faction:$morph_to_unit" } } , "$unit:morph:$morph_discount{ $c }";
|
|
}
|
|
elsif ( $command_type{ $c } =~ /produce/i ) {
|
|
$produce_skill{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/produce-skill/\@value");
|
|
my $produce_unit_tmp = get_value($xpath, "/unit/commands/command/type[\@value='produce']/parent::*/produced-unit");
|
|
$produce_unit{ $c } = $produce_unit_tmp;
|
|
push @{ $c_produced_units{ $u } }, $produce_unit_tmp;
|
|
}
|
|
elsif ( $command_type{ $c } =~ /repair/i ) {
|
|
my $repaired_units = $xpath->find("/unit/commands/command/name[\@value='$command']/parent::*/repaired-units/*");
|
|
foreach my $repaired_unit ( $repaired_units->get_nodelist ) {
|
|
XML::XPath::XMLParser::as_string( $repaired_unit ) =~ /name=\"(.+?)\"/;
|
|
push @{ $c_repaired_units{ $c } }, $1;
|
|
}
|
|
}
|
|
elsif ( $command_type{ $c } =~ /harvest/i ) {
|
|
my $harvested_resources = $xpath->find("/unit/commands/command/name[\@value='$command']/parent::*/harvested-resources/*");
|
|
foreach my $harvested_resource ( $harvested_resources->get_nodelist ) {
|
|
XML::XPath::XMLParser::as_string( $harvested_resource ) =~ /name=\"(.+?)\"/;
|
|
push @{ $c_harvested_resources{ $c } }, $1;
|
|
}
|
|
$max_load{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/max-load/\@value");
|
|
$hits_per_unit{ $c } = get_value($xpath, "/unit/commands/command/name[\@value='$command']/parent::*/hits-per-unit/\@value");
|
|
}
|
|
}
|
|
}
|
|
|
|
# now read $resource_requirements as set above
|
|
foreach my $resource_requirement ( $resource_requirements->get_nodelist ) {
|
|
print "req: ".XML::XPath::XMLParser::as_string( $resource_requirement ) . "\n";
|
|
XML::XPath::XMLParser::as_string( $resource_requirement ) =~ /name=\"(.+?)\" amount=\"(.+?)\"/;
|
|
my $req_name = $1;
|
|
my $req_amount = $2;
|
|
print "cost: $u $req_name:$req_amount\n";
|
|
|
|
if ( $req_amount ) {
|
|
push @{ $c_resource_requirement{ $u } }, "$req_name:$req_amount";
|
|
|
|
# sort cows to workers but avoid buildings giving food
|
|
if ( $req_amount < 0 && $req_name eq "food" && !$building{ $u } ) {
|
|
$worker{ $u } = "1";
|
|
}
|
|
}
|
|
}
|
|
|
|
# now read resources stored
|
|
my $resources_stored = $xpath->find("/unit/parameters/resources-stored/resource");
|
|
foreach my $resource_stored ( $resources_stored->get_nodelist ) {
|
|
print "req: ".XML::XPath::XMLParser::as_string( $resource_stored ) . "\n";
|
|
XML::XPath::XMLParser::as_string( $resource_stored ) =~ /name=\"(.+?)\" amount=\"(.+?)\"/;
|
|
my $res_name = $1;
|
|
my $res_amount = $2;
|
|
print "resource store: $u $res_name:$res_amount\n";
|
|
|
|
if ( $res_amount ) {
|
|
push @{ $c_resource_store{ $u } }, "$res_name:$res_amount";
|
|
|
|
}
|
|
}
|
|
|
|
# read levels
|
|
my $levels_path = $xpath->find("/unit/parameters/levels/level");
|
|
foreach my $level_xml ( $levels_path->get_nodelist ) {
|
|
XML::XPath::XMLParser::as_string( $level_xml ) =~ /name=\"(.+?)\" kills=\"(.+?)\"/;
|
|
my $name = $1;
|
|
my $kills = $2;
|
|
|
|
push @{ $u_levels{ $u } }, "$name:$kills";
|
|
|
|
}
|
|
|
|
my $url = &link_unit($faction, $unit, undef, undef, "file_only" );
|
|
|
|
# no /g to avoid spreading "shield level 2" in 3 rows
|
|
$unit_pretty =~ s/ /\n/;
|
|
|
|
# create graphviz-node
|
|
&g_add_node( $faction, $unit, $unit_pretty, $url, $building{$u}, $upgrade{$u} );
|
|
|
|
# definition of
|
|
# a. where to find requiremtns in the XML-data
|
|
# 1. if it's stored as parent-child or child-parent (REQUIREMENT, COMMAND)
|
|
# 2. which style of arrow should be used in graph (see cpan.org for graphviz-documentation)
|
|
# 3. relation between units (Produce, Build, ...)
|
|
my %req_data;
|
|
$req_data{"/unit/parameters/unit-requirements/*"} = "REQUIREMENT:dotted:Requirement";
|
|
$req_data{"/unit/parameters/upgrade-requirements/*"} = "REQUIREMENT:dotted:Upgrade-Requirement";
|
|
$req_data{"/unit/commands/command/type[\@value='upgrade']/parent::*/produced-upgrade"} = "COMMAND:solid:Upgrade";
|
|
$req_data{"/unit/commands/command/type[\@value='morph']/parent::*/morph-unit"} = "COMMAND:dashed:Morph";
|
|
$req_data{"/unit/commands/command/type[\@value='produce']/parent::*/produced-unit"} = "COMMAND:solid:Produce";
|
|
$req_data{"/unit/commands/command/type[\@value='build']/parent::*/buildings/building"} = "COMMAND:bold:Build";
|
|
|
|
foreach my $location ( keys %req_data ) {
|
|
|
|
my ( $order, $style, $relation ) = split(/:/, $req_data{"$location"} );
|
|
|
|
my $unit_requirements = $xpath->find("$location");
|
|
foreach my $unit_requirement ( $unit_requirements->get_nodelist ) {
|
|
print "req: ".XML::XPath::XMLParser::as_string( $unit_requirement ) . "\n";
|
|
XML::XPath::XMLParser::as_string( $unit_requirement ) =~ /name=\"(.+?)\"/;
|
|
my $req_name = $1;
|
|
|
|
# generating an hash of an array
|
|
if ( $order eq "COMMAND" ) {
|
|
|
|
&g_add_edge($faction, $unit, $req_name, $style, $relation );
|
|
|
|
if ( $relation eq "Morph" ) {
|
|
# dealt with in section skills
|
|
}
|
|
elsif ( $relation eq "Build" ) {
|
|
push @{$created_by_unit{ "$faction:$req_name" } } , "$unit:build";
|
|
push @{ $c_unit_allows{"$u:Build"} }, "$faction:$req_name";
|
|
print "build: $u = $req_name:build\n";
|
|
}
|
|
elsif ( $relation eq "Produce" ) {
|
|
push @{$created_by_unit{ "$faction:$req_name" } } , "$unit:produce";
|
|
push @{ $c_unit_allows{"$u:Produce"} }, "$faction:$req_name";
|
|
print "produce: $u = $req_name:produce\n";
|
|
}
|
|
elsif ( $relation eq "Upgrade" ) {
|
|
push @{$created_by_unit{ "$faction:$req_name" } } , "$unit:upgrade";
|
|
push @{ $c_unit_allows{"$u:Upgrade"} }, "$faction:$req_name";
|
|
push @{ $c_unit_requires{"$faction:$req_name"} }, $u;
|
|
print "upgrade: $u = $req_name:upgrade\n";
|
|
|
|
# some commands to upgrade of the egypt faction contain unit-requirements and upgrade-requirements
|
|
# f.e. research_scarab of the temple
|
|
my $command = get_value($xpath, "$location/parent::*/produced-upgrade[\@name='$req_name']/parent::*/name");
|
|
my $c = "$faction:$unit:$command";
|
|
my $req_name_upgrade = $c_upgrade_requirements{ $c };
|
|
|
|
if ( $req_name_upgrade ) {
|
|
print "FFF-found upgrade-req command $c to get $req_name requires: $faction:$req_name_upgrade\n";
|
|
push @{ $c_unit_requires{"$faction:$req_name"} }, "$faction:$req_name_upgrade";
|
|
&g_add_edge($faction, $req_name_upgrade, $req_name, "dotted", "Upgrade-Requirement" );
|
|
}
|
|
|
|
my $req_name_unit = $c_unit_requirements{ $c };
|
|
|
|
if ( $req_name_unit ) {
|
|
print "FFF-found unit-req command: $c to get $req_name requires: $faction:$req_name_unit\n";
|
|
push @{ $c_unit_requires{"$faction:$req_name"} }, "$faction:$req_name_unit";
|
|
&g_add_edge($faction, $req_name_unit, $req_name, "dotted", "Requirement" );
|
|
}
|
|
}
|
|
else {
|
|
die "grep me: ererrerrrerere\n";
|
|
#push @{ $c_unit_allows{$u} }, "$faction:$req_name";
|
|
#push @{ $c_unit_requires{"$faction:$req_name"} }, $u;
|
|
}
|
|
}
|
|
elsif ( $order eq "REQUIREMENT" ) {
|
|
&g_add_edge($faction, $req_name, $unit, $style, $relation );
|
|
push @{ $c_unit_allows{"$faction:$req_name:$relation"} }, $u;
|
|
push @{ $c_unit_requires{$u} }, "$faction:$req_name";
|
|
|
|
}
|
|
else {
|
|
die "unknown order: $order . grep me <sadsaasdsas\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
$icon{ $u } =~ s/^.+\///;
|
|
|
|
return ( $icon{$u} );
|
|
}
|
|
|
|
sub header {
|
|
|
|
my ( $title, $faction ) = @_;
|
|
|
|
$title .= " (".$glest_version.") ";
|
|
|
|
my $header = $cfg->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 =~ /(?<!value-percent-multiplier)[ \t]*=[ \t]*\"[ \t]*(.+?)[ \t]*\"/ ) {
|
|
$value = $1;
|
|
|
|
if ( $attribute =~ /value-percent-multiplier[ \t]*=[ \t]*\"[ \t]*true[ \t]*\"/ ) {
|
|
$value = "$value%";
|
|
}
|
|
}
|
|
#else {
|
|
# $value = $attribute;
|
|
#}
|
|
}
|
|
return $value;
|
|
|
|
}
|
|
|
|
|
|
sub g_add_node {
|
|
|
|
my ( $faction, $unit, $unit_pretty, $url, $building, $upgrade ) = @_;
|
|
#print "g_add_node: $unit, <$url>, $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 )."<P>\n";
|
|
print OUTHTML &diagram_links_html( $faction )."<P>\n";
|
|
|
|
print OUTHTML "<img src=\"images/$faction/${faction}_techtree_graph_${map}.png\" usemap=#test>\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 <BR>(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 .= "<BR> + 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 .= "<NOBR>".&html_icon_resource($resource, 16)."$amount_total</NOBR> ";
|
|
my $cost_icon_overview .= "<NOBR>".&html_icon_resource($resource, 16)."$add_nbsp$amount_total</NOBR> ";
|
|
return ( $cost, $cost_icon, $cost_icon_overview );
|
|
}
|
|
|
|
|
|
sub html_icon {
|
|
my ( $u, $size ) = @_;
|
|
my ( $faction, $unit ) = split(/:/, $u );
|
|
|
|
return "<IMG SRC=\"$images_path/$faction/$unit/".$icon{$u}."\" HEIGHT=$size WIDTH=$size ALT=\"".&format_name( $unit )."\">";
|
|
}
|
|
|
|
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 "<IMG SRC=\"$images_path/$faction/$unit/".$full_png."\" ALT=\"".&format_name( $unit )."\">";
|
|
#return "<IMG SRC=\"$images_path/$faction/$unit/".$full_png."\" HEIGHT=$height WIDTH=$width ALT=\"".&format_name( $unit )."\">";
|
|
}
|
|
|
|
|
|
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 "<IMG SRC=\"$images_path/$faction/$unit/".$command_icon{$c}."\" HEIGHT=$size WIDTH=$size ALT=\"".&format_name( $command )."\">";
|
|
}
|
|
|
|
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 = "<A HREF=\"${file}\">$link_text</A>";
|
|
}
|
|
}
|
|
else {
|
|
my $file = "${faction}_techtree.html#${unit}_full";
|
|
if ( $file_only ) {
|
|
$link = $file;
|
|
}
|
|
else {
|
|
$link = "<A HREF=\"$file\">$link_text</A>";
|
|
}
|
|
}
|
|
|
|
return $link;
|
|
}
|
|
|
|
sub link_attack_and_armor_types {
|
|
my ( $link_to ) = @_;
|
|
my $html = "<a href=\"attack_and_armor_types.html#$link_to\">".&format_name($link_to)."</A>" 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 = "<TR><TD>Attack Command: $command_pretty<BR>".&html_icon_command( $c, 32 )."</TD><TD>\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<BR>\n";
|
|
}
|
|
elsif (
|
|
$attack_air{ $s }
|
|
) {
|
|
$target .= "Only air";
|
|
$full_attack_tmp .= "Target: $target units<BR>\n";
|
|
}
|
|
elsif (
|
|
$attack_land{ $s }
|
|
) {
|
|
$target .= "Only ground";
|
|
$full_attack_tmp .= "Target: $target units<BR>\n";
|
|
}
|
|
|
|
|
|
if ( $attack_range{ $s } > $max_range ) {
|
|
$max_range = $attack_range{ $s };
|
|
}
|
|
|
|
|
|
$full_attack_tmp .= "Strength: $attack_strenght{ $s }+-$attack_var{ $s }<BR>\n";
|
|
|
|
# show attack as range ( 100-200)
|
|
#$full_attack_tmp .= "Strength: ".($attack_strenght{ $s }-$attack_var{ $s })."-".($attack_strenght{ $s }+$attack_var{ $s })."<BR>\n";
|
|
|
|
#$full_attack_tmp .= "Strength-Variance: ".$attack_var{ $s }."<BR>\n";
|
|
#$full_attack_tmp .= "Strength: ".$attack_strenght{ $s }."<BR>\n";
|
|
#$full_attack_tmp .= "Strength-Variance: ".$attack_var{ $s }."<BR>\n";
|
|
|
|
$full_attack_tmp .= "Range: ".$attack_range{ $s }."<BR>\n";
|
|
if ( $splash{ $s } ) {
|
|
$full_attack_tmp .= "Splash-Radius: $splash_radius{ $s }<BR>\n";
|
|
$full_attack_tmp .= "Splash also damages own units!<BR>\n" if ($splash_damage_all{ $s });
|
|
}
|
|
$full_attack_tmp .= "Type: ".&link_attack_and_armor_types($attack_type{ $s })." <BR>\n";
|
|
$full_attack_tmp .= "Attack Speed: ".$speed{ $s }."<BR>\n";
|
|
$full_attack_tmp .= "Start Time: ".$attack_start_time{ $s }."<BR>\n";
|
|
$full_attack_tmp .= "Energy-Cost: ".$ep_cost{ $s }."<BR>\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\"<BR>\n";
|
|
$full_attack_tmp .= "(\"Hold Position\" requires ".&link_unit($faction, $requirement).")<BR>\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).")<BR>\n";
|
|
}
|
|
}
|
|
|
|
$full_attack_tmp .= "</TD></TR>\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 <IMG SRC=...> for resource (gold, wood, stone, ...)
|
|
my ($resource, $size) = @_;
|
|
return "<IMG SRC=\"images/resources/$resource.bmp\" HEIGHT=$size WIDTH=$size ALT=\"".&format_name( $resource )."\">";
|
|
}
|
|
|
|
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 =<TIPS>) {
|
|
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)</><I>$1<\/I></;
|
|
}
|
|
|
|
return "<H4>Choose faction: $tmp_links </H4><P>\n";
|
|
}
|
|
|
|
sub diagram_links_html {
|
|
|
|
|
|
my ( $faction ) = @_;
|
|
|
|
my $graph_file;
|
|
|
|
my $html="<H4>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 .= "<a href=\"$graph_file\">".&format_name($type)."</a> |\n";
|
|
}
|
|
chop $html;
|
|
chop $html;
|
|
chop $html;
|
|
$html .="</H4>\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 .= "<TABLE BORDER=1><TR><TH> </TH>\n";
|
|
foreach my $armor ( @armor_types ) {
|
|
$table .= "<TH> ".format_name($armor)." </TH>\n";
|
|
}
|
|
$table .= "</TR>\n";
|
|
|
|
foreach my $attack ( @attack_types ) {
|
|
$table .= "<TR><TH> ".&format_name( $attack)." </TH>\n";
|
|
foreach my $armor ( @armor_types ) {
|
|
my $mul = ($damage_multiplier{"$attack:$armor"} || 1);
|
|
if ( $mul > 1 ) {
|
|
#$table .= "<TD BGCOLOR=LIGHTGREEN>";
|
|
$table .= "<TD>";
|
|
}
|
|
elsif ( $mul < 1 ) {
|
|
#$table .= "<TD BGCOLOR=ORANGE>";
|
|
$table .= "<TD>";
|
|
}
|
|
else {
|
|
$table .= "<TD>";
|
|
}
|
|
|
|
|
|
$table .= " ".$mul;
|
|
$table .= "</TD>";
|
|
}
|
|
$table .= "</TR>\n";
|
|
}
|
|
$table .= "</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 "<H5>Values larger than 1 mean more damage, smaller than 1 less damage.</H5><P>\n";
|
|
|
|
print HTML $table;
|
|
|
|
my $pack_file_short = $pack_file;
|
|
$pack_file =~ s/.+\///;
|
|
print HTML "<H5>This information is extracted from $pack_file.</H5><P>\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 .= "<TD ALIGN=CENTER>";
|
|
my $full_tmp .= "<TR><TD>Movement Type:</TD><TD>";
|
|
|
|
# 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 .= "</TD>\n";
|
|
$full_tmp .= "</TD>\n";
|
|
|
|
return ( $overview_tmp, $full_tmp );
|
|
}
|
|
|
|
sub show_special_pages {
|
|
return "<H4>$special_pages</H4>";
|
|
}
|
|
|
|
sub do_upgrade_benefits {
|
|
|
|
# show the benefit of an upgrade
|
|
my ( $u ) = @_;
|
|
|
|
my $upgrade_benefits="";
|
|
my $upgrade_benefits_html="";
|
|
|
|
$upgrade_benefits_html .= "<TR><TD>Increase Hitpoints: </TD><TD>+".$max_hp{$u}."</TD></TR>\n" if ( $max_hp{$u} );
|
|
$upgrade_benefits_html .= "<TR><TD>Increase Energy-Points: </TD><TD>+".$max_ep{$u}."</TD></TR>\n" if ( $max_ep{$u} );
|
|
$upgrade_benefits_html .= "<TR><TD>Increase Sight: </TD><TD>+".$sight{$u}."</TD></TR>\n" if ( $sight{$u} );
|
|
$upgrade_benefits_html .= "<TR><TD>Increase Attack Strength: </TD><TD>+".$attack_strenght{$u}."</TD></TR>\n" if ( $attack_strenght{$u} );
|
|
$upgrade_benefits_html .= "<TR><TD>Increase Attack Range: </TD><TD>+".$attack_range{$u}."</TD></TR>\n" if ( $attack_range{$u} );
|
|
$upgrade_benefits_html .= "<TR><TD>Increase Armor: </TD><TD>+".$armor{$u}."</TD></TR>\n" if ( $armor{$u} );
|
|
$upgrade_benefits_html .= "<TR><TD>Increase Move: </TD><TD>+".$move_speed{$u}."</TD></TR>\n" if ( $move_speed{$u} );
|
|
$upgrade_benefits_html .= "<TR><TD>Increase Production Speed: </TD><TD>+".$production_speed{$u}."</TD></TR>\n" if ( $production_speed{$u} );
|
|
|
|
$upgrade_benefits = $upgrade_benefits_html;
|
|
# for overview remove HTML-tags
|
|
$upgrade_benefits =~ s/<\/?TD>//gi;
|
|
$upgrade_benefits =~ s/<TR>//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 );
|
|
}
|