###########################################################
# EnemyFormations - Railshooter Module
# Creates Enemy Formations
###########################################################

# DESCRIPTION:
# These Functions can be used to create a formation made up of n
# enemies of the specified type.  The enemies are then moved as a
# group using one Lerp Interval or a Sequence of Lerp Intervals.


from direct.showbase.ShowBaseGlobal import *
from direct.interval.IntervalGlobal import *
from direct.task import Task
from pandac.PandaModules import *

# Import Railshooter modules
import ClassGlobals
import EnemyCraft
import Level1
import EnemyBoss


########################################
# Wall Formation/Block Formation
########################################
# Create n Enemies in a Wall Formation (Block Formation)
def enemyWall(n, height, enemyClass, speed, numShots, accuracy, shootDelay):

    # Set Raildummy Position
    startZ = 15
    startX = 0
    startY = 0

    # Set waiting time before Player ready to Shoot
    shootWait = 4.0 

    # Dummy Object - Moves the Entire Formation
    formation = Level1.railDummy.attachNewNode('formation' + str(ClassGlobals.formationNum))
    ClassGlobals.formationList[ClassGlobals.formationNum] = formation

    currentNum = ClassGlobals.formationNum
    ClassGlobals.formationNum += 1

    # Create n enemies in formation
    for y in range(n):
	# Make Enemy
	e1 = EnemyCraft.enemyCraft(ClassGlobals.enemyNum, enemyClass, numShots, accuracy, shootWait, shootDelay, speed)
	e1.enemy.reparentTo(formation)

	# Add to List of Enemies and update count
	ClassGlobals.enemyList[ClassGlobals.enemyNum] = e1
        ClassGlobals.enemyNum += 1

	# For the First Ship
	if y == 0:
	    e1.enemy.setPos(startX, 0, startZ+height)
	    counter = 1	

	# Odd numbered Ships go to the Left
	elif (y % 2) == 1:
	    e1.enemy.setPos(startX+10*counter, 0, startZ+height)
	    
	# Even numbered Ships on the Right
	elif (y % 2) == 0:
 	    e1.enemy.setPos(startX-10*counter, 0, startZ+height)
	    counter += 1

    # Interval for Moving the Formation
    flyAnim1 = formation.posInterval(speed, Point3(startX, startY, startZ+height), startPos=Point3(startX, startY+1000, startZ+height),  bakeInStart=0)

    fly1 = Sequence(flyAnim1, Func(ClassGlobals.formationList[currentNum].removeNode), name='fly1' + str(ClassGlobals.enemyNum))
    fly1.start()


########################################
# Sneak Attack with Wall Formation
########################################
# Create n Enemies in a Wall Formation flying from behind player
def enemySneakAttack(n, height, enemyClass, speed, numShots, accuracy, shootDelay):

    # Set Raildummy Position
    startZ = 15
    startX = 0
    startY = 0

    # Set waiting time before Player ready to Shoot
    shootWait = 4.0 

    # Dummy Object - Moves the Entire Formation
    formation = Level1.railDummy.attachNewNode('formation' + str(ClassGlobals.formationNum))
    ClassGlobals.formationList[ClassGlobals.formationNum] = formation

    currentNum = ClassGlobals.formationNum
    ClassGlobals.formationNum += 1

    # Create n enemies in formation
    for y in range(n):
	# Make Enemy
	e1 = EnemyCraft.enemyCraft(ClassGlobals.enemyNum, enemyClass, numShots, accuracy, shootWait, shootDelay, speed)
	e1.enemy.reparentTo(formation)
	
	# Add to List of Enemies and update count
	ClassGlobals.enemyList[ClassGlobals.enemyNum] = e1
	ClassGlobals.enemyNum += 1

	# Make Enemy Reverse Facing
	e1.enemy.setHpr(180, 0, 0)

	# For the First Ship
	if y == 0:
	    e1.enemy.setPos(startX, 0, startZ+height)
	    counter = 1	

	# Odd numbered Ships go to the Left
	elif (y % 2) == 1:
	    e1.enemy.setPos(startX+10*counter, 0, startZ+height)
	    
	# Even numbered Ships on the Right
	elif (y % 2) == 0:
 	    e1.enemy.setPos(startX-10*counter, 0, startZ+height)
	    counter += 1

    # Interval for Moving the Formation
    flyAnim1 = formation.posInterval(speed, Point3(startX, startY+600, startZ+height), startPos=Point3(startX, startY-100, startZ+height), bakeInStart=0)

    fly1 = Sequence(flyAnim1, Func(ClassGlobals.formationList[currentNum].removeNode), name='fly1' + str(ClassGlobals.enemyNum))
    fly1.start()


