blobwarsAttrition/src/hub/hub.c

289 lines
6.5 KiB
C
Raw Normal View History

2018-01-24 08:16:52 +01:00
/*
Copyright (C) 2018 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "hub.h"
static void unlockAllLevels(void);
static void unlockMission(char *id);
static int getMissionStatus(char *id);
static void loadMissions(void);
static void unlockNeighbouringMission(HubMission *sourceMission);
static int missionComparator(const void *a, const void *b);
static HubMission hubMissionHead;
static HubMission *hubMissionTail;
void initHub(void)
{
int unlockedMissions;
HubMission *prevMission, *mission;
Tuple *t;
memset(&hubMissionHead, 0, sizeof(HubMission));
hubMissionTail = &hubMissionHead;
loadMissions();
if (dev.cheatLevels)
{
unlockAllLevels();
}
unlockedMissions = 0;
for (t = game.missionStatusHead.next ; t != NULL ; t = t->next)
{
if (t->value.i != MS_INCOMPLETE)
{
unlockedMissions++;
}
}
prevMission = &hubMissionHead;
for (mission = hubMissionHead.next ; mission != NULL ; mission = mission->next)
{
if (mission->unlockCount > unlockedMissions && !dev.cheatLevels)
{
if (mission == hubMissionTail)
{
hubMissionTail = prevMission;
}
prevMission->next = mission->next;
free(mission);
mission = prevMission;
}
else
{
mission->status = getMissionStatus(mission->id);
2018-01-28 17:14:17 +01:00
if (mission->unlockCount == 0 && mission->status == MS_LOCKED)
2018-01-24 08:16:52 +01:00
{
mission->status = MS_INCOMPLETE;
unlockMission(mission->id);
}
}
prevMission = mission;
}
for (mission = hubMissionHead.next ; mission != NULL ; mission = mission->next)
{
if (mission->status == MS_COMPLETE || mission->status == MS_MISSING_HEART_CELL || mission->status == MS_PARTIAL)
{
unlockNeighbouringMission(mission);
}
if (mission->status == MS_MISSING_HEART_CELL)
{
2018-01-28 17:14:17 +01:00
STRNCPY(mission->description, _("All objectives for this misson have been completed. However, there is a Cell or a Heart left to find. See if you can locate it."), MAX_DESCRIPTION_LENGTH);
2018-01-24 08:16:52 +01:00
}
}
prevMission = &hubMissionHead;
for (mission = hubMissionHead.next ; mission != NULL ; mission = mission->next)
{
2018-01-28 17:14:17 +01:00
if (mission->status == MS_LOCKED || mission->status == MS_COMPLETE)
2018-01-24 08:16:52 +01:00
{
if (mission == hubMissionTail)
{
hubMissionTail = prevMission;
}
prevMission->next = mission->next;
free(mission);
mission = prevMission;
}
prevMission = mission;
}
}
static int getMissionStatus(char *id)
{
Tuple *t;
for (t = game.missionStatusHead.next ; t != NULL ; t = t->next)
{
if (strcmp(t->key, id) == 0)
{
return t->value.i;
}
}
2018-01-28 17:14:17 +01:00
return MS_LOCKED;
2018-01-24 08:16:52 +01:00
}
static void unlockMission(char *id)
{
Tuple *t;
for (t = game.missionStatusHead.next ; t != NULL ; t = t->next)
{
if (strcmp(t->key, id) == 0)
{
2018-01-28 17:14:17 +01:00
if (t->value.i == MS_LOCKED)
2018-01-24 08:16:52 +01:00
{
t->value.i = MS_INCOMPLETE;
2018-01-28 17:14:17 +01:00
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, "Unlocked mission %s", id);
2018-01-24 08:16:52 +01:00
}
2018-01-28 17:14:17 +01:00
2018-01-24 08:16:52 +01:00
return;
}
}
t = malloc(sizeof(Tuple));
memset(t, 0, sizeof(Tuple));
game.missionStatusTail->next = t;
game.missionStatusTail = t;
STRNCPY(t->key, id, MAX_NAME_LENGTH);
t->value.i = MS_INCOMPLETE;
2018-01-28 17:14:17 +01:00
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, "Unlocked mission %s", id);
2018-01-24 08:16:52 +01:00
}
static void unlockAllLevels(void)
{
HubMission *mission;
for (mission = hubMissionHead.next ; mission != NULL ; mission = mission->next)
{
2018-01-28 17:14:17 +01:00
if (mission->status == MS_LOCKED || mission->status == MS_INCOMPLETE)
2018-01-24 08:16:52 +01:00
{
mission->status = MS_INCOMPLETE;
unlockMission(mission->id);
}
}
}
static void loadMissions(void)
{
2018-01-28 17:14:17 +01:00
cJSON *root, *node;
char *text;
HubMission *mission;
text = readFile("data/hub/missions.json");
root = cJSON_Parse(text);
for (node = cJSON_GetObjectItem(root, "missions")->child ; node != NULL ; node = node->next)
{
mission = malloc(sizeof(HubMission));
memset(mission, 0, sizeof(HubMission));
hubMissionTail->next = mission;
hubMissionTail = mission;
STRNCPY(mission->id, cJSON_GetObjectItem(node, "id")->valuestring, MAX_NAME_LENGTH);
STRNCPY(mission->name, cJSON_GetObjectItem(node, "name")->valuestring, MAX_NAME_LENGTH);
STRNCPY(mission->description, cJSON_GetObjectItem(node, "description")->valuestring, MAX_DESCRIPTION_LENGTH);
mission->x = cJSON_GetObjectItem(node, "x")->valueint;
mission->y = cJSON_GetObjectItem(node, "y")->valueint;
mission->status = MS_LOCKED;
mission->unlockCount = cJSON_GetObjectItem(node, "unlockCount")->valueint;
}
cJSON_Delete(root);
free(text);
2018-01-24 08:16:52 +01:00
}
static void unlockNeighbouringMission(HubMission *sourceMission)
{
HubMission *mission, *missions[32];
int i;
i = 0;
memset(missions, 0, sizeof(HubMission*) * 32);
for (mission = hubMissionHead.next ; mission != NULL ; mission = mission->next)
{
mission->distance = 99999;
if (mission->status == MS_COMPLETE || mission->status == MS_MISSING_HEART_CELL || mission->status == MS_PARTIAL)
{
continue;
}
mission->distance = getDistance(mission->x, mission->y, sourceMission->x, sourceMission->y);
missions[i++] = mission;
}
qsort(missions, i, sizeof(HubMission*), missionComparator);
mission = missions[0];
if (mission != NULL)
{
2018-01-28 17:14:17 +01:00
if (mission->status == MS_LOCKED || mission->status == MS_INCOMPLETE)
2018-01-24 08:16:52 +01:00
{
mission->status = MS_INCOMPLETE;
unlockMission(mission->id);
}
mission = missions[1];
if (mission != NULL)
{
2018-01-28 17:14:17 +01:00
if (mission->status == MS_LOCKED || mission->status == MS_INCOMPLETE)
2018-01-24 08:16:52 +01:00
{
mission->status = MS_INCOMPLETE;
unlockMission(mission->id);
}
}
}
}
HubMission *getMissionAt(float x, float y)
{
HubMission *rtn;
HubMission *mission;
float distance, dist;
rtn = NULL;
distance = 32;
for (mission = hubMissionHead.next ; mission != NULL ; mission = mission->next)
{
dist = getDistance(x, y, mission->x, mission->y);
if (dist < distance)
{
rtn = mission;
distance = dist;
}
}
return rtn;
}
static int missionComparator(const void *a, const void *b)
{
HubMission *m1 = *((HubMission**)a);
HubMission *m2 = *((HubMission**)b);
return m2->distance - m1->distance;
}