/**
 * @todo Add sound code
 * @todo change 3 in delay of ExploAnim
 */
void BarrelExplosionActionEvent::run()
{
	// Play the flame sound #1
	//pc::sfxeng->PlaySound("firebl3.aud");

	// Play the large fire misc anim
	Uint32 numImageNapalmBarrel = pc::imgcache->loadImage("napalm3.shp");
	// 3 = delay 14 = num image in ^    -36 = height/2 in ^  -36 = width/2 in ^
	new ExplosionAnim(3, position, numImageNapalmBarrel, 14, -36, -36);

	Uint32 curpos = 0;
	Uint32 xtiles = 0;
	Uint32 ytiles = 0;
	Uint32 xpos, ypos;

	for (ypos = 0; ypos < p::ccmap->getHeight(); ypos++)
	{
		for (xpos = 0; xpos < p::ccmap->getWidth(); xpos++)
		{
			curpos = xpos + ypos * p::ccmap->getWidth();

			xtiles = position % p::ccmap->getWidth() - curpos % p::ccmap->getWidth();
			ytiles = position / p::ccmap->getWidth() - curpos / p::ccmap->getWidth();

		double distance = sqrt((double)(xtiles*xtiles + ytiles*ytiles));

			double realDamage = 256;
			for (unsigned int m = 0; m<distance; m++)
			{
				realDamage = realDamage * 0.3;
			}

            Sint16 damage = (Sint16)realDamage;
			if (damage > 1)
			{
				// Structure to find
            	Structure* str = p::uspool->getStructureAt(curpos, false);
				// If their are a structure
            	if (str != 0)
            	{
            		str->applyDamage(damage, 0, 0);
            	}
            	else
            	{
            		// Find an unit
            		Unit* unitTarget = p::uspool->getGroundUnitAt(curpos, 0x80);
            		if (unitTarget != 0)
            		{
            			unitTarget->applyDamage(damage, 0, 0);
            		}
            	}
			}
		}
	}

	// After launched anim and apply damage, destroy this animation
	delete this;
}
void ProjectileAnim::run()
{
    Uint32 oldpos;
    Unit* utarget = 0;
    Structure* starget = 0;
    
    if (fuelled) {
        --fuel;
    }
    if (heatseek) 
    {
        double pixelspertick;
        double totlen;
        float alpha;
        --seekfuel;
        dest = target->getBPos(l2o->cellpos);
        subdest = target->getSubpos();
        pixelspertick = (double)weap->getSpeed()/4.0;
        xdiff = (l2o->cellpos)%p::ccmap->getWidth() - dest%p::ccmap->getWidth();
        ydiff = (l2o->cellpos)/p::ccmap->getWidth() - dest/p::ccmap->getWidth();
        if ((xdiff == 0) && (ydiff == 0)) {
            xmod = 0;
            ymod = 0;
        } else {
            xdiff *= 24;
            ydiff *= 24;
            totlen = sqrt(xdiff*xdiff+ydiff*ydiff);
            xmod = -(xdiff*pixelspertick)/totlen;
            ymod = -(ydiff*pixelspertick)/totlen;
            if (weap->getProjectile()->doesRotate()) {
                if( xdiff == 0 ) {
                    if( ydiff < 0 ) {
                        alpha = -M_PI_2;
                    } else {
                        alpha = M_PI_2;
                    }
                } else {
                    alpha = atan((float)ydiff/(float)xdiff);
                    if( xdiff < 0 ) {
                        alpha = M_PI+alpha;
                    }
                }
                facing = (40-(Sint8)(alpha*16/M_PI))&0x1f;
                l2o->imagenums[0] = weap->getProjectile()->getImageNum()+facing;

            }
        }
        if (seekfuel == 0) {
            heatseek = false;
            target->unrefer();
        }
    }
    //check if we are close enough to target to stop modifying
    if( fabs(xdiff) < fabs(xmod) )
    {
        xmod = 0;
    }
    if( fabs(ydiff) < fabs(ymod) )
    {
        ymod = 0;
    }
    
    // if we are so close both
    if (xmod == 0 && ymod == 0) 
    {
    	// Play the anim for piff
    	Uint32 numPiffShp = pc::imgcache->loadImage("piff.shp", -1);
    	Uint32 numPiffPiffShp = pc::imgcache->loadImage("piffpiff.shp", -1);
    	Uint32 numAtomShp = pc::imgcache->loadImage("atomsfx.shp", -1);
    	Uint32 type = weap->getWarhead()->getType()->getExplosion();
    	switch (type)
    	{
    	case 1:
    		new ExplosionAnim(1, dest, numPiffShp, 4, 0,0);    		
    		//	target->getXoffset(), 
    		//	target->getYoffset());
    		break;
    	case 2:
    		new ExplosionAnim(1, dest, numPiffPiffShp, 8, 0, 0);
    		break;
    	default:
    		//new ExplosionAnim(1, dest, numAtomShp, 27, 0, 0);
    		break;
    	} 
    	
    	// Play report of the weapon 
    	//pc::sfxeng->PlaySound(weap->getProjectile()->lnkProjectileData->Warhead()->getExplosionsound());  	        
    	
    	
    	
    	
    	// @todo _PLAY ANIMATION ONLY IF IN PROJECTILE THEIR ARE "Animates" = 'yes'
        // projectile hit..
        /*if( weap->getWarhead()->getExplosionsound() != NULL ) {
            pc::sfxeng->PlaySound(weap->getWarhead()->getExplosionsound());
        }        
        */
    	//printf("0\n");
    	//
    	// @todo test image death
    	//
    	/*
    	Uint32 imageExplosionNum;
    	//int explosionimage = pc::imagepool->size()<<16;    
    	Uint32 type = weap->getWarhead()->getType()->getExplosion();
    	// 1=piff
    	if (type==1)
    	{printf("1\n");
    	
    		// Load the image
    		imageExplosionNum = pc::imgcache->loadImage("piff.shp");
    		SHPImage* temp;
    		try {
    			temp = new SHPImage(, -1);
    		} catch (...) {
    			logger->error("Unenable to load the image of piff\n");
    			throw new ImageNotFound("Unenable to load the image of piff");
    		}
    		
    		new ExplosionAnim(1, dest, imageExplosionNum, 4, 0, 0);
    	}
    	
    	// 2=piffs
    	if (type==2)
    	{
    		SHPImage* temp;
    		try {
    			temp = new SHPImage("piffpiff.shp", -1);
    		} catch (...) {
    			logger->error("Unenable to load the image of piffpiff\n");
    			throw new ImageNotFound("Unenable to load the image of piffpiff");;
    	    }
    	    new ExplosionAnim(1, dest, explosionimage, 8, 0, 0);
    	}
    	*/
    	
    	
    	
    	
    	
    	// Apply damages to a structure if founded
        starget = p::uspool->getStructureAt(dest,weap->getWall());
        if( starget != 0 ) {
            starget->applyDamage((Sint16)weap->getDamage(),weap,owner);
            delete this;
            return;
        }

        
        // Apply damages to a Unit if founded
        utarget = p::uspool->getUnitAt(dest, subdest);
        if( (utarget != 0) || inaccurate )
        {
            if (inaccurate) 
            {
                for (int sud=0; sud<5; ++sud) 
                {
                    utarget = p::uspool->getUnitAt(dest, sud);
                    if (utarget != 0) 
                    {
                        // each soldier in that cell gets one third of
                        // normal damage
                        utarget->applyDamage((Sint16)((float)weap->getDamage()/3.0),weap,owner);
                    }
                } // targeted soldier gets full normal damage
                utarget = p::uspool->getUnitAt(dest, subdest);
                if (utarget != 0) { // soldier might have already been killed
                    utarget->applyDamage((Sint16)(2.0*(double)weap->getDamage()/3.0),weap,owner);
                }
                delete this;
                return;
            } else {
                utarget->applyDamage((Sint16)weap->getDamage(),weap,owner);
                delete this;
                return;
            }
        }
        delete this;
        return;
    }
    if (!heatseek) {
        // decrease xdiff by xmod and ydiff by ymod
        xdiff += xmod;
        ydiff += ymod;
    }
    // move the actual projectile
    rxoffs += xmod;
    ryoffs += ymod;

    oldpos = l2o->cellpos;
    while( rxoffs < 0 ) {
        rxoffs += 24;
        --l2o->cellpos;
    }
    while(rxoffs >= 24) {
        rxoffs -= 24;
        ++l2o->cellpos;
    }

    while( ryoffs < 0 ) {
        ryoffs += 24;
        l2o->cellpos -= p::ccmap->getWidth();
    }
    while( ryoffs >= 24 ) {
        ryoffs -= 24;
        l2o->cellpos += p::ccmap->getWidth();
    }
    l2o->xoffsets[0] = (Sint8)rxoffs;
    l2o->yoffsets[0] = (Sint8)ryoffs;

    if( oldpos != l2o->cellpos) {
        p::uspool->removeL2overlay(l2entry);
        l2entry = p::uspool->addL2overlay(l2o->cellpos, l2o);
    }
    setDelay(1);
    
    // The weapon is fuelled
    if (fuelled && fuel == 0) {   	
    	// @todo _PLAY ANIMATION ONLY IF IN PROJECTILE THEIR ARE "Animates" = 'yes'
    	// projectile hit..
    	/*       if( weap->getWarhead()->getExplosionsound() != NULL ) {
            pc::sfxeng->PlaySound(weap->getWarhead()->getExplosionsound());
        }
        new ExplosionAnim(1, l2o->cellpos, weap->getWarhead()->getEImage(),
                          weap->getWarhead()->getESteps(), 0, 0);
        */
        delete this;
        return;
    }
    p::aequeue->scheduleEvent(this);
}