User:Barracuda/wiki-fgd.pl
This is a quick, buggy and very dirty Perl script to convert a FGD file into wikitext. It creates a .wiki file for each entity it can find in the given FGD. Feel free to edit this page for improvements and bug fixes.
#!/usr/bin/perl -w
use strict;
die "Usage: wiki-fgd.pl <fgd> [game]\n" if @ARGV < 1;
my $fgd_file = $ARGV[0];
my $game = defined($ARGV[1]) ? $ARGV[1] : "base";
my $read_entry = 0;
my @entry;
my $wiki_dir = $fgd_file;
$wiki_dir =~ s/\..*//;
mkdir $wiki_dir unless -d $wiki_dir;
$/ = "\r\n";
open(FGD, "<$fgd_file") or die "Couldn't open '$fgd_file': $!\n";
while (<FGD>) {
if (m/^@(?!include)/) {
$read_entry = 1;
}
next if not $read_entry;
# skip comments
next if m!^\s*//!;
push(@entry, $_);
if (m/^\]/ || m/\[\]/) {
$read_entry = 0;
parse_entry(join('', @entry));
@entry = ();
}
}
close(FGD);
sub parse_entry {
$_ = shift;
my @keyvalues = ();
my @flags = ();
my @inputs = ();
my @outputs = ();
if (m/^@([a-zA-Z]+)Class( base\(([^)]*)\))?[^=]+= *(\w+)(\s+:\s+"([^[]+)")?/) {
my ($type, $base, $name, $desc) = ($1, $3, $4, $6);
#keyvalues
while (m/(\w+)\((\w+)\)\s*:\s*"([^"]*)"\s*:\s*([0-9.-]+|"[^"]*")?(\s*:\s*"([^"]*)")?(\s*=\s*\[([^]]+)\])?/g) {
my ($vname, $vtype, $name, $default, $desc, $choices) = ($1, $2, $3, $4, $6, $8);
my $extra = '';
if (defined($choices)) {
my $tmp = $choices;
# remove whitespaces
$tmp =~ s/\s+//g;
# check for yes/no -> boolean
if ($tmp eq '0:"No"1:"Yes"') {
$vtype = 'boolean';
} else {
while ($choices =~ m/([0-9.-]+)\s*:\s*"([^"]+)"/g) {
my ($value, $desc) = ($1, $2);
$extra .= "\n:* $value : $desc";
}
}
}
$name = escape_param($name);
my $kv = "{{KV|$name|$vtype";
if (defined($desc)) {
$desc = escape_param($desc);
$kv .= "|$desc";
}
$kv .= "}}$extra";
push(@keyvalues, $kv);
}
#flags
while (m/spawnflags\((\w+)\)\s*=\s*\[([^]]+)\]/g) {
my ($name, $flag_list) = ($1, $2);
while ($flag_list =~ m/(\d+)\s*:\s*"([^"]+)"/g) {
my ($value, $desc) = ($1, $2);
push(@flags, "* $value : $desc");
}
}
#in-/outputs
while (m/(input|output)\s+(\w+)\((\w+)\)( *: *"([^"]*)")?/g) {
my ($iotype, $name, $ptype, $desc) = ($1, $2, $3, $5);
$name = escape_param($name);
my $io = "{{IO|$name";
if (defined($desc) && $desc) {
$desc = escape_param($desc);
$io .= "|$desc";
}
if ($ptype ne "void") {
$io .= "|param=$ptype";
}
$io .= "}}";
if ($iotype eq "input") {
push(@inputs, $io);
} else {
push(@outputs, $io);
}
}
#base template
if (defined($base)) {
my @bases = split(/,/, $base);
foreach (@bases){
$_ = trim($_);
if ($_ eq 'Targetname') {
push(@keyvalues, "{{KV Targetname}}");
push(@inputs, "{{I Targetname}}");
push(@outputs, "{{O Targetname}}");
} elsif ($_ eq 'Parentname') {
push(@keyvalues, "{{KV Parentname}}");
push(@inputs, "{{I Parentname}}");
} elsif ($_ eq 'Angles') {
push(@keyvalues, "{{KV Angles}}");
} elsif ($_ eq 'EnableDisable') {
push(@keyvalues, "{{KV EnableDisable}}");
push(@inputs, "{{I EnableDisable}}");
} elsif ($_ eq 'Toggle') {
push(@inputs, "{{I Toggle}}");
} elsif ($_ eq 'Trigger') {
push(@keyvalues, "{{KV Trigger}}");
push(@flags, "{{Fl Trigger}}");
push(@inputs, "{{I Trigger}}");
push(@outputs, "{{O Trigger}}");
} elsif ($_ eq 'Origin') {
push(@keyvalues, "{{KV Origin}}");
} elsif ($_ eq 'Global') {
push(@keyvalues, "{{KV Global}}");
} elsif ($_ eq 'Inputfilter') {
push(@keyvalues, "{{KV InputFilter}}");
} elsif ($_ eq 'Shadow') {
push(@keyvalues, "{{KV Shadow}}");
push(@inputs, "{{I Shadow}}");
} elsif ($_ eq 'Door') {
push(@keyvalues, "{{KV Door}}");
push(@flags, "{{Fl Door}}");
push(@inputs, "{{I Door}}");
push(@outputs, "{{O Door}}");
} elsif (m/^(PropDynamicBase|prop_dynamic_base)$/) {
push(@keyvalues, "{{KV PropDynamicBase}}");
push(@flags, "{{Fl PropDynamicBase}}");
push(@inputs, "{{I PropDynamicBase}}");
push(@outputs, "{{O PropDynamicBase}}");
} elsif ($_ eq 'BasePropPhysics') {
push(@keyvalues, "{{KV BasePropPhysics}}");
push(@flags, "{{Fl BasePropPhysics}}");
push(@inputs, "{{I BasePropPhysics}}");
push(@outputs, "{{O BasePropPhysics}}");
} elsif ($_ eq 'BaseNPC') {
push(@keyvalues, "{{KV BaseNPC}}");
push(@flags, "{{Fl BaseNPC}}");
push(@inputs, "{{I BaseNPC}}");
push(@outputs, "{{O BaseNPC}}");
} elsif ($_ eq 'RenderFields') {
push(@keyvalues, "{{KV RenderFields}}");
push(@inputs, "{{I RenderFields}}");
push(@outputs, "{{O RenderFields}}");
} elsif ($_ eq 'DXLevelChoice') {
push(@keyvalues, "{{KV DXLevelChoice}}");
} elsif ($_ eq 'BaseFilter') {
push(@keyvalues, "{{KV BaseFilter}}");
push(@inputs, "{{I BaseFilter}}");
push(@outputs, "{{O BaseFilter}}");
} elsif ($_ eq 'Reflection') {
push(@keyvalues, "{{KV Reflection}}");
push(@inputs, "{{I Reflection}}");
} elsif ($_ eq 'TalkNPC') {
push(@keyvalues, "{{KV TalkNPC}}");
push(@inputs, "{{I TalkNPC}}");
} elsif ($_ eq 'Weapon') {
push(@inputs, "{{O Weapon}}");
} elsif ($game eq 'tf2') {
# TF2
if ($_ eq 'ObjectABS') {
push(@keyvalues, "{{KV TFObject}}");
push(@inputs, "{{I TFObject}}");
push(@outputs, "{{O TFObject}}");
} elsif ($_ eq 'BaseObject') {
push(@keyvalues, "{{KV TFBaseObject}}");
push(@flags, "{{Fl TFBaseObject}}");
} elsif (m/^(TeamNum|TFTeam)$/) {
push(@keyvalues, "{{KV TFTeam}}");
push(@flags, "{{I TFTeam}}");
} elsif ($_ eq 'GameType') {
push(@keyvalues, "{{KV TFGameType}}");
} else {
warn "Unknown base: $_ for $name";
}
} elsif ($game eq 'portal2') {
# Portal 2
if ($_ eq 'LinkedPortalDoor') {
push(@keyvalues, "{{KV LinkedPortalDoor}}");
push(@inputs, "{{I LinkedPortalDoor}}");
push(@outputs, "{{O LinkedPortalDoor}}");
} elsif ($_ eq 'BaseProjector') {
push(@keyvalues, "{{KV BaseProjector}}");
push(@inputs, "{{I BaseProjector}}");
} else {
warn "Unknown base: $_ for $name";
}
} else {
warn "Unknown base: $_ for $name";
}
}
}
if ($type =~ /^(Point|NPC|Filter|Base)$/) {
$type = "point";
} elsif ($type eq "Solid") {
$type = "brush";
} else {
warn "Unknown class type: $type";
return;
}
if (defined($desc)) {
$desc =~ s/"\s*\+\s*"//g;
$desc =~ s/\\n/\n/g;
$desc = escape_param($desc);
}
#printing
my $wiki_file = "$wiki_dir/$name.wiki";
open(WIKI, ">$wiki_file") or die "Couldn't open '$wiki_file': $!\n";
if (!defined($desc)) {
print WIKI "{{stub}}\n\n";
}
print WIKI "{{$game $type|$name}}\n\n";
print WIKI "==Entity description==\n";
if (defined($desc)) {
print WIKI "$desc\n\n";
} else {
print WIKI "{{todo|add description}}\n\n";
}
print_section("Keyvalues", @keyvalues);
print_section("Flags", @flags);
print_section("Inputs", @inputs);
print_section("Outputs", @outputs);
close(WIKI);
print "Created $wiki_file\n";
} else {
warn "Unrecognized entry";
}
}
sub print_section {
my ($name, @array) = @_;
if (scalar(@array) > 0) {
print WIKI "==$name==\n";
print WIKI join("\n", @array);
print WIKI "\n\n";
}
}
sub escape_param {
my $string = shift;
$string =~ s/=/{{=}}/g;
return $string;
}
sub trim
{
my $string = shift;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
}