########################################
# Left Flank Assault
########################################
# Create n Enemies that Attack from the Left
def enemyLeftFlank(n, height, enemyClass, speed, numShots, accuracy, shootDelay, hoverWait):

    # Set Raildummy Position
    startZ = 15
    startX = 0
    startY = 0

    # Set waiting time before Player ready to Shoot
    shootWait = speed+1

    # Dummy Object - Moves the Entire Formation
    formation = Level1.railDummy.attachNewNode('formation' + str(ClassGlobals.formationNum))
    ClassGlobals.formationList[ClassGlobals.formationNum] = formation

    currentNum = ClassGlobals.formationNum
    ClassGlobals.formationNum += 1

    # Create n enemies in formation
    for y in range(n):
	# Make Enemy
	e1 = EnemyCraft.enemyCraft(ClassGlobals.enemyNum, enemyClass, numShots, accuracy, shootWait, shootDelay, speed*2 + hoverWait)
	e1.enemy.reparentTo(formation)
	
	# Add to List of Enemies and update count
	ClassGlobals.enemyList[ClassGlobals.enemyNum] = e1
	ClassGlobals.enemyNum += 1

	# For the First Ship
	if y == 0:
	    e1.enemy.setPos(startX, 80, startZ)
	    counter = 1	

	# Odd numbered Ships go to the Left
	elif (y % 2) == 1:
	    e1.enemy.setPos(startX, 100, startZ+10*counter)
	    
	# Even numbered Ships on the Right
	elif (y % 2) == 0:
 	    e1.enemy.setPos(startX, 100, startZ-10*counter)
	    counter += 1

    # Interval for Moving the Formation
    flyAnim1 = formation.posInterval(speed, Point3(startX-height, startY, startZ), startPos=Point3(startX-100, startY, startZ), other=Level1.railDummy, bakeInStart=0, blendType='easeInOut')
    flyAnim2 = formation.posInterval(speed, Point3(startX-100, startY, startZ), startPos=Point3(startX-height, startY, startZ), other=Level1.railDummy, bakeInStart=0, blendType='easeInOut')

    fly1 = Sequence(flyAnim1, Wait(hoverWait), flyAnim2, Func(ClassGlobals.formationList[currentNum].removeNode), name='fly1' + str(ClassGlobals.enemyNum))
    fly1.start()


