=comment

Doodad members are:

T		int			The Doodad's type. 0 means text.
OWNER	int			The Doodad's owner (0 for player 1, 1 for player 2, other means no owner)
HOSTILE	int			1 if the doodad can collision with players and damage them.
LIFETIME int		The amount of time before this doodad dies. -1 means infinite.

POS		(int,int)	The Doodad's logical position.
SIZE	(int,int)	The Doodad's physical size.
SPEED	(int,int)	The Doodad's logical speed.
ACCEL	(int,int)	The Doodad's logical acceleration.
DIR		int			1: heading right; -1: heading left (implies flipped state)

GFXOWNER int		The Doodad's graphics owner (0 for player 1, 1 for player 2, -1 means global)
FIRSTFRAME int		The first frame of the doodad (only meaningful if GFXOWNER is a player).
FRAMES	int			The number of frames.
SA		int			Animation speed
F		int			The Doodad's frame.
TEXT	string		The text displayed in a text doodad.

INITCODE sub		This will run then the doodad is created.
UPDATECODE sub		This will be ran instead of MoveDoodad if defined.



Doodad types are:
0		Text
1		Zoli's shot
2		UPi's shot
3		UPi's explosion
4		UPi's familiar
5		Tooth

=cut


use strict;

require 'Collision.pl';


package Doodad;


%Doodad::DoodadDefinitions = (
'ZoliShot' => {
	'T'  => 1,					'HOSTILE' => 1,				'LIFETIME' => -1,
	'SIZE'	=> [ 64, 64 ],		'SPEED'	=> [ 48, -25 ],		'ACCEL'	=> [ 0, 2 ],

	'GFXOWNER' => -1,			'FIRSTFRAME' => 0,			'FRAMES' => 6,
	'SA' => 1/10,
},

'Tooth' => {
	'T' => 5,					'HOSTILE' => 0,				'LIFETIME' => -1,
	'SIZE'	=> [ 24, 24 ],		'SPEED' => [ 20, -20 ],		'ACCEL' => [ 0, 2 ],
	'GFXOWNER' => -1,			'FIRSTFRAME' => 0,			'FRAMES' => 12,
	'SA' => 1/4,
	'INITCODE' => sub {
		my ($self) = @_;
		$self->{SA} = $self->{SA} * $self->{DIR};
	},
	'UPDATECODE' => sub {
		my ($self) = @_;
		if ( $self->{POS}->[1] > (440 * $::GAMEBITS2) ) {
			$self->{SPEED}->[1] = -abs( $self->{SPEED}->[1] / 2 );
			$self->{POS}->[1] = 439 * $::GAMEBITS2;
		}
		MoveDoodad( $self );
	},
},

'UPiShot' => {
	'T' => 2,					'HOSTILE' => 1,				'LIFETIME' => -1,
	'SIZE' => [170, 22],		'SPEED' => [ 48, 0 ],		'ACCEL' => [ 0, 0 ],
	
	'GFXOWNER' => 0,			'FIRSTFRAME' => 340,		'FRAMES' => 5,
	'SA' => 1/5,
},

'UPiExplosion' => {
	'T' => 3,					'HOSTILE' => 0,				'LIFETIME' => 30,
	'SIZE' => [ 58, 80],		'SPEED' => [ 0, 0 ],		'ACCEL' => [ 0, 0 ],
	
	'GFXOWNER' => 0,			'FIRSTFRAME' => 345,		'FRAMES' => 15,
	'SA' => 1/2,
},

'UPiFamiliar' => {
	'T' => 4,					'HOSTILE' => 0,				'LIFETIME' => -1,
	'SIZE' => [ 20, 20],		'SPEED' => [ 0, 0 ],		'ACCEL' => [ 0, 0 ],
	
	'GFXOWNER' => 0,			'FIRSTFRAME' => 360,		'FRAMES' => 3,
	'SA' => 1/10,				
	
	'ANGLE' => 0,
	'UPDATECODE' => sub {
		my ($self) = @_;
		my ($fighter, $frame, $head, $targetposx, $targetposy);
		
		$fighter = $::Fighters[$self->{OWNER}];
		$frame = $fighter->{FRAMES}->[$fighter->{FR}];
		$head = $frame->{head};

		$self->{ANGLE} += 0.05 * $self->{DIR};
		$targetposx = $fighter->{X} + $head->[0] * $::GAMEBITS2 * $fighter->{DIR} + sin( $self->{ANGLE} ) * 300;
		$targetposy = $fighter->{Y} + $head->[1] * $::GAMEBITS2 + cos( $self->{ANGLE} ) * 300;
		
		if ( $fighter->{HP} > 0 )
		{
			$self->{ACCEL}->[0] = ($targetposx - $self->{POS}->[0] ) / 200;
			$self->{ACCEL}->[1] = ($targetposy - $self->{POS}->[1] ) / 200;
			$self->{SPEED}->[0] += $self->{ACCEL}->[0];
			$self->{SPEED}->[1] += $self->{ACCEL}->[1];
			$self->{SPEED}->[0] *= 0.95;
			$self->{SPEED}->[1] *= 0.95;
		}
		
		#$self->{SPEED}->[0] = ($targetposx - $self->{POS}->[0]) / 30;
		#$self->{SPEED}->[1] = ($targetposy - $self->{POS}->[1]) / 30;
		$self->{POS}->[0] += $self->{SPEED}->[0];
		$self->{POS}->[1] += $self->{SPEED}->[1];

		$self->{F} += $self->{SA};
		$self->{F} -= $self->{FRAMES} if $self->{F} > ($self->{FRAMES} + $self->{FIRSTFRAME});

		return 0;
	},
},

);


