FreewarWiki:Bot/Skripts/npcmap.pl: Unterschied zwischen den Versionen

aus FreewarWiki, der Referenz für Freewar
Zur Navigation springen Zur Suche springen
Keine Bearbeitungszusammenfassung
 
Keine Bearbeitungszusammenfassung
Zeile 1: Zeile 1:
<pre>
use strict;
use strict;
use GD;
use GD;
Zeile 191: Zeile 192:
     return 9;
     return 9;
}
}
</pre>

Version vom 16. Februar 2009, 19:04 Uhr

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;
}