bool CampaignEntryTryLoad( CampaignEntry *entry, const char *path, GameMode mode) { char *buf; int numMissions; if (!IsCampaignOK(path, &buf, &numMissions)) { return false; } // cap length of title size_t maxLen = 70; if (strlen(buf) > maxLen) { buf[maxLen] = '\0'; } char title[256]; sprintf(title, "%s (%d)", buf, numMissions); CampaignEntryInit(entry, title, mode); CSTRDUP(entry->Filename, PathGetBasename(path)); // Get relative path for the campaign entry, so when we transmit it to // network clients they can load it regardless of install path char pathBuf[CDOGS_PATH_MAX]; RelPathFromCWD(pathBuf, path); CSTRDUP(entry->Path, pathBuf); entry->NumMissions = numMissions; CFREE(buf); return true; }
void ConvertCampaignSetting(CampaignSetting *dest, CampaignSettingOld *src) { int i; CFREE(dest->Title); CSTRDUP(dest->Title, src->title); CFREE(dest->Author); CSTRDUP(dest->Author, src->author); CFREE(dest->Description); CSTRDUP(dest->Description, src->description); for (i = 0; i < src->missionCount; i++) { Mission m; MissionInit(&m); ConvertMission(&m, &src->missions[i]); CArrayPushBack(&dest->Missions, &m); } CharacterStoreTerminate(&dest->characters); CharacterStoreInit(&dest->characters); for (i = 0; i < src->characterCount; i++) { Character *ch = CharacterStoreAddOther(&dest->characters); ConvertCharacter(ch, &src->characters[i]); CharacterSetLooks(ch, &ch->looks); } }
void CampaignEntryCopy(CampaignEntry *dst, CampaignEntry *src) { memcpy(dst, src, sizeof *dst); if (src->Filename) CSTRDUP(dst->Filename, src->Filename); if (src->Path) CSTRDUP(dst->Path, src->Path); if (src->Info) CSTRDUP(dst->Info, src->Info); }
bool CampaignEntryTryLoad( CampaignEntry *entry, const char *path, campaign_mode_e mode) { char *buf; int numMissions; if (!IsCampaignOK(path, &buf, &numMissions)) { return false; } // cap length of title size_t maxLen = 70; if (strlen(buf) > maxLen) { buf[maxLen] = '\0'; } char title[256]; sprintf(title, "%s (%d)", buf, numMissions); CampaignEntryInit(entry, title, mode); CSTRDUP(entry->Filename, PathGetBasename(path)); CSTRDUP(entry->Path, path); entry->IsBuiltin = false; entry->NumMissions = numMissions; CFREE(buf); return true; }
char *YAJLGetStr(yajl_val node, const char *name) { char *in = YAJL_GET_STRING(YAJLFindNode(node, name)); char *out; CSTRDUP(out, in); return out; }
const char *GetHomeDirectory(void) { const char *p; if (cdogs_homepath != NULL) { return cdogs_homepath; } p = getenv("CDOGS_CONFIG_DIR"); if (p != NULL && strlen(p) != 0) { CSTRDUP(cdogs_homepath, p); return cdogs_homepath; } p = getenv(HOME_DIR_ENV); if (p != NULL && strlen(p) != 0) { CCALLOC(cdogs_homepath, strlen(p) + 2); strcpy(cdogs_homepath, p); cdogs_homepath[strlen(p)] = '/'; return cdogs_homepath; } fprintf(stderr,"%s%s%s%s", "##############################################################\n", "# You don't have the environment variables HOME or USER set. #\n", "# It is suggested you get a better shell. :D #\n", "##############################################################\n"); return ""; }
static char *MakeMapObjectTooltip(const MapObject *mo) { // Add a descriptive tooltip for the map object char buf[512]; // Construct text representing explosion guns char exBuf[256]; strcpy(exBuf, ""); if (mo->DestroyGuns.size > 0) { sprintf(exBuf, "\nExplodes: "); for (int i = 0; i < (int)mo->DestroyGuns.size; i++) { if (i > 0) { strcat(exBuf, ", "); } const GunDescription **g = CArrayGet(&mo->DestroyGuns, i); strcat(exBuf, (*g)->name); } } sprintf(buf, "%s\nHealth: %d%s", mo->Name, mo->Health, exBuf); char *tmp; CSTRDUP(tmp, buf); return tmp; }
void ConfigResetDefault(Config *c) { switch (c->Type) { case CONFIG_TYPE_STRING: CFREE(c->u.String.Value); if (c->u.String.Default != NULL) { CSTRDUP(c->u.String.Value, c->u.String.Default); } break; case CONFIG_TYPE_INT: c->u.Int.Value = c->u.Int.Default; break; case CONFIG_TYPE_FLOAT: c->u.Float.Value = c->u.Float.Default; break; case CONFIG_TYPE_BOOL: c->u.Bool.Value = c->u.Bool.Default; break; case CONFIG_TYPE_ENUM: c->u.Enum.Value = c->u.Enum.Default; break; case CONFIG_TYPE_GROUP: CA_FOREACH(Config, child, c->u.Group) ConfigResetDefault(child); CA_FOREACH_END() break; default: CASSERT(false, "Unknown config type"); break; } }
void CampaignEntryInit( CampaignEntry *entry, const char *title, campaign_mode_e mode) { memset(entry, 0, sizeof *entry); CSTRDUP(entry->Info, title); entry->Mode = mode; }
static void LoadGunSpawners(CArray *classes, const CArray *guns) { for (int i = 0; i < (int)guns->size; i++) { const GunDescription *g = CArrayGet(guns, i); if (!g->IsRealGun) { continue; } MapObject m; memset(&m, 0, sizeof m); char buf[256]; sprintf(buf, "%s spawner", g->name); CSTRDUP(m.Name, buf); m.Normal.Pic = PicManagerGetPic(&gPicManager, "spawn_pad"); m.Normal.Offset = Vec2iNew( -m.Normal.Pic->size.x / 2, TILE_HEIGHT / 2 - m.Normal.Pic->size.y); m.Size = Vec2iNew(TILE_WIDTH, TILE_HEIGHT); m.Health = 0; m.Type = MAP_OBJECT_TYPE_PICKUP_SPAWNER; sprintf(buf, "gun_%s", g->name); m.u.PickupClass = StrPickupClass(buf); CArrayPushBack(classes, &m); } }
Config *ConfigGet(Config *c, const char *name) { char *nameCopy; CSTRDUP(nameCopy, name); char *pch = strtok(nameCopy, "."); while (pch != NULL) { if (c->Type != CONFIG_TYPE_GROUP) { CASSERT(false, "Invalid config type"); goto bail; } bool found = false; CA_FOREACH(Config, child, c->u.Group) if (strcmp(child->Name, pch) == 0) { c = child; found = true; break; } CA_FOREACH_END() if (!found) { CASSERT(false, "Config not found"); goto bail; } pch = strtok(NULL, "."); } bail: CFREE(nameCopy); return c; }
static UIObject *CreateSetKeyObjs(Vec2i pos, EditorBrush *brush) { UIObject *o2; UIObject *c = UIObjectCreate(UITYPE_CONTEXT_MENU, 0, pos, Vec2iZero()); UIObject *o = UIObjectCreate( UITYPE_CUSTOM, 0, Vec2iZero(), Vec2iNew(TILE_WIDTH + 4, TILE_HEIGHT + 4)); o->ChangeFunc = BrushSetBrushTypeSetKey; o->u.CustomDrawFunc = DrawKey; o->OnFocusFunc = ActivateIndexedEditorBrush; o->OnUnfocusFunc = DeactivateIndexedEditorBrush; pos = Vec2iZero(); for (int i = -1; i < KEY_COUNT; i++) { o2 = UIObjectCopy(o); o2->IsDynamicData = 1; CMALLOC(o2->Data, sizeof(IndexedEditorBrush)); ((IndexedEditorBrush *)o2->Data)->Brush = brush; ((IndexedEditorBrush *)o2->Data)->ItemIndex = i; o2->Pos = pos; if (i == -1) { // -1 means no key CSTRDUP(o2->Tooltip, "no key"); } UIObjectAddChild(c, o2); pos.x += o->Size.x; } UIObjectDestroy(o); return c; }
/* void LoadSoundFromNode(Mix_Chunk **value, json_t *node, const char *name) { if (json_find_first_label(node, name) == NULL) { return; } if (!TryLoadValue(&node, name)) { return; } *value = StrSound(node->text); } void LoadPic(const Pic **value, json_t *node, const char *name) { if (json_find_first_label(node, name)) { char *tmp = GetString(node, name); *value = PicManagerGetPic(&gPicManager, tmp); CFREE(tmp); } } void LoadBulletGuns(CArray *guns, json_t *node, const char *name) { node = json_find_first_label(node, name); if (node == NULL || node->child == NULL) { return; } CArrayInit(guns, sizeof(const GunDescription *)); for (json_t *gun = node->child->child; gun; gun = gun->next) { const GunDescription *g = StrGunDescription(gun->text); CArrayPushBack(guns, &g); } } void LoadColor(color_t *c, json_t *node, const char *name) { if (json_find_first_label(node, name) == NULL) { return; } if (!TryLoadValue(&node, name)) { return; } *c = StrColor(node->text); } */ yajl_val YAJLFindNode(yajl_val node, const char *path) { // max 256 levels const char *pathSplit[256]; for (int i = 0; i < 256; i++) pathSplit[i] = NULL; char *pathCopy; CSTRDUP(pathCopy, path); char *pch = strtok(pathCopy, "/"); int i = 0; yajl_val out = NULL; while (pch != NULL) { if (i == 256) { fprintf(stderr, "JSON path too long: '%s'\n", path); goto bail; } pathSplit[i] = pch; i++; pch = strtok(NULL, "/"); } out = yajl_tree_get(node, pathSplit, yajl_t_any); bail: CFREE(pathCopy); return out; }
void MapObjectsLoadJSON(CArray *classes, json_t *root) { int version; LoadInt(&version, root, "Version"); if (version > VERSION || version <= 0) { CASSERT(false, "cannot read map objects file version"); return; } json_t *pickupsNode = json_find_first_label(root, "MapObjects")->child; for (json_t *child = pickupsNode->child; child; child = child->next) { MapObject m; LoadMapObject(&m, child); CArrayPushBack(classes, &m); } ReloadDestructibles(&gMapObjects); // Load blood objects CArrayClear(&gMapObjects.Bloods); for (int i = 0;; i++) { char buf[CDOGS_FILENAME_MAX]; sprintf(buf, "blood%d", i); if (StrMapObject(buf) == NULL) { break; } char *tmp; CSTRDUP(tmp, buf); CArrayPushBack(&gMapObjects.Bloods, &tmp); } }
UIObject *CreateAddItemObjs( Vec2i pos, EditorBrush *brush, CampaignOptions *co) { const int th = FontH(); UIObject *o2; UIObject *c = UIObjectCreate(UITYPE_CONTEXT_MENU, 0, pos, Vec2iZero()); UIObject *o = UIObjectCreate( UITYPE_LABEL, 0, Vec2iZero(), Vec2iNew(65, th)); o->Data = brush; pos = Vec2iZero(); o2 = UIObjectCopy(o); o2->Label = "Player start"; o2->ChangeFunc = BrushSetBrushTypeSetPlayerStart; o2->Pos = pos; CSTRDUP(o2->Tooltip, "Location where players start"); o2->OnFocusFunc = ActivateBrush; o2->OnUnfocusFunc = DeactivateBrush; o2->Data = brush; UIObjectAddChild(c, o2); pos.y += th; o2 = UIObjectCopy(o); o2->Label = "Map item >"; o2->Pos = pos; UIObjectAddChild(o2, CreateAddMapItemObjs( o2->Size, AddMapItemBrushObjFunc, brush, sizeof(IndexedEditorBrush), true)); UIObjectAddChild(c, o2); pos.y += th; o2 = UIObjectCopy(o); o2->Label = "Pickup spawner >"; o2->Pos = pos; UIObjectAddChild(o2, CreateAddPickupSpawnerObjs( o2->Size, AddPickupSpawnerBrushObjFunc, brush, sizeof(IndexedEditorBrush))); UIObjectAddChild(c, o2); pos.y += th; o2 = UIObjectCopy(o); o2->Label = "Character >"; o2->Pos = pos; UIObjectAddChild(o2, CreateAddCharacterObjs(o2->Size, brush, co)); UIObjectAddChild(c, o2); pos.y += th; o2 = UIObjectCopy(o); o2->Label = "Objective >"; o2->Pos = pos; UIObjectAddChild(o2, CreateAddObjectiveObjs(o2->Size, brush, co)); UIObjectAddChild(c, o2); pos.y += th; o2 = UIObjectCopy(o); o2->Label = "Key >"; o2->Pos = pos; UIObjectAddChild(o2, CreateAddKeyObjs(o2->Size, brush)); UIObjectAddChild(c, o2); UIObjectDestroy(o); return c; }
void ObjectiveCopy(Objective *dst, const Objective *src) { memcpy(dst, src, sizeof *dst); if (src->Description) { CSTRDUP(dst->Description, src->Description); } }
menu_t *MenuCreate(const char *name, menu_type_e type) { menu_t *menu; CCALLOC(menu, sizeof(menu_t)); CSTRDUP(menu->name, name); menu->type = type; menu->parentMenu = NULL; return menu; }
static void ConvertMissionObjective( MissionObjective *dest, struct MissionObjectiveOld *src) { CFREE(dest->Description); CSTRDUP(dest->Description, src->description); dest->Type = src->type; dest->Index = src->index; dest->Count = src->count; dest->Required = src->required; dest->Flags = src->flags; }
static Config ConfigNew(const char *name, const ConfigType type) { Config c; memset(&c, 0, sizeof c); if (name != NULL) { CSTRDUP(c.Name, name); } c.Type = type; return c; }
UIObject *CreateCampaignSeedObj(const struct vec2i pos, CampaignOptions *co) { const int th = FontH(); UIObject *o = UIObjectCreate( UITYPE_LABEL, 0, svec2i_zero(), svec2i(50, th)); o->ChangesData = true; o->u.LabelFunc = CampaignGetSeedStr; o->Data = co; o->ChangeFunc = CampaignChangeSeed; CSTRDUP(o->Tooltip, "Preview with different random seed"); o->Pos = pos; return o; }
static void AddDestructibles(MapObjects *m, const CArray *classes) { for (int i = 0; i < (int)classes->size; i++) { const MapObject *mo = CArrayGet(classes, i); if (mo->Health > 0) { char *s; CSTRDUP(s, mo->Name); CArrayPushBack(&m->Destructibles, &s); } } }
static void LoadOldPic( PicManager *pm, const char *name, const TOffsetPic *pic) { // Don't use old pics if new ones are available if (PicManagerGetPic(pm, name) != NULL) { return; } NamedPic p; CSTRDUP(p.name, name); const Pic *original = PicManagerGetFromOld(pm, pic->picIndex); PicCopy(&p.pic, original); CArrayPushBack(&pm->pics, &p); }
static void CreateAddCharacterSubObjs(UIObject *c, void *vData) { EditorBrushAndCampaign *data = vData; CharacterStore *store = &data->Campaign->Setting.characters; if (c->Children.size == store->OtherChars.size) { return; } // Recreate the child UI objects c->Highlighted = NULL; UIObject **objs = c->Children.data; for (int i = 0; i < (int)c->Children.size; i++, objs++) { UIObjectDestroy(*objs); } CArrayTerminate(&c->Children); CArrayInit(&c->Children, sizeof c); UIObject *o = UIObjectCreate( UITYPE_CUSTOM, 0, Vec2iZero(), Vec2iNew(TILE_WIDTH + 4, TILE_HEIGHT * 2 + 4)); o->ChangeFunc = BrushSetBrushTypeAddCharacter; o->u.CustomDrawFunc = DrawCharacter; o->OnFocusFunc = ActivateEditorBrushAndCampaignBrush; o->OnUnfocusFunc = DeactivateEditorBrushAndCampaignBrush; Vec2i pos = Vec2iZero(); int width = 8; for (int i = 0; i < (int)store->OtherChars.size; i++) { UIObject *o2 = UIObjectCopy(o); Character *ch = CArrayGet(&store->OtherChars, i); CSTRDUP(o2->Tooltip, ch->Gun->name); o2->IsDynamicData = 1; CMALLOC(o2->Data, sizeof(EditorBrushAndCampaign)); ((EditorBrushAndCampaign *)o2->Data)->Brush.Brush = data->Brush.Brush; ((EditorBrushAndCampaign *)o2->Data)->Campaign = data->Campaign; ((EditorBrushAndCampaign *)o2->Data)->Brush.u.ItemIndex = i; o2->Pos = pos; UIObjectAddChild(c, o2); pos.x += o->Size.x; if (((i + 1) % width) == 0) { pos.x = 0; pos.y += o->Size.y; } } UIObjectDestroy(o); }
char *MakePlacementFlagTooltip(const MapObject *mo) { // Add a descriptive tooltip for the map object char buf[512]; // Construct text representing the placement flags char pfBuf[128]; if (mo->Flags == 0) { sprintf(pfBuf, "anywhere\n"); } else { strcpy(pfBuf, ""); for (int i = 1; i < PLACEMENT_COUNT; i++) { if (mo->Flags & (1 << i)) { if (strlen(pfBuf) > 0) { strcat(pfBuf, ", "); } strcat(pfBuf, PlacementFlagStr(i)); } } } // Construct text representing explosion guns char exBuf[256]; strcpy(exBuf, ""); if (mo->DestroyGuns.size > 0) { sprintf(exBuf, "\nExplodes: "); for (int i = 0; i < (int)mo->DestroyGuns.size; i++) { if (i > 0) { strcat(exBuf, ", "); } const WeaponClass **wc = CArrayGet(&mo->DestroyGuns, i); strcat(exBuf, (*wc)->name); } } sprintf( buf, "%s\nHealth: %d\nPlacement: %s%s", mo->Name, mo->Health, pfBuf, exBuf); char *tmp; CSTRDUP(tmp, buf); return tmp; }
static UIObject *CreateAddObjectiveObjs( Vec2i pos, EditorBrush *brush, CampaignOptions *co) { UIObject *c = UIObjectCreate(UITYPE_CONTEXT_MENU, 0, pos, Vec2iZero()); // Need to update UI objects dynamically as new objectives can be // added and removed c->OnFocusFunc = CreateAddObjectiveSubObjs; CSTRDUP(c->Tooltip, "Manually place objectives\nThe rest will be randomly placed"); c->IsDynamicData = 1; CMALLOC(c->Data, sizeof(EditorBrushAndCampaign)); ((EditorBrushAndCampaign *)c->Data)->Brush.Brush = brush; ((EditorBrushAndCampaign *)c->Data)->Campaign = co; return c; }
static void SetupSpawner( MapObject *m, const char *spawnerName, const char *pickupClassName) { memset(m, 0, sizeof *m); CSTRDUP(m->Name, spawnerName); m->Pic.Type = PICTYPE_NORMAL; m->Pic.u.Pic = PicManagerGetPic(&gPicManager, "spawn_pad"); m->Pic.UseMask = true; m->Pic.u1.Mask = colorWhite; const Vec2i size = CPicGetSize(&m->Pic); m->Offset = Vec2iNew(-size.x / 2, TILE_HEIGHT / 2 - size.y); m->Size = TILE_SIZE; m->Health = 0; m->DrawLast = true; m->Type = MAP_OBJECT_TYPE_PICKUP_SPAWNER; m->u.PickupClass = StrPickupClass(pickupClassName); }
static void LoadCampaignsFromFolder( campaign_list_t *list, const char *name, const char *path, const GameMode mode) { tinydir_dir dir; int i; CSTRDUP(list->Name, name); if (tinydir_open_sorted(&dir, path) == -1) { printf("Cannot load campaigns from path %s\n", path); return; } for (i = 0; i < (int)dir.n_files; i++) { tinydir_file file; tinydir_readfile_n(&dir, &file, i); // Ignore campaigns that start with a ~ // These are autosaved const bool isArchive = strcmp(file.extension, "cdogscpn") == 0 || strcmp(file.extension, "CDOGSCPN") == 0; if (file.is_dir && !isArchive && strcmp(file.name, ".") != 0 && strcmp(file.name, "..") != 0) { campaign_list_t subFolder; CampaignListInit(&subFolder); LoadCampaignsFromFolder(&subFolder, file.name, file.path, mode); CArrayPushBack(&list->subFolders, &subFolder); } else if ((file.is_reg || isArchive) && file.name[0] != '~') { CampaignEntry entry; if (CampaignEntryTryLoad(&entry, file.path, mode)) { CArrayPushBack(&list->list, &entry); } } } tinydir_close(&dir); }
int ScanCampaignOld(const char *filename, char **title, int *missions) { FILE *f; int i; CampaignSettingOld setting; debug(D_NORMAL, "filename: %s\n", filename); f = fopen(filename, "rb"); if (f != NULL) { f_read32(f, &i, sizeof(i)); if (i != CAMPAIGN_MAGIC) { fclose(f); debug(D_NORMAL, "Filename: %s\n", filename); debug(D_NORMAL, "Magic: %d FileM: %d\n", CAMPAIGN_MAGIC, i); debug(D_NORMAL, "ScanCampaignOld - bad file!\n"); return -1; } f_read32(f, &i, sizeof(i)); if (i != CAMPAIGN_VERSION) { fclose(f); debug( D_NORMAL, "ScanCampaignOld - version mismatch (expected %d, read %d)\n", CAMPAIGN_VERSION, i); return -1; } f_read(f, setting.title, sizeof(setting.title)); f_read(f, setting.author, sizeof(setting.author)); f_read(f, setting.description, sizeof(setting.description)); f_read32(f, &setting.missionCount, sizeof(setting.missionCount)); CSTRDUP(*title, setting.title); *missions = setting.missionCount; fclose(f); return 0; } perror("ScanCampaignOld - couldn't read file:"); return -1; }
// Load all the template names to the menu entries static void PostEnterLoadTemplateNames(menu_t *menu, void *data) { bool *isSave = (bool *)data; for (int i = 0; i < (int)gPlayerTemplates.size; i++) { // Add menu if necessary if (i == (int)menu->u.normal.subMenus.size) { MenuAddSubmenu(menu, MenuCreateBack("")); } menu_t *subMenu = CArrayGet(&menu->u.normal.subMenus, i); const PlayerTemplate *pt = CArrayGet(&gPlayerTemplates, i); CFREE(subMenu->name); CSTRDUP(subMenu->name, pt->name); } if (*isSave && menu->u.normal.subMenus.size == gPlayerTemplates.size) { MenuAddSubmenu(menu, MenuCreateBack("(new)")); } }
static void LoadAmmoSpawners(CArray *classes, const CArray *ammo) { for (int i = 0; i < (int)ammo->size; i++) { const Ammo *a = CArrayGet(ammo, i); MapObject m; memset(&m, 0, sizeof m); char buf[256]; sprintf(buf, "%s spawner", a->Name); CSTRDUP(m.Name, buf); m.Normal.Pic = PicManagerGetPic(&gPicManager, "spawn_pad"); m.Normal.Offset = Vec2iNew( -m.Normal.Pic->size.x / 2, TILE_HEIGHT / 2 - m.Normal.Pic->size.y); m.Size = Vec2iNew(TILE_WIDTH, TILE_HEIGHT); m.Health = 0; m.Type = MAP_OBJECT_TYPE_PICKUP_SPAWNER; sprintf(buf, "ammo_%s", a->Name); m.u.PickupClass = StrPickupClass(buf); CArrayPushBack(classes, &m); } }