=comment

CreateDoodad creates a new doodad, and appends it to the global doodad list,
@Doodads. The parameters are:
	x		int		The logical horizontal position of the center of the doodad
	y		int		The logical vertical position of the center of the doodad
	t		string	The type of the doodad (doodad types are described above)
	dir		int		1 or -1
	owner	int		The number of the player who 'owns' the doodad (0 or 1, anything else means no owner)

=cut

sub CreateDoodad
{
	my ($x, $y, $t, $dir, $owner) = @_;
	my ($doodad, $doodaddef, $w, $h);
	
	$doodaddef = $Doodad::DoodadDefinitions{$t};
	
	if ( ( not defined $doodaddef ) and $t != 0 )
	{
		print "CreateDoodad: Doodad $doodaddef doesn't exist!\n";
		return;
	}
	
	if ( defined $doodaddef )
	{
		$w = $doodaddef->{SIZE}->[0];
		$h = $doodaddef->{SIZE}->[1];
		$t = $doodaddef->{T};
	}
	else
	{
		$w = $h = $t = 0;
		$doodaddef = {};
	}
	
	$doodad = {
		'T'			=> $t,
		'OWNER'		=> $owner,
		'HOSTILE'	=> 0,
		'LIFETIME'	=> -1,
		
		'POS'		=> [ $x - $w * $::GAMEBITS2 / 2, $y - $h * $::GAMEBITS2 / 2 ],
		'SIZE'		=> [ $w, $h ],
		'SPEED'		=> [ 0, 0 ],
		'ACCEL'		=> [ 0, 0 ],
		'DIR'		=> $dir,
		
		'GFXOWNER'	=> $owner,
		'FIRSTFRAME'=> 0,
		'FRAMES'	=> 1,
		'SA'		=> 0,
		'F'			=> 0,
		'TEXT'		=> '',
		%{$doodaddef},
	};
	
	$doodad->{SIZE}  = [@{$doodaddef->{SIZE}} ] if defined $doodaddef->{SIZE};
	$doodad->{SPEED} = [@{$doodaddef->{SPEED}}] if defined $doodaddef->{SPEED};
	$doodad->{ACCEL} = [@{$doodaddef->{ACCEL}}] if defined $doodaddef->{ACCEL};
	$doodad->{F}	 = $doodad->{FIRSTFRAME};
	
	$doodad->{SPEED}->[0] *= $doodad->{DIR};
	$doodad->{ACCEL}->[0] *= $doodad->{DIR};
	$doodad->{GFXOWNER} = $owner if $doodad->{GFXOWNER} >= 0;
	
	if ( exists $doodad->{INITCODE} )
	{
		# Call the updatecode.
		&{$doodad->{INITCODE}}( $doodad );
	}
	
	push @::Doodads, ($doodad);
	return $doodad;
}



