FreewarWiki:Bot/Skripts/npcmap.pl

aus FreewarWiki, der Referenz für Freewar
Zur Navigation springen Zur Suche springen
Dieses Script ist hier lediglich archiviert und nicht direkt lauffähig. Wenn Du es benutzen möchtest, musst Du es lokal abspeichern und mit einem geeigneten Interpreter ausführen lassen. Zum Übernehmen solltest Du nicht den unten angezeigten Text verwenden, sondern den Quelltext des Wiki-Artikels: Dazu wählst Du Bearbeiten und kopierst den (meist zwischen PRE-Tags eingefassten) Scripttext.

Sofern Du die Scripte dauerhaft lokal abgespeichert hältst, solltest Du sie vor der nächsten Ausführung darauf prüfen, ob sie noch aktuell sind.

Letzter Bearbeiter: Cembon — Zuletzt bearbeitet: 16.03.2012
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;
}