Пример #1
0
void Sheep::doStuff(const EventHandler&, const std::vector< std::vector<TileSprite*> >& tiles,
                    std::map< std::string, Entity* >& entities, sf::Time animate)
{
    //Compute the gravity
    computeGravity(animate);

    //Check the collisions, set the new distances and do the move
    Collide collideTiles = collideWithTiles(tiles, animate.asSeconds());
    setDistance(collideTiles);
    move(animate.asSeconds()*(speed.x), animate.asSeconds()*speed.y);
    sprite->update(animate);

    doAttack(entities);

    if (damageCD)
    {
        --damageCD;
    }
}
Пример #2
0
//////////////////////////////////////////////////////////////////////////
// tickBehaviour
void GaGameUnit::tickBehaviour( BcFixed Delta )
{
#if PSY_DEBUG
	static BcU32 BreakID = BcErrorCode;
	if( ID_ == BreakID )
	{
		BcBreakpoint;
	}
#endif

	switch( Behaviour_ )
	{
	case BEHAVIOUR_IDLE:
		{
			CurrState_.Velocity_ = BcFixedVec2d( 0.0f, 0.0f );
			BcU32 NearestUnit = pSimulator_->findNearestUnit( CurrState_.Position_, ID_, 1 << ( 1 - TeamID_ ) );
			if( NearestUnit != BcErrorCode )
			{
				doAttack( NearestUnit );
			}
		}
		break;

	case BEHAVIOUR_GUARD:
		{
			CurrState_.Velocity_ = BcFixedVec2d( 0.0f, 0.0f );
			BcU32 NearestUnit = pSimulator_->findNearestUnit( CurrState_.Position_, ID_, 1 << ( 1 - TeamID_ ) );
			if( NearestUnit != BcErrorCode )
			{
				doAttack( NearestUnit );
			}
		}
		break;

	case BEHAVIOUR_MOVE:
		{
			BcU32 NearestUnit = pSimulator_->findNearestUnit( CurrState_.Position_, ID_, 1 << ( 1 - TeamID_ ) );
			if( IsAttackMove_ && inRangeForAttack( NearestUnit ) == RANGE_IN )
			{
				CurrState_.Velocity_ = BcFixedVec2d( 0.0f, 0.0f );

				doAttack( NearestUnit );
			}
			else
			{
				// Reset attack timer.
				AttackTimer_ = BcMax( AttackTimer_,  BcFixed( Desc_.CoolDownMultiplier_ ) / Desc_.RateOfAttack_ );
				
				// Make longer whe moving.
				AttackTimer_ = BcMin( BcFixed( 1.0f ) / Desc_.RateOfAttack_, AttackTimer_ + ( BcFixed( 1.0f ) / Desc_.RateOfAttack_ ) * ( Delta * 0.05f ) );

				// Calculate velocity vector.
				CurrState_.Velocity_ = BcFixedVec2d( MoveTargetPosition_ - CurrState_.Position_ ).normal() * Desc_.MoveSpeed_;
				BcFixed MoveDistance = Desc_.MoveSpeed_ * Delta;
				if( ( CurrState_.Position_ - MoveTargetPosition_ ).magnitudeSquared() < ( MoveDistance * MoveDistance ) )
				{
					CurrState_.Position_ = MoveTargetPosition_;
					setBehaviourIdle();
				}
			}
		}
		break;

	case BEHAVIOUR_ATTACK:
		{
			TRange Range = inRangeForAttack( TargetUnitID_ );
			if( Range == RANGE_IN )
			{
				doAttack( TargetUnitID_ );
			}
			else
			{
				// Reset attack timer.
				AttackTimer_ = BcMax( AttackTimer_,  BcFixed( Desc_.CoolDownMultiplier_ ) / ( Desc_.RateOfAttack_ ) );

				// Make longer whe moving.
				AttackTimer_ = BcMin( BcFixed( 1.0f ) / Desc_.RateOfAttack_, AttackTimer_ + ( BcFixed( 1.0f ) / Desc_.RateOfAttack_ ) * ( Delta * 0.05f ) );

				// Get unit position.
				GaGameUnit* pUnit = pSimulator_->getUnit( TargetUnitID_ );
				if( pUnit != NULL )
				{
					BcFixedVec2d Direction = ( getPosition() - pUnit->getPosition() ).normal() * ( ( Desc_.MinRange_ + Desc_.Range_ ) * 0.5f );
					MoveTargetPosition_ = pUnit->getPosition() + Direction;
				}
				else
				{
					// Attack move to previous target.
					IsAttackMove_ = BcTrue;
					Behaviour_ = BEHAVIOUR_MOVE;
				}

				// Calculate velocity vector.
				CurrState_.Velocity_ = BcFixedVec2d( MoveTargetPosition_ - CurrState_.Position_ ).normal() * Desc_.MoveSpeed_;

				// If we moved further away, then stop and set target.
				BcFixed CurrMagnitudeSquared = ( CurrState_.Position_ - MoveTargetPosition_ ).magnitudeSquared();
				BcFixed PrevMagnitudeSquared = ( PrevState_.Position_ - MoveTargetPosition_ ).magnitudeSquared();
				if( CurrMagnitudeSquared > PrevMagnitudeSquared )
				{
					setBehaviourIdle();
				}
			}
		}
		break;

	case BEHAVIOUR_DAMAGE:
		{
			// Calculate velocity vector.
			CurrState_.Velocity_ = BcFixedVec2d( MoveTargetPosition_ - CurrState_.Position_ ).normal() * Desc_.MoveSpeed_;
			BcFixed MoveDistance = Desc_.MoveSpeed_ * Delta;
			if( ( CurrState_.Position_ - MoveTargetPosition_ ).magnitudeSquared() < ( MoveDistance * MoveDistance ) )
			{
				CurrState_.Position_ = MoveTargetPosition_;

				// Cause damage.
				pSimulator_->applyDamage( MoveTargetPosition_, Desc_.Range_, Desc_.Health_ );

				// Debug point!
				pSimulator_->addDebugPoint( getPosition(), Desc_.Range_, RsColour::YELLOW );

				if( Desc_.pHitSound_ != NULL )
				{
					GaTopState::pImpl()->playSound( Desc_.pHitSound_, MoveTargetPosition_ );
				}

				// Set as dead.
				setBehaviourDead();
			}
		}
		break;
	}

	// Attack timer.
	if( AttackTimer_ > 0.0f )
	{
		AttackTimer_ -= Delta;
	}
	else if( AttackTimer_ < 0.0f )
	{
		AttackTimer_ = 0.0f;
	}

	// Death.
	if( Health_ <= 0.0f )
	{
		Health_ = 0.0f;
		Behaviour_ = BEHAVIOUR_DEAD;
	}
}
Пример #3
0
//returns ms elapsed, -2 if the monster dies
int
shMonster::doPet ()
{
    int i, n;
    shCoord coord[9];
    int info[9];
    int best = -1;
    int score, bestscore = -9999;
    int flags = kLinedUp | kTrap;
    int res = -1;
    int dist;
    int scrubbot = isA (kMonScrubbot);

    int val_linedup;
    int val_adjacent;
    int val_dist;
    int val_track;
    int val_monst;

    shMonster *c;
    int elapsed;

    /* first priority is always to drink any beer in our square! */
    res = drinkBeer ();
    if (-1 != res) return res;

    if (mHP > mMaxHP / 4) {
        flags |= kMonster;
    }

    if (canSee (&Hero)) {
        findPetGoal ();

        val_linedup = -10;
        val_dist = -2;
        val_track = -5;
        val_adjacent = RNG (3) ? -5 : 10;
        val_monst = 10;
    } else {
        mDestX = Hero.mX;
        mDestY = Hero.mY;
        val_linedup = 0;
        val_dist = -1;
        val_track = -10;

        val_adjacent = 5;
        val_monst = 5;
    }

    if (isSessile ()) {
        val_monst += 50;
    }

    if (scrubbot) flags |= kFreeWreck;
    n = findSquares (flags, coord, info);
    for (i = 0; i < n; i++) {
        score = 0;
        if (info[i] & kTrap
            and RNG (30)) /* small chance that a pet will walk on a trap*/
        {
            score -= 30;
        }
        if (info[i] & kFreeWreck) score += 50;
        if (info[i] & kLinedUp) score += val_linedup;
        if (info[i] & kMonster) {
            c = (shMonster *) mLevel->getCreature (coord[i].mX, coord[i].mY);
            if (c and !c->isHero () and !c->isPet () and c->isHostile () and
            /* Smart bombs and missiles should be ready to sacrifice
               themselves on any hostile target. isExplosive checks this. */
                (c->mCLevel <= mCLevel + 1 or isExplosive ()))
            {
                score += c->isHostile () ? val_monst : val_monst / 2;
            } else if (c != this) {
                score -= 30;
            }
        }
        if (coord[i].mX == mX and coord[i].mY == mY) {
            score -= 10;
        }
        if (areAdjacent (coord[i].mX, coord[i].mY, Hero.mX, Hero.mY))
            score += val_adjacent;
        dist = distance (coord[i].mX, coord[i].mY, mDestX, mDestY);
        if (dist > 50 and val_dist > 0) { dist = 50; }
        score += val_dist * dist;

        int ti;
        for (ti = 0 ; ti < TRACKLEN; ti++) {
            if (mTrack[ti].mX == coord[i].mX and mTrack[ti].mY == coord[i].mY) {
                score += val_track;
            }
        }

        if (score > bestscore) {
            bestscore = score;
            best = i;
        }
    }

    if (-1 == best) {
        /* nothing to do but stay where we are for now */
        return 500;
    }
    if (coord[best].mX == mX and coord[best].mY == mY) {
        if (info[best] & kFreeWreck) {
            shObjectVector *v = mLevel->getObjects (mX, mY);
            shObject *obj;
            for (int i = 0; i < v->count (); ++i) {
                obj = v->get (i);
                if (obj->isA (kObjWreck)) {
                    v->remove (obj);
                    if (0 == v->count ()) {
                        delete v;
                        mLevel->setObjects (mX, mY, NULL);
                    }
                    return utilizeWreck (obj);
                }
            }
        }
        return 250;
    } else {
        if (info[best] & kMonster) {
            c = (shMonster *)
                mLevel->getCreature (coord[best].mX, coord[best].mY);
            doAttack (c, &elapsed);
            return elapsed;
        }
        if (!isSessile ())
            return doMove (vectorDirection (mX, mY,
                                            coord[best].mX, coord[best].mY));
    }
    return 250;
}