FreewarWiki:Bot/Skripts/npcmap.pl
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;
}