Exemple #1
0
void DrawLaserSight(
	const ActorPics *pics, const TActor *a, const Vec2i picPos)
{
	// Don't draw if dead or transparent
	if (pics->IsDead || pics->IsTransparent) return;
	// Check config
	const LaserSight ls = ConfigGetEnum(&gConfig, "Game.LaserSight");
	if (ls != LASER_SIGHT_ALL &&
		!(ls == LASER_SIGHT_PLAYERS && a->PlayerUID >= 0))
	{
		return;
	}
	// Draw weapon indicators
	const GunDescription *g = ActorGetGun(a)->Gun;
	Vec2i muzzlePos = Vec2iAdd(
		picPos, Vec2iFull2Real(GunGetMuzzleOffset(g, a->direction)));
	muzzlePos.y -= g->MuzzleHeight / Z_FACTOR;
	const double radians = dir2radians[a->direction] + g->AngleOffset;
	const int range = GunGetRange(g);
	color_t color = colorCyan;
	color.a = 64;
	const double spreadHalf =
		(g->Spread.Count - 1) * g->Spread.Width / 2 + g->Recoil / 2;
	if (spreadHalf > 0)
	{
		DrawLaserSightSingle(muzzlePos, radians - spreadHalf, range, color);
		DrawLaserSightSingle(muzzlePos, radians + spreadHalf, range, color);
	}
	else
	{
		DrawLaserSightSingle(muzzlePos, radians, range, color);
	}
}
Exemple #2
0
bool AIContextSetState(AIContext *c, const AIState s)
{
	const bool isChange = c->State != s;
	c->State = s;
	if (isChange)
	{
		AIContextSetChatterDelay(
			c, ConfigGetEnum(&gConfig, "Interface.AIChatter"));
	}
	return isChange;
}
Exemple #3
0
void GraphicsConfigSetFromConfig(GraphicsConfig *gc, Config *c)
{
    GraphicsConfigSet(
        gc,
        Vec2iNew(
            ConfigGetInt(c, "Graphics.ResolutionWidth"),
            ConfigGetInt(c, "Graphics.ResolutionHeight")),
        ConfigGetBool(c, "Graphics.Fullscreen"),
        ConfigGetInt(c, "Graphics.ScaleFactor"),
        (ScaleMode)ConfigGetEnum(c, "Graphics.ScaleMode"),
        ConfigGetInt(c, "Graphics.Brightness"));
}
Exemple #4
0
static void PlayerSpecialCommands(TActor *actor, const int cmd)
{
	if ((cmd & CMD_BUTTON2) && CMD_HAS_DIRECTION(cmd))
	{
		if (ConfigGetEnum(&gConfig, "Game.SwitchMoveStyle") == SWITCHMOVE_SLIDE)
		{
			SlideActor(actor, cmd);
		}
	}
	else if (
		(actor->lastCmd & CMD_BUTTON2) &&
		!(cmd & CMD_BUTTON2) &&
		!actor->specialCmdDir &&
		!actor->CanPickupSpecial &&
		!(ConfigGetEnum(&gConfig, "Game.SwitchMoveStyle") == SWITCHMOVE_SLIDE && CMD_HAS_DIRECTION(cmd)) &&
		ActorCanSwitchGun(actor))
	{
		GameEvent e = GameEventNew(GAME_EVENT_ACTOR_SWITCH_GUN);
		e.u.ActorSwitchGun.UID = actor->uid;
		e.u.ActorSwitchGun.GunIdx = (actor->gunIndex + 1) % actor->guns.size;
		GameEventsEnqueue(&gGameEvents, e);
	}
}
static void SetupQuickPlayEnemy(Character *enemy, const GunDescription *gun)
{
	CharacterShuffleAppearance(enemy);
	enemy->Gun = gun;
	enemy->speed =GenerateQuickPlayParam(
		ConfigGetEnum(&gConfig, "QuickPlay.EnemySpeed"), 64, 112, 160, 256);
	if (IsShortRange(enemy->Gun))
	{
		enemy->speed = enemy->speed * 4 / 3;
	}
	if (IsShortRange(enemy->Gun))
	{
		enemy->bot->probabilityToMove = 35 + (rand() % 35);
	}
	else
	{
		enemy->bot->probabilityToMove = 30 + (rand() % 30);
	}
	enemy->bot->probabilityToTrack = 10 + (rand() % 60);
	if (!enemy->Gun->CanShoot)
	{
		enemy->bot->probabilityToShoot = 0;
	}
	else if (IsHighDPS(enemy->Gun))
	{
		enemy->bot->probabilityToShoot = 1 + (rand() % 3);
	}
	else
	{
		enemy->bot->probabilityToShoot = 1 + (rand() % 6);
	}
	enemy->bot->actionDelay = rand() % (50 + 1);
	enemy->maxHealth = GenerateQuickPlayParam(
		ConfigGetEnum(&gConfig, "QuickPlay.EnemyHealth"), 10, 20, 40, 60);
	enemy->flags = 0;
}
Exemple #6
0
void HUDDraw(HUD *hud, const input_device_e pausingDevice)
{
	char s[50];
	int flags = 0;
	const int numPlayersAlive =
		GetNumPlayers(PLAYER_ALIVE_OR_DYING, false, false);
	const int numLocalPlayers = GetNumPlayers(PLAYER_ANY, false, true);
	const int numLocalPlayersAlive =
		GetNumPlayers(PLAYER_ALIVE_OR_DYING, false, true);

	Rect2i r;
	r.Size = Vec2iNew(
		hud->device->cachedConfig.Res.x,
		hud->device->cachedConfig.Res.y);
	if (numLocalPlayersAlive <= 1)
	{
		flags = 0;
	}
	else if (
		ConfigGetEnum(&gConfig, "Interface.Splitscreen") == SPLITSCREEN_NEVER)
	{
		flags |= HUDFLAGS_SHARE_SCREEN;
	}
	else if (numLocalPlayers == 2)
	{
		r.Size.x /= 2;
		flags |= HUDFLAGS_HALF_SCREEN;
	}
	else if (numLocalPlayers == 3 || numLocalPlayers == 4)
	{
		r.Size.x /= 2;
		r.Size.y /= 2;
		flags |= HUDFLAGS_QUARTER_SCREEN;
	}
	else
	{
		assert(0 && "not implemented");
	}

	int idx = 0;
	for (int i = 0; i < (int)gPlayerDatas.size; i++, idx++)
	{
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		if (!p->IsLocal)
		{
			idx--;
			continue;
		}
		int drawFlags = flags;
		r.Pos = Vec2iZero();
		if (idx & 1)
		{
			r.Pos.x = r.Size.x;
			drawFlags |= HUDFLAGS_PLACE_RIGHT;
		}
		if (idx >= 2)
		{
			r.Pos.y = r.Size.y;
			drawFlags |= HUDFLAGS_PLACE_BOTTOM;
		}
		TActor *player = NULL;
		if (IsPlayerAlive(p))
		{
			player = ActorGetByUID(p->ActorUID);
		}
		DrawPlayerStatus(hud, p, player, drawFlags, r);
		DrawScoreUpdate(&hud->scoreUpdates[idx], drawFlags);
		DrawHealthUpdate(&hud->healthUpdates[idx], drawFlags);
		DrawAmmoUpdate(&hud->ammoUpdates[idx], drawFlags);
	}
	// Only draw radar once if shared
	if (ConfigGetBool(&gConfig, "Interface.ShowHUDMap") &&
		(flags & HUDFLAGS_SHARE_SCREEN) &&
		IsAutoMapEnabled(gCampaign.Entry.Mode))
	{
		DrawSharedRadar(hud->device, RADAR_SCALE, hud->showExit);
	}

	if (numPlayersAlive == 0)
	{
		if (AreAllPlayersDeadAndNoLives())
		{
			if (!IsPVP(gCampaign.Entry.Mode))
			{
				FontStrCenter("Game Over!");
			}
			else
			{
				FontStrCenter("All Kill!");
			}
		}
	}
	else if (hud->mission->state == MISSION_STATE_PICKUP)
	{
		int timeLeft = gMission.pickupTime + PICKUP_LIMIT - gMission.time;
		sprintf(s, "Pickup in %d seconds\n",
			(timeLeft + (FPS_FRAMELIMIT - 1)) / FPS_FRAMELIMIT);
		FontStrCenter(s);
	}

	if (pausingDevice != INPUT_DEVICE_UNSET)
	{
		Vec2i pos = Vec2iScaleDiv(Vec2iMinus(
			gGraphicsDevice.cachedConfig.Res,
			FontStrSize("Foo\nPress foo or bar to unpause\nBaz")), 2);
		const int x = pos.x;
		FontStr("<Paused>", pos);

		pos.y += FontH();
		pos = FontStr("Press ", pos);
		color_t c = colorWhite;
		const char *buttonName =
			InputGetButtonNameColor(pausingDevice, 0, CMD_ESC, &c);
		pos = FontStrMask(buttonName, pos, c);
		FontStr(" again to quit", pos);

		pos.x = x;
		pos.y += FontH();
		pos = FontStr("Press ", pos);
		buttonName = InputGetButtonNameColor(
			pausingDevice, 0, CMD_BUTTON1, &c);
		pos = FontStrMask(buttonName, pos, c);
		pos = FontStr(" or ", pos);
		buttonName = InputGetButtonNameColor(
			pausingDevice, 0, CMD_BUTTON2, &c);
		pos = FontStrMask(buttonName, pos, c);
		FontStr(" to unpause", pos);
	}

	if (hud->messageTicks > 0 || hud->messageTicks == -1)
	{
		// Draw the message centered, and just below the automap
		Vec2i pos = Vec2iNew(
			(hud->device->cachedConfig.Res.x -
			FontStrW(hud->message)) / 2,
			AUTOMAP_SIZE + AUTOMAP_PADDING + AUTOMAP_PADDING);
		FontStrMask(hud->message, pos, colorCyan);
	}

	if (ConfigGetBool(&gConfig, "Interface.ShowFPS"))
	{
		FPSCounterDraw(&hud->fpsCounter);
	}
	if (ConfigGetBool(&gConfig, "Interface.ShowTime"))
	{
		WallClockDraw(&hud->clock);
	}

	DrawKeycards(hud);

	// Draw elapsed mission time as MM:SS
	int missionTimeSeconds = gMission.time / FPS_FRAMELIMIT;
	sprintf(s, "%d:%02d",
		missionTimeSeconds / 60, missionTimeSeconds % 60);

	FontOpts opts = FontOptsNew();
	opts.HAlign = ALIGN_CENTER;
	opts.Area = hud->device->cachedConfig.Res;
	opts.Pad.y = 5;
	FontStrOpt(s, Vec2iZero(), opts);

	if (HasObjectives(gCampaign.Entry.Mode))
	{
		DrawObjectiveCounts(hud);
	}
}
void CollisionSystemInit(CollisionSystem *cs)
{
	cs->allyCollision = ConfigGetEnum(&gConfig, "Game.AllyCollision");
}
Exemple #8
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++;
    }
}
void SetupQuickPlayCampaign(CampaignSetting *setting)
{
	Mission *m;
	CMALLOC(m, sizeof *m);
	MissionInit(m);
	m->WallStyle = rand() % WALL_STYLE_COUNT;
	m->FloorStyle = rand() % FLOOR_STYLE_COUNT;
	m->RoomStyle = rand() % FLOOR_STYLE_COUNT;
	m->ExitStyle = rand() % GetExitCount();
	m->KeyStyle = rand() % KEYSTYLE_COUNT;
	strcpy(
		m->DoorStyle, DoorStyleStr(rand() % gPicManager.doorStyleNames.size));
	m->Size = GenerateQuickPlayMapSize(
		ConfigGetEnum(&gConfig, "QuickPlay.MapSize"));
	m->Type = MAPTYPE_CLASSIC;	// TODO: generate different map types
	switch (m->Type)
	{
	case MAPTYPE_CLASSIC:
		m->u.Classic.Walls = GenerateQuickPlayParam(
			ConfigGetEnum(&gConfig, "QuickPlay.WallCount"), 0, 5, 15, 30);
		m->u.Classic.WallLength = GenerateQuickPlayParam(
			ConfigGetEnum(&gConfig, "QuickPlay.WallLength"), 1, 3, 6, 12);
		m->u.Classic.CorridorWidth = rand() % 3 + 1;
		m->u.Classic.Rooms.Count = GenerateQuickPlayParam(
			ConfigGetEnum(&gConfig, "QuickPlay.RoomCount"), 0, 2, 5, 12);
		m->u.Classic.Rooms.Min = rand() % 10 + 5;
		m->u.Classic.Rooms.Max = rand() % 10 + m->u.Classic.Rooms.Min;
		m->u.Classic.Rooms.Edge = 1;
		m->u.Classic.Rooms.Overlap = 1;
		m->u.Classic.Rooms.Walls = rand() % 5;
		m->u.Classic.Rooms.WallLength = rand() % 6 + 1;
		m->u.Classic.Rooms.WallPad = rand() % 4 + 1;
		m->u.Classic.Squares = GenerateQuickPlayParam(
			ConfigGetEnum(&gConfig, "QuickPlay.SquareCount"), 0, 1, 3, 6);
		m->u.Classic.Doors.Enabled = rand() % 2;
		m->u.Classic.Doors.Min = 1;
		m->u.Classic.Doors.Max = 6;
		m->u.Classic.Pillars.Count = rand() % 5;
		m->u.Classic.Pillars.Min = rand() % 3 + 1;
		m->u.Classic.Pillars.Max = rand() % 3 + m->u.Classic.Pillars.Min;
		break;
	default:
		assert(0 && "unknown map type");
		break;
	}
	CharacterStoreTerminate(&setting->characters);
	CharacterStoreInit(&setting->characters);
	int c = GenerateQuickPlayParam(
		ConfigGetEnum(&gConfig, "QuickPlay.EnemyCount"), 3, 5, 8, 12);
	SetupQuickPlayEnemies(m, c, &setting->characters);

	c = GenerateQuickPlayParam(
		ConfigGetEnum(&gConfig, "QuickPlay.ItemCount"), 0, 2, 5, 10);
	for (int i = 0; i < c; i++)
	{
		MapObjectDensity mop;
		mop.M = IndexMapObject(rand() % MapObjectsCount(&gMapObjects));
		mop.Density = GenerateQuickPlayParam(
			ConfigGetEnum(&gConfig, "QuickPlay.ItemCount"), 0, 5, 10, 20);
		CArrayPushBack(&m->MapObjectDensities, &mop);
	}
	m->EnemyDensity = (40 + (rand() % 20)) / m->Enemies.size;
	CA_FOREACH(const GunDescription, g, gGunDescriptions.Guns)
		if (g->IsRealGun)
		{
			CArrayPushBack(&m->Weapons, &g);
		}
	CA_FOREACH_END()
	m->WallMask = RandomBGColor();
	m->FloorMask = RandomBGColor();
	m->RoomMask = RandomBGColor();
	m->AltMask = RandomBGColor();

	CFREE(setting->Title);
	CSTRDUP(setting->Title, "Quick play");
	CFREE(setting->Author);
	CSTRDUP(setting->Author, "");
	CFREE(setting->Description);
	CSTRDUP(setting->Description, "");
	CArrayPushBack(&setting->Missions, m);
	CFREE(m);
}
Exemple #10
0
void GraphicsInitialize(GraphicsDevice *g)
{
    if (g->IsInitialized && !g->cachedConfig.RestartFlags)
    {
        return;
    }

    if (!g->IsWindowInitialized)
    {
        char buf[CDOGS_PATH_MAX];
        GetDataFilePath(buf, "cdogs_icon.bmp");
        g->icon = IMG_Load(buf);
        AddSupportedGraphicsModes(g);
        g->IsWindowInitialized = true;
    }

    g->IsInitialized = false;

    const int w = g->cachedConfig.Res.x;
    const int h = g->cachedConfig.Res.y;

    const bool initRenderer =
        !!(g->cachedConfig.RestartFlags & RESTART_RESOLUTION);
    const bool initTextures =
        !!(g->cachedConfig.RestartFlags &
           (RESTART_RESOLUTION | RESTART_SCALE_MODE));
    const bool initBrightness =
        !!(g->cachedConfig.RestartFlags &
           (RESTART_RESOLUTION | RESTART_SCALE_MODE | RESTART_BRIGHTNESS));

    if (initRenderer)
    {
        Uint32 sdlFlags = SDL_WINDOW_RESIZABLE;
        if (g->cachedConfig.Fullscreen)
        {
            sdlFlags |= SDL_WINDOW_FULLSCREEN;
        }

        LOG(LM_GFX, LL_INFO, "graphics mode(%dx%d %dx)",
            w, h, g->cachedConfig.ScaleFactor);
        // Get the previous window's size and recreate it
        Vec2i windowSize = Vec2iNew(
                               w * g->cachedConfig.ScaleFactor, h * g->cachedConfig.ScaleFactor);
        if (g->window)
        {
            SDL_GetWindowSize(g->window, &windowSize.x, &windowSize.y);
        }
        LOG(LM_GFX, LL_DEBUG, "destroying previous renderer");
        SDL_DestroyTexture(g->screen);
        SDL_DestroyTexture(g->bkg);
        SDL_DestroyTexture(g->brightnessOverlay);
        SDL_DestroyRenderer(g->renderer);
        SDL_FreeFormat(g->Format);
        SDL_DestroyWindow(g->window);
        LOG(LM_GFX, LL_DEBUG, "creating window %dx%d flags(%X)",
            windowSize.x, windowSize.y, sdlFlags);
        if (SDL_CreateWindowAndRenderer(
                    windowSize.x, windowSize.y, sdlFlags,
                    &g->window, &g->renderer) == -1 ||
                g->window == NULL || g->renderer == NULL)
        {
            LOG(LM_GFX, LL_ERROR, "cannot create window or renderer: %s",
                SDL_GetError());
            return;
        }
        char title[32];
        sprintf(title, "C-Dogs SDL %s%s",
                g->cachedConfig.IsEditor ? "Editor " : "",
                CDOGS_SDL_VERSION);
        LOG(LM_GFX, LL_DEBUG, "setting title(%s) and icon", title);
        SDL_SetWindowTitle(g->window, title);
        SDL_SetWindowIcon(g->window, g->icon);
        g->Format = SDL_AllocFormat(SDL_PIXELFORMAT_ARGB8888);

        if (SDL_RenderSetLogicalSize(g->renderer, w, h) != 0)
        {
            LOG(LM_GFX, LL_ERROR, "cannot set renderer logical size: %s",
                SDL_GetError());
            return;
        }

        GraphicsSetBlitClip(
            g, 0, 0, g->cachedConfig.Res.x - 1, g->cachedConfig.Res.y - 1);
    }

    if (initTextures)
    {
        if (!initRenderer)
        {
            SDL_DestroyTexture(g->screen);
            SDL_DestroyTexture(g->bkg);
            SDL_DestroyTexture(g->brightnessOverlay);
        }

        // Set render scale mode
        const char *renderScaleQuality = "nearest";
        switch ((ScaleMode)ConfigGetEnum(&gConfig, "Graphics.ScaleMode"))
        {
        case SCALE_MODE_NN:
            renderScaleQuality = "nearest";
            break;
        case SCALE_MODE_BILINEAR:
            renderScaleQuality = "linear";
            break;
        default:
            CASSERT(false, "unknown scale mode");
            break;
        }
        LOG(LM_GFX, LL_DEBUG, "setting scale quality %s", renderScaleQuality);
        if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, renderScaleQuality))
        {
            LOG(LM_GFX, LL_WARN, "cannot set render quality hint: %s",
                SDL_GetError());
        }

        g->screen = CreateTexture(
                        g->renderer, SDL_TEXTUREACCESS_STREAMING, Vec2iNew(w, h),
                        SDL_BLENDMODE_BLEND, 255);
        if (g->screen == NULL)
        {
            return;
        }

        CFREE(g->buf);
        CCALLOC(g->buf, GraphicsGetMemSize(&g->cachedConfig));
        g->bkg = CreateTexture(
                     g->renderer, SDL_TEXTUREACCESS_STATIC, Vec2iNew(w, h),
                     SDL_BLENDMODE_NONE, 255);
        if (g->bkg == NULL)
        {
            return;
        }
    }

    if (initBrightness)
    {
        if (!initRenderer && !initTextures)
        {
            SDL_DestroyTexture(g->brightnessOverlay);
        }

        const int brightness = ConfigGetInt(&gConfig, "Graphics.Brightness");
        // Alpha is approximately 50% max
        const Uint8 alpha = (Uint8)(brightness > 0 ? brightness : -brightness) * 13;
        g->brightnessOverlay = CreateTexture(
                                   g->renderer, SDL_TEXTUREACCESS_STATIC, Vec2iNew(w, h),
                                   SDL_BLENDMODE_BLEND, alpha);
        if (g->brightnessOverlay == NULL)
        {
            return;
        }
        const color_t overlayColour = brightness > 0 ? colorWhite : colorBlack;
        DrawRectangle(g, Vec2iZero(), g->cachedConfig.Res, overlayColour, 0);
        SDL_UpdateTexture(
            g->brightnessOverlay, NULL, g->buf,
            g->cachedConfig.Res.x * sizeof(Uint32));
        memset(g->buf, 0, GraphicsGetMemSize(&g->cachedConfig));
        g->cachedConfig.Brightness = brightness;
    }

    g->IsInitialized = true;
    g->cachedConfig.Res.x = w;
    g->cachedConfig.Res.y = h;
    g->cachedConfig.RestartFlags = 0;
}
Exemple #11
0
static void DrawActorPics(const TTileItem *t, const Vec2i picPos)
{
    const ActorPics pics = t->getActorPicsFunc(t->id);
    if (pics.IsDead)
    {
        if (pics.IsDying)
        {
            int pic = pics.OldPics[0];
            if (pic == 0)
            {
                return;
            }
            if (pics.IsTransparent)
            {
                DrawBTPic(
                    &gGraphicsDevice,
                    PicManagerGetFromOld(&gPicManager, pic),
                    Vec2iAdd(picPos, pics.Pics[0].offset),
                    pics.Tint);
            }
            else
            {
                DrawTTPic(
                    picPos.x + pics.Pics[0].offset.x,
                    picPos.y + pics.Pics[0].offset.y,
                    PicManagerGetOldPic(&gPicManager, pic),
                    pics.Table);
            }
        }
    }
    else if (pics.IsTransparent)
    {
        for (int i = 0; i < 3; i++)
        {
            Pic *oldPic = PicManagerGetFromOld(
                              &gPicManager, pics.OldPics[i]);
            if (oldPic == NULL)
            {
                continue;
            }
            DrawBTPic(
                &gGraphicsDevice,
                oldPic,
                Vec2iAdd(picPos, pics.Pics[i].offset),
                pics.Tint);
        }
    }
    else
    {
        DrawShadow(&gGraphicsDevice, picPos, Vec2iNew(8, 6));
        for (int i = 0; i < 3; i++)
        {
            PicPaletted *oldPic = PicManagerGetOldPic(
                                      &gPicManager, pics.OldPics[i]);
            if (oldPic == NULL)
            {
                continue;
            }
            BlitOld(
                picPos.x + pics.Pics[i].offset.x,
                picPos.y + pics.Pics[i].offset.y,
                oldPic,
                pics.Table, BLIT_TRANSPARENT);
        }

        const TActor *a = CArrayGet(&gActors, t->id);

        // Draw weapon indicators
        if (ConfigGetEnum(&gConfig, "Game.LaserSight") == LASER_SIGHT_ALL ||
                (ConfigGetEnum(&gConfig, "Game.LaserSight") == LASER_SIGHT_PLAYERS && a->PlayerUID >= 0))
        {
            DrawLaserSight(a, picPos);
        }
    }
}