void PicManagerClear(CArray *pics, CArray *sprites) { for (int i = 0; i < (int)pics->size; i++) { NamedPic *n = CArrayGet(pics, i); CFREE(n->name); PicFree(&n->pic); } CArrayClear(pics); for (int i = 0; i < (int)sprites->size; i++) { NamedSpritesFree(CArrayGet(sprites, i)); } CArrayClear(sprites); }
static void DrawDebris(DrawBuffer *b, Vec2i offset) { Tile *tile = &b->tiles[0][0]; for (int y = 0; y < Y_TILES; y++) { CArrayClear(&b->displaylist); for (int x = 0; x < b->Size.x; x++, tile++) { if (tile->flags & MAPTILE_OUT_OF_SIGHT) { continue; } CA_FOREACH(ThingId, tid, tile->things) const TTileItem *ti = ThingIdGetTileItem(tid); if (TileItemIsDebris(ti)) { CArrayPushBack(&b->displaylist, &ti); } CA_FOREACH_END() } DrawBufferSortDisplayList(b); CA_FOREACH(const TTileItem *, tp, b->displaylist) DrawThing(b, *tp, offset); CA_FOREACH_END() tile += X_TILES - b->Size.x; } }
static void DrawWallsAndThings(DrawBuffer *b, Vec2i offset) { Vec2i pos; Tile *tile = &b->tiles[0][0]; pos.y = b->dy + cWallOffset.dy + offset.y; for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT) { CArrayClear(&b->displaylist); pos.x = b->dx + cWallOffset.dx + offset.x; for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH) { if (tile->flags & MAPTILE_IS_WALL) { if (!(tile->flags & MAPTILE_DELAY_DRAW)) { DrawWallColumn(y, pos, tile); } } else if (tile->flags & MAPTILE_OFFSET_PIC) { // Drawing doors // Doors may be offset; vertical doors are drawn centered // horizontal doors are bottom aligned Vec2i doorPos = pos; doorPos.x += (TILE_WIDTH - tile->picAlt->pic.size.x) / 2; if (tile->picAlt->pic.size.y > 16) { doorPos.y += TILE_HEIGHT - (tile->picAlt->pic.size.y % TILE_HEIGHT); } BlitMasked( &gGraphicsDevice, &tile->picAlt->pic, doorPos, GetTileLOSMask(tile), 0); } // Draw the items that are in LOS if (tile->flags & MAPTILE_OUT_OF_SIGHT) { continue; } CA_FOREACH(ThingId, tid, tile->things) const TTileItem *ti = ThingIdGetTileItem(tid); // Don't draw debris, they are drawn later if (TileItemIsDebris(ti)) { continue; } CArrayPushBack(&b->displaylist, &ti); CA_FOREACH_END() } DrawBufferSortDisplayList(b); CA_FOREACH(const TTileItem *, tp, b->displaylist) DrawThing(b, *tp, offset); CA_FOREACH_END() tile += X_TILES - b->Size.x; } }
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); } }
static void DrawDebris(DrawBuffer *b, struct vec2i offset) { Tile *tile = &b->tiles[0][0]; for (int y = 0; y < Y_TILES; y++) { CArrayClear(&b->displaylist); for (int x = 0; x < b->Size.x; x++, tile++) { if (tile->outOfSight) { continue; } CA_FOREACH(ThingId, tid, tile->things) const Thing *ti = ThingIdGetThing(tid); if (ThingDrawLast(ti)) { CArrayPushBack(&b->displaylist, &ti); } CA_FOREACH_END() } DrawBufferSortDisplayList(b); CA_FOREACH(const Thing *, tp, b->displaylist) DrawThing(b, *tp, offset); CA_FOREACH_END() tile += X_TILES - b->Size.x; } }
void BulletClassesClear(CArray *classes) { for (int i = 0; i < (int)classes->size; i++) { BulletClassFree(CArrayGet(classes, i)); } CArrayClear(classes); }
void AmmoClassesClear(CArray *ammo) { CA_FOREACH(Ammo, a, *ammo) CFREE(a->Name); CFREE(a->Sound); CFREE(a->DefaultGun); CA_FOREACH_END() CArrayClear(ammo); }
void SoundClear(CArray *sounds) { for (int i = 0; i < (int)sounds->size; i++) { SoundData *sound = CArrayGet(sounds, i); Mix_FreeChunk(sound->data); } CArrayClear(sounds); }
static void ReloadDestructibles(MapObjects *mo) { CA_FOREACH(char *, s, mo->Destructibles) CFREE(*s); CA_FOREACH_END() CArrayClear(&mo->Destructibles); AddDestructibles(mo, &mo->Classes); AddDestructibles(mo, &mo->CustomClasses); }
void MapObjectsClear(CArray *classes) { for (int i = 0; i < (int)classes->size; i++) { MapObject *c = CArrayGet(classes, i); CFREE(c->Name); CArrayTerminate(&c->DestroyGuns); } CArrayClear(classes); }
void WeaponClassesClear(CArray *classes) { for (int i = 0; i < (int)classes->size; i++) { GunDescription *gd = CArrayGet(classes, i); CFREE(gd->name); CFREE(gd->Description); } CArrayClear(classes); }
void AmmoClassesClear(CArray *ammo) { for (int i = 0; i < (int)ammo->size; i++) { Ammo *a = CArrayGet(ammo, i); CFREE(a->Name); CFREE(a->Sound); } CArrayClear(ammo); }
static void ReloadDestructibles(MapObjects *mo) { for (int i = 0; i < (int)mo->Destructibles.size; i++) { char **s = CArrayGet(&mo->Destructibles, i); CFREE(*s); } CArrayClear(&mo->Destructibles); AddDestructibles(mo, &mo->Classes); AddDestructibles(mo, &mo->CustomClasses); }
static void DrawWallsAndThings(DrawBuffer *b, struct vec2i offset) { struct vec2i pos; Tile *tile = &b->tiles[0][0]; pos.y = b->dy + WALL_OFFSET_Y + offset.y; const bool useFog = ConfigGetBool(&gConfig, "Game.Fog"); for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT) { CArrayClear(&b->displaylist); pos.x = b->dx + offset.x; for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH) { if (tile->Class->Type == TILE_CLASS_WALL) { DrawLOSPic(tile, tile->Class->Pic, pos, useFog); } else if (tile->Class->Type == TILE_CLASS_DOOR && tile->ClassAlt && tile->ClassAlt->Pic) { // Drawing doors // Doors may be offset; vertical doors are drawn centered // horizontal doors are bottom aligned struct vec2i doorPos = pos; const Pic *pic = tile->ClassAlt->Pic; doorPos.x += (TILE_WIDTH - pic->size.x) / 2; if (pic->size.y > 16) { doorPos.y += TILE_HEIGHT - (pic->size.y % TILE_HEIGHT); } DrawLOSPic(tile, pic, doorPos, useFog); } // Draw the items that are in LOS if (tile->outOfSight) { continue; } CA_FOREACH(ThingId, tid, tile->things) const Thing *ti = ThingIdGetThing(tid); // Drawn later if (ThingDrawLast(ti)) { continue; } CArrayPushBack(&b->displaylist, &ti); CA_FOREACH_END() } DrawBufferSortDisplayList(b); CA_FOREACH(const Thing *, tp, b->displaylist) DrawThing(b, *tp, offset); CA_FOREACH_END() tile += X_TILES - b->Size.x; } }
void ToTitleScreen(const bool start) { countdownMs = -1; ResetMovement(); MusicSetLoud(false); BackgroundsInit(&BG); Start = start; if (Start) { sprintf( WelcomeMessage, "%s to pause\n%s to exit", GetPausePrompt(), GetExitGamePrompt()); } else { // Find out the result of the game int maxScore = 0; for (int i = 0; i < MAX_PLAYERS; i++) { if (players[i].Score > maxScore) maxScore = players[i].Score; } winners = 0; for (int i = 0; i < MAX_PLAYERS; i++) { if (!players[i].Enabled) continue; if (players[i].Score == maxScore) { winnerIndices[winners] = i; winners++; } } if (PlayerEnabledCount() == 1) { sprintf( WelcomeMessage, "Your score was %d!\n%s to exit", maxScore, GetExitGamePrompt()); } else if (winners == 1) { sprintf( WelcomeMessage, "Wins with score %d!\n%s to exit", maxScore, GetExitGamePrompt()); } else { sprintf( WelcomeMessage, "Tied with score %d!\n%s to exit", maxScore, GetExitGamePrompt()); } HighScoresAdd(maxScore); } HighScoreDisplayInit(&HSD); CArrayClear(&Particles); SpaceReset(&space); // Add bottom edge so we don't fall through SpaceAddBottomEdge(&space); // Initialise players here for (int i = 0; i < MAX_PLAYERS; i++) { PlayerInit(&players[i], i, cpv( (i + 1) * FIELD_WIDTH / (MAX_PLAYERS + 1), FIELD_HEIGHT * 0.75f)); playersEnabled[i] = false; } // Add platforms for players to jump off for (int i = 0; i < MAX_PLAYERS; i++) { BlockInit( &blocks[i], (i + 1) * FIELD_WIDTH / (MAX_PLAYERS + 1) - BLOCK_WIDTH / 2, BLOCK_Y, BLOCK_WIDTH); } GatherInput = TitleScreenGatherInput; DoLogic = TitleScreenDoLogic; OutputFrame = TitleScreenOutputFrame; }
static void ConvertMission( Mission *dest, struct MissionOld *src, const int charCount) { int i; CFREE(dest->Title); CSTRDUP(dest->Title, src->title); CFREE(dest->Description); CSTRDUP(dest->Description, src->description); dest->Type = MAPTYPE_CLASSIC; dest->Size = Vec2iNew(src->mapWidth, src->mapHeight); dest->WallStyle = src->wallStyle; dest->FloorStyle = src->floorStyle; dest->RoomStyle = src->roomStyle; dest->ExitStyle = src->exitStyle; dest->KeyStyle = src->keyStyle; strcpy(dest->DoorStyle, DoorStyleStr(src->doorStyle)); for (i = 0; i < src->objectiveCount; i++) { MissionObjective mo; memset(&mo, 0, sizeof mo); ConvertMissionObjective(&mo, &src->objectives[i]); CArrayPushBack(&dest->Objectives, &mo); } // Note: modulo for compatibility with older, buggy missions for (i = 0; i < src->baddieCount; i++) { int n = src->baddies[i] % charCount; CArrayPushBack(&dest->Enemies, &n); } for (i = 0; i < src->specialCount; i++) { int n = src->specials[i] % charCount; CArrayPushBack(&dest->SpecialChars, &n); } for (i = 0; i < src->itemCount; i++) { MapObjectDensity mod; mod.M = IntMapObject(src->items[i]); mod.Density = src->itemDensity[i]; CArrayPushBack(&dest->MapObjectDensities, &mod); } dest->EnemyDensity = src->baddieDensity; CArrayClear(&dest->Weapons); for (i = 0; i < WEAPON_MAX; i++) { if ((src->weaponSelection & (1 << i)) || !src->weaponSelection) { GunDescription *g = CArrayGet(&gGunDescriptions.Guns, i); CArrayPushBack(&dest->Weapons, &g); } } strcpy(dest->Song, src->song); dest->WallMask = RangeToColor(abs(src->wallRange) % COLORRANGE_COUNT); dest->FloorMask = RangeToColor(abs(src->floorRange) % COLORRANGE_COUNT); dest->RoomMask = RangeToColor(abs(src->roomRange) % COLORRANGE_COUNT); dest->AltMask = RangeToColor(abs(src->altRange) % COLORRANGE_COUNT); dest->u.Classic.Walls = src->wallCount; dest->u.Classic.WallLength = src->wallLength; dest->u.Classic.CorridorWidth = 1; dest->u.Classic.Rooms.Count = src->roomCount; dest->u.Classic.Rooms.Min = 6; dest->u.Classic.Rooms.Max = 10; dest->u.Classic.Rooms.Edge = 0; dest->u.Classic.Rooms.Walls = 0; dest->u.Classic.Squares = src->squareCount; dest->u.Classic.Doors.Enabled = 1; dest->u.Classic.Doors.Min = dest->u.Classic.Doors.Max = 1; dest->u.Classic.Pillars.Count = 0; }
void EditorBrushSetHighlightedTiles(EditorBrush *b) { bool useSimpleHighlight = true; switch (b->Type) { case BRUSHTYPE_POINT: // fallthrough case BRUSHTYPE_ROOM_PAINTER: useSimpleHighlight = true; break; case BRUSHTYPE_LINE: if (b->IsPainting) { useSimpleHighlight = 0; // highlight a line CArrayClear(&b->HighlightedTiles); AlgoLineDrawData data; data.Draw = EditorBrushHighlightPoint; data.data = b; BresenhamLineDraw(b->LastPos, b->Pos, &data); } break; case BRUSHTYPE_BOX: // fallthrough case BRUSHTYPE_ROOM: // fallthrough case BRUSHTYPE_SET_EXIT: if (b->IsPainting) { Vec2i v; Vec2i d = Vec2iNew( b->Pos.x > b->LastPos.x ? 1 : -1, b->Pos.y > b->LastPos.y ? 1 : -1); useSimpleHighlight = 0; CArrayClear(&b->HighlightedTiles); for (v.y = b->LastPos.y; v.y != b->Pos.y + d.y; v.y += d.y) { for (v.x = b->LastPos.x; v.x != b->Pos.x + d.x; v.x += d.x) { if (v.x == b->LastPos.x || v.x == b->Pos.x || v.y == b->LastPos.y || v.y == b->Pos.y) { EditorBrushHighlightPoint(b, v); } } } } break; case BRUSHTYPE_BOX_FILLED: if (b->IsPainting) { Vec2i v; Vec2i d = Vec2iNew( b->Pos.x > b->LastPos.x ? 1 : -1, b->Pos.y > b->LastPos.y ? 1 : -1); useSimpleHighlight = 0; CArrayClear(&b->HighlightedTiles); for (v.y = b->LastPos.y; v.y != b->Pos.y + d.y; v.y += d.y) { for (v.x = b->LastPos.x; v.x != b->Pos.x + d.x; v.x += d.x) { EditorBrushHighlightPoint(b, v); } } } break; case BRUSHTYPE_SELECT: if (b->IsPainting) { if (b->IsMoving) { Vec2i v; Vec2i offset = Vec2iNew( b->Pos.x - b->DragPos.x, b->Pos.y - b->DragPos.y); useSimpleHighlight = 0; CArrayClear(&b->HighlightedTiles); for (v.y = 0; v.y < b->SelectionSize.y; v.y++) { for (v.x = 0; v.x < b->SelectionSize.x; v.x++) { Vec2i vOffset = Vec2iAdd( Vec2iAdd(v, b->SelectionStart), offset); EditorBrushHighlightPoint(b, vOffset); } } } else { // resize the selection Vec2i v; Vec2i d = Vec2iNew( b->Pos.x > b->LastPos.x ? 1 : -1, b->Pos.y > b->LastPos.y ? 1 : -1); useSimpleHighlight = 0; CArrayClear(&b->HighlightedTiles); for (v.y = b->LastPos.y; v.y != b->Pos.y + d.y; v.y += d.y) { for (v.x = b->LastPos.x; v.x != b->Pos.x + d.x; v.x += d.x) { EditorBrushHighlightPoint(b, v); } } } } else { // If there's a valid selection, draw that instead if (b->SelectionSize.x > 0 && b->SelectionSize.y > 0) { Vec2i v; useSimpleHighlight = 0; CArrayClear(&b->HighlightedTiles); for (v.y = 0; v.y < b->SelectionSize.y; v.y++) { for (v.x = 0; v.x < b->SelectionSize.x; v.x++) { Vec2i vOffset = Vec2iAdd(v, b->SelectionStart); EditorBrushHighlightPoint(b, vOffset); } } } } default: // do nothing break; } if (useSimpleHighlight) { // Simple highlight at brush tip based on brush size CArrayClear(&b->HighlightedTiles); EditorBrushHighlightPoint(b, b->Pos); } }
EditorResult EditorBrushStopPainting(EditorBrush *b, Mission *m) { EditorResult result = EDITOR_RESULT_NONE; if (b->IsPainting) { switch (b->Type) { case BRUSHTYPE_LINE: EditorBrushPaintLine(b, m); result = EDITOR_RESULT_CHANGED; break; case BRUSHTYPE_BOX: EditorBrushPaintBox(b, m, b->PaintType, MAP_UNSET); result = EDITOR_RESULT_CHANGED; break; case BRUSHTYPE_BOX_FILLED: EditorBrushPaintBox(b, m, b->PaintType, b->PaintType); result = EDITOR_RESULT_CHANGED; break; case BRUSHTYPE_ROOM: EditorBrushPaintBox(b, m, MAP_WALL, MAP_ROOM); result = EDITOR_RESULT_CHANGED; break; case BRUSHTYPE_ROOM_PAINTER: // Reload map to update tiles result = EDITOR_RESULT_RELOAD; break; case BRUSHTYPE_SELECT: if (b->IsMoving) { // Move the tiles from the source to the target // Need to copy all the tiles to a temp buffer first in case // we are moving to an overlapped position CArray movedTiles; Vec2i v; int i; int delta; CArrayInit(&movedTiles, sizeof(unsigned short)); // Copy tiles to temp from selection, setting them to MAP_FLOOR // in the process for (v.y = 0; v.y < b->SelectionSize.y; v.y++) { for (v.x = 0; v.x < b->SelectionSize.x; v.x++) { Vec2i vOffset = Vec2iAdd(v, b->SelectionStart); int idx = vOffset.y * m->Size.x + vOffset.x; unsigned short *tile = CArrayGet( &m->u.Static.Tiles, idx); CArrayPushBack(&movedTiles, tile); *tile = MAP_FLOOR; } } // Move the selection to the new position b->SelectionStart.x += b->Pos.x - b->DragPos.x; b->SelectionStart.y += b->Pos.y - b->DragPos.y; // Copy tiles to the new area, for parts of the new area that // are valid i = 0; for (v.y = 0; v.y < b->SelectionSize.y; v.y++) { for (v.x = 0; v.x < b->SelectionSize.x; v.x++) { Vec2i vOffset = Vec2iAdd(v, b->SelectionStart); if (vOffset.x >= 0 && vOffset.x < m->Size.x && vOffset.y >= 0 && vOffset.y < m->Size.y) { int idx = vOffset.y * m->Size.x + vOffset.x; unsigned short *tileFrom = CArrayGet(&movedTiles, i); unsigned short *tileTo = CArrayGet( &m->u.Static.Tiles, idx); *tileTo = *tileFrom; result = EDITOR_RESULT_CHANGED_AND_RELOAD; } i++; } } // Update the selection to fit within map boundaries delta = -b->SelectionStart.x; if (delta > 0) { b->SelectionStart.x += delta; b->SelectionSize.x -= delta; } delta = -b->SelectionStart.y; if (delta > 0) { b->SelectionStart.y += delta; b->SelectionSize.y -= delta; } delta = b->SelectionStart.x + b->SelectionSize.x - m->Size.x; if (delta > 0) { b->SelectionSize.x -= delta; } delta = b->SelectionStart.y + b->SelectionSize.y - m->Size.y; if (delta > 0) { b->SelectionSize.y -= delta; } // Check if the selection is still valid; if not, invalidate it if (b->SelectionSize.x < 0 || b->SelectionSize.y < 0) { b->SelectionSize = Vec2iZero(); } b->IsMoving = 0; } else { // Record the selection size b->SelectionStart = Vec2iMin(b->LastPos, b->Pos); b->SelectionSize.x = abs(b->LastPos.x - b->Pos.x) + 1; b->SelectionSize.y = abs(b->LastPos.y - b->Pos.y) + 1; // Disallow 1x1 selection sizes if (b->SelectionSize.x <= 1 && b->SelectionSize.y <= 1) { b->SelectionSize = Vec2iZero(); } } break; case BRUSHTYPE_SET_EXIT: { Vec2i exitStart = Vec2iMin(b->LastPos, b->Pos); Vec2i exitEnd = Vec2iMax(b->LastPos, b->Pos); // Clamp within map boundaries exitStart = Vec2iClamp( exitStart, Vec2iZero(), Vec2iMinus(m->Size, Vec2iUnit())); exitEnd = Vec2iClamp( exitEnd, Vec2iZero(), Vec2iMinus(m->Size, Vec2iUnit())); // Check that size is big enough Vec2i size = Vec2iAdd(Vec2iMinus(exitEnd, exitStart), Vec2iUnit()); if (size.x >= 3 && size.y >= 3) { // Check that exit area has changed if (!Vec2iEqual(exitStart, m->u.Static.Exit.Start) || !Vec2iEqual(exitEnd, m->u.Static.Exit.End)) { m->u.Static.Exit.Start = exitStart; m->u.Static.Exit.End = exitEnd; result = EDITOR_RESULT_CHANGED_AND_RELOAD; } } } break; default: // do nothing break; } } b->IsPainting = 0; CArrayClear(&b->HighlightedTiles); return result; }
static void DrawWallsAndThings(DrawBuffer *b, Vec2i offset) { Vec2i pos; Tile *tile = &b->tiles[0][0]; pos.y = b->dy + WALL_OFFSET_Y + offset.y; const bool useFog = ConfigGetBool(&gConfig, "Game.Fog"); for (int y = 0; y < Y_TILES; y++, pos.y += TILE_HEIGHT) { CArrayClear(&b->displaylist); pos.x = b->dx + offset.x; for (int x = 0; x < b->Size.x; x++, tile++, pos.x += TILE_WIDTH) { if (tile->flags & MAPTILE_IS_WALL) { if (!(tile->flags & MAPTILE_DELAY_DRAW)) { DrawWallColumn(y, pos, tile); } } else if (tile->flags & MAPTILE_OFFSET_PIC) { // Drawing doors // Doors may be offset; vertical doors are drawn centered // horizontal doors are bottom aligned Vec2i doorPos = pos; doorPos.x += (TILE_WIDTH - tile->picAlt->pic.size.x) / 2; if (tile->picAlt->pic.size.y > 16) { doorPos.y += TILE_HEIGHT - (tile->picAlt->pic.size.y % TILE_HEIGHT); } switch (GetTileLOS(tile, useFog)) { case TILE_LOS_NORMAL: Blit(&gGraphicsDevice, &tile->picAlt->pic, doorPos); break; case TILE_LOS_FOG: BlitMasked( &gGraphicsDevice, &tile->picAlt->pic, doorPos, colorFog, false); break; case TILE_LOS_NONE: default: // don't draw anything break; } } // Draw the items that are in LOS if (tile->flags & MAPTILE_OUT_OF_SIGHT) { continue; } CA_FOREACH(ThingId, tid, tile->things) const TTileItem *ti = ThingIdGetTileItem(tid); // Drawn later if (TileItemDrawLast(ti)) { continue; } CArrayPushBack(&b->displaylist, &ti); CA_FOREACH_END() } DrawBufferSortDisplayList(b); CA_FOREACH(const TTileItem *, tp, b->displaylist) DrawThing(b, *tp, offset); CA_FOREACH_END() tile += X_TILES - b->Size.x; } }
void CArrayRelease(void *cArray) { CArray realArray = (CArray)cArray; CArrayClear(realArray); free(realArray->elements); realArray->capacity = 0; }
static void ConvertMission(Mission *dest, struct MissionOld *src) { int i; CFREE(dest->Title); CSTRDUP(dest->Title, src->title); CFREE(dest->Description); CSTRDUP(dest->Description, src->description); dest->Type = MAPTYPE_CLASSIC; dest->Size = Vec2iNew(src->mapWidth, src->mapHeight); dest->WallStyle = src->wallStyle; dest->FloorStyle = src->floorStyle; dest->RoomStyle = src->roomStyle; dest->ExitStyle = src->exitStyle; dest->KeyStyle = src->keyStyle; dest->DoorStyle = src->doorStyle; for (i = 0; i < src->objectiveCount; i++) { MissionObjective mo; memset(&mo, 0, sizeof mo); ConvertMissionObjective(&mo, &src->objectives[i]); CArrayPushBack(&dest->Objectives, &mo); } for (i = 0; i < src->baddieCount; i++) { int n = src->baddies[i]; CArrayPushBack(&dest->Enemies, &n); } for (i = 0; i < src->specialCount; i++) { int n = src->specials[i]; CArrayPushBack(&dest->SpecialChars, &n); } for (i = 0; i < src->itemCount; i++) { int n = src->items[i]; CArrayPushBack(&dest->Items, &n); } for (i = 0; i < src->itemCount; i++) { int n = src->itemDensity[i]; CArrayPushBack(&dest->ItemDensities, &n); } dest->EnemyDensity = src->baddieDensity; CArrayClear(&dest->Weapons); for (i = 0; i < WEAPON_MAX; i++) { if ((src->weaponSelection & (1 << i)) || !src->weaponSelection) { GunDescription *g = CArrayGet(&gGunDescriptions, i); CArrayPushBack(&dest->Weapons, &g); } } strcpy(dest->Song, src->song); dest->WallColor = src->wallRange; dest->FloorColor = src->floorRange; dest->RoomColor = src->roomRange; dest->AltColor = src->altRange; dest->u.Classic.Walls = src->wallCount; dest->u.Classic.WallLength = src->wallLength; dest->u.Classic.CorridorWidth = 1; dest->u.Classic.Rooms.Count = src->roomCount; dest->u.Classic.Rooms.Min = 6; dest->u.Classic.Rooms.Max = 10; dest->u.Classic.Rooms.Edge = 0; dest->u.Classic.Rooms.Walls = 0; dest->u.Classic.Squares = src->squareCount; dest->u.Classic.Doors.Enabled = 1; dest->u.Classic.Doors.Min = dest->u.Classic.Doors.Max = 1; dest->u.Classic.Pillars.Count = 0; }
static void CreateAddMapItemSubObjs(UIObject *c, void *vData) { const CreateAddMapItemObjsImplData *data = vData; const int pageSize = data->GridSize.x * data->GridSize.y; // Check if we need to recreate the objs // TODO: this is a very heavyweight way to do it int count = 0; bool allChildrenSame = true; for (int i = 0; i < MapObjectsCount(&gMapObjects); i++) { MapObject *mo = IndexMapObject(i); UIObject *o2 = UIObjectCreate(UITYPE_CUSTOM, 0, svec2i_zero(), data->GridItemSize); o2->IsDynamicData = true; CCALLOC(o2->Data, data->DataSize); if (!data->ObjFunc(o2, mo, data->Data)) { UIObjectDestroy(o2); continue; } const int pageIdx = count / pageSize; if (pageIdx >= (int)c->Children.size) { allChildrenSame = false; break; } const UIObject **op = CArrayGet(&c->Children, pageIdx); const UIObject **octx = CArrayGet(&(*op)->Children, 0); const int idx = count % pageSize; if (idx >= (int)(*octx)->Children.size) { allChildrenSame = false; break; } const UIObject **oc = CArrayGet(&(*octx)->Children, idx); if (memcmp(o2->Data, (*oc)->Data, data->DataSize) != 0) { allChildrenSame = false; UIObjectDestroy(o2); break; } count++; UIObjectDestroy(o2); } int cCount = CountAddMapItemSubObjs(c); if (cCount == count && allChildrenSame) { 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); } CArrayClear(&c->Children); // Create pagination int pageNum = 1; UIObject *pageLabel = NULL; UIObject *page = NULL; UIObject *o = UIObjectCreate(UITYPE_CUSTOM, 0, svec2i_zero(), data->GridItemSize); o->ChangesData = true; const struct vec2i gridStart = svec2i_zero(); struct vec2i pos = svec2i_zero(); count = 0; for (int i = 0; i < MapObjectsCount(&gMapObjects); i++) { // Only add normal map objects MapObject *mo = IndexMapObject(i); UIObject *o2 = UIObjectCopy(o); o2->IsDynamicData = true; CCALLOC(o2->Data, data->DataSize); if (!data->ObjFunc(o2, mo, data->Data)) { UIObjectDestroy(o2); continue; } o2->Pos = pos; if (count == 0) { pageLabel = UIObjectCreate( UITYPE_LABEL, 0, svec2i((pageNum - 1) * 10, 0), svec2i(10, FontH())); char buf[32]; sprintf(buf, "%d", pageNum); UIObjectSetDynamicLabel(pageLabel, buf); page = UIObjectCreate( UITYPE_CONTEXT_MENU, 0, svec2i_add(data->PageOffset, pageLabel->Size), svec2i_zero()); UIObjectAddChild(pageLabel, page); pageNum++; } UIObjectAddChild(page, o2); pos.x += o->Size.x; if (((count + 1) % data->GridSize.x) == 0) { pos.x = gridStart.x; pos.y += o->Size.y; } count++; if (count == pageSize) { count = 0; pos = gridStart; UIObjectAddChild(c, pageLabel); } } if (pageLabel != NULL) { UIObjectAddChild(c, pageLabel); } UIObjectDestroy(o); }
void GameEventsClear(CArray *store) { CArrayClear(store); }