From b64e9e70fc5b43a11ed5a71f05460d7d14deafcc Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 6 May 2016 10:56:58 +0100 Subject: [PATCH] Added EF_DROPS_ITEM, to allow ships to drop items when destroyed in challenge mode. --- src/battle/fighters.c | 41 ++++++++++++++++++++++++++++--------- src/battle/fighters.h | 1 + src/battle/hud.c | 4 ++++ src/battle/items.c | 31 +++++++++++++++++++--------- src/battle/player.c | 23 ++++++++++++++++++++- src/battle/player.h | 1 + src/challenges/challenges.c | 29 +++++++++++++++++++++++++- src/challenges/challenges.h | 1 - src/defs.h | 2 ++ src/structs.h | 1 + src/system/lookup.c | 2 ++ 11 files changed, 113 insertions(+), 23 deletions(-) diff --git a/src/battle/fighters.c b/src/battle/fighters.c index 63aab77..30d2d62 100644 --- a/src/battle/fighters.c +++ b/src/battle/fighters.c @@ -312,7 +312,7 @@ void doFighter(void) else { battle.stats[STAT_ALLIES_KILLED]++; - if (!battle.isEpic || game.currentMission->challengeData.isChallenge) + if (!battle.isEpic && !game.currentMission->challengeData.isChallenge) { addHudMessage(colors.red, _("Ally has been killed")); } @@ -415,12 +415,18 @@ void damageFighter(Entity *e, int amount, long flags) { if (e->shield > 0) { - e->shield = MAX(0, e->shield - amount / 2); + amount /= 2; + + e->shield -= amount; + + if (e->shield < 0) + { + amount = -e->shield; + } } - else + + if (amount >= 0) { - playBattleSound(SND_MAG_HIT, e->x, e->y); - e->systemPower = MAX(0, e->systemPower - amount); e->systemHit = 255; @@ -430,6 +436,8 @@ void damageFighter(Entity *e, int amount, long flags) e->shield = e->maxShield = 0; e->action = NULL; } + + playBattleSound(SND_MAG_HIT, e->x, e->y); } } else if (flags & BF_SHIELD_DAMAGE) @@ -449,9 +457,17 @@ void damageFighter(Entity *e, int amount, long flags) { if (e->shield > 0) { - e->shield = MAX(0, e->shield - amount); + e->shield -= amount; + + amount = 0; + + if (e->shield < 0) + { + amount = -e->shield; + } } - else + + if (amount >= 0) { e->health -= amount; e->armourHit = 255; @@ -464,11 +480,11 @@ void damageFighter(Entity *e, int amount, long flags) { e->shieldHit = 255; - /* don't allow the shield to recharge immediately after taking a hit */ - e->shieldRecharge = e->shieldRechargeRate; - playBattleSound(SND_SHIELD_HIT, e->x, e->y); } + + /* don't allow the shield to recharge immediately after taking a hit */ + e->shieldRecharge = e->shieldRechargeRate; /* * Sometimes run away if you take too much damage in a short space of time @@ -543,6 +559,11 @@ static void die(void) awardTrophy("PANDORAN"); } } + + if (self->flags & EF_DROPS_ITEMS) + { + addRandomItem(self->x, self->y); + } } static void immediateDie(void) diff --git a/src/battle/fighters.h b/src/battle/fighters.h index 67f6d1e..c4f5e6c 100644 --- a/src/battle/fighters.h +++ b/src/battle/fighters.h @@ -50,6 +50,7 @@ extern int getJSONValue(cJSON *node, char *name, int defValue); extern char **toTypeArray(char *types, int *numTypes); extern char *getJSONValueStr(cJSON *node, char *name, char *defValue); extern void awardTrophy(char *id); +extern void addRandomItem(int x, int y); extern App app; extern Battle battle; diff --git a/src/battle/hud.c b/src/battle/hud.c index c6f3050..006d720 100644 --- a/src/battle/hud.c +++ b/src/battle/hud.c @@ -450,6 +450,10 @@ static void drawObjectives(void) { drawText(SCREEN_WIDTH / 2, 35, 14, TA_CENTER, colors.white, "%d / %d", battle.stats[STAT_ITEMS_COLLECTED] + battle.stats[STAT_ITEMS_COLLECTED_PLAYER], game.currentMission->challengeData.itemLimit); } + else if (game.currentMission->challengeData.playerItemLimit) + { + drawText(SCREEN_WIDTH / 2, 35, 14, TA_CENTER, colors.white, "%d / %d", battle.stats[STAT_ITEMS_COLLECTED_PLAYER], game.currentMission->challengeData.playerItemLimit); + } else if (game.currentMission->challengeData.rescueLimit) { drawText(SCREEN_WIDTH / 2, 35, 14, TA_CENTER, colors.white, "%d / %d", battle.stats[STAT_CIVILIANS_RESCUED], game.currentMission->challengeData.rescueLimit); diff --git a/src/battle/items.c b/src/battle/items.c index bd79b85..6bfc07e 100644 --- a/src/battle/items.c +++ b/src/battle/items.c @@ -46,7 +46,7 @@ void loadItemDefs(void) e->type = ET_ITEM; e->active = 1; STRNCPY(e->name, cJSON_GetObjectItem(node, "name")->valuestring, MAX_NAME_LENGTH); - STRNCPY(e->defName, cJSON_GetObjectItem(node, "name")->valuestring, MAX_NAME_LENGTH); + STRNCPY(e->defName, cJSON_GetObjectItem(node, "defName")->valuestring, MAX_NAME_LENGTH); e->texture = getTexture(cJSON_GetObjectItem(node, "texture")->valuestring); e->health = e->maxHealth = FPS; e->flags = EF_NO_HEALTH_BAR; @@ -70,29 +70,40 @@ Entity *spawnItem(char *name) def = getItemDef(name); memcpy(item, def, sizeof(Entity)); - - item->dx = rand() % 100 - rand() % 100; - item->dx *= 0.01; - item->dy = rand() % 100 - rand() % 100; - item->dy *= 0.01; + item->action = action; return item; } -static Entity *getItemDef(char *name) +void addRandomItem(int x, int y) +{ + Entity *e; + + e = spawnItem("smallCrate"); + e->x = x; + e->y = y; + + e->speed = 1; + e->dx = rand() % 200 - rand() % 200; + e->dy = rand() % 200 - rand() % 200; + e->dx *= 0.01; + e->dy *= 0.01; +} + +static Entity *getItemDef(char *defName) { Entity *e; for (e = defHead.next ; e != NULL ; e = e->next) { - if (strcmp(e->name, name) == 0) + if (strcmp(e->defName, defName) == 0) { return e; } } - printf("Error: no such item '%s'\n", name); + printf("Error: no such item '%s'\n", defName); exit(1); } @@ -105,7 +116,7 @@ static void action(void) for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) { - if ((e->flags & EF_COLLECTS_ITEMS) && collision(self->x - (self->w / 2), self->y - (self->h / 2), self->w, self->h, e->x - (e->w / 2), e->y - (e->h / 2), e->w, e->h)) + if (e->alive == ALIVE_ALIVE && (e->flags & EF_COLLECTS_ITEMS) && collision(self->x - (self->w / 2), self->y - (self->h / 2), self->w, self->h, e->x - (e->w / 2), e->y - (e->h / 2), e->w, e->h)) { self->health = 0; playBattleSound(SND_GET_ITEM, self->x, self->y); diff --git a/src/battle/player.c b/src/battle/player.c index fa82792..9918fa0 100644 --- a/src/battle/player.c +++ b/src/battle/player.c @@ -613,10 +613,12 @@ int playerHasGun(int type) void loadPlayer(cJSON *node) { char *type; - int side; + int side, addFlags; + long flags; type = cJSON_GetObjectItem(node, "type")->valuestring; side = lookup(cJSON_GetObjectItem(node, "side")->valuestring); + flags = -1; player = spawnFighter(type, 0, 0, side); player->x = BATTLE_AREA_WIDTH / 2; @@ -627,6 +629,25 @@ void loadPlayer(cJSON *node) player->x = (cJSON_GetObjectItem(node, "x")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_WIDTH; player->y = (cJSON_GetObjectItem(node, "y")->valuedouble / BATTLE_AREA_CELLS) * BATTLE_AREA_HEIGHT; } + + if (cJSON_GetObjectItem(node, "flags")) + { + flags = flagsToLong(cJSON_GetObjectItem(node, "flags")->valuestring, &addFlags); + } + + if (flags != -1) + { + if (addFlags) + { + player->flags |= flags; + } + else + { + player->flags = flags; + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Flags for Player replaced"); + } + } if (strcmp(type, "Tug") == 0) { diff --git a/src/battle/player.h b/src/battle/player.h index 7f39fb5..071ff89 100644 --- a/src/battle/player.h +++ b/src/battle/player.h @@ -45,6 +45,7 @@ extern Entity *spawnFighter(char *name, int x, int y, int side); extern int isAcceptControl(void); extern void resetAcceptControls(void); extern void awardTrophy(char *id); +extern long flagsToLong(char *flags, int *add); extern App app; extern Battle battle; diff --git a/src/challenges/challenges.c b/src/challenges/challenges.c index 7274089..d0d5ef7 100644 --- a/src/challenges/challenges.c +++ b/src/challenges/challenges.c @@ -59,6 +59,7 @@ void initChallenges(void) challengeDescription[CHALLENGE_PLAYER_KILLS] = _("Take down %d enemy targets"); challengeDescription[CHALLENGE_DISABLE] = _("Disable %d or more enemy fighters"); challengeDescription[CHALLENGE_ITEMS] = _("Collect %d packages"); + challengeDescription[CHALLENGE_PLAYER_ITEMS] = _("Collect %d packages"); challengeDescription[CHALLENGE_RESCUE] = _("Rescue %d civilians"); tail = &game.challengeMissionHead; @@ -96,6 +97,7 @@ void loadChallenge(Mission *mission, cJSON *node) mission->challengeData.escapeLimit = getJSONValue(node, "escapeLimit", 0); mission->challengeData.waypointLimit = getJSONValue(node, "waypointLimit", 0); mission->challengeData.itemLimit = getJSONValue(node, "itemLimit", 0); + mission->challengeData.playerItemLimit = getJSONValue(node, "playerItemLimit", 0); mission->challengeData.rescueLimit = getJSONValue(node, "rescueLimit", 0); /* restrictions */ @@ -187,6 +189,11 @@ static int challengeFinished(void) return 1; } + if (game.currentMission->challengeData.playerItemLimit > 0 && battle.stats[STAT_ITEMS_COLLECTED_PLAYER] >= game.currentMission->challengeData.playerItemLimit) + { + return 1; + } + if (game.currentMission->challengeData.rescueLimit > 0 && (battle.stats[STAT_CIVILIANS_RESCUED] + battle.stats[STAT_CIVILIANS_KILLED]) >= game.currentMission->challengeData.rescueLimit) { return 1; @@ -257,6 +264,7 @@ static int updateChallenges(void) break; case CHALLENGE_ITEMS: + case CHALLENGE_PLAYER_ITEMS: updateItemsChallenge(c); break; } @@ -384,12 +392,31 @@ static void updateItemsChallenge(Challenge *c) { if (!c->passed) { - c->passed = battle.stats[STAT_ITEMS_COLLECTED] + battle.stats[STAT_ITEMS_COLLECTED_PLAYER] >= c->value; + if (c->type == CHALLENGE_ITEMS) + { + c->passed = battle.stats[STAT_ITEMS_COLLECTED] + battle.stats[STAT_ITEMS_COLLECTED_PLAYER] >= c->value; + } + else + { + c->passed = battle.stats[STAT_ITEMS_COLLECTED_PLAYER] >= c->value; + } } } char *getChallengeDescription(Challenge *c) { + if (c->type == CHALLENGE_TIME) + { + if (c->value <= 90) + { + return getFormattedChallengeDescription(challengeDescription[CHALLENGE_TIME], c->value); + } + else + { + return getFormattedChallengeDescription(_("Complete challenge in %s or less"), timeToString(c->value * FPS, 0)); + } + } + return getFormattedChallengeDescription(challengeDescription[c->type], c->value); } diff --git a/src/challenges/challenges.h b/src/challenges/challenges.h index bc73a13..79f56ef 100644 --- a/src/challenges/challenges.h +++ b/src/challenges/challenges.h @@ -30,7 +30,6 @@ extern char *getTranslatedString(char *string); extern char *getLookupName(char *prefix, long num); extern char *timeToString(long millis, int showHours); extern void updateAccuracyStats(unsigned int *stats); -extern char *timeToString(long millis, int showHours); extern int getJSONValue(cJSON *node, char *name, int defValue); extern long lookup(char *name); extern void awardStatsTrophies(void); diff --git a/src/defs.h b/src/defs.h index 9025723..17b6908 100644 --- a/src/defs.h +++ b/src/defs.h @@ -107,6 +107,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define EF_NO_HEALTH_BAR (2 << 21) #define EF_FRIENDLY_HEALTH_BAR (2 << 22) #define EF_NO_THREAT (2 << 23) +#define EF_DROPS_ITEMS (2 << 24) #define AIF_NONE 0 #define AIF_FOLLOWS_PLAYER (2 << 0) @@ -316,6 +317,7 @@ enum CHALLENGE_PLAYER_KILLS, CHALLENGE_DISABLE, CHALLENGE_ITEMS, + CHALLENGE_PLAYER_ITEMS, CHALLENGE_RESCUE, CHALLENGE_SURVIVE, CHALLENGE_MAX diff --git a/src/structs.h b/src/structs.h index a44adef..76cb24d 100644 --- a/src/structs.h +++ b/src/structs.h @@ -253,6 +253,7 @@ typedef struct { int killLimit; int lossLimit; int itemLimit; + int playerItemLimit; int escapeLimit; int waypointLimit; int rescueLimit; diff --git a/src/system/lookup.c b/src/system/lookup.c index 6383095..da8210b 100644 --- a/src/system/lookup.c +++ b/src/system/lookup.c @@ -69,6 +69,7 @@ void initLookups(void) addLookup("EF_AI_IGNORE", EF_AI_IGNORE); addLookup("EF_NO_THREAT", EF_NO_THREAT); addLookup("EF_NO_HEALTH_BAR", EF_NO_HEALTH_BAR); + addLookup("EF_DROPS_ITEMS", EF_DROPS_ITEMS); addLookup("AIF_NONE", AIF_NONE); addLookup("AIF_MOVES_TO_PLAYER", AIF_MOVES_TO_PLAYER); @@ -148,6 +149,7 @@ void initLookups(void) addLookup("CHALLENGE_PLAYER_KILLS", CHALLENGE_PLAYER_KILLS); addLookup("CHALLENGE_DISABLE", CHALLENGE_DISABLE); addLookup("CHALLENGE_ITEMS", CHALLENGE_ITEMS); + addLookup("CHALLENGE_PLAYER_ITEMS", CHALLENGE_PLAYER_ITEMS); addLookup("CHALLENGE_RESCUE", CHALLENGE_RESCUE); addLookup("STAT_PERCENT_COMPLETE", STAT_PERCENT_COMPLETE);