Added EF_DROPS_ITEM, to allow ships to drop items when destroyed in challenge mode.

This commit is contained in:
Steve 2016-05-06 10:56:58 +01:00
parent 8f7a2ec575
commit b64e9e70fc
11 changed files with 113 additions and 23 deletions

View File

@ -312,7 +312,7 @@ void doFighter(void)
else else
{ {
battle.stats[STAT_ALLIES_KILLED]++; 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")); addHudMessage(colors.red, _("Ally has been killed"));
} }
@ -415,12 +415,18 @@ void damageFighter(Entity *e, int amount, long flags)
{ {
if (e->shield > 0) 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->systemPower = MAX(0, e->systemPower - amount);
e->systemHit = 255; e->systemHit = 255;
@ -430,6 +436,8 @@ void damageFighter(Entity *e, int amount, long flags)
e->shield = e->maxShield = 0; e->shield = e->maxShield = 0;
e->action = NULL; e->action = NULL;
} }
playBattleSound(SND_MAG_HIT, e->x, e->y);
} }
} }
else if (flags & BF_SHIELD_DAMAGE) else if (flags & BF_SHIELD_DAMAGE)
@ -449,9 +457,17 @@ void damageFighter(Entity *e, int amount, long flags)
{ {
if (e->shield > 0) 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->health -= amount;
e->armourHit = 255; e->armourHit = 255;
@ -464,11 +480,11 @@ void damageFighter(Entity *e, int amount, long flags)
{ {
e->shieldHit = 255; 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); 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 * 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"); awardTrophy("PANDORAN");
} }
} }
if (self->flags & EF_DROPS_ITEMS)
{
addRandomItem(self->x, self->y);
}
} }
static void immediateDie(void) static void immediateDie(void)

View File

@ -50,6 +50,7 @@ extern int getJSONValue(cJSON *node, char *name, int defValue);
extern char **toTypeArray(char *types, int *numTypes); extern char **toTypeArray(char *types, int *numTypes);
extern char *getJSONValueStr(cJSON *node, char *name, char *defValue); extern char *getJSONValueStr(cJSON *node, char *name, char *defValue);
extern void awardTrophy(char *id); extern void awardTrophy(char *id);
extern void addRandomItem(int x, int y);
extern App app; extern App app;
extern Battle battle; extern Battle battle;

View File

@ -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); 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) 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); drawText(SCREEN_WIDTH / 2, 35, 14, TA_CENTER, colors.white, "%d / %d", battle.stats[STAT_CIVILIANS_RESCUED], game.currentMission->challengeData.rescueLimit);

View File

@ -46,7 +46,7 @@ void loadItemDefs(void)
e->type = ET_ITEM; e->type = ET_ITEM;
e->active = 1; e->active = 1;
STRNCPY(e->name, cJSON_GetObjectItem(node, "name")->valuestring, MAX_NAME_LENGTH); 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->texture = getTexture(cJSON_GetObjectItem(node, "texture")->valuestring);
e->health = e->maxHealth = FPS; e->health = e->maxHealth = FPS;
e->flags = EF_NO_HEALTH_BAR; e->flags = EF_NO_HEALTH_BAR;
@ -70,29 +70,40 @@ Entity *spawnItem(char *name)
def = getItemDef(name); def = getItemDef(name);
memcpy(item, def, sizeof(Entity)); 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; item->action = action;
return item; 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; Entity *e;
for (e = defHead.next ; e != NULL ; e = e->next) for (e = defHead.next ; e != NULL ; e = e->next)
{ {
if (strcmp(e->name, name) == 0) if (strcmp(e->defName, defName) == 0)
{ {
return e; return e;
} }
} }
printf("Error: no such item '%s'\n", name); printf("Error: no such item '%s'\n", defName);
exit(1); exit(1);
} }
@ -105,7 +116,7 @@ static void action(void)
for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) 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; self->health = 0;
playBattleSound(SND_GET_ITEM, self->x, self->y); playBattleSound(SND_GET_ITEM, self->x, self->y);

