From ea3ac38b0db119fe30a5f30f60c2823a496710f7 Mon Sep 17 00:00:00 2001 From: Cong Date: Tue, 10 Dec 2013 20:36:18 +1100 Subject: [PATCH] Add Mission Complete message (fixes #198) Fix autosave LastMission bug - LastMission was always the last autosave in the file Change game messages to be cyan and under the automap --- src/autosave.c | 5 ++++- src/cdogs/actors.c | 10 +++++++--- src/cdogs/color.c | 1 + src/cdogs/color.h | 1 + src/cdogs/game_events.h | 8 +++++++- src/cdogs/hud.c | 22 +++++++++++++++------- src/cdogs/hud.h | 5 ++++- src/cdogs/mission.c | 15 +++++++++++++-- src/cdogs/mission.h | 3 ++- src/cdogs/objs.c | 3 ++- src/game.c | 16 ++++++++++------ 11 files changed, 66 insertions(+), 23 deletions(-) diff --git a/src/autosave.c b/src/autosave.c index 196be348f..1bb0519cf 100644 --- a/src/autosave.c +++ b/src/autosave.c @@ -131,13 +131,16 @@ void AutosaveLoad(Autosave *autosave, const char *filename) printf("Error parsing autosave '%s'\n", filename); goto bail; } + // Note: need to load missions before LastMission because the former + // will overwrite the latter, since AutosaveAddMission also + // writes to LastMission + LoadMissionNodes(autosave, root, "Missions"); if (json_find_first_label(root, "LastMission")) { LoadMissionNode( &autosave->LastMission, json_find_first_label(root, "LastMission")->child); } - LoadMissionNodes(autosave, root, "Missions"); bail: json_free_value(&root); diff --git a/src/cdogs/actors.c b/src/cdogs/actors.c index bc780727f..84b9baa3a 100644 --- a/src/cdogs/actors.c +++ b/src/cdogs/actors.c @@ -534,7 +534,8 @@ static void PickupObject(TActor * actor, TObject * object) break; */ } - CheckMissionObjective(object->tileItem.flags, OBJECTIVE_COLLECT); + CheckMissionObjective( + &gMission, object->tileItem.flags, OBJECTIVE_COLLECT); RemoveObject(object); SoundPlayAt( &gSoundDevice, @@ -588,7 +589,9 @@ int MoveActor(TActor * actor, int x, int y) 0) { otherCharacter->flags &= ~FLAGS_PRISONER; CheckMissionObjective( - otherCharacter->tileItem.flags, OBJECTIVE_RESCUE); + &gMission, + otherCharacter->tileItem.flags, + OBJECTIVE_RESCUE); } } @@ -687,7 +690,8 @@ void InjureActor(TActor * actor, int injury) SND_HAHAHA, Vec2iNew(actor->tileItem.x, actor->tileItem.y)); } - CheckMissionObjective(actor->tileItem.flags, OBJECTIVE_KILL); + CheckMissionObjective( + &gMission, actor->tileItem.flags, OBJECTIVE_KILL); } } diff --git a/src/cdogs/color.c b/src/cdogs/color.c index b43a7c52a..438a5f310 100644 --- a/src/cdogs/color.c +++ b/src/cdogs/color.c @@ -41,6 +41,7 @@ color_t colorDarker = { 192, 192, 192, 255 }; color_t colorPurple = { 192, 0, 192, 255 }; color_t colorGray = { 128, 128, 128, 255 }; color_t colorYellow = { 255, 255, 128, 255 }; +color_t colorCyan = { 0, 255, 255, 255 }; color_t ColorMult(color_t c, color_t m) { diff --git a/src/cdogs/color.h b/src/cdogs/color.h index 2c8a065ac..c9be8c8d2 100644 --- a/src/cdogs/color.h +++ b/src/cdogs/color.h @@ -49,6 +49,7 @@ extern color_t colorDarker; extern color_t colorPurple; extern color_t colorGray; extern color_t colorYellow; +extern color_t colorCyan; color_t ColorMult(color_t c, color_t m); color_t ColorAlphaBlend(color_t a, color_t b); diff --git a/src/cdogs/game_events.h b/src/cdogs/game_events.h index 04cf63191..2dcef4511 100644 --- a/src/cdogs/game_events.h +++ b/src/cdogs/game_events.h @@ -35,7 +35,8 @@ typedef enum { - GAME_EVENT_SCREEN_SHAKE + GAME_EVENT_SCREEN_SHAKE, + GAME_EVENT_SET_MESSAGE } GameEventType; typedef struct @@ -44,6 +45,11 @@ typedef struct union { int ShakeAmount; + struct + { + char Message[256]; + int Ticks; + } SetMessage; } u; } GameEvent; diff --git a/src/cdogs/hud.c b/src/cdogs/hud.c index 3c21f1d7b..3ef3f85f0 100644 --- a/src/cdogs/hud.c +++ b/src/cdogs/hud.c @@ -126,18 +126,21 @@ void HUDInit( WallClockInit(&hud->clock); } -void HUDDisplayMessage(HUD *hud, const char *msg) +void HUDDisplayMessage(HUD *hud, const char *msg, int ticks) { strcpy(hud->message, msg); - hud->messageTicks = 140; + hud->messageTicks = ticks; } void HUDUpdate(HUD *hud, int ms) { - hud->messageTicks -= ms; - if (hud->messageTicks < 0) + if (hud->messageTicks >= 0) { - hud->messageTicks = 0; + hud->messageTicks -= ms; + if (hud->messageTicks < 0) + { + hud->messageTicks = 0; + } } FPSCounterUpdate(&hud->fpsCounter, ms); WallClockUpdate(&hud->clock, ms); @@ -513,9 +516,14 @@ void HUDDraw(HUD *hud, int isPaused) CDogsTextStringAtCenter("Press Esc again to quit"); } - if (hud->messageTicks > 0) + if (hud->messageTicks > 0 || hud->messageTicks == -1) { - CDogsTextStringSpecial(hud->message, TEXT_XCENTER | TEXT_TOP, 0, 20); + // Draw the message centered, and just below the automap + Vec2i pos = Vec2iNew( + (hud->device->cachedConfig.ResolutionWidth - + TextGetStringWidth(hud->message)) / 2, + AUTOMAP_SIZE + AUTOMAP_PADDING + AUTOMAP_PADDING); + DrawTextStringMasked(hud->message, hud->device, pos, colorCyan); } if (hud->config->ShowFPS) diff --git a/src/cdogs/hud.h b/src/cdogs/hud.h index dffab5716..b1a0afa26 100644 --- a/src/cdogs/hud.h +++ b/src/cdogs/hud.h @@ -70,7 +70,10 @@ void HUDInit( InterfaceConfig *config, GraphicsDevice *device, struct MissionOptions *mission); -void HUDDisplayMessage(HUD *hud, const char *msg); + +// Set ticks to -1 to display a message indefinitely +void HUDDisplayMessage(HUD *hud, const char *msg, int ticks); + void HUDUpdate(HUD *hud, int ms); void HUDDraw(HUD *hud, int isPaused); diff --git a/src/cdogs/mission.c b/src/cdogs/mission.c index 8c437ec32..621a3c9fe 100644 --- a/src/cdogs/mission.c +++ b/src/cdogs/mission.c @@ -51,6 +51,8 @@ #include #include #include + +#include "game_events.h" #include "gamedata.h" #include "map.h" #include "palette.h" @@ -906,7 +908,8 @@ void SetPaletteRanges(int wall_range, int floor_range, int room_range, int alt_r SetRange(ALT_COLORS, abs(alt_range) % COLORRANGE_COUNT); } -int CheckMissionObjective(int flags, ObjectiveType type) +int CheckMissionObjective( + struct MissionOptions *options, int flags, ObjectiveType type) { int idx; if (!(flags & TILEITEM_OBJECTIVE)) @@ -914,11 +917,19 @@ int CheckMissionObjective(int flags, ObjectiveType type) return 0; } idx = ObjectiveFromTileItem(flags); - if (gMission.missionData->objectives[idx].type != type) + if (options->missionData->objectives[idx].type != type) { return 0; } gMission.objectives[idx].done++; + if (CanCompleteMission(options)) + { + GameEvent msg; + msg.Type = GAME_EVENT_SET_MESSAGE; + strcpy(msg.u.SetMessage.Message, "Mission Complete"); + msg.u.SetMessage.Ticks = -1; + GameEventsEnqueue(&gGameEvents, msg); + } return 1; } diff --git a/src/cdogs/mission.h b/src/cdogs/mission.h index 3608344c6..a1996de65 100644 --- a/src/cdogs/mission.h +++ b/src/cdogs/mission.h @@ -72,7 +72,8 @@ void SetupMission(int index, int buildTables, CampaignOptions *campaign); void SetPaletteRanges(int wall_range, int floor_range, int room_range, int alt_range); // If object is a mission objective, complete it and return true -int CheckMissionObjective(int flags, ObjectiveType type); +int CheckMissionObjective( + struct MissionOptions *options, int flags, ObjectiveType type); int CanCompleteMission(struct MissionOptions *options); int IsMissionComplete(struct MissionOptions *options); diff --git a/src/cdogs/objs.c b/src/cdogs/objs.c index 7b7479504..9fbe90a82 100644 --- a/src/cdogs/objs.c +++ b/src/cdogs/objs.c @@ -438,7 +438,8 @@ static void DamageObject( if (object->structure <= 0) { object->structure = 0; - if (CheckMissionObjective(object->tileItem.flags, OBJECTIVE_DESTROY)) + if (CheckMissionObjective( + &gMission, object->tileItem.flags, OBJECTIVE_DESTROY)) { if (player >= 0) { diff --git a/src/game.c b/src/game.c index c258c06ed..b837d25b4 100644 --- a/src/game.c +++ b/src/game.c @@ -625,16 +625,20 @@ Vec2i GetPlayerCenter(GraphicsDevice *device, int player) return center; } -void HandleGameEvents(GameEventStore *store, int *shakeAmount) +void HandleGameEvents(GameEventStore *store, HUD *hud, int *shakeAmount) { int i; for (i = 0; i < store->count; i++) { - switch (store->events[i].Type) + GameEvent *e = &store->events[i]; + switch (e->Type) { case GAME_EVENT_SCREEN_SHAKE: - *shakeAmount = GetShakeAmount( - *shakeAmount, store->events[i].u.ShakeAmount); + *shakeAmount = GetShakeAmount(*shakeAmount, e->u.ShakeAmount); + break; + case GAME_EVENT_SET_MESSAGE: + HUDDisplayMessage( + hud, e->u.SetMessage.Message, e->u.SetMessage.Ticks); break; default: assert(0 && "unknown game event"); @@ -659,7 +663,7 @@ int gameloop(void) if (MusicGetStatus(&gSoundDevice) != MUSIC_OK) { - HUDDisplayMessage(&hud, MusicGetErrorMessage(&gSoundDevice)); + HUDDisplayMessage(&hud, MusicGetErrorMessage(&gSoundDevice), 140); } missionTime = 0; @@ -752,7 +756,7 @@ int gameloop(void) { if (!gConfig.Game.SlowMotion || (frames & 1) == 0) { - HandleGameEvents(&gGameEvents, &shakeAmount); + HandleGameEvents(&gGameEvents, &hud, &shakeAmount); for (i = 0; i < gOptions.numPlayers; i++) {