########################################
# Right Flank Assault
########################################
# Create n Enemies that attack from the Right
def enemyRightFlank(n, height, enemyClass, speed, numShots, accuracy, shootDelay, hoverWait):

    # Set Raildummy Position
    startZ = 15
    startX = 0
    startY = 0

    # Set waiting time before Player ready to Shoot
    shootWait = speed+1

    # Dummy Object - Moves the Entire Formation
    formation = Level1.railDummy.attachNewNode('formation' + str(ClassGlobals.formationNum))
    ClassGlobals.formationList[ClassGlobals.formationNum] = formation

    currentNum = ClassGlobals.formationNum
    ClassGlobals.formationNum += 1

    # Create n enemies in formation
    for y in range(n):
	# Make Enemy
	e1 = EnemyCraft.enemyCraft(ClassGlobals.enemyNum, enemyClass, numShots, accuracy, shootWait, shootDelay, speed*2 + hoverWait)
	e1.enemy.reparentTo(formation)
	
	# Add to List of Enemies and update count
	ClassGlobals.enemyList[ClassGlobals.enemyNum] = e1
	ClassGlobals.enemyNum += 1

	# For the First Ship
	if y == 0:
	    e1.enemy.setPos(startX, 80, startZ)
	    counter = 1	

	# Odd numbered Ships go to the Left
	elif (y % 2) == 1:
	    e1.enemy.setPos(startX, 100, startZ+10*counter)
	    
	# Even numbered Ships on the Right
	elif (y % 2) == 0:
 	    e1.enemy.setPos(startX, 100, startZ-10*counter)
	    counter += 1

    # Interval for Moving the Formation
    flyAnim1 = formation.posInterval(speed, Point3(startX+height, startY, startZ), startPos=Point3(startX+100, startY, startZ), bakeInStart=0, blendType='easeInOut')
    flyAnim2 = formation.posInterval(speed, Point3(startX+100, startY, startZ), startPos=Point3(startX+height, startY, startZ), bakeInStart=0, blendType='easeInOut')
    fly1 = Sequence(flyAnim1, Wait(hoverWait), flyAnim2, Func(ClassGlobals.formationList[currentNum].removeNode), name='fly1' + str(ClassGlobals.enemyNum))
    fly1.start()


########################################
# Hover Assault Formation
########################################
# Create n Enemies in a Row that Rise Up in front of Player
def enemyHoverAssault(n, depth, height, enemyClass, speed, numShots, accuracy, shootDelay):

    # Set Raildummy Position
    startZ = 0
    startX = 0
    startY = depth

    # Set waiting time before Player ready to Shoot
    shootWait = 4.0 
    hoverWait = 7.0

    # Dummy Object - Moves the Entire Formation
    formation = Level1.railDummy.attachNewNode('formation' + str(ClassGlobals.formationNum))
    ClassGlobals.formationList[ClassGlobals.formationNum] = formation

    currentNum = ClassGlobals.formationNum
    ClassGlobals.formationNum += 1

    # Create n enemies in formation
    for y in range(n):
	# Make Enemy
	e1 = EnemyCraft.enemyCraft(ClassGlobals.enemyNum, enemyClass, numShots, accuracy, shootWait, shootDelay, speed*2 + hoverWait)
	e1.enemy.reparentTo(formation)
	
	# Add to List of Enemies and update count
	ClassGlobals.enemyList[ClassGlobals.enemyNum] = e1
	ClassGlobals.enemyNum += 1

	# For the First Ship
	if y == 0:
	    e1.enemy.setPos(startX, startY - 25, startZ)
	    counter = 1	

	# Odd numbered Ships go to the Left
	elif (y % 2) == 1:
	    e1.enemy.setPos(startX+10*counter, startY, startZ)
	    
	# Even numbered Ships on the Right
	elif (y % 2) == 0:
 	    e1.enemy.setPos(startX-10*counter, startY, startZ)
	    counter += 1

    # Interval for Moving the Formation
    flyAnim1 = formation.posInterval(speed, Point3(startX, startY, startZ+height), startPos=Point3(startX, startY, startZ), bakeInStart=0, blendType='easeInOut')
    flyAnim2 = formation.posInterval(speed, Point3(startX, startY-1000, startZ+height), startPos=Point3(startX, startY, startZ+height), bakeInStart=0, blendType='easeInOut')
    fly1 = Sequence(flyAnim1, Wait(hoverWait), flyAnim2, Func(ClassGlobals.formationList[currentNum].removeNode), name='fly1' + str(ClassGlobals.enemyNum))
    fly1.start()


