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 ;
}