예제 #1
0
/**
**  Missile flies from x,y to x1,y1 than bounces NumBounces times
*/
void MissilePointToPointBounce::Action()
{
	this->Wait = this->Type->Sleep;
	if (PointToPointMissile(this)) {
		if (this->State < 2 * this->Type->NumBounces - 1 && this->TotalStep) {
			int xstep;
			int ystep;

			xstep = (this->DX - this->SourceX) * 1024 / this->TotalStep;
			ystep = (this->DY - this->SourceY) * 1024 / this->TotalStep;
			this->DX += xstep * (TileSizeX + TileSizeY) * 3 / 4 / 1024;
			this->DY += ystep * (TileSizeX + TileSizeY) * 3 / 4 / 1024;

			this->State++; // !(State & 1) to initialise
			this->SourceX = this->X;
			this->SourceY = this->Y;
			PointToPointMissile(this);
			//this->State++;
			MissileHit(this);
			// FIXME: hits to left and right
			// FIXME: reduce damage effects on later impacts
		} else {
			MissileHit(this);
			this->TTL = 0;
		}
	} else {
		NextMissileFrame(this, 1, 0);
	}
}
예제 #2
0
/**
**  Missile shows hit points?
*/
void MissileHit::Action()
{
	this->Wait = this->Type->Sleep;
	if (PointToPointMissile(this)) {
		::MissileHit(this);
		this->TTL = 0;
	}
}
예제 #3
0
/**
**  Missile flies from x,y to x1,y1 and stays there for a moment
*/
void MissilePointToPointCycleOnce::Action()
{
	this->Wait = this->Type->Sleep;
	if (PointToPointMissile(this)) {
		MissileHit(this);
		this->TTL = 0;
	} else {
		NextMissileFrameCycle(this);
	}
}
예제 #4
0
/**
**  Missile flies from x,y to x1,y1 showing the first frame
**  and then shows a hit animation.
*/
void MissilePointToPointWithHit::Action()
{
	this->Wait = this->Type->Sleep;
	if (PointToPointMissile(this)) {
		if (NextMissileFrame(this, 1, 0)) {
			MissileHit(this);
			this->TTL = 0;
		}
	}
}
예제 #5
0
/**
**  Death-Coil class. Damages organic units and gives to the caster.
**
**  @todo  do it configurable.
*/
void MissileDeathCoil::Action()
{
	this->Wait = this->Type->Sleep;
	if (PointToPointMissile(*this)) {
		Assert(this->SourceUnit != NULL);
		CUnit &source = *this->SourceUnit;

		if (source.Destroyed) {
			return;
		}
		// source unit still exists
		//
		// Target unit still exists and casted on a special target
		//
		if (this->TargetUnit && !this->TargetUnit->Destroyed
			&& this->TargetUnit->CurrentAction() == UnitActionDie) {
			HitUnit(&source, *this->TargetUnit, this->Damage);
			if (source.CurrentAction() != UnitActionDie) {
				source.Variable[HP_INDEX].Value += this->Damage;
				if (source.Variable[HP_INDEX].Value > source.Variable[HP_INDEX].Max) {
					source.Variable[HP_INDEX].Value = source.Variable[HP_INDEX].Max;
				}
			}
		} else {
			//
			// No target unit -- try enemies in range 5x5 // Must be parametrable
			//
			std::vector<CUnit *> table;
			const Vec2i destPos = Map.MapPixelPosToTilePos(this->destination);
			const Vec2i range(2, 2);
			Select(destPos - range, destPos + range, table, IsEnemyWith(*source.Player));

			if (table.empty()) {
				return;
			}
			const size_t n = table.size();  // enemy count
			const int damage = std::min<int>(1, this->Damage / n);

			// disperse damage between them
			for (size_t i = 0; i != n; ++i) {
				HitUnit(&source, *table[i], damage);
			}
			if (source.CurrentAction() != UnitActionDie) {
				source.Variable[HP_INDEX].Value += this->Damage;
				if (source.Variable[HP_INDEX].Value > source.Variable[HP_INDEX].Max) {
					source.Variable[HP_INDEX].Value = source.Variable[HP_INDEX].Max;
				}
			}
		}
		this->TTL = 0;
	}
}
예제 #6
0
/**
**  Whirlwind controller
**
**  @todo do it more configurable.
*/
void MissileWhirlwind::Action()
{
	// Animate, move.
	if (!this->AnimWait--) {
		if (this->NextMissileFrame(1, 0)) {
			this->SpriteFrame = 0;
			PointToPointMissile(*this);
		}
		this->AnimWait = this->Type->Sleep;
	}
	this->Wait = 1;

	// Center of the tornado
	const PixelPos pixelCenter = this->position + this->Type->size / 2;
	const PixelPos centerOffset(PixelTileSize.x / 2, PixelTileSize.y);
	const Vec2i center = Map.MapPixelPosToTilePos(pixelCenter + centerOffset);

	//Wyrmgus start
	Assert(this->Type->AttackSpeed);
//	if (!(this->TTL % CYCLES_PER_SECOND / 10)) {
	if (!(this->TTL % CYCLES_PER_SECOND / this->Type->AttackSpeed)) { //AttackSpeed is by default 10
	//Wyrmgus end
		this->MissileHit();
	}
	// Changes direction every 3 seconds (approx.)
	if (!(this->TTL % 100)) { // missile has reached target unit/spot
		Vec2i newPos;

		do {
			// find new destination in the map
			newPos.x = center.x + SyncRand() % 5 - 2;
			newPos.y = center.y + SyncRand() % 5 - 2;
		} while (!Map.Info.IsPointOnMap(newPos));
		this->destination = Map.TilePosToMapPixelPos_Center(newPos);
		this->source = this->position;
		this->State = 0;
		DebugPrint("Whirlwind new direction: %d, %d, TTL: %d\n" _C_
				   this->destination.x _C_ this->destination.y _C_ this->TTL);
	}
}
예제 #7
0
//FIXME: (Fabrice) I don't know if my update for missile visibility is fully
//correct.
global void MissileActions(void)
{
    int missile;

    for( missile=0; missile<NumMissiles; ++missile ) {
        if( Missiles[missile].Type==MissileFree ) {
            continue;
        }
        if( Missiles[missile].Wait-- ) {
            continue;
        }
        if (MissileVisible(missile)) {
            // check before movement
            MustRedraw|=RedrawMap;
        }
        switch( Missiles[missile].Type->Class ) {

        case MissileClassPointToPoint:
            Missiles[missile].Wait=1;
            if( PointToPointMissile(missile) ) {
                MissileHit(missile);
                Missiles[missile].Type=MissileFree;
            } else {
                //
                //	Animate missile, cycle through frames
                //
                Missiles[missile].Frame+=5;
                if( (Missiles[missile].Frame&127)
                        >=Missiles[missile].Type->RleSprite->NumFrames ) {
                    Missiles[missile].Frame=
                        // (Missiles[missile].Frame&128)|
                        (Missiles[missile].Frame
                         -Missiles[missile].Type->RleSprite
                         ->NumFrames);
                }
                DebugLevel3("Frame %d of %d\n"
                            ,Missiles[missile].Frame
                            ,Missiles[missile].Type->RleSprite->NumFrames);

            }
            break;

        case MissileClassPointToPointWithDelay:
            Missiles[missile].Wait=1;
            if( PointToPointMissile(missile) ) {
                switch( Missiles[missile].State++ ) {
                case 1:
                    // FIXME: bounces up.
                    PlayMissileSound(Missiles+missile,
                                     Missiles[missile].Type->ImpactSound.Sound);
                    // FIXME: make this configurable!!
                    switch( Missiles[missile].Type->Type ) {
                    case MissileSmallCannon:
                        MakeMissile(MissileCannonExplosion
                                    ,Missiles[missile].X
                                    ,Missiles[missile].Y
                                    ,0,0);
                        break;
                    case MissileBigCannon:
                        MakeMissile(MissileCannonTowerExplosion
                                    ,Missiles[missile].X
                                    ,Missiles[missile].Y
                                    ,0,0);
                        break;
                    case MissileCatapultRock:
                    case MissileBallistaBolt:
                        MakeMissile(MissileImpact
                                    ,Missiles[missile].X
                                    ,Missiles[missile].Y
                                    ,0,0);
                        break;
                    }
                    break;
                default:
                    MissileHit(missile);
                    Missiles[missile].Type=MissileFree;
                    break;
                }
            } else {
                //
                //	Animate missile, depends on the way.
                //
                // FIXME: how?
            }
            break;

        case MissileClassPointToPoint3Bounces:
            Missiles[missile].Wait=1;
            if( PointToPointMissile(missile) ) {
                //
                //	3 Bounces.
                //
                switch( Missiles[missile].State ) {
                case 1:
                case 3:
                case 5:
                    Missiles[missile].State+=2;
                    Missiles[missile].DX+=
                        Missiles[missile].Xstep*TileSizeX*2;
                    Missiles[missile].DY+=
                        Missiles[missile].Ystep*TileSizeY*2;
                    PlayMissileSound(Missiles+missile,
                                     Missiles[missile].Type->ImpactSound.Sound);
                    MakeMissile(MissileExplosion
                                ,Missiles[missile].X
                                ,Missiles[missile].Y
                                ,0,0);
                    MissileHit(missile);
                    // FIXME: hits to left and right
                    // FIXME: reduce damage
                    break;
                default:
                    Missiles[missile].Type=MissileFree;
                    break;
                }
            } else {
                //
                //	Animate missile, cycle through frames
                //
                Missiles[missile].Frame+=5;
                if( (Missiles[missile].Frame&127)
                        >=Missiles[missile].Type->RleSprite->NumFrames ) {
                    Missiles[missile].Frame=
                        // (Missiles[missile].Frame&128)|
                        (Missiles[missile].Frame
                         -Missiles[missile].Type->RleSprite
                         ->NumFrames);
                }
                DebugLevel3("Frame %d of %d\n"
                            ,Missiles[missile].Frame
                            ,Missiles[missile].Type->RleSprite->NumFrames);

            }
            break;

        case MissileClassPointToPointWithHit:
            Missiles[missile].Wait=1;
            if( PointToPointMissile(missile) ) {
                //
                //	Animate hit
                //
                Missiles[missile].Frame+=5;
                if( (Missiles[missile].Frame&127)
                        >=Missiles[missile].Type->RleSprite->NumFrames ) {
                    MissileHit(missile);
                    Missiles[missile].Type=MissileFree;
                }
            }
            break;

        case MissileClassStayWithDelay:
            Missiles[missile].Wait=1;
            if( ++Missiles[missile].Frame
                    ==Missiles[missile].Type->RleSprite
                    ->NumFrames ) {
                MissileHit(missile);
                Missiles[missile].Type=MissileFree;
            }
            break;

        case MissileClassCycleOnce:
            Missiles[missile].Wait=Missiles[missile].Type->Speed;
            switch( Missiles[missile].State ) {
            case 0:
            case 2:
                ++Missiles[missile].State;
                break;
            case 1:
                if( ++Missiles[missile].Frame
                        ==Missiles[missile].Type->RleSprite
                        ->NumFrames ) {
                    --Missiles[missile].Frame;
                    ++Missiles[missile].State;
                }
                break;
            case 3:
                if( !Missiles[missile].Frame-- ) {
                    MissileHit(missile);
                    Missiles[missile].Type=MissileFree;
                }
                break;
            }
            break;
        }
        if (Missiles[missile].Type!=MissileFree && MissileVisible(missile)) {
            // check after movement
            MustRedraw|=RedrawMap;
        }
    }
}