View File

@ -613,10 +613,12 @@ int playerHasGun(int type)
void loadPlayer(cJSON *node) void loadPlayer(cJSON *node)
{ {
char *type; char *type;
int side; int side, addFlags;
long flags;
type = cJSON_GetObjectItem(node, "type")->valuestring; type = cJSON_GetObjectItem(node, "type")->valuestring;
side = lookup(cJSON_GetObjectItem(node, "side")->valuestring); side = lookup(cJSON_GetObjectItem(node, "side")->valuestring);
flags = -1;
player = spawnFighter(type, 0, 0, side); player = spawnFighter(type, 0, 0, side);
player->x = BATTLE_AREA_WIDTH / 2; 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->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; 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) if (strcmp(type, "Tug") == 0)
{ {

View File

@ -45,6 +45,7 @@ extern Entity *spawnFighter(char *name, int x, int y, int side);
extern int isAcceptControl(void); extern int isAcceptControl(void);
extern void resetAcceptControls(void); extern void resetAcceptControls(void);
extern void awardTrophy(char *id); extern void awardTrophy(char *id);
extern long flagsToLong(char *flags, int *add);
extern App app; extern App app;
extern Battle battle; extern Battle battle;

View File

@ -59,6 +59,7 @@ void initChallenges(void)
challengeDescription[CHALLENGE_PLAYER_KILLS] = _("Take down %d enemy targets"); challengeDescription[CHALLENGE_PLAYER_KILLS] = _("Take down %d enemy targets");
challengeDescription[CHALLENGE_DISABLE] = _("Disable %d or more enemy fighters"); challengeDescription[CHALLENGE_DISABLE] = _("Disable %d or more enemy fighters");
challengeDescription[CHALLENGE_ITEMS] = _("Collect %d packages"); challengeDescription[CHALLENGE_ITEMS] = _("Collect %d packages");
challengeDescription[CHALLENGE_PLAYER_ITEMS] = _("Collect %d packages");
challengeDescription[CHALLENGE_RESCUE] = _("Rescue %d civilians"); challengeDescription[CHALLENGE_RESCUE] = _("Rescue %d civilians");
tail = &game.challengeMissionHead; tail = &game.challengeMissionHead;
@ -96,6 +97,7 @@ void loadChallenge(Mission *mission, cJSON *node)
mission->challengeData.escapeLimit = getJSONValue(node, "escapeLimit", 0); mission->challengeData.escapeLimit = getJSONValue(node, "escapeLimit", 0);
mission->challengeData.waypointLimit = getJSONValue(node, "waypointLimit", 0); mission->challengeData.waypointLimit = getJSONValue(node, "waypointLimit", 0);
mission->challengeData.itemLimit = getJSONValue(node, "itemLimit", 0); mission->challengeData.itemLimit = getJSONValue(node, "itemLimit", 0);
mission->challengeData.playerItemLimit = getJSONValue(node, "playerItemLimit", 0);
mission->challengeData.rescueLimit = getJSONValue(node, "rescueLimit", 0); mission->challengeData.rescueLimit = getJSONValue(node, "rescueLimit", 0);
/* restrictions */ /* restrictions */
@ -187,6 +189,11 @@ static int challengeFinished(void)
return 1; 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) if (game.currentMission->challengeData.rescueLimit > 0 && (battle.stats[STAT_CIVILIANS_RESCUED] + battle.stats[STAT_CIVILIANS_KILLED]) >= game.currentMission->challengeData.rescueLimit)
{ {
return 1; return 1;
@ -257,6 +264,7 @@ static int updateChallenges(void)
break; break;
case CHALLENGE_ITEMS: case CHALLENGE_ITEMS:
case CHALLENGE_PLAYER_ITEMS:
updateItemsChallenge(c); updateItemsChallenge(c);
break; break;
} }
@ -384,12 +392,31 @@ static void updateItemsChallenge(Challenge *c)
{ {
if (!c->passed) 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) 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); return getFormattedChallengeDescription(challengeDescription[c->type], c->value);
} }

