Benutzer:Three Of Twelve/npcmap.pl

aus FreewarWiki, der Referenz für Freewar
Zur Navigation springen Zur Suche springen
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 %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; }
}

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)

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 @bounds = (400, 400, 2, 2);
while (<MAP>) {
    my ($gebiet, $betretbar, $x, $y, $npcname) = split(/;/);
    next if ($x < 2 || $y < 2 || $x > 400 || $y > 400);
    $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]);
    # 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);

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->colorAllocate($r, $g, $b);
    printf STDERR "%x %x %x = %x\n", $r, $g, $b,  $colors->{$key};
}
 
foreach my $x(keys(%mapcolor)) {
    next if ($x < 2 || $x > 400);
    foreach my $y(keys(%{$mapcolor{$x}})) {
        next if ($y < 2 || $x > 400);
        my $ax = ($x - $bounds[0]) * $width + ($width - $tilesize) / 2;
	my $ay = ($y - $bounds[1]) * $width + ($width - $tilesize) / 2;
	$map->filledRectangle($ax, $ay, $ax + $tilesize - 1, $ay + $tilesize - 1, $colors->{$mapcolor{$x}->{$y}->[0]});
	if (defined($mapcolor{$x}->{$y}->[1])) {
	    my $poly = new GD::Polygon();
	    $poly->addPt($ax + $tilesize - 1, $ay);
	    $poly->addPt($ax + $tilesize - 1, $ay + $tilesize - 1);
	    $poly->addPt($ax, $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->colorExact(($rgb1[0] + $rgb2[0]) / 2, ($rgb1[1] + $rgb2[1]) / 2, ($rgb1[2] + $rgb2[2]) / 2);
	    $intermediate = $map->colorAllocate(($rgb1[0] + $rgb2[0]) / 2, ($rgb1[1] + $rgb2[1]) / 2, ($rgb1[2] + $rgb2[2]) / 2) if ($intermediate == -1);
	    $map->line($ax + $tilesize - 1, $ay, $ax, $ay + $tilesize - 1, $intermediate);
	}
    }
}

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;
}
64px-PD-icon.svg.png Diese Artikel wurde von ihrem Urheberrechtsinhaber in die Gemeinfreiheit („public domain“) übergeben. Dies gilt weltweit und zeitlich unbeschränkt.

Für den Fall, dass dies nach lokaler Rechtslage nicht möglich ist, wie beispielsweise in Deutschland:
Der Urheberrechtsinhaber hat für diesen Artikel ein unbeschränktes Nutzungsrecht ohne Bedingungen im gesetzlich möglichen Umfang gewährt.