Kategorien
FreewarWiki:Bot/Skripts/npcmap.pl
< FreewarWiki:Bot | Skripts
use strict; use GD; # Farbdefinition fuer die NPC-Klassen my $colors = { "1" => 0x4db34d, "2" => 0x33e53f, "3" => 0x7ae533, "4" => 0xaae533, "5" => 0xd9e533, "6" => 0xe5c433, "7" => 0xe59833, "8" => 0xe56b33, "9" => 0xe53f33 }; # Argumente auswerten my $sourceimg; my $maplist; my $npclist; my $tilesize; my $alpha = 0; my %args = @ARGV; while (my ($key, $val) = each(%args)) { if ($key eq "-source") { $sourceimg = $val; } if ($key eq "-maplist") { $maplist = $val; } if ($key eq "-npclist") { $npclist = $val; } if ($key eq "-tilesize") { $tilesize = $val; } if ($key eq "-alpha") { $alpha = $val; } } die(" Aufruf: perl npcmap.pl [Optionen] > Zieldatei.png Moegliche Optionen: -source Karten-Quelldatei Name der Karten-Quelldatei (erforderlich) -maplist Kartenfeldliste Name der Datei mit der Kartenfeldliste im Format Gebiet;Begehbarkit;X;Y;NPCs;Bild-URL (erforderlich) -npclist NPC-Liste Name der Datei mit der NPC-Liste im Format NPC-Name;Staerke;LP;XP;GM;Vorkommen;Drops (erforderlich) -tilesize Zahl Groesse des eingefaerbten Teils pro Feld (optional, Standard: 60% der Kartenfeldgroesse) -alpha Zahl Alphakanal der Farbkacheln, Wert zwischen 0 und 127. 0 ist undurchsichtig, 127 vollstaendig transparent. Halbtransparenz bspw. wird also durch 63 erzielt. (optional, Standard: 0, also deckend) Beispiel: perl npclist.pl -source Karte.jpg -maplist maplist.txt -npclist npclist.txt > NPC-Karte.png ") if (not $sourceimg or not $maplist or not $npclist); # Bild-Objekt erstellen my $mapsource = GD::Image->new($sourceimg); my $map = GD::Image->new($mapsource->width, $mapsource->height, 1); $map->copy($mapsource, 0, 0, 0, 0, $map->width, $map->height); # Farbzuordnung und Grenzen ermitteln open (NPC, $npclist); my %npc; while (<NPC>) { my ($name, $atk, $lp, $xp, $gm) = split(/;/); $npc{$name}->{"atk"} = $atk; $npc{$name}->{"lp"} = $lp; $npc{$name}->{"xp"} = $xp; $npc{$name}->{"gm"} = $gm; } close(NPC); open (MAP, $maplist); my %mapcolor; my $min_x = 2; my $min_y = 2; my $max_x = 400; my $max_y = 400; my @bounds = ($max_x, $max_y, $min_x, $min_y); while (<MAP>) { my ($gebiet, $betretbar, $x, $y, $npcnames, $img, $passagen) = split(/;/); next if ($x < $min_x || $y < $min_y || $x > $max_x || $y > $max_y); $bounds[0] = $x if ($x < $bounds[0]); $bounds[1] = $y if ($y < $bounds[1]); $bounds[2] = $x if ($x > $bounds[2]); $bounds[3] = $y if ($y > $bounds[3]); foreach my $npcname(split(/\//, $npcnames)) { # es folgt eine Bastelheuristik, die die in der Kartenliste # auftretenden NPC-Namen mit denen aus der NPC-Liste in Ein- # klang bringt (Worttrennung entfernen usw.) my $tmpname = $npcname; $tmpname =~ s/- //g; if (!defined($npc{$tmpname})) { $tmpname = $npcname; $tmpname =~ s/- /-/g; if (!defined($npc{$tmpname})) { $tmpname = ucfirst($npcname); $tmpname =~ s/- //g; if (!defined($npc{$tmpname})) { $tmpname = ucfirst($npcname); $tmpname =~ s/- /-/g; $tmpname = $npcname if (!defined($npc{$tmpname})); } } } if (!defined($npc{$tmpname})) { print STDERR "NPC $npcname auf $x/$y nicht gefunden\n" unless ($npcname eq "" or $npcname eq "none"); } else { if (defined($mapcolor{$x}->{$y}->[0])) { if (npcclass($npc{$tmpname}) > $mapcolor{$x}->{$y}->[0]) { $mapcolor{$x}->{$y}->[1] = npcclass($npc{$tmpname}); } elsif (npcclass($npc{$tmpname}) != $mapcolor{$x}->{$y}->[0]) { $mapcolor{$x}->{$y}->[1] = $mapcolor{$x}->{$y}->[0]; $mapcolor{$x}->{$y}->[0] = npcclass($npc{$tmpname}); } } else { $mapcolor{$x}->{$y}->[0] = npcclass($npc{$tmpname}); }} } } # Kartenfeld-Groesse errechnen my $width = $map->width() / ($bounds[2] - $bounds[0] + 1); $tilesize = int($width * 0.6 + 0.5) if (!$tilesize); $map->alphaBlending(1); foreach my $key(keys(%{$colors})) { my $v = $colors->{$key}; printf STDERR "$key: %x->", $v; my $b = $v & 0xff; $v = $v >> 8; my $g = $v & 0xff; $v = $v >> 8; my $r = $v & 0xff; $colors->{$key} = $map->colorAllocateAlpha($r, $g, $b, $alpha); printf STDERR "%x %x %x = %x\n", $r, $g, $b, $colors->{$key}; } foreach my $x(keys(%mapcolor)) { next if ($x < $min_x || $x > $max_x); foreach my $y(keys(%{$mapcolor{$x}})) { next if ($y < $min_y || $y > $max_y); my $ax = ($x - $bounds[0]) * $width + ($width - $tilesize) / 2; my $ay = ($y - $bounds[1]) * $width + ($width - $tilesize) / 2; if (defined($mapcolor{$x}->{$y}->[1])) { my $poly = new GD::Polygon(); $poly->addPt($ax, $ay); $poly->addPt($ax + $tilesize - 2, $ay); $poly->addPt($ax, $ay + $tilesize - 2); $map->filledPolygon($poly, $colors->{$mapcolor{$x}->{$y}->[0]}); $poly = new GD::Polygon(); $poly->addPt($ax + $tilesize - 1, $ay + 1); $poly->addPt($ax + $tilesize - 1, $ay + $tilesize - 1); $poly->addPt($ax + 1, $ay + $tilesize - 1); $map->filledPolygon($poly, $colors->{$mapcolor{$x}->{$y}->[1]}); # Gleichheit der Farben! ;-) # Der "Fairness" halber wird die Mittellinie mit der Mischfarbe gezeichnet. # Naja, eigentlich sieht's einfach besser aus. my @rgb1 = $map->rgb($colors->{$mapcolor{$x}->{$y}->[0]}); my @rgb2 = $map->rgb($colors->{$mapcolor{$x}->{$y}->[1]}); my $intermediate = $map->colorAllocateAlpha(($rgb1[0] + $rgb2[0]) / 2, ($rgb1[1] + $rgb2[1]) / 2, ($rgb1[2] + $rgb2[2]) / 2, $alpha); $map->line($ax + $tilesize - 1, $ay, $ax, $ay + $tilesize - 1, $intermediate); } else { $map->filledRectangle($ax, $ay, $ax + $tilesize - 1, $ay + $tilesize - 1, $colors->{$mapcolor{$x}->{$y}->[0]}); } } } print $map->png; # NPCs in eine Klasse von 1 (schwach) bis 9 (stark) einordnen. # Geschieht hier einfach durch eine Betrachtung des Produkts # aus LP und A. sub npcclass { my ($npc) = @_; my $i = $npc->{"lp"} * $npc->{"atk"}; return 1 if ($i < 8); return 2 if ($i < 18); return 3 if ($i < 31); return 4 if ($i < 51); return 5 if ($i < 201); return 6 if ($i < 2001); return 7 if ($i < 10001); return 8 if ($i < 100001); return 9; }