Пример #1
0
static int Ticks_Synchronize(void)
{
	int ticks = 1;
	TActor *actor;

	/*
	while (gameTicks <= 1) {
		//debug("delay... gameTicks=%d\n", gameTicks);
		SDL_Delay(30);
	}
	*/

/*	while (gameTicks > GAMETICKS_PER_FRAME) {
		debug("update... gameTicks=%d\n", gameTicks); */


		ticks++;
		if (!gameIsPaused) {
			UpdateMobileObjects();
			actor = ActorList();
			while (actor) {
				CommandActor(actor, actor->lastCmd);
				actor = actor->next;
			}
		}

/*	} 	*/


	return ticks;
}
Пример #2
0
void CommandBadGuys(int ticks)
{
    int count = 0;
    int delayModifier;
    int rollLimit;

    switch (ConfigGetEnum(&gConfig, "Game.Difficulty"))
    {
    case DIFFICULTY_VERYEASY:
        delayModifier = 4;
        rollLimit = 300;
        break;
    case DIFFICULTY_EASY:
        delayModifier = 2;
        rollLimit = 200;
        break;
    case DIFFICULTY_HARD:
        delayModifier = 1;
        rollLimit = 75;
        break;
    case DIFFICULTY_VERYHARD:
        delayModifier = 1;
        rollLimit = 50;
        break;
    default:
        delayModifier = 1;
        rollLimit = 100;
        break;
    }

    CA_FOREACH(TActor, actor, gActors)
    if (!actor->isInUse)
    {
        continue;
    }
    const CharBot *bot = ActorGetCharacter(actor)->bot;
    if (!(actor->PlayerUID >= 0 || (actor->flags & FLAGS_PRISONER)))
    {
        if ((actor->flags & (FLAGS_VICTIM | FLAGS_GOOD_GUY)) != 0)
        {
            gAreGoodGuysPresent = 1;
        }

        count++;
        int cmd = 0;

        // Wake up if it can see a player
        if ((actor->flags & FLAGS_SLEEPING) &&
                actor->aiContext->Delay == 0)
        {
            if (CanSeeAPlayer(actor))
            {
                actor->flags &= ~FLAGS_SLEEPING;
                ActorSetAIState(actor, AI_STATE_NONE);
            }
            actor->aiContext->Delay = bot->actionDelay * delayModifier;
            // Randomly change direction
            int newDir = (int)actor->direction + ((rand() % 2) * 2 - 1);
            if (newDir < (int)DIRECTION_UP)
            {
                newDir = (int)DIRECTION_UPLEFT;
            }
            if (newDir == (int)DIRECTION_COUNT)
            {
                newDir = (int)DIRECTION_UP;
            }
            cmd = DirectionToCmd((int)newDir);
        }
        // Go to sleep if the player's too far away
        if (!(actor->flags & FLAGS_SLEEPING) &&
                actor->aiContext->Delay == 0 &&
                !(actor->flags & FLAGS_AWAKEALWAYS))
        {
            if (!IsCloseToPlayer(actor->Pos, (40 * 16) << 8))
            {
                actor->flags |= FLAGS_SLEEPING;
                ActorSetAIState(actor, AI_STATE_IDLE);
            }
        }

        if (!actor->dead && !(actor->flags & FLAGS_SLEEPING))
        {
            bool bypass = false;
            const int roll = rand() % rollLimit;
            if (actor->flags & FLAGS_FOLLOWER)
            {
                if (IsCloseToPlayer(actor->Pos, 32 << 8))
                {
                    cmd = 0;
                    ActorSetAIState(actor, AI_STATE_IDLE);
                }
                else
                {
                    cmd = AIGoto(
                              actor, AIGetClosestPlayerPos(actor->Pos), true);
                    ActorSetAIState(actor, AI_STATE_FOLLOW);
                }
            }
            else if (!!(actor->flags & FLAGS_SNEAKY) &&
                     !!(actor->flags & FLAGS_VISIBLE) &&
                     DidPlayerShoot())
            {
                cmd = AIHuntClosest(actor) | CMD_BUTTON1;
                if (actor->flags & FLAGS_RUNS_AWAY)
                {
                    // Turn back and shoot for running away characters
                    cmd = AIReverseDirection(cmd);
                }
                bypass = true;
                ActorSetAIState(actor, AI_STATE_HUNT);
            }
            else if (actor->flags & FLAGS_DETOURING)
            {
                cmd = BrightWalk(actor, roll);
                ActorSetAIState(actor, AI_STATE_TRACK);
            }
            else if (actor->aiContext->Delay > 0)
            {
                cmd = actor->lastCmd & ~CMD_BUTTON1;
            }
            else
            {
                if (roll < bot->probabilityToTrack)
                {
                    cmd = AIHuntClosest(actor);
                    ActorSetAIState(actor, AI_STATE_HUNT);
                }
                else if (roll < bot->probabilityToMove)
                {
                    cmd = DirectionToCmd(rand() & 7);
                    ActorSetAIState(actor, AI_STATE_TRACK);
                }
                else
                {
                    cmd = 0;
                }
                actor->aiContext->Delay = bot->actionDelay * delayModifier;
            }
            if (!bypass)
            {
                if (WillFire(actor, roll))
                {
                    cmd |= CMD_BUTTON1;
                    if (!!(actor->flags & FLAGS_FOLLOWER) &&
                            (actor->flags & FLAGS_GOOD_GUY))
                    {
                        // Shoot in a random direction away
                        for (int j = 0; j < 10; j++)
                        {
                            direction_e d =
                                (direction_e)(rand() % DIRECTION_COUNT);
                            if (!IsFacingPlayer(actor, d))
                            {
                                cmd = DirectionToCmd(d) | CMD_BUTTON1;
                                break;
                            }
                        }
                    }
                    if (actor->flags & FLAGS_RUNS_AWAY)
                    {
                        // Turn back and shoot for running away characters
                        cmd |= AIReverseDirection(AIHuntClosest(actor));
                    }
                    ActorSetAIState(actor, AI_STATE_HUNT);
                }
                else
                {
                    if ((actor->flags & FLAGS_VISIBLE) == 0)
                    {
                        // I think this is some hack to make sure invisible enemies don't fire so much
                        ActorGetGun(actor)->lock = 40;
                    }
                    if (cmd && !IsDirectionOK(actor, CmdToDirection(cmd)) &&
                            (actor->flags & FLAGS_DETOURING) == 0)
                    {
                        Detour(actor);
                        cmd = 0;
                        ActorSetAIState(actor, AI_STATE_TRACK);
                    }
                }
            }
        }
        actor->aiContext->Delay =
            MAX(0, actor->aiContext->Delay - ticks);
        CommandActor(actor, cmd, ticks);
    }
    else if ((actor->flags & FLAGS_PRISONER) != 0)
    {
        CommandActor(actor, 0, ticks);
    }
    CA_FOREACH_END()
    if (gMission.missionData->Enemies.size > 0 &&
            gMission.missionData->EnemyDensity > 0 &&
            count < MAX(1, (gMission.missionData->EnemyDensity * ConfigGetInt(&gConfig, "Game.EnemyDensity")) / 100))
    {
        NActorAdd aa = NActorAdd_init_default;
        aa.UID = ActorsGetNextUID();
        aa.CharId = CharacterStoreGetRandomBaddieId(
                        &gCampaign.Setting.characters);
        aa.Direction = rand() % DIRECTION_COUNT;
        const Character *c =
            CArrayGet(&gCampaign.Setting.characters.OtherChars, aa.CharId);
        aa.Health = CharacterGetStartingHealth(c, true);
        aa.FullPos = PlaceAwayFromPlayers(&gMap);
        GameEvent e = GameEventNew(GAME_EVENT_ACTOR_ADD);
        e.u.ActorAdd = aa;
        GameEventsEnqueue(&gGameEvents, e);
        gBaddieCount++;
    }
}
Пример #3
0
int gameloop(void)
{
	struct Buffer *buffer;
	int ticks;
	int c = 0;
	int cmd1, cmd2;
	int done = NO;
	time_t t;
	struct tm *tp;

	buffer = NewBuffer();
	SetClip(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);

	if (ModuleStatus() != MODULE_OK)
		DisplayMessage(ModuleMessage());

	gameIsPaused = NO;

	missionTime = 0;
	//screenShaking = 0;
	while (!done) {
		frames++;

		Ticks_FrameBegin();

		ticks = Ticks_Synchronize();

		if (gOptions.displaySlices)
			SetColorZero(32, 0, 0);

		DrawScreen(buffer, gPlayer1, gPlayer2);

		if (gOptions.displaySlices)
			SetColorZero(0, 0, 0);

		if (screenShaking) {
			screenShaking -= ticks;
			if (screenShaking < 0)
				screenShaking = 0;
		}

		debug(D_VERBOSE, "frames... %d\n", frames);

		if (Ticks_TimeElapsed(TICKS_PER_SEC)) {
			fps = frames;
			debug(D_NORMAL, "fps = %d\n", fps);
			frames = 0;

			t = time(NULL);
			tp = localtime(&t);
			timeHours = tp->tm_hour;
			timeMinutes = tp->tm_min;
		}

		if (messageTicks > 0)
			messageTicks -= ticks;

		StatusDisplay();

		if (!gameIsPaused) {
			missionTime += ticks;
			if ((gPlayer1 || gPlayer2) && MissionCompleted()) {
				if (gMission.pickupTime == PICKUP_LIMIT)
					PlaySound(SND_DONE, 0, 255);
				gMission.pickupTime -= ticks;
				if (gMission.pickupTime <= 0)
					done = YES;
			} else
				gMission.pickupTime = PICKUP_LIMIT;
		}

		if (gOptions.displaySlices)
			SetColorZero(0, 0, 32);

		if (gOptions.displaySlices)
			SetColorZero(0, 0, 0);

		CopyToScreen();

		if (!gameIsPaused) {
			if (!gOptions.slowmotion || (frames & 1) == 0) {
				UpdateAllActors(ticks);
				UpdateMobileObjects();

				GetPlayerInput(&cmd1, &cmd2);

				if (gPlayer1 && !PlayerSpecialCommands(
							gPlayer1, cmd1, &gPlayer1Data)) {
					CommandActor(gPlayer1, cmd1);
				}
				if (gPlayer2 && !PlayerSpecialCommands(
							gPlayer2, cmd2, &gPlayer2Data)) {
					CommandActor(gPlayer2, cmd2);
				}

				if (gOptions.badGuys)
					CommandBadGuys();

				UpdateWatches();
			}
		} else {
			GetPlayerInput(&cmd1, &cmd2);
		}

		if (!gPlayer1 && !gPlayer2) {
			done = YES;
			c = 0;
		} else {
			c = HandleKey(&done, cmd1 | cmd2);
		}

		Ticks_FrameEnd();
	}
	free(buffer);

	return c != keyEsc;
}
Пример #4
0
void CommandBadGuys(int ticks)
{
	int count = 0;
	int delayModifier;
	int rollLimit;

	switch (gConfig.Game.Difficulty)
	{
	case DIFFICULTY_VERYEASY:
		delayModifier = 4;
		rollLimit = 300;
		break;
	case DIFFICULTY_EASY:
		delayModifier = 2;
		rollLimit = 200;
		break;
	case DIFFICULTY_HARD:
		delayModifier = 1;
		rollLimit = 75;
		break;
	case DIFFICULTY_VERYHARD:
		delayModifier = 1;
		rollLimit = 50;
		break;
	default:
		delayModifier = 1;
		rollLimit = 100;
		break;
	}

	for (int i = 0; i < (int)gActors.size; i++)
	{
		TActor *actor = CArrayGet(&gActors, i);
		if (!actor->isInUse)
		{
			continue;
		}
		const CharBot *bot = actor->character->bot;
		if (!(actor->pData || (actor->flags & FLAGS_PRISONER)))
		{
			if ((actor->flags & (FLAGS_VICTIM | FLAGS_GOOD_GUY)) != 0)
			{
				gAreGoodGuysPresent = 1;
			}

			count++;
			int cmd = 0;

			// Wake up if it can see a player
			if ((actor->flags & FLAGS_SLEEPING) &&
				actor->aiContext->Delay == 0)
			{
				if (CanSeeAPlayer(actor))
				{
					actor->flags &= ~FLAGS_SLEEPING;
					actor->aiContext->State = AI_STATE_NONE;
				}
				actor->aiContext->Delay = bot->actionDelay * delayModifier;
				// Randomly change direction
				int newDir = (int)actor->direction + ((rand() % 2) * 2 - 1);
				if (newDir < (int)DIRECTION_UP)
				{
					newDir = (int)DIRECTION_UPLEFT;
				}
				if (newDir == (int)DIRECTION_COUNT)
				{
					newDir = (int)DIRECTION_UP;
				}
				cmd = DirectionToCmd((int)newDir);
			}
			// Go to sleep if the player's too far away
			if (!(actor->flags & FLAGS_SLEEPING) &&
				actor->aiContext->Delay == 0 &&
				!(actor->flags & FLAGS_AWAKEALWAYS))
			{
				if (!IsCloseToPlayer(actor->Pos, (40 * 16) << 8))
				{
					actor->flags |= FLAGS_SLEEPING;
					actor->aiContext->State = AI_STATE_IDLE;
				}
			}

			if (!actor->dead && !(actor->flags & FLAGS_SLEEPING))
			{
				bool bypass = false;
				const int roll = rand() % rollLimit;
				if (actor->flags & FLAGS_FOLLOWER)
				{
					if (IsCloseToPlayer(actor->Pos, 32 << 8))
					{
						cmd = 0;
						actor->aiContext->State = AI_STATE_IDLE;
					}
					else
					{
						cmd = AIGoto(
							actor, AIGetClosestPlayerPos(actor->Pos), true);
						actor->aiContext->State = AI_STATE_FOLLOW;
					}
				}
				else if (!!(actor->flags & FLAGS_SNEAKY) &&
					!!(actor->flags & FLAGS_VISIBLE) &&
					DidPlayerShoot())
				{
					cmd = AIHuntClosest(actor) | CMD_BUTTON1;
					if (actor->flags & FLAGS_RUNS_AWAY)
					{
						// Turn back and shoot for running away characters
						cmd = AIReverseDirection(cmd);
					}
					bypass = 1;
					actor->aiContext->State = AI_STATE_HUNT;
				}
				else if (actor->flags & FLAGS_DETOURING)
				{
					cmd = BrightWalk(actor, roll);
					actor->aiContext->State = AI_STATE_TRACK;
				}
				else if (actor->aiContext->Delay > 0)
				{
					cmd = actor->lastCmd & ~CMD_BUTTON1;
				}
				else
				{
					if (roll < bot->probabilityToTrack)
					{
						cmd = AIHuntClosest(actor);
						actor->aiContext->State = AI_STATE_HUNT;
					}
					else if (roll < bot->probabilityToMove)
					{
						cmd = DirectionToCmd(rand() & 7);
						actor->aiContext->State = AI_STATE_TRACK;
					}
					else
					{
						cmd = 0;
					}
					actor->aiContext->Delay = bot->actionDelay * delayModifier;
				}
				if (!bypass)
				{
					if (WillFire(actor, roll))
					{
						cmd |= CMD_BUTTON1;
						if (!!(actor->flags & FLAGS_FOLLOWER) &&
							(actor->flags & FLAGS_GOOD_GUY))
						{
							// Shoot in a random direction away
							for (int j = 0; j < 10; j++)
							{
								direction_e d =
									(direction_e)(rand() % DIRECTION_COUNT);
								if (!IsFacingPlayer(actor, d))
								{
									cmd = DirectionToCmd(d) | CMD_BUTTON1;
									break;
								}
							}
						}
						if (actor->flags & FLAGS_RUNS_AWAY)
						{
							// Turn back and shoot for running away characters
							cmd |= AIReverseDirection(AIHuntClosest(actor));
						}
						actor->aiContext->State = AI_STATE_HUNT;
					}
					else
					{
						if ((actor->flags & FLAGS_VISIBLE) == 0)
						{
							// I think this is some hack to make sure invisible enemies don't fire so much
							actor->weapon.lock = 40;
						}
						if (cmd && !IsDirectionOK(actor, CmdToDirection(cmd)) &&
							(actor->flags & FLAGS_DETOURING) == 0)
						{
							Detour(actor);
							cmd = 0;
							actor->aiContext->State = AI_STATE_TRACK;
						}
					}
				}
			}
			actor->aiContext->Delay =
				MAX(0, actor->aiContext->Delay - ticks);
			CommandActor(actor, cmd, ticks);
		}
		else if ((actor->flags & FLAGS_PRISONER) != 0)
		{
			CommandActor(actor, 0, ticks);
		}
	}
	if (gMission.missionData->Enemies.size > 0 &&
		gMission.missionData->EnemyDensity > 0 &&
		count < MAX(1, (gMission.missionData->EnemyDensity * gConfig.Game.EnemyDensity) / 100))
	{
		Character *character = CharacterStoreGetRandomBaddie(
			&gCampaign.Setting.characters);
		TActor *baddie = CArrayGet(&gActors, ActorAdd(character, NULL));
		PlaceBaddie(baddie);
		gBaddieCount++;
	}
}