static const char *MissionGetObjectiveFlags(UIObject *o, void *vData) { int flags; static char s[128]; UNUSED(o); MissionIndexData *data = vData; if (!CampaignGetCurrentMission(data->co)) return NULL; if ((int)CampaignGetCurrentMission(data->co)->Objectives.size <= data->index) { return NULL; } flags = GetMissionObjective( CampaignGetCurrentMission(data->co), data->index)->Flags; if (!flags) { return "(normal)"; } sprintf(s, "%s %s %s %s %s", (flags & OBJECTIVE_HIDDEN) ? "hidden" : "", (flags & OBJECTIVE_POSKNOWN) ? "pos.known" : "", (flags & OBJECTIVE_HIACCESS) ? "access" : "", (flags & OBJECTIVE_UNKNOWNCOUNT) ? "no-count" : "", (flags & OBJECTIVE_NOACCESS) ? "no-access" : ""); return s; }
static void MissionChangeRoomsOverlap(void *data, int d) { UNUSED(d); CampaignOptions *co = data; CampaignGetCurrentMission(co)->u.Cave.Rooms.Overlap = !CampaignGetCurrentMission(co)->u.Cave.Rooms.Overlap; }
static void MissionChangeRoomMax(void *data, int d) { CampaignOptions *co = data; CampaignGetCurrentMission(co)->u.Cave.Rooms.Max = CLAMP(CampaignGetCurrentMission(co)->u.Cave.Rooms.Max + d, 5, 50); CampaignGetCurrentMission(co)->u.Cave.Rooms.Min = MIN( CampaignGetCurrentMission(co)->u.Cave.Rooms.Min, CampaignGetCurrentMission(co)->u.Cave.Rooms.Max); }
static const char *MissionGetRoomWallPadStr(UIObject *o, void *data) { static char s[128]; UNUSED(o); CampaignOptions *co = data; if (!CampaignGetCurrentMission(co)) return NULL; sprintf(s, "RoomWallPad: %d", CampaignGetCurrentMission(co)->u.Cave.Rooms.WallPad); return s; }
static const char *MissionGetSquareCountStr(UIObject *o, void *data) { static char s[128]; UNUSED(o); CampaignOptions *co = data; if (!CampaignGetCurrentMission(co)) return NULL; sprintf(s, "Sqr: %d", CampaignGetCurrentMission(co)->u.Cave.Squares); return s; }
static const char *MissionGetObjectiveStr(UIObject *o, void *vData) { UNUSED(o); MissionIndexData *data = vData; if (!CampaignGetCurrentMission(data->co)) return NULL; if ((int)CampaignGetCurrentMission(data->co)->Objectives.size <= data->index) return NULL; return ObjectiveTypeStr(((const Objective *)CArrayGet( &CampaignGetCurrentMission(data->co)->Objectives, data->index))->Type); }
static void MissionDrawDoorEnabled( UIObject *o, GraphicsDevice *g, struct vec2i pos, void *data) { UNUSED(o); UNUSED(g); CampaignOptions *co = data; if (!CampaignGetCurrentMission(co)) return; DisplayFlag( svec2i_add(pos, o->Pos), "Doors", CampaignGetCurrentMission(co)->u.Cave.DoorsEnabled, UIObjectIsHighlighted(o)); }
static void MissionDrawRoomsOverlap( UIObject *o, GraphicsDevice *g, struct vec2i pos, void *data) { UNUSED(o); UNUSED(g); UNUSED(pos); CampaignOptions *co = data; if (!CampaignGetCurrentMission(co)) return; DisplayFlag( svec2i_add(pos, o->Pos), "Room overlap", CampaignGetCurrentMission(co)->u.Cave.Rooms.Overlap, UIObjectIsHighlighted(o)); }
static const char *MissionGetObjectiveTotal(UIObject *o, void *vData) { static char s[128]; UNUSED(o); MissionIndexData *data = vData; if (!CampaignGetCurrentMission(data->co)) return NULL; if ((int)CampaignGetCurrentMission(data->co)->Objectives.size <= data->index) { return NULL; } sprintf(s, "out of %d", GetMissionObjective( CampaignGetCurrentMission(data->co), data->index)->Count); return s; }
static void Delete(int xc, int yc) { Mission *mission = CampaignGetCurrentMission(&gCampaign); switch (yc) { case YC_CHARACTERS: DeleteCharacter(mission, xc); break; case YC_SPECIALS: DeleteSpecial(mission, xc); break; case YC_ITEMS: DeleteItem(mission, xc); break; default: if (yc >= YC_OBJECTIVES) { DeleteObjective(mission, yc - YC_OBJECTIVES); } else { DeleteMission(&gCampaign); } AdjustYC(&yc); break; } fileChanged = 1; Setup(0); }
static void MissionChangeDoorEnabled(void *data, int d) { UNUSED(d); CampaignOptions *co = data; Mission *m = CampaignGetCurrentMission(co); m->u.Cave.DoorsEnabled = !m->u.Cave.DoorsEnabled; }
static void MissionChangeObjectiveRequired(void *vData, int d) { MissionIndexData *data = vData; Objective *o = GetMissionObjective( CampaignGetCurrentMission(data->co), data->index); o->Required = CLAMP_OPPOSITE(o->Required + d, 0, MIN(100, o->Count)); }
void CampaignAndMissionSetup( int buildTables, CampaignOptions *campaign, struct MissionOptions *mo) { CampaignSeedRandom(campaign); SetupMission( buildTables, CampaignGetCurrentMission(campaign), mo, campaign->MissionIndex); }
static const char *CampaignGetSeedStr(UIObject *o, void *data) { static char s[128]; UNUSED(o); CampaignOptions *co = data; if (!CampaignGetCurrentMission(co)) return NULL; sprintf(s, "Seed: %d", ConfigGetInt(&gConfig, "Game.RandomSeed")); return s; }
static const char *MissionGetFillPercentStr(UIObject *o, void *data) { UNUSED(o); CampaignOptions *co = data; const Mission *m = CampaignGetCurrentMission(co); if (m == NULL) return NULL; static char s[128]; sprintf(s, "Fill: %d%%", m->u.Cave.FillPercent); return s; }
static const char *MissionGetCorridorWidthStr(UIObject *o, void *data) { UNUSED(o); CampaignOptions *co = data; const Mission *m = CampaignGetCurrentMission(co); if (m == NULL) return NULL; static char s[128]; sprintf(s, "CorridorWidth: %d", m->u.Cave.CorridorWidth); return s; }
static void MissionChangeFillPercent(void *data, int d) { CampaignOptions *co = data; Mission *m = CampaignGetCurrentMission(co); if (gEventHandlers.keyboard.modState & KMOD_SHIFT) { d *= 10; } m->u.Cave.FillPercent = CLAMP(m->u.Cave.FillPercent + d, 0, 100); }
void DeleteMission(CampaignOptions *co) { CASSERT( co->MissionIndex < (int)co->Setting.Missions.size, "invalid mission index"); MissionTerminate(CampaignGetCurrentMission(co)); CArrayDelete(&co->Setting.Missions, co->MissionIndex); if (co->MissionIndex >= (int)co->Setting.Missions.size) { co->MissionIndex = MAX(0, (int)co->Setting.Missions.size - 1); } }
static void MissionCheckTypeStatic(UIObject *o, void *data) { CampaignOptions *co = data; Mission *m = CampaignGetCurrentMission(co); if (!m || m->Type != MAPTYPE_STATIC) { o->IsVisible = false; // Need to unhighlight to prevent children being drawn UIObjectUnhighlight(o); return; } o->IsVisible = true; }
static void ObjectiveChangeType(void *vData, int d) { UNUSED(d); ObjectiveChangeTypeData *data = vData; Objective *o = GetMissionObjective( CampaignGetCurrentMission(data->C), data->ObjectiveIdx); if (o->Type == data->Type) { return; } o->Type = data->Type; MissionResetObjectiveIndex(o); }
static Vec2i GetMouseTile(EventHandlers *e) { Mission *m = CampaignGetCurrentMission(&gCampaign); if (!m) { return Vec2iNew(-1, -1); } else { return Vec2iNew( (e->mouse.currentPos.x - sDrawBuffer.dx) / TILE_WIDTH + sDrawBuffer.xStart, (e->mouse.currentPos.y - sDrawBuffer.dy) / TILE_HEIGHT + sDrawBuffer.yStart); } }
static void AdjustXC(int yc, int *xc) { Mission *mission = CampaignGetCurrentMission(&gCampaign); switch (yc) { case YC_CAMPAIGNTITLE: *xc = CLAMP_OPPOSITE(*xc, 0, XC_CAMPAIGNDESC); break; case YC_MISSIONTITLE: *xc = CLAMP_OPPOSITE(*xc, 0, XC_MUSICFILE); break; case YC_MISSIONLOOKS: *xc = CLAMP_OPPOSITE(*xc, 0, XC_COLOR4); break; case YC_CHARACTERS: if (mission && mission->Enemies.size > 0) { *xc = CLAMP_OPPOSITE(*xc, 0, (int)mission->Enemies.size - 1); } break; case YC_SPECIALS: if (mission && mission->SpecialChars.size > 0) { *xc = CLAMP_OPPOSITE(*xc, 0, (int)mission->SpecialChars.size - 1); } break; case YC_ITEMS: if (mission && mission->Items.size > 0) { *xc = CLAMP_OPPOSITE(*xc, 0, (int)mission->Items.size - 1); } break; case YC_WEAPONS: *xc = CLAMP_OPPOSITE(*xc, 0, XC_MAXWEAPONS); break; default: if (yc >= YC_OBJECTIVES) { *xc = CLAMP_OPPOSITE(*xc, 0, XC_FLAGS); } break; } }
void DrawKey(UIObject *o, GraphicsDevice *g, struct vec2i pos, void *vData) { const IndexedEditorBrush *data = vData; if (data->u.ItemIndex == -1) { // No key; don't draw return; } const Mission *m = CampaignGetCurrentMission(&gCampaign); const Pic *pic = CPicGetPic( &KeyPickupClass(m->KeyStyle, data->u.ItemIndex)->Pic, 0); pos = svec2i_add(svec2i_add(pos, o->Pos), svec2i_scale_divide(o->Size, 2)); pos = svec2i_subtract(pos, svec2i_scale_divide(pic->size, 2)); Blit(g, pic, pos); }
static void MissionChangeObjectiveTotal(void *vData, int d) { MissionIndexData *data = vData; const Mission *m = CampaignGetCurrentMission(data->co); Objective *o = GetMissionObjective(m, data->index); o->Count = CLAMP_OPPOSITE(o->Count + d, o->Required, 100); // Don't let the total reduce to less than static ones we've placed if (m->Type == MAPTYPE_STATIC) { CA_FOREACH(const ObjectivePositions, op, m->u.Static.Objectives) if (op->Index == data->index) { o->Count = MAX(o->Count, (int)op->Positions.size); break; } CA_FOREACH_END() }
static void Setup(int buildTables) { Mission *m = CampaignGetCurrentMission(&gCampaign); if (!m) { return; } MissionCopy(&lastMission, ¤tMission); MissionCopy(¤tMission, m); MissionOptionsTerminate(&gMission); CampaignAndMissionSetup(buildTables, &gCampaign, &gMission); MakeBackground(&gGraphicsDevice, buildTables); sCursorTile = TileNone(); Autosave(); sJustLoaded = true; sHasUnbakedChanges = false; }
static void DrawObjective( UIObject *o, GraphicsDevice *g, Vec2i pos, void *vData) { UNUSED(g); EditorBrushAndCampaign *data = vData; Mission *m = CampaignGetCurrentMission(data->Campaign); const Objective *obj = CArrayGet(&m->Objectives, data->Brush.u.ItemIndex); CharacterStore *store = &data->Campaign->Setting.characters; pos = Vec2iAdd(Vec2iAdd(pos, o->Pos), Vec2iScaleDiv(o->Size, 2)); switch (obj->Type) { case OBJECTIVE_KILL: { Character *c = CArrayGet( &store->OtherChars, CharacterStoreGetSpecialId(store, data->Brush.Index2)); DrawCharacterSimple(c, pos, DIRECTION_DOWN, false, false); } break; case OBJECTIVE_RESCUE: { Character *c = CArrayGet( &store->OtherChars, CharacterStoreGetPrisonerId(store, data->Brush.Index2)); DrawCharacterSimple(c, pos, DIRECTION_DOWN, false, false); } break; case OBJECTIVE_COLLECT: { const Pic *p = obj->u.Pickup->Pic; pos = Vec2iMinus(pos, Vec2iScaleDiv(p->size, 2)); Blit(&gGraphicsDevice, p, pos); } break; case OBJECTIVE_DESTROY: DisplayMapItem(pos, obj->u.MapObject); break; default: assert(0 && "invalid objective type"); break; } }
static void AdjustYC(int *yc) { Mission *mission = CampaignGetCurrentMission(&gCampaign); if (mission) { if (mission->Objectives.size) { *yc = CLAMP_OPPOSITE( *yc, 0, YC_OBJECTIVES + (int)mission->Objectives.size - 1); } else { *yc = CLAMP_OPPOSITE(*yc, 0, YC_OBJECTIVES); } } else { *yc = CLAMP_OPPOSITE(*yc, 0, YC_MISSIONINDEX); } }
static char *MissionGetObjectiveDescription(UIObject *o, void *data) { MissionObjectiveData *mData = data; Mission *m = CampaignGetCurrentMission(mData->Campaign); if (!m) { return NULL; } int i = mData->MissionObjectiveIndex; if ((int)m->Objectives.size <= i) { if (i == 0) { // first objective and mission has no objectives o->u.Textbox.IsEditable = false; return "-- mission objectives --"; } return NULL; } o->u.Textbox.IsEditable = true; return ((const Objective *)CArrayGet(&m->Objectives, i))->Description; }
static void MissionCheckObjectiveDescription(UIObject *o, void *data) { MissionObjectiveData *mData = data; Mission *m = CampaignGetCurrentMission(mData->Campaign); if (!m) { o->IsVisible = false; return; } int i = mData->MissionObjectiveIndex; if ((int)m->Objectives.size <= i) { if (i == 0) { // first objective and mission has no objectives o->IsVisible = true; return; } o->IsVisible = false; return; } o->IsVisible = true; }
static void CreateAddObjectiveSubObjs(UIObject *c, void *vData) { EditorBrushAndCampaign *data = vData; Mission *m = CampaignGetCurrentMission(data->Campaign); // Check if the data is still the same; if so don't recreate the // child UI objects // This is because during the course of UI operations, this element // could be highlighted again; if we recreate then we invalidate // UI pointers. bool needToRecreate = false; int childIndex = 0; CA_FOREACH(const Objective, obj, m->Objectives) int secondaryCount = 1; const CharacterStore *store = &data->Campaign->Setting.characters; switch (obj->Type) { case OBJECTIVE_KILL: secondaryCount = (int)store->specialIds.size; break; case OBJECTIVE_COLLECT: break; case OBJECTIVE_DESTROY: break; case OBJECTIVE_RESCUE: secondaryCount = (int)store->prisonerIds.size; break; default: continue; } for (int j = 0; j < (int)secondaryCount; j++) { if ((int)c->Children.size <= childIndex) { needToRecreate = true; break; } UIObject *o2 = *(UIObject **)CArrayGet(&c->Children, childIndex); if (((EditorBrushAndCampaign *)o2->Data)->Brush.u.ItemIndex != _ca_index || ((EditorBrushAndCampaign *)o2->Data)->Brush.Index2 != j) { needToRecreate = true; break; } childIndex++; } if (needToRecreate) { break; } CA_FOREACH_END() if (!needToRecreate) { return; } // Recreate the child UI objects c->Highlighted = NULL; CA_FOREACH(UIObject *, obj, c->Children) UIObjectDestroy(*obj); CA_FOREACH_END() 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 = BrushSetBrushTypeAddObjective; o->u.CustomDrawFunc = DrawObjective; o->OnFocusFunc = ActivateEditorBrushAndCampaignBrush; o->OnUnfocusFunc = DeactivateEditorBrushAndCampaignBrush; Vec2i pos = Vec2iZero(); CA_FOREACH(const Objective, obj, m->Objectives) int secondaryCount = 1; const CharacterStore *store = &data->Campaign->Setting.characters; switch (obj->Type) { case OBJECTIVE_KILL: secondaryCount = (int)store->specialIds.size; o->Size.y = TILE_HEIGHT * 2 + 4; break; case OBJECTIVE_COLLECT: o->Size.y = TILE_HEIGHT + 4; break; case OBJECTIVE_DESTROY: o->Size.y = TILE_HEIGHT * 2 + 4; break; case OBJECTIVE_RESCUE: secondaryCount = (int)store->prisonerIds.size; o->Size.y = TILE_HEIGHT * 2 + 4; break; default: continue; } for (int j = 0; j < (int)secondaryCount; j++) { UIObject *o2 = UIObjectCopy(o); CSTRDUP(o2->Tooltip, ObjectiveTypeStr(obj->Type)); o2->IsDynamicData = true; 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 = _ca_index; ((EditorBrushAndCampaign *)o2->Data)->Brush.Index2 = j; o2->Pos = pos; UIObjectAddChild(c, o2); pos.x += o->Size.x; } pos.x = 0; pos.y += o->Size.y; CA_FOREACH_END() UIObjectDestroy(o); }