########################################
# Drop Assault Formation
########################################
# Create n Enemies in a Row that Drop Down from the Sky in front of Player
def enemyDropAssault(n, depth, height, enemyClass, speed, numShots, accuracy, shootDelay):

    # Set Raildummy Position
    startZ = 100
    startX = 0
    startY = depth

    # Set waiting time before Player ready to Shoot
    shootWait = 4.0 
    hoverWait = 7.0

    # Dummy Object - Moves the Entire Formation
    formation = Level1.railDummy.attachNewNode('formation' + str(ClassGlobals.formationNum))
    ClassGlobals.formationList[ClassGlobals.formationNum] = formation

    currentNum = ClassGlobals.formationNum
    ClassGlobals.formationNum += 1

    # Create n enemies in formation
    for y in range(n):
	# Make Enemy
	e1 = EnemyCraft.enemyCraft(ClassGlobals.enemyNum, enemyClass, numShots, accuracy, shootWait, shootDelay, speed*2 + hoverWait)
	e1.enemy.reparentTo(formation)
	
	# Add to List of Enemies and update count
	ClassGlobals.enemyList[ClassGlobals.enemyNum] = e1
	ClassGlobals.enemyNum += 1

	# For the First Ship
	if y == 0:
	    e1.enemy.setPos(startX, startY - 25, startZ)
	    counter = 1	

	# Odd numbered Ships go to the Left
	elif (y % 2) == 1:
	    e1.enemy.setPos(startX+10*counter, startY, startZ)

	# Even numbered Ships on the Right
	elif (y % 2) == 0:
 	    e1.enemy.setPos(startX-10*counter, startY, startZ)
	    counter += 1

    # Interval for Moving the Formation
    flyAnim1 = formation.posInterval(speed, Point3(startX, startY, height-100), startPos=Point3(startX, startY, startZ), bakeInStart=0, blendType='easeInOut')
    flyAnim2 = formation.posInterval(speed, Point3(startX, startY-1000, height-100), startPos=Point3(startX, startY, height-100), bakeInStart=0, blendType='easeInOut')
    fly1 = Sequence(flyAnim1, Wait(hoverWait), flyAnim2, Func(ClassGlobals.formationList[currentNum].removeNode), name='fly1' + str(ClassGlobals.enemyNum))
    fly1.start()


########################################
# Super-Heavy Enemy Powerup Carrier 1
########################################
# Creates 1 Super-Heavy Enemy drops in from above
def miniBoss1(depth, height, speed, numShots, shootDelay, hoverWait):

    # Set Raildummy Position
    startZ = 100
    startX = depth
    startY = 120
    enemyClass = 'superHeavy'

    # Set waiting time before Player ready to Shoot
    shootWait = 4.0 

    # Make Enemy
    e1 = EnemyCraft.enemyCraft(ClassGlobals.enemyNum, enemyClass, numShots, 0, shootWait, shootDelay, speed*2 + hoverWait)

    # Add to List of Enemies and update count
    ClassGlobals.enemyList[ClassGlobals.enemyNum] = e1
    ClassGlobals.enemyNum += 1

    # Interval for Moving the Super-Heavy Class Robot
    flyAnim1 = e1.enemy.posInterval(speed, Point3(startX, startY, height), startPos=Point3(startX, startY, startZ), bakeInStart=0, blendType='easeInOut')
    flyAnim2 = e1.enemy.posInterval(speed, Point3(startX, startY, startZ), startPos=Point3(startX, startY, height), bakeInStart=0, blendType='easeInOut')

    # Sequence to run through the Intervals in Order
    fly1 = Sequence(flyAnim1, Wait(hoverWait), flyAnim2, name='fly1' + str(ClassGlobals.enemyNum))
    fly1.start()


########################################
# Boss Battle
########################################
# Create Boss Battle
def bossBattle():

    # Make Boss
    e1 = EnemyBoss.enemyBoss()
    e1.boss.setPos(Level1.railDummy, 0, 3800, -55)
    


