static void LoadGameConfigNode(GameConfig *config, json_t *node) { if (node == NULL) { return; } node = node->child; LoadBool(&config->FriendlyFire, node, "FriendlyFire"); config->RandomSeed = atoi(json_find_first_label(node, "RandomSeed")->child->text); JSON_UTILS_LOAD_ENUM(config->Difficulty, node, "Difficulty", StrDifficulty); LoadBool(&config->SlowMotion, node, "SlowMotion"); LoadInt(&config->EnemyDensity, node, "EnemyDensity"); LoadInt(&config->NonPlayerHP, node, "NonPlayerHP"); LoadInt(&config->PlayerHP, node, "PlayerHP"); LoadBool(&config->Fog, node, "Fog"); LoadInt(&config->SightRange, node, "SightRange"); LoadBool(&config->Shadows, node, "Shadows"); LoadBool(&config->MoveWhenShooting, node, "MoveWhenShooting"); JSON_UTILS_LOAD_ENUM( config->SwitchMoveStyle, node, "SwitchMoveStyle", StrSwitchMoveStyle); LoadBool(&config->ShotsPushback, node, "ShotsPushback"); JSON_UTILS_LOAD_ENUM( config->AllyCollision, node, "AllyCollision", StrAllyCollision); LoadBool(&config->HealthPickups, node, "HealthPickups"); }
static void LoadMapObject(MapObject *m, json_t *node) { memset(m, 0, sizeof *m); m->Idx = -1; LoadInt(&m->Idx, node, "Index"); m->Name = GetString(node, "Name"); LoadPic(&m->Normal.Pic, node, "Pic", "OldPic"); LoadPic(&m->Wreck.Pic, node, "WreckPic", "OldWreckPic"); if (m->Normal.Pic) { // Default offset: centered X, align bottom of tile and sprite m->Normal.Offset = Vec2iNew( -m->Normal.Pic->size.x / 2, TILE_HEIGHT / 2 - m->Normal.Pic->size.y); LoadVec2i(&m->Normal.Offset, node, "Offset"); } if (m->Wreck.Pic) { m->Wreck.Offset = Vec2iScaleDiv(m->Wreck.Pic->size, -2); LoadVec2i(&m->Wreck.Offset, node, "WreckOffset"); } // Default tile size m->Size = Vec2iNew(TILE_WIDTH, TILE_HEIGHT); LoadVec2i(&m->Size, node, "Size"); LoadInt(&m->Health, node, "Health"); LoadBulletGuns(&m->DestroyGuns, node, "DestroyGuns"); json_t *flagsNode = json_find_first_label(node, "Flags"); if (flagsNode != NULL && flagsNode->child != NULL) { for (json_t *flagNode = flagsNode->child->child; flagNode; flagNode = flagNode->next) { m->Flags |= 1 << StrPlacementFlag(flagNode->text); } } // Special types JSON_UTILS_LOAD_ENUM(m->Type, node, "Type", StrMapObjectType); switch (m->Type) { case MAP_OBJECT_TYPE_NORMAL: // Do nothing break; case MAP_OBJECT_TYPE_PICKUP_SPAWNER: { char *tmp = GetString(node, "Pickup"); m->u.PickupClass = StrPickupClass(tmp); CFREE(tmp); } break; default: CASSERT(false, "unknown error"); break; } }
void ObjectiveLoadJSON(Objective *o, json_t *node, const int version) { memset(o, 0, sizeof *o); o->Description = GetString(node, "Description"); JSON_UTILS_LOAD_ENUM(o->Type, node, "Type", StrObjectiveType); // Set objective colours based on type o->color = ObjectiveTypeColor(o->Type); if (version < 8) { // Index numbers used for all objective classes; convert them // to their class handles LoadInt(&o->u.Index, node, "Index"); switch (o->Type) { case OBJECTIVE_COLLECT: o->u.Pickup = IntPickupClass(o->u.Index); break; case OBJECTIVE_DESTROY: o->u.MapObject = IntMapObject(o->u.Index); break; default: // do nothing break; } } else { char *tmp; switch (o->Type) { case OBJECTIVE_COLLECT: tmp = GetString(node, "Pickup"); o->u.Pickup = StrPickupClass(tmp); CFREE(tmp); break; case OBJECTIVE_DESTROY: tmp = GetString(node, "MapObject"); o->u.MapObject = StrMapObject(tmp); CFREE(tmp); break; default: LoadInt(&o->u.Index, node, "Index"); break; } } LoadInt(&o->Count, node, "Count"); LoadInt(&o->Required, node, "Required"); LoadInt(&o->Flags, node, "Flags"); }
static void LoadGraphicsConfigNode(GraphicsConfig *config, json_t *node) { if (node == NULL) { return; } node = node->child; LoadInt(&config->Brightness, node, "Brightness"); LoadInt(&config->Res.x, node, "ResolutionWidth"); LoadInt(&config->Res.y, node, "ResolutionHeight"); LoadBool(&config->Fullscreen, node, "Fullscreen"); LoadInt(&config->ScaleFactor, node, "ScaleFactor"); LoadInt(&config->ShakeMultiplier, node, "ShakeMultiplier"); JSON_UTILS_LOAD_ENUM(config->ScaleMode, node, "ScaleMode", StrScaleMode); }
static void ConfigLoadVisit(Config *c, json_t *node) { if (node == NULL) { fprintf(stderr, "Error loading config: node %s not found\n", c->Name); return; } switch (c->Type) { case CONFIG_TYPE_STRING: CASSERT(false, "not implemented"); break; case CONFIG_TYPE_INT: LoadInt(&c->u.Int.Value, node, c->Name); if (c->u.Int.Min > 0) c->u.Int.Value = MAX(c->u.Int.Value, c->u.Int.Min); if (c->u.Int.Max > 0) c->u.Int.Value = MIN(c->u.Int.Value, c->u.Int.Max); break; case CONFIG_TYPE_FLOAT: LoadDouble(&c->u.Float.Value, node, c->Name); if (c->u.Float.Min > 0) c->u.Float.Value = MAX(c->u.Float.Value, c->u.Float.Min); if (c->u.Float.Max > 0) c->u.Float.Value = MIN(c->u.Float.Value, c->u.Float.Max); break; case CONFIG_TYPE_BOOL: LoadBool(&c->u.Bool.Value, node, c->Name); break; case CONFIG_TYPE_ENUM: JSON_UTILS_LOAD_ENUM( c->u.Enum.Value, node, c->Name, c->u.Enum.StrToEnum); if (c->u.Enum.Min > 0) c->u.Enum.Value = MAX(c->u.Enum.Value, c->u.Enum.Min); if (c->u.Enum.Max > 0) c->u.Enum.Value = MIN(c->u.Enum.Value, c->u.Enum.Max); break; case CONFIG_TYPE_GROUP: { // If the config has no name, then it is the root element // Load children directly to the node // Otherwise, find the named child if (c->Name != NULL) { node = json_find_first_label(node, c->Name); if (node == NULL) { fprintf(stderr, "Error loading config: node %s not found\n", c->Name); return; } node = node->child; } CA_FOREACH(Config, child, c->u.Group) ConfigLoadVisit(child, node); CA_FOREACH_END() } break; default: CASSERT(false, "Unknown config type"); break; } }
void LoadMissions(CArray *missions, json_t *missionsNode, int version) { json_t *child; for (child = missionsNode->child; child; child = child->next) { Mission m; MissionInit(&m); m.Title = GetString(child, "Title"); m.Description = GetString(child, "Description"); JSON_UTILS_LOAD_ENUM(m.Type, child, "Type", StrMapType); LoadInt(&m.Size.x, child, "Width"); LoadInt(&m.Size.y, child, "Height"); if (version <= 10) { int style; LoadInt(&style, child, "WallStyle"); strcpy(m.WallStyle, IntWallStyle(style)); LoadInt(&style, child, "FloorStyle"); strcpy(m.FloorStyle, IntFloorStyle(style)); LoadInt(&style, child, "RoomStyle"); strcpy(m.RoomStyle, IntRoomStyle(style)); } else { char *tmp = GetString(child, "WallStyle"); strcpy(m.WallStyle, tmp); CFREE(tmp); tmp = GetString(child, "FloorStyle"); strcpy(m.FloorStyle, tmp); CFREE(tmp); tmp = GetString(child, "RoomStyle"); strcpy(m.RoomStyle, tmp); CFREE(tmp); } if (version <= 9) { int style; LoadInt(&style, child, "ExitStyle"); strcpy(m.ExitStyle, IntExitStyle(style)); } else { char *tmp = GetString(child, "ExitStyle"); strcpy(m.ExitStyle, tmp); CFREE(tmp); } if (version <= 8) { int keyStyle; LoadInt(&keyStyle, child, "KeyStyle"); strcpy(m.KeyStyle, IntKeyStyle(keyStyle)); } else { char *tmp = GetString(child, "KeyStyle"); strcpy(m.KeyStyle, tmp); CFREE(tmp); } if (version <= 5) { int doorStyle; LoadInt(&doorStyle, child, "DoorStyle"); strcpy(m.DoorStyle, IntDoorStyle(doorStyle)); } else { char *tmp = GetString(child, "DoorStyle"); strcpy(m.DoorStyle, tmp); CFREE(tmp); } LoadMissionObjectives( &m.Objectives, json_find_first_label(child, "Objectives")->child, version); LoadIntArray(&m.Enemies, child, "Enemies"); LoadIntArray(&m.SpecialChars, child, "SpecialChars"); if (version <= 3) { CArray items; CArrayInit(&items, sizeof(int)); LoadIntArray(&items, child, "Items"); CArray densities; CArrayInit(&densities, sizeof(int)); LoadIntArray(&densities, child, "ItemDensities"); for (int i = 0; i < (int)items.size; i++) { MapObjectDensity mod; mod.M = IntMapObject(*(int *)CArrayGet(&items, i)); mod.Density = *(int *)CArrayGet(&densities, i); CArrayPushBack(&m.MapObjectDensities, &mod); } } else { json_t *modsNode = json_find_first_label(child, "MapObjectDensities"); if (modsNode && modsNode->child) { modsNode = modsNode->child; for (json_t *modNode = modsNode->child; modNode; modNode = modNode->next) { MapObjectDensity mod; mod.M = StrMapObject( json_find_first_label(modNode, "MapObject")->child->text); LoadInt(&mod.Density, modNode, "Density"); CArrayPushBack(&m.MapObjectDensities, &mod); } } } LoadInt(&m.EnemyDensity, child, "EnemyDensity"); LoadWeapons( &m.Weapons, json_find_first_label(child, "Weapons")->child); strcpy(m.Song, json_find_first_label(child, "Song")->child->text); if (version <= 4) { // Load colour indices int wc, fc, rc, ac; LoadInt(&wc, child, "WallColor"); LoadInt(&fc, child, "FloorColor"); LoadInt(&rc, child, "RoomColor"); LoadInt(&ac, child, "AltColor"); m.WallMask = RangeToColor(wc); m.FloorMask = RangeToColor(fc); m.RoomMask = RangeToColor(rc); m.AltMask = RangeToColor(ac); } else { LoadColor(&m.WallMask, child, "WallMask"); LoadColor(&m.FloorMask, child, "FloorMask"); LoadColor(&m.RoomMask, child, "RoomMask"); LoadColor(&m.AltMask, child, "AltMask"); } switch (m.Type) { case MAPTYPE_CLASSIC: LoadInt(&m.u.Classic.Walls, child, "Walls"); LoadInt(&m.u.Classic.WallLength, child, "WallLength"); LoadInt(&m.u.Classic.CorridorWidth, child, "CorridorWidth"); LoadClassicRooms( &m, json_find_first_label(child, "Rooms")->child); LoadInt(&m.u.Classic.Squares, child, "Squares"); LoadClassicDoors(&m, child, "Doors"); LoadClassicPillars(&m, child, "Pillars"); break; case MAPTYPE_STATIC: if (!TryLoadStaticMap(&m, child, version)) { continue; } break; case MAPTYPE_CAVE: LoadInt(&m.u.Cave.FillPercent, child, "FillPercent"); LoadInt(&m.u.Cave.Repeat, child, "Repeat"); LoadInt(&m.u.Cave.R1, child, "R1"); LoadInt(&m.u.Cave.R2, child, "R2"); break; default: assert(0 && "unknown map type"); continue; } CArrayPushBack(missions, &m); } }
static bool TryLoadMapObject(MapObject *m, json_t *node, const int version) { memset(m, 0, sizeof *m); m->Name = GetString(node, "Name"); // Pic json_t *normalNode = json_find_first_label(node, "Pic"); if (normalNode != NULL && normalNode->child != NULL) { if (version < 2) { CPicLoadNormal(&m->Pic, normalNode->child); } else { CPicLoadJSON(&m->Pic, normalNode->child); } // Pic required for map object if (!CPicIsLoaded(&m->Pic)) { LOG(LM_MAIN, LL_ERROR, "pic not found for map object(%s)", m->Name); goto bail; } } if (CPicIsLoaded(&m->Pic)) { // Default offset: centered X, align bottom of tile and sprite const Vec2i size = CPicGetSize(&m->Pic); m->Offset = Vec2iNew(-size.x / 2, TILE_HEIGHT / 2 - size.y); LoadVec2i(&m->Offset, node, "Offset"); } // Wreck if (version < 3) { // Assume old wreck pic is wreck json_t *wreckNode = json_find_first_label(node, "WreckPic"); if (wreckNode != NULL && wreckNode->child != NULL) { if (version < 2) { LoadStr(&m->Wreck, node, "WreckPic"); } else { LoadStr(&m->Wreck, wreckNode, "Pic"); } } } else { LoadStr(&m->Wreck, node, "Wreck"); } // Default tile size m->Size = TILE_SIZE; LoadVec2i(&m->Size, node, "Size"); LoadVec2i(&m->PosOffset, node, "PosOffset"); LoadInt(&m->Health, node, "Health"); LoadBulletGuns(&m->DestroyGuns, node, "DestroyGuns"); // Flags json_t *flagsNode = json_find_first_label(node, "Flags"); if (flagsNode != NULL && flagsNode->child != NULL) { for (json_t *flagNode = flagsNode->child->child; flagNode; flagNode = flagNode->next) { m->Flags |= 1 << StrPlacementFlag(flagNode->text); } } LoadBool(&m->DrawLast, node, "DrawLast"); // Special types JSON_UTILS_LOAD_ENUM(m->Type, node, "Type", StrMapObjectType); switch (m->Type) { case MAP_OBJECT_TYPE_NORMAL: // Do nothing break; case MAP_OBJECT_TYPE_PICKUP_SPAWNER: { char *tmp = GetString(node, "Pickup"); m->u.PickupClass = StrPickupClass(tmp); CFREE(tmp); } break; default: CASSERT(false, "unknown error"); break; } // DestroySpawn - pickups to spawn on destruction json_t *destroySpawnNode = json_find_first_label(node, "DestroySpawn"); if (destroySpawnNode != NULL && destroySpawnNode->child != NULL) { CArrayInit(&m->DestroySpawn, sizeof(MapObjectDestroySpawn)); for (json_t *dsNode = destroySpawnNode->child->child; dsNode; dsNode = dsNode->next) { MapObjectDestroySpawn mods; memset(&mods, 0, sizeof mods); JSON_UTILS_LOAD_ENUM(mods.Type, dsNode, "Type", StrPickupType); LoadDouble(&mods.SpawnChance, dsNode, "SpawnChance"); CArrayPushBack(&m->DestroySpawn, &mods); } } return true; bail: return false; }