sub CreateTextDoodad
{
	my ($x, $y, $owner, $text) = @_;
	my ($self);
	$self = CreateDoodad($x, $y, 0, 0, $owner);
	$self->{'TEXT'} = $text;
	$self->{'GFXOWNER'} = -1;
	return $self;
}



sub RewindData
{
	my ($self) = @_;

	return {
		%{$self},
		POS			=> [ @{$self->{POS}} ],
		SIZE		=> [ @{$self->{SIZE}} ],
		SPEED		=> [ @{$self->{SPEED}} ],
		ACCEL		=> [ @{$self->{ACCEL}} ],
	}
}


=comment
UpdateDoodad is called once every game tick.

It should return 0 if the doodad is still active.
If UpdateDoodad returns nonzero, it will be removed in this tick and
deleted.
=cut

sub UpdateDoodad
{
	my ($doodad) = @_;
	
	if ( exists $doodad->{UPDATECODE} )
	{
		# Call the updatecode.
		return &{$doodad->{UPDATECODE}}( $doodad );
	}
	else
	{
		return MoveDoodad( $doodad );
	}
}


sub MoveDoodad
{
	my ($doodad) = @_;
	
	if ( $doodad->{LIFETIME} >= 0 )
	{
		$doodad->{LIFETIME} -= 1;
		if ( $doodad->{LIFETIME} < 0 )
		{
			# Doodad dies.
			return 1;
		}
	}

	$doodad->{SPEED}->[0] += $doodad->{ACCEL}->[0];
	$doodad->{SPEED}->[1] += $doodad->{ACCEL}->[1];
	$doodad->{POS}  ->[0] += $doodad->{SPEED}->[0];
	$doodad->{POS}  ->[1] += $doodad->{SPEED}->[1];
	
	$doodad->{F} += $doodad->{SA};
	$doodad->{F} -= $doodad->{FRAMES} if $doodad->{F} > ($doodad->{FRAMES} + $doodad->{FIRSTFRAME});
	$doodad->{F} += $doodad->{FRAMES} if $doodad->{F} < $doodad->{FIRSTFRAME};

	if ( $doodad->{POS}->[0] > $::BGWIDTH2 ) { return 1; }
	if ( $doodad->{POS}->[0] < $doodad->{SIZE}->[0] * $::GAMEBITS2 ) { return 1; }
	if ( $doodad->{POS}->[1] > $::SCRHEIGHT2 ) { return 1; }
	if ( $doodad->{POS}->[1] < $doodad->{SIZE}->[1] * $::GAMEBITS2 ) { return 1; }
	
	if ( $doodad->{HOSTILE} )
	{
		CheckDoodadHit($doodad);
	}
	
#	print "Doodad: POS=", join(',', @{$doodad->{POS}}), 
#		  "; SPEED=", join(',', @{$doodad->{SPEED}}), 
#		  "; ACCEL=", join(',', @{$doodad->{ACCEL}}), "\n";
	
	return 0;
}


sub CheckDoodadHit($)
{
	my ( $self ) = @_;

	my ( @poly, $x, $y, $w, $h, $i, $fighter );
	$x = $self->{POS}->[0] / $::GAMEBITS2;
	$y = $self->{POS}->[1] / $::GAMEBITS2;
	$w = $self->{SIZE}->[0];
	$h = $self->{SIZE}->[1];
	
	for ( $i=0; $i<$::NUMPLAYERS; ++$i )
	{
		next if $i == $self->{OWNER};
		$fighter = $::Fighters[$i];
		
		@poly = (
			$x, $y,
			$x+$w, $y,
			$x+$w, $y+$h,
			$x, $y+$h );

		if ( $fighter->IsHitAt( \@poly ) )
		{
			DoHitPlayer($self, $fighter);
		}
	}
	
}


sub DoHitPlayer($$)
{
	my ($self,$player) = @_;

	$self->{HOSTILE} = 0;
	$player->HitEvent( $::Fighters[$self->{OWNER}], 'Hit', $self->{T} );
}
=cut

return 1;

