#!/usr/bin/perl -w

# convert a bunch to halflife/worldcraft MAP text

# use WC;
# $map = asMap($bunch);

# (c) Copyright by Tels 1999-2000. All Rights Reserved. Do NOT distribute.
# Updates and support on bloodgate.com/thief

# todo: too much
#  * hue, saturation convert to rgb
#  * more constant
#  * conversion from brushes to vertex/triangles

# We dont need to support every entitiy/object here, because it is pretty generic. It
# just takes the objects from the bunch->{olist} and then put one after one. So if
# you set the proper properties on the objects beforehand, all will be well instantly.
# The only problem here is the conversion from Thief-style void-in-solid to hl/wc 
# solid-in-void brushes/triangles, which isnt done yet. I imagine that a solid-cubes
# only approach may work out. if you have to use extra objects and have no conversion
# yet, you may as well create the level from scratch, anyway. or we make an virtual
# "brush" called "triangles" and have it just a have the list of triangles. Custom 
# room&/thing generators could then generate the triangle list directly. Oh well...:/

# 2000-06-04 v0.0.1 Tels: first version, layout, light, object(), property()
# 2000-06-07 v0.0.2 Tels: fixed some stuff, tested it
                        
package Cowgen::WC;
require Exporter;
@ISA     = qw(Exporter);
@EXPORT  = qw(
           asMap

           WC_NORMAL WC_FLICKER_A WC_SLOW_STRONG_PULSE WC_CANDLE_A WC_FAST_STROBE 
           WC_GENTLE_PULSE WC_FLICEKR_B WC_CANDLE_B WC_CANDLE_C WC_SLOW_STROBE 
           WC_FLOUROSCENT_FLICKER WC_SLOW_PULSE_NO_BLACK
           );
#@EXPORT_OK = qw();

use Cowgen::Bunch;
use Cowgen::Dromed;
use strict 'vars';

my $opening = "{\n";
my $closing = "}\n";

my $VERSION = 0.02;
my $count = "000";

sub asMap
  { 
  # take a bunch, and create a map file from it
  # parameters: bunch, wadfiles
  my $b = shift || return "";
  my $wads = shift; # list of wadfiles
  my $m = $opening;
  $m .= '"classname" "worldspawn"'."\n";
  $m .= '"wad" "';
  foreach (@$wads)
    {
    $m .= "$_;";
    }
  $m .= "\"\n";
  # iterate over brushes first
  $b->iterate ( over => 'brushes', call => \&entity, params => [ \$m ]);
  $m .= $closing;
  # iterate over objects/lights
  $b->iterate ( over => 'objects,lights', call => \&entity, params => [ \$m ]);
  return $m; 
  }

sub entity
  {
  # bunch, entity, entitytype, maptext, called by asMap=>interate
  my ($b,$o,$t,$m) = @_;  
  $$m .= wc_brush($o) if ($t eq "brushes");
  $$m .= wc_brushLight($o) if ($t eq "lights");
  $$m .= wc_object($o) if ($t eq "objects");
  }

sub wc_brushLight
  {
  # create "fake" object and use object() to put it
  my $l = shift;
  my $o = {};
  $o->{x} = $l->{x};  
  $o->{y} = $l->{y};  
  $o->{z} = $l->{z};
  my $name = "light_".$count++;
  $o->{prop}->{name} = [ $name ];
  $o->{prop}->{classname} = [ "light" ];
  # note WC defines lights as red, green, blue, bright. At least the bright
  # value should be rendundand, since 128, 128, 128, 255 should be equal to
  # 255,255,255,128 (or am I wrong?)
  $o->{prop}->{_light} = [ $l->{red}, $l->{green}, $l->{blue}, 255 ]; 
  return wc_object($o);
  }

sub wc_brush
  {
  # take solid brush and put it
  my $b = shift;
  return "" if $b->{type} != solid();
  my $brush = "";
  return $brush;
  }

sub wc_object
  {
  # take ref to object and put it
  my $o = shift || return "";
  my $op = $o->{prop}; # properties
  my $e = $opening;
  foreach my $n (
  sort 
   { my ($c,$d); $c = $a; $d = $b; $c =~ s/[^a-z]//g; $d =~ s/[^a-z]//g; $c cmp $d; } 
   keys %{$op})
    {
    $e .= property($n,$op->{$n});
    }
  $e .= "\"origin\" \"$o->{x} $o->{y} $o->{z}\"\n";
  $e .= $closing;
  return $e;
  }

sub property
  {
  # take a ref to an property, and put it down
  # params: name, ref_to_array
  my $n = shift || "unknown_name";
  my $h = shift || [];
  my $line = "\"$n\" \"";
  foreach (@$h)
    {
    $line .= "$_ ";
    }
  $line =~ s/\s$//; # remove last char
  $line .= "\"\n";
  return $line;
  }

# some constants
use constant WC_NORMAL => 0;
use constant WC_FLICKER_A => 1;
use constant WC_SLOW_STRONG_PULSE => 2;
use constant WC_CANDLE_A => 3;
use constant WC_FAST_STROBE =>  4;
use constant WC_GENTLE_PULSE => 5;
use constant WC_FLICEKR_B => 6;
use constant WC_CANDLE_B => 7;
use constant WC_CANDLE_C => 8;
use constant WC_SLOW_STROBE => 9;
use constant WC_FLOUROSCENT_FLICKER => 10;
use constant WC_SLOW_PULSE_NO_BLACK => 11;

# sample formats:

# a brush light (or an object "light"")
#{
#"classname" "light"
#"_light" "243 183 22 100"
#"style" "6"
#"origin" "320 128 116"
#}

# an object properties: name => "monster_human_grunt"
#           angle => "191"
#           TriggerCondition => "0" (case sensitive? uh oh)
#           x,y,z => "936 -40 56"
#{
#"classname" "monster_human_grunt"
#"angle" "191"
#"TriggerCondition" "0"
#"origin" "936 -40 56"
#}

#{
#"classname" "worldspawn"
#"wad" "\games\halflife\valve\halflife.wad;\games\halflife\valve\decals.wad"
#{
#( 207 152 144 ) ( 239 152 144 ) ( 239 152 160 ) C1A1W1D -15 0 0 1.000000 1.000000
# etc

1;

