"""game_projectiles.py

   This is a basic setup for a projectile system

   Adventures on Planet Zephulor by Aaron Hachez. 

   All code, artwork, and sound copyright 2003, Aaron Hachez.

   ----------------------------------------------------------------------------------------

   This file is part of "Adventures on Planet Zephulor".

   A copy of the GNU General Public License should be included with any
   redistribution of this program in a file named "COPYING.txt".

   "Adventures on Planet Zephulor" is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   "Adventures on Planet Zephulor" is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with "Adventures on Planet Zephulor"; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

   ----------------------------------------------------------------------------------------

   "Adventures on Planet Zephulor" uses the following libraries:

   PyGame
   SDL

   Both are at the time of this writing, licensed under the GNU LGPL. Please see
   the included file LGPL for details 
"""

import sys
import pygame
import myimg

class base_bullet:
    """A single bullet"""

    # This id indicates that this is a non-falling/non-jumping object
    id = 9

    # The screen rect location of this bullet
    screenrect = None

    # The bounding rect for this bullet
    boundrect = None

    # The map rect
    maprect = None

    # The sprite width and height
    width = 16
    height = 16

    # The x and y velocity
    xvel = 12
    yvel = 0

    # The ammount of decay in x and y velocities
    xdecay = 0
    ydecay = 0

    # Hit points, how much damage it takes to destroy this bullet
    hitpoints = 1

    # The damage this bullet causes
    dodamage = 1

    # Offscreen flag
    offscreen = 0

    def __init__(self, xystart=(0, 0), mapxystart=(0, 0), xyvel=(0, 0), boundoffset=[0, 0, 0, 0], damage=1):
        """Initialize bullet object"""

        self.screenrect = [0, 0, self.width, self.height]
        self.boundrect = [ boundoffset[0],
                           boundoffset[1],
                           self.width - boundoffset[2],
                           self.height - boundoffset[3] ]

        self.maprect = [0, 0, self.width, self.height]

        self.screenrect[0] += xystart[0]
        self.screenrect[1] += xystart[1]
        self.screenrect[2] += xystart[0]
        self.screenrect[3] += xystart[1]

        # Adjust bound rect to proper start position
        self.boundrect[0] += mapxystart[0]
        self.boundrect[1] += mapxystart[1]
        self.boundrect[2] += mapxystart[0]
        self.boundrect[3] += mapxystart[1]

        # Adjust map rect to proper start position
        self.maprect[0] += mapxystart[0]
        self.maprect[1] += mapxystart[1]
        self.maprect[2] += mapxystart[0]
        self.maprect[3] += mapxystart[1]

        self.xvel = xyvel[0]
        self.yvel = xyvel[1]

        # Copy damage modifier
        self.dodamage = damage

    def update(self):
        """Update bullet position etc"""

        # We must update all of the associated rects

        self.ydecay += self.ydecay
        self.xdecay += self.xdecay

        self.xdecay = int(self.xdecay)
        self.ydecay = int(self.ydecay)

        # Screen rect, the position on screen
        self.screenrect[0] += self.xvel + self.xdecay
        self.screenrect[1] += self.yvel + self.ydecay
        self.screenrect[2] += self.xvel + self.xdecay
        self.screenrect[3] += self.yvel + self.ydecay

        # Bound rect, the actual bounding box
        self.boundrect[0] += self.xvel + self.xdecay
        self.boundrect[1] += self.yvel + self.ydecay
        self.boundrect[2] += self.xvel + self.xdecay
        self.boundrect[3] += self.yvel + self.ydecay

        # map rect, the actual maping box
        self.maprect[0] += self.xvel + self.xdecay
        self.maprect[1] += self.yvel + self.ydecay
        self.maprect[2] += self.xvel + self.xdecay
        self.maprect[3] += self.yvel + self.ydecay

    def adjposscr(self, x=None, y=None):
        """If x (or y) move screen coords by value of x (or y). Default arguments are x=None and y=None"""

        # Add x adjustment to xpos
        if x != None:
            self.screenrect[0] += x
            self.screenrect[2] += x

        # Add y adjustment to ypos
        if y != None:
            self.screenrect[1] += y
            self.screenrect[3] += y

    def adjposmap(self, x=None, y=None):
        """If x (or y) move bound by value of x (or y). Default arguments are x=None and y=None"""

        # Add x adjustment to xpos
        if x != None:
            self.boundrect[0] += x
            self.boundrect[2] += x
            self.maprect[0] += x
            self.maprect[2] += x

        # Add y adjustment to ypos
        if y != None:
            self.boundrect[1] += y
            self.boundrect[3] += y
            self.maprect[1] += y
            self.maprect[3] += y

    def ifcollide(self, overlaprect, tiledata, top, left):
        """Handle collision"""

        # If there is not any tile data, we don't care about the tile
        if tiledata:
            # If the tile data does not indicate the tile as passable
            if not tiledata[0]:
                # Destroy bullet
                self.getdamage(1)

    def ifcollidechar(self, overlaprect, char, top, left):
        """Handle collision with char"""

        if char.jumpbonus or char.firebonus or char.invulnbonus or char.dodamage < 0:
            return

        # Deliver damage to the char in question
        char.getdamage(self.dodamage)

        # Destroy bullet
        self.getdamage(1)

    def getdamage(self, damage):
        """Take damage and apply it, then return remaining hitpoints"""

        self.hitpoints -= damage

        return(self.hitpoints)

class bullet_group:
    """A group of bullets"""

    # A list containing the bullets
    bulletlist = None

    # The image for this bullet
    bulletimage = None

    width = 16
    height = 16

    def __init__(self, bulletfile):
        """Initialize bullet group"""

        self.bulletlist = []

        self.load(bulletfile)

    def load(self, filename):
        """Load bullet image"""

        self.bulletimage = myimg.loadimage(filename, colorkey=-1)

    def add(self, (x, y), (x2, y2), (xvel, yvel), dodamage=1):
        """Add a bullet to the list"""

        self.bulletlist.append( base_bullet( (x, y), (x2, y2), (xvel, yvel), damage=dodamage ) )

    def delete(self, bullet):
        """Remove a bullet from the list"""

        self.bulletlist.remove(bullet)

    def adjposscr(self, x=None, y=None):
        """If x (or y) move all bullet screen coords by value of x (or y). Default arguments are x=None and y=None"""

        for bullet in self.bulletlist:
            # Add x adjustment to xpos
            if x != None:
                bullet.screenrect[0] += x
                bullet.screenrect[2] += x
    
            # Add y adjustment to ypos
            if y != None:
                bullet.screenrect[1] += y
                bullet.screenrect[3] += y
    
    def update(self):
        """Run update routines for bullets"""
        
        for bullet in self.bulletlist:
            bullet.update()
            
            # If this bullets hit points are at or below zero
            if bullet.hitpoints <= 0:
                # Remove it from the list
                self.delete(bullet)

    def draw(self, screen):
        """Draw each bullet to the screen"""

        for bullet in self.bulletlist:
            screen.blit(self.bulletimage, (bullet.screenrect[0], bullet.screenrect[1]) )