View File

@ -30,7 +30,6 @@ extern char *getTranslatedString(char *string);
extern char *getLookupName(char *prefix, long num); extern char *getLookupName(char *prefix, long num);
extern char *timeToString(long millis, int showHours); extern char *timeToString(long millis, int showHours);
extern void updateAccuracyStats(unsigned int *stats); extern void updateAccuracyStats(unsigned int *stats);
extern char *timeToString(long millis, int showHours);
extern int getJSONValue(cJSON *node, char *name, int defValue); extern int getJSONValue(cJSON *node, char *name, int defValue);
extern long lookup(char *name); extern long lookup(char *name);
extern void awardStatsTrophies(void); extern void awardStatsTrophies(void);

View File

@ -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_NO_HEALTH_BAR (2 << 21)
#define EF_FRIENDLY_HEALTH_BAR (2 << 22) #define EF_FRIENDLY_HEALTH_BAR (2 << 22)
#define EF_NO_THREAT (2 << 23) #define EF_NO_THREAT (2 << 23)
#define EF_DROPS_ITEMS (2 << 24)
#define AIF_NONE 0 #define AIF_NONE 0
#define AIF_FOLLOWS_PLAYER (2 << 0) #define AIF_FOLLOWS_PLAYER (2 << 0)
@ -316,6 +317,7 @@ enum
CHALLENGE_PLAYER_KILLS, CHALLENGE_PLAYER_KILLS,
CHALLENGE_DISABLE, CHALLENGE_DISABLE,
CHALLENGE_ITEMS, CHALLENGE_ITEMS,
CHALLENGE_PLAYER_ITEMS,
CHALLENGE_RESCUE, CHALLENGE_RESCUE,
CHALLENGE_SURVIVE, CHALLENGE_SURVIVE,
CHALLENGE_MAX CHALLENGE_MAX

View File

@ -253,6 +253,7 @@ typedef struct {
int killLimit; int killLimit;
int lossLimit; int lossLimit;
int itemLimit; int itemLimit;
int playerItemLimit;
int escapeLimit; int escapeLimit;
int waypointLimit; int waypointLimit;
int rescueLimit; int rescueLimit;

View File

@ -69,6 +69,7 @@ void initLookups(void)
addLookup("EF_AI_IGNORE", EF_AI_IGNORE); addLookup("EF_AI_IGNORE", EF_AI_IGNORE);
addLookup("EF_NO_THREAT", EF_NO_THREAT); addLookup("EF_NO_THREAT", EF_NO_THREAT);
addLookup("EF_NO_HEALTH_BAR", EF_NO_HEALTH_BAR); addLookup("EF_NO_HEALTH_BAR", EF_NO_HEALTH_BAR);
addLookup("EF_DROPS_ITEMS", EF_DROPS_ITEMS);
addLookup("AIF_NONE", AIF_NONE); addLookup("AIF_NONE", AIF_NONE);
addLookup("AIF_MOVES_TO_PLAYER", AIF_MOVES_TO_PLAYER); 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_PLAYER_KILLS", CHALLENGE_PLAYER_KILLS);
addLookup("CHALLENGE_DISABLE", CHALLENGE_DISABLE); addLookup("CHALLENGE_DISABLE", CHALLENGE_DISABLE);
addLookup("CHALLENGE_ITEMS", CHALLENGE_ITEMS); addLookup("CHALLENGE_ITEMS", CHALLENGE_ITEMS);
addLookup("CHALLENGE_PLAYER_ITEMS", CHALLENGE_PLAYER_ITEMS);
addLookup("CHALLENGE_RESCUE", CHALLENGE_RESCUE); addLookup("CHALLENGE_RESCUE", CHALLENGE_RESCUE);
addLookup("STAT_PERCENT_COMPLETE", STAT_PERCENT_COMPLETE); addLookup("STAT_PERCENT_COMPLETE", STAT_PERCENT_COMPLETE);