bool MissionStaticTryAddCharacter(Mission *m, int ch, Vec2i pos) { assert(m->Type == MAPTYPE_STATIC && "invalid map type"); unsigned short tile = MissionGetTile(m, pos); // Remove any characters already there MissionStaticTryRemoveCharacterAt(m, pos); if (IsClear(tile)) { // Check if the character already has an entry, and add to its list // of positions bool hasAdded = false; CA_FOREACH(CharacterPositions, cp, m->u.Static.Characters) if (cp->Index == ch) { CArrayPushBack(&cp->Positions, &pos); hasAdded = true; break; } CA_FOREACH_END() // If not, create a new entry if (!hasAdded) { CharacterPositions cp; cp.Index = ch; CArrayInit(&cp.Positions, sizeof(Vec2i)); CArrayPushBack(&cp.Positions, &pos); CArrayPushBack(&m->u.Static.Characters, &cp); } return true; } return false; }
EditorResult EditorBrushStartPainting(EditorBrush *b, Mission *m, int isMain) { if (!b->IsPainting) { b->LastPos = b->Pos; } b->PaintType = isMain ? b->MainType : b->SecondaryType; switch (b->Type) { case BRUSHTYPE_POINT: b->IsPainting = true; EditorBrushPaintLine(b, m); return EDITOR_RESULT_CHANGED; case BRUSHTYPE_LINE: // fallthrough case BRUSHTYPE_BOX: // fallthrough case BRUSHTYPE_BOX_FILLED: // fallthrough case BRUSHTYPE_ROOM: // fallthrough case BRUSHTYPE_SET_EXIT: // don't paint until the end break; case BRUSHTYPE_ROOM_PAINTER: EditorBrushPaintRoom(b, m); return EDITOR_RESULT_CHANGED; case BRUSHTYPE_SELECT: // Perform state changes if we've started painting if (!b->IsPainting) { if (!b->IsMoving) { // check if the click was inside the selection // If so, start moving if (b->Pos.x >= b->SelectionStart.x && b->Pos.y >= b->SelectionStart.y && b->Pos.x < b->SelectionStart.x + b->SelectionSize.x && b->Pos.y < b->SelectionStart.y + b->SelectionSize.y) { b->IsMoving = 1; b->DragPos = b->Pos; } } } break; case BRUSHTYPE_FILL: // Use flood fill to change all the tiles of the same type to // another type // Don't paint if target already same type // Special case: don't flood-fill doors if ((MissionGetTile(m, b->Pos) & MAP_MASKACCESS) != b->PaintType && b->PaintType != MAP_DOOR) { FloodFillData data; data.Fill = MissionFillTile; data.IsSame = MissionIsTileSame; PaintFloodFillData pData; pData.m = m; pData.fromType = MissionGetTile(m, b->Pos) & MAP_MASKACCESS; pData.toType = b->PaintType; data.data = &pData; if (CFloodFill(b->Pos, &data)) { return EDITOR_RESULT_CHANGED; } } return EDITOR_RESULT_NONE; case BRUSHTYPE_SET_PLAYER_START: if (MissionGetTile(m, b->Pos) == MAP_ROOM || MissionGetTile(m, b->Pos) == MAP_FLOOR) { m->u.Static.Start = b->Pos; return EDITOR_RESULT_CHANGED; } break; case BRUSHTYPE_ADD_ITEM: if (isMain) { if (MissionStaticTryAddItem(m, b->u.MapObject, b->Pos)) { return EDITOR_RESULT_CHANGED_AND_RELOAD; } } else { if (MissionStaticTryRemoveItemAt(m, b->Pos)) { return EDITOR_RESULT_CHANGED_AND_RELOAD; } } break; case BRUSHTYPE_ADD_WRECK: if (isMain) { const char **destructibleName = CArrayGet(&gMapObjects.Destructibles, b->u.ItemIndex); if (MissionStaticTryAddWreck( m, StrMapObject(*destructibleName), b->Pos)) { return EDITOR_RESULT_CHANGED_AND_RELOAD; } } else { if (MissionStaticTryRemoveWreckAt(m, b->Pos)) { return EDITOR_RESULT_CHANGED_AND_RELOAD; } } break; case BRUSHTYPE_ADD_CHARACTER: if (isMain) { if (MissionStaticTryAddCharacter(m, b->u.ItemIndex, b->Pos)) { return EDITOR_RESULT_CHANGED_AND_RELOAD; } } else { if (MissionStaticTryRemoveCharacterAt(m, b->Pos)) { return EDITOR_RESULT_CHANGED_AND_RELOAD; } } break; case BRUSHTYPE_ADD_OBJECTIVE: if (isMain) { if (MissionStaticTryAddObjective( m, b->u.ItemIndex, b->Index2, b->Pos)) { return EDITOR_RESULT_CHANGED_AND_RELOAD; } } else { if (MissionStaticTryRemoveObjectiveAt(m, b->Pos)) { return EDITOR_RESULT_CHANGED_AND_RELOAD; } } break; case BRUSHTYPE_ADD_KEY: if (isMain) { if (MissionStaticTryAddKey(m, b->u.ItemIndex, b->Pos)) { return EDITOR_RESULT_CHANGED_AND_RELOAD; } } else { if (MissionStaticTryRemoveKeyAt(m, b->Pos)) { return EDITOR_RESULT_CHANGED_AND_RELOAD; } } break; case BRUSHTYPE_SET_KEY: if (isMain || b->u.ItemIndex > 0) { if (MissionStaticTrySetKey(m, b->u.ItemIndex, b->Pos)) { return EDITOR_RESULT_CHANGED_AND_RELOAD; } } else { if (MissionStaticTryUnsetKeyAt(m, b->Pos)) { return EDITOR_RESULT_CHANGED_AND_RELOAD; } } break; default: assert(0 && "unknown brush type"); break; } b->IsPainting = 1; return EDITOR_RESULT_NONE; }