home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / GAMES_C / DEU50.ZIP / SOURCE.ZIP / EDITOBJ.C < prev    next >
C/C++ Source or Header  |  1994-03-30  |  51KB  |  1,719 lines

  1. /*
  2.    Doom Editor Utility, by Brendon Wyber and Raphaël Quinet.
  3.  
  4.    You are allowed to use any parts of this code in another program, as
  5.    long as you give credits to the authors in the documentation and in
  6.    the program itself.  Read the file README.1ST for more information.
  7.  
  8.    This program comes with absolutely no warranty.
  9.  
  10.    EDITOBJ.C - object editing routines.
  11. */
  12.  
  13. /* the includes */
  14. #include "deu.h"
  15. #include "levels.h"
  16.  
  17.  
  18. /*
  19.    display the information about one object
  20. */
  21.  
  22. void DisplayObjectInfo( int objtype, int objnum)
  23. {
  24.    char texname[ 9];
  25.    int  tag, n;
  26.    int  x0, y0;
  27.  
  28.    switch (objtype)
  29.    {
  30.    case OBJ_THINGS:
  31.       x0 = 0;
  32.       y0 = ScrMaxY - 60;
  33.       if (InfoShown)
  34.      y0 -= 13;
  35.       DrawScreenBox3D( x0, y0, x0 + 260, y0 + 60);
  36.       if (objnum < 0)
  37.       {
  38.      DrawScreenText( x0 + 60, y0 + 20, "Use the cursor to");
  39.      DrawScreenText( x0 + 72, y0 + 30, "select a Thing  ");
  40.      break;
  41.       }
  42.       SetColor( YELLOW);
  43.       DrawScreenText( x0 + 5, y0 + 5, "Selected Thing (#%d)", objnum);
  44.       SetColor( BLACK);
  45.       DrawScreenText( -1, y0 + 20, "Coordinates:  (%d, %d)", Things[ objnum].xpos, Things[ objnum].ypos);
  46.       DrawScreenText( -1, -1, "Type:         %s", GetThingName( Things[ objnum].type));
  47.       DrawScreenText( -1, -1, "Angle:        %s", GetAngleName( Things[ objnum].angle));
  48.       DrawScreenText( -1, -1, "Appears when: %s", GetWhenName( Things[ objnum].when));
  49.       break;
  50.    case OBJ_LINEDEFS:
  51.       x0 = 0;
  52.       y0 = ScrMaxY - 80;
  53.       if (InfoShown)
  54.      y0 -= 13;
  55.       DrawScreenBox3D(   x0, y0, x0 + 218, y0 + 80);
  56.       if (objnum >= 0)
  57.       {
  58.      SetColor( YELLOW);
  59.      DrawScreenText( x0 + 5, y0 + 5, "Selected LineDef (#%d)", objnum);
  60.      SetColor( BLACK);
  61.      DrawScreenText( -1, y0 + 20, "Vertexes:    (#%d, #%d)", LineDefs[ objnum].start, LineDefs[ objnum].end);
  62.      DrawScreenText( -1, -1, "Flags:%3d    %s", LineDefs[ objnum].flags, GetLineDefFlagsName( LineDefs[ objnum].flags));
  63.      DrawScreenText( -1, -1, "Type: %3d %s", LineDefs[ objnum].type, GetLineDefTypeName( LineDefs[ objnum].type));
  64.      tag = LineDefs[ objnum].tag;
  65.      if (tag > 0)
  66.      {
  67.         for (n = 0; n < NumSectors; n++)
  68.            if (Sectors[ n].tag == tag)
  69.           break;
  70.      }
  71.      else
  72.         n = NumSectors;
  73.      if (n < NumSectors)
  74.         DrawScreenText( -1, -1, "Sector tag:  %d (#%d)", tag, n);
  75.      else
  76.         DrawScreenText( -1, -1, "Sector tag:  %d (none)", tag);
  77.      DrawScreenText( -1, -1, "1st SideDef: #%d", LineDefs[ objnum].sidedef1);
  78.      DrawScreenText( -1, -1, "2nd SideDef: #%d", LineDefs[ objnum].sidedef2);
  79.       }
  80.       else
  81.       {
  82.     SetColor( DARKGRAY);
  83.     DrawScreenText( x0 + 25, y0 + 35, "(No LineDef selected)");
  84.       }
  85.       x0 = 220;
  86.       y0 = ScrMaxY - 80;
  87.       if (InfoShown)
  88.      y0 -= 13;
  89.       DrawScreenBox3D( x0, y0, x0 + 218, y0 + 80);
  90.       if (objnum >= 0 && LineDefs[ objnum].sidedef1 >= 0)
  91.       {
  92.      SetColor( YELLOW);
  93.      DrawScreenText( x0 + 5, y0 + 5, "First SideDef (#%d)", LineDefs[ objnum].sidedef1);
  94.      SetColor( BLACK);
  95.      texname[ 8] = '\0';
  96.      strncpy( texname, SideDefs[ LineDefs[ objnum].sidedef1].tex3, 8);
  97.      DrawScreenText( -1, y0 + 20, "Normal texture: %s", texname);
  98.      strncpy( texname, SideDefs[ LineDefs[ objnum].sidedef1].tex1, 8);
  99.      DrawScreenText( -1, -1, "Upper texture:  %s", texname);
  100.      strncpy( texname, SideDefs[ LineDefs[ objnum].sidedef1].tex2, 8);
  101.      DrawScreenText( -1, -1, "Lower texture:  %s", texname);
  102.      DrawScreenText( -1, -1, "Tex. X offset:  %d", SideDefs[ LineDefs[ objnum].sidedef1].xoff);
  103.      DrawScreenText( -1, -1, "Tex. Y offset:  %d", SideDefs[ LineDefs[ objnum].sidedef1].yoff);
  104.      DrawScreenText( -1, -1, "Sector:         #%d", SideDefs[ LineDefs[ objnum].sidedef1].sector);
  105.       }
  106.       else
  107.       {
  108.     SetColor( DARKGRAY);
  109.     DrawScreenText( x0 + 25, y0 + 35, "(No first SideDef)");
  110.       }
  111.       x0 = 440;
  112.       y0 = ScrMaxY - 80;
  113.       if (InfoShown)
  114.      y0 -= 13;
  115.       DrawScreenBox3D( x0, y0, x0 + 200, y0 + 80);
  116.       if (objnum >= 0 && LineDefs[ objnum].sidedef2 >= 0)
  117.       {
  118.      SetColor( YELLOW);
  119.      DrawScreenText( x0 + 5, y0 + 5, "Second SideDef (#%d)", LineDefs[ objnum].sidedef2);
  120.      SetColor( BLACK);
  121.      texname[ 8] = '\0';
  122.      strncpy( texname, SideDefs[ LineDefs[ objnum].sidedef2].tex3, 8);
  123.      DrawScreenText( -1, y0 + 20, "Normal texture: %s", texname);
  124.      strncpy( texname, SideDefs[ LineDefs[ objnum].sidedef2].tex1, 8);
  125.      DrawScreenText( -1, -1, "Upper texture:  %s", texname);
  126.      strncpy( texname, SideDefs[ LineDefs[ objnum].sidedef2].tex2, 8);
  127.      DrawScreenText( -1, -1, "Lower texture:  %s", texname);
  128.      DrawScreenText( -1, -1, "Tex. X offset:  %d", SideDefs[ LineDefs[ objnum].sidedef2].xoff);
  129.      DrawScreenText( -1, -1, "Tex. Y offset:  %d", SideDefs[ LineDefs[ objnum].sidedef2].yoff);
  130.      DrawScreenText( -1, -1, "Sector:         #%d", SideDefs[ LineDefs[ objnum].sidedef2].sector);
  131.       }
  132.       else
  133.       {
  134.     SetColor( DARKGRAY);
  135.     DrawScreenText( x0 + 25, y0 + 35, "(No second SideDef)");
  136.       }
  137.       break;
  138.    case OBJ_VERTEXES:
  139.       x0 = 0;
  140.       y0 = ScrMaxY - 30;
  141.       if (InfoShown)
  142.      y0 -= 13;
  143.       DrawScreenBox3D( x0, y0, x0 + 220, y0 + 30);
  144.       if (objnum < 0)
  145.       {
  146.      SetColor( DARKGRAY);
  147.      DrawScreenText( x0 + 30, y0 + 12, "(No Vertex selected)");
  148.      break;
  149.       }
  150.       SetColor( YELLOW);
  151.       DrawScreenText( x0 + 5, y0 + 5, "Selected Vertex (#%d)", objnum);
  152.       SetColor( BLACK);
  153.       DrawScreenText( -1, y0 + 20, "Coordinates: (%d, %d)", Vertexes[ objnum].x, Vertexes[ objnum].y);
  154.       break;
  155.    case OBJ_SECTORS:
  156.       x0 = 0;
  157.       y0 = ScrMaxY - 90;
  158.       if (InfoShown)
  159.      y0 -= 13;
  160.       DrawScreenBox3D( x0, y0, x0 + 255, y0 + 90);
  161.       if (objnum < 0)
  162.       {
  163.     SetColor( DARKGRAY);
  164.     DrawScreenText( x0 + 48, y0 + 35, "(No Sector selected)");
  165.     break;
  166.       }
  167.       SetColor( YELLOW);
  168.       DrawScreenText( x0 + 5, y0 + 5, "Selected Sector (#%d)", objnum);
  169.       SetColor( BLACK);
  170.       DrawScreenText( -1, y0 + 20, "Floor height:    %d", Sectors[ objnum].floorh);
  171.       DrawScreenText( -1, -1, "Ceiling height:  %d", Sectors[ objnum].ceilh);
  172.       texname[ 8] = '\0';
  173.       strncpy( texname, Sectors[ objnum].floort, 8);
  174.       DrawScreenText( -1, -1, "Floor texture:   %s", texname);
  175.       strncpy( texname, Sectors[ objnum].ceilt, 8);
  176.       DrawScreenText( -1, -1, "Ceiling texture: %s", texname);
  177.       DrawScreenText( -1, -1, "Light level:     %d", Sectors[ objnum].light);
  178.       DrawScreenText( -1, -1, "Type: %3d        %s", Sectors[ objnum].special, GetSectorTypeName( Sectors[ objnum].special));
  179.       tag = Sectors[ objnum].tag;
  180.       if (tag == 0)
  181.      n = NumLineDefs;
  182.       else
  183.      for (n = 0; n < NumLineDefs; n++)
  184.         if (LineDefs[ n].tag == tag)
  185.            break;
  186.       if (n < NumLineDefs)
  187.      DrawScreenText( -1, -1, "LineDef tag:     %d (#%d)", tag, n);
  188.       else if (tag == 99 || tag == 999)
  189.      DrawScreenText( -1, -1, "LineDef tag:     %d (stairs?)", tag);
  190.       else if (tag == 666)
  191.      DrawScreenText( -1, -1, "LineDef tag:     %d (lower@end)", tag);
  192.       else
  193.      DrawScreenText( -1, -1, "LineDef tag:     %d (none)", tag);
  194.       break;
  195.    }
  196. }
  197.  
  198.  
  199.  
  200. /*
  201.    display and execute a "things" menu
  202. */
  203.  
  204. int DisplayThingsMenu( int x0, int y0, char *menutitle, ...)
  205. {
  206.    va_list args;
  207.    int val, num;
  208.    int thingid[ 30];
  209.    char *menustr[ 30];
  210.  
  211.    /* put the va_args in the menustr table */
  212.    num = 0;
  213.    va_start( args, menutitle);
  214.    while ((num < 30) && ((thingid[ num] = va_arg( args, int)) >= 0))
  215.    {
  216.       menustr[ num] = GetThingName( thingid[ num]);
  217.       num++;
  218.    }
  219.    va_end( args);
  220.  
  221.    /* display the menu */
  222.    val = DisplayMenuArray( x0, y0, menutitle, num, NULL, menustr) - 1;
  223.  
  224.    /* return the thing id, if valid */
  225.    if (val < 0 || val >= num)
  226.      return -1;
  227.    return thingid[ val];
  228. }
  229.  
  230.  
  231.  
  232. /*
  233.    display and execute a "linedef type" menu
  234. */
  235. int DisplayLineDefTypeMenu( int x0, int y0, char *menutitle, ...)
  236. {
  237.    va_list args;
  238.    int val, num;
  239.    int typeid[ 30];
  240.    char *menustr[ 30];
  241.  
  242.    /* put the va_args in the menustr table */
  243.    num = 0;
  244.    va_start( args, menutitle);
  245.    while ((num < 30) && ((typeid[ num] = va_arg( args, int)) >= 0))
  246.    {
  247.       menustr[ num] = GetLineDefTypeLongName( typeid[ num]);
  248.       num++;
  249.    }
  250.    va_end( args);
  251.  
  252.    /* display the menu */
  253.    val = DisplayMenuArray( x0, y0, menutitle, num, NULL, menustr) - 1;
  254.  
  255.    /* return the thing id, if valid */
  256.    if (val < 0 || val >= num)
  257.      return -1;
  258.    return typeid[ val];
  259. }
  260.  
  261.  
  262.  
  263. /*
  264.    ask for an object number and check for maximum valid number
  265.    (this is just like InputIntegerValue, but with a different prompt)
  266. */
  267. int InputObjectNumber( int x0, int y0, int objtype, int curobj)
  268. {
  269.    int val, key;
  270.    char prompt[ 80];
  271.  
  272.    if (UseMouse)
  273.       HideMousePointer();
  274.    sprintf( prompt, "Enter a %s number between 0 and %d:", GetObjectTypeName( objtype), GetMaxObjectNum( objtype));
  275.    if (x0 < 0)
  276.       x0 = (ScrMaxX - 25 - 8 * strlen( prompt)) / 2;
  277.    if (y0 < 0)
  278.       y0 = (ScrMaxY - 55) / 2;
  279.    DrawScreenBox3D( x0, y0, x0 + 25 + 8 * strlen( prompt), y0 + 55);
  280.    SetColor( WHITE);
  281.    DrawScreenText( x0 + 10, y0 + 8, prompt);
  282.    val = curobj;
  283.    while (((key = InputInteger( x0 + 10, y0 + 28, &val, 0, GetMaxObjectNum( objtype))) & 0x00FF) != 0x000D && (key & 0x00FF) != 0x001B)
  284.       Beep();
  285.    if (UseMouse)
  286.       ShowMousePointer();
  287.    return val;
  288. }
  289.  
  290.  
  291.  
  292. /*
  293.    ask for an object number and display a warning message
  294. */
  295. int InputObjectXRef( int x0, int y0, int objtype, Bool allownone, int curobj)
  296. {
  297.    int val, key;
  298.    char prompt[ 80];
  299.  
  300.    if (UseMouse)
  301.       HideMousePointer();
  302.    sprintf( prompt, "Enter a %s number between 0 and %d%c", GetObjectTypeName( objtype), GetMaxObjectNum( objtype), allownone ? ',' : ':');
  303.    val = strlen( prompt);
  304.    if (val < 40)
  305.       val = 40;
  306.    if (x0 < 0)
  307.       x0 = (ScrMaxX - 25 - 8 * val) / 2;
  308.    if (y0 < 0)
  309.       y0 = (ScrMaxY - (allownone ? 85 : 75)) / 2;
  310.    DrawScreenBox3D( x0, y0, x0 + 25 + 8 * val, y0 + (allownone ? 85 : 75));
  311.    SetColor( WHITE);
  312.    DrawScreenText( x0 + 10, y0 + 8, prompt);
  313.    if (allownone)
  314.       DrawScreenText( x0 + 10, y0 + 18, "or -1 for none:");
  315.    SetColor( RED);
  316.    DrawScreenText( x0 + 10, y0 + (allownone ? 60 : 50), "Warning: modifying the cross-references");
  317.    DrawScreenText( x0 + 10, y0 + (allownone ? 70 : 60), "between some objects may crash the game.");
  318.    val = curobj;
  319.    while (((key = InputInteger( x0 + 10, y0 + (allownone ? 38 : 28), &val, allownone ? -1 : 0, GetMaxObjectNum( objtype))) & 0x00FF) != 0x000D && (key & 0x00FF) != 0x001B)
  320.       Beep();
  321.    if (UseMouse)
  322.       ShowMousePointer();
  323.    return val;
  324. }
  325.  
  326.  
  327.  
  328. /*
  329.    ask for two vertex numbers and check for maximum valid number
  330. */
  331. int Input2VertexNumbers( int x0, int y0, char *prompt1, int *v1, int *v2)
  332. {
  333.    int  val, key;
  334.    int  maxlen, first;
  335.    Bool ok;
  336.    char prompt2[ 80];
  337.  
  338.    if (UseMouse)
  339.       HideMousePointer();
  340.    sprintf( prompt2, "Enter two numbers between 0 and %d:", NumVertexes - 1);
  341.    if (strlen( prompt1) > strlen( prompt2))
  342.       maxlen = strlen( prompt1);
  343.    else
  344.       maxlen = strlen( prompt2);
  345.    if (x0 < 0)
  346.       x0 = (ScrMaxX - 25 - 8 * maxlen) / 2;
  347.    if (y0 < 0)
  348.       y0 = (ScrMaxY - 75) / 2;
  349.    DrawScreenBox3D( x0, y0, x0 + 25 + 8 * maxlen, y0 + 75);
  350.    DrawScreenText( x0 + 10, y0 + 36, "From this Vertex");
  351.    DrawScreenText( x0 + 180, y0 + 36, "To this Vertex");
  352.    SetColor( WHITE);
  353.    DrawScreenText( x0 + 10, y0 + 8, prompt1);
  354.    DrawScreenText( x0 + 10, y0 + 18, prompt2);
  355.    first = TRUE;
  356.    key = 0;
  357.    for (;;)
  358.    {
  359.       ok = TRUE;
  360.       DrawScreenBox3D( x0 + 10, y0 + 48, x0 + 71, y0 + 61);
  361.       if (*v1 < 0 || *v1 >= NumVertexes)
  362.       {
  363.      SetColor( DARKGRAY);
  364.      ok = FALSE;
  365.       }
  366.       DrawScreenText( x0 + 14, y0 + 51, "%d", *v1);
  367.       DrawScreenBox3D( x0 + 180, y0 + 48, x0 + 241, y0 + 61);
  368.       if (*v2 < 0 || *v2 >= NumVertexes)
  369.       {
  370.      SetColor( DARKGRAY);
  371.      ok = FALSE;
  372.       }
  373.       DrawScreenText( x0 + 184, y0 + 51, "%d", *v2);
  374.       if (first)
  375.      key = InputInteger( x0 + 10, y0 + 48, v1, 0, NumVertexes - 1);
  376.       else
  377.      key = InputInteger( x0 + 180, y0 + 48, v2, 0, NumVertexes - 1);
  378.       if ((key & 0xFF00) == 0x4B00 || (key & 0xFF00) == 0x4D00 || (key & 0x00FF) == 0x0009 || (key & 0xFF00) == 0x0F00)
  379.      first = !first;
  380.       else if ((key & 0x00FF) == 0x001B)
  381.      break;
  382.       else if ((key & 0x00FF) == 0x000D)
  383.       {
  384.      if (first)
  385.         first = FALSE;
  386.      else if (ok)
  387.         break;
  388.      else
  389.         Beep();
  390.       }
  391.       else
  392.      Beep();
  393.    }
  394.    if (UseMouse)
  395.       ShowMousePointer();
  396.    return ((key & 0x00FF) == 0x000D);
  397. }
  398.  
  399.  
  400.  
  401. /*
  402.    edit an object or a group of objects
  403. */
  404.  
  405. void EditObjectsInfo( int x0, int y0, int objtype, SelPtr obj)
  406. {
  407.    char  *menustr[ 30];
  408.    char   texname[ 9];
  409.    int    n, val;
  410.    SelPtr cur, sdlist;
  411.  
  412.    if (obj == NULL)
  413.       return;
  414.    switch (objtype)
  415.    {
  416.    case OBJ_THINGS:
  417.       for (n = 0; n < 6; n++)
  418.      menustr[ n] = GetMemory( 60);
  419.       sprintf( menustr[ 5], "Edit Thing #%d", obj->objnum);
  420.       sprintf( menustr[ 0], "Change Type          (Current: %s)", GetThingName( Things[ obj->objnum].type));
  421.       sprintf( menustr[ 1], "Change Angle         (Current: %s)", GetAngleName( Things[ obj->objnum].angle));
  422.       sprintf( menustr[ 2], "Change When Appears  (Current: %s)", GetWhenName( Things[ obj->objnum].when));
  423.       sprintf( menustr[ 3], "Change X position    (Current: %d)", Things[ obj->objnum].xpos);
  424.       sprintf( menustr[ 4], "Change Y position    (Current: %d)", Things[ obj->objnum].ypos);
  425.       val = DisplayMenuArray( x0, y0, menustr[ 5], 5, NULL, menustr);
  426.       for (n = 0; n < 6; n++)
  427.      free( menustr[ n]);
  428.       switch (val)
  429.       {
  430.       case 1:
  431.      switch (DisplayMenu( x0 + 42, y0 + 34, "Select Class",
  432.                   "Player",
  433.                   "Enemy",
  434.                   "Weapon",
  435.                   "Bonus",
  436.                   "Decoration",
  437.                   "Decoration (light sources)",
  438.                   "Decoration (dead bodies)",
  439.                   "Decoration (hanging bodies)",
  440.                   "Teleport landing",
  441.                   "(Enter a decimal value)",
  442.                   NULL))
  443.      {
  444.      case 1:
  445.         val = DisplayThingsMenu( x0 + 84, y0 + 68, "Select Start Position Type",
  446.                      THING_PLAYER1,
  447.                      THING_PLAYER2,
  448.                      THING_PLAYER3,
  449.                      THING_PLAYER4,
  450.                      THING_DEATHMATCH,
  451.                      -1);
  452.         break;
  453.  
  454.      case 2:
  455.         val = DisplayThingsMenu( x0 + 84, y0 + 78, "Select Enemy",
  456.                      THING_TROOPER,
  457.                      THING_SARGEANT,
  458.                      THING_IMP,
  459.                      THING_DEMON,
  460.                      THING_SPECTOR,
  461.                      THING_BARON,
  462.                      THING_LOSTSOUL,
  463.                      THING_CACODEMON,
  464.                      THING_CYBERDEMON,
  465.                      THING_SPIDERBOSS,
  466.                      -1);
  467.         break;
  468.  
  469.      case 3:
  470.         val = DisplayThingsMenu( x0 + 84, y0 + 88, "Select Weapon",
  471.                      THING_SHOTGUN,
  472.                      THING_CHAINGUN,
  473.                      THING_LAUNCHER,
  474.                      THING_PLASMAGUN,
  475.                      THING_CHAINSAW,
  476.                      THING_SHELLS,
  477.                      THING_AMMOCLIP,
  478.                      THING_ROCKET,
  479.                      THING_ENERGYCELL,
  480.                      THING_BFG9000,
  481.                      THING_SHELLBOX,
  482.                      THING_AMMOBOX,
  483.                      THING_ROCKETBOX,
  484.                      THING_ENERGYPACK,
  485.                      THING_BACKPACK,
  486.                      -1);
  487.         break;
  488.  
  489.      case 4:
  490.         val = DisplayThingsMenu( x0 + 84, y0 + 98, "Select Bonus",
  491.                      THING_REDCARD,
  492.                      THING_YELLOWCARD,
  493.                      THING_BLUECARD,
  494.                      THING_REDSKULLKEY,
  495.                      THING_YELLOWSKULLKEY,
  496.                      THING_BLUESKULLKEY,
  497.                      THING_ARMBONUS1,
  498.                      THING_GREENARMOR,
  499.                      THING_BLUEARMOR,
  500.                      THING_HLTBONUS1,
  501.                      THING_STIMPACK,
  502.                      THING_MEDKIT,
  503.                      THING_SOULSPHERE,
  504.                      THING_BLURSPHERE,
  505.                      THING_MAP,
  506.                      THING_RADSUIT,
  507.                      THING_LITEAMP,
  508.                      THING_BESERK,
  509.                      THING_INVULN,
  510.                      -1);
  511.         break;
  512.  
  513.      case 5:
  514.         val = DisplayThingsMenu( x0 + 84, y0 + 108, "Select Decoration",
  515.                      THING_BARREL,
  516.                      THING_TECHCOLUMN,
  517.                      THING_TGREENPILLAR,
  518.                      THING_TREDPILLAR,
  519.                      THING_SGREENPILLAR,
  520.                      THING_SREDPILLAR,
  521.                      THING_PILLARHEART,
  522.                      THING_PILLARSKULL,
  523.                      THING_EYEINSYMBOL,
  524.                      THING_BROWNSTUB,
  525.                      THING_GREYTREE,
  526.                      THING_BROWNTREE,
  527.                      -1);
  528.         break;
  529.  
  530.      case 6:
  531.         val = DisplayThingsMenu( x0 + 84, y0 + 118, "Select Decoration",
  532.                      THING_CANDLE,
  533.                      THING_LAMP,
  534.                      THING_CANDELABRA,
  535.                      THING_TBLUETORCH,
  536.                      THING_TGREENTORCH,
  537.                      THING_TREDTORCH,
  538.                      THING_SBLUETORCH,
  539.                      THING_SGREENTORCH,
  540.                      THING_SREDTORCH,
  541.                      -1);
  542.         break;
  543.  
  544.      case 7:
  545.         val = DisplayThingsMenu( x0 + 84, y0 + 128, "Select Decoration",
  546.                      THING_DEADPLAYER,
  547.                      THING_DEADTROOPER,
  548.                      THING_DEADSARGEANT,
  549.                      THING_DEADIMP,
  550.                      THING_DEADDEMON,
  551.                      THING_DEADCACODEMON,
  552.                      THING_BONES,
  553.                      THING_BONES2,
  554.                      THING_POOLOFBLOOD,
  555.                      THING_SKULLTOPPOLE,
  556.                      THING_HEADSKEWER,
  557.                      THING_PILEOFSKULLS,
  558.                      THING_IMPALEDBODY,
  559.                      THING_IMPALEDBODY2,
  560.                      THING_SKULLSINFLAMES,
  561.                      -1);
  562.         break;
  563.  
  564.      case 8:
  565.         val = DisplayThingsMenu( x0 + 84, y0 + 138, "Select Decoration",
  566.                      THING_HANGINGSWAYING,
  567.                      THING_HANGINGARMSOUT,
  568.                      THING_HANGINGONELEG,
  569.                      THING_HANGINGTORSO,
  570.                      THING_HANGINGLEG,
  571.                      THING_HANGINGSWAYING2,
  572.                      THING_HANGINGARMSOUT2,
  573.                      THING_HANGINGONELEG2,
  574.                      THING_HANGINGTORSO2,
  575.                      THING_HANGINGLEG2,
  576.                      -1);
  577.         break;
  578.  
  579.      case 9:
  580.         val = THING_TELEPORT;
  581.         break;
  582.  
  583.      case 10:
  584.         val = InputIntegerValue( x0 + 84, y0 + 158, 0, 9999, Things[ obj->objnum].type);
  585.         break;
  586.  
  587.      default:
  588.         Beep();
  589.         return;
  590.      }
  591.      if (val >= 0)
  592.      {
  593.         for (cur = obj; cur; cur = cur->next)
  594.            Things[ cur->objnum].type = val;
  595.         MadeChanges = TRUE;
  596.      }
  597.      break;
  598.  
  599.       case 2:
  600.      switch (DisplayMenu( x0 + 42, y0 + 44, "Select Angle",
  601.                   "North",
  602.                   "NorthEast",
  603.                   "East",
  604.                   "SouthEast",
  605.                   "South",
  606.                   "SouthWest",
  607.                   "West",
  608.                   "NorthWest",
  609.                   NULL))
  610.      {
  611.      case 1:
  612.         for (cur = obj; cur; cur = cur->next)
  613.            Things[ cur->objnum].angle = 90;
  614.         MadeChanges = TRUE;
  615.         break;
  616.      case 2:
  617.         for (cur = obj; cur; cur = cur->next)
  618.            Things[ cur->objnum].angle = 45;
  619.         MadeChanges = TRUE;
  620.         break;
  621.      case 3:
  622.         for (cur = obj; cur; cur = cur->next)
  623.            Things[ cur->objnum].angle = 0;
  624.         MadeChanges = TRUE;
  625.         break;
  626.      case 4:
  627.         for (cur = obj; cur; cur = cur->next)
  628.            Things[ cur->objnum].angle = 315;
  629.         MadeChanges = TRUE;
  630.         break;
  631.      case 5:
  632.         for (cur = obj; cur; cur = cur->next)
  633.            Things[ cur->objnum].angle = 270;
  634.         MadeChanges = TRUE;
  635.         break;
  636.      case 6:
  637.         for (cur = obj; cur; cur = cur->next)
  638.            Things[ cur->objnum].angle = 225;
  639.         MadeChanges = TRUE;
  640.         break;
  641.      case 7:
  642.         for (cur = obj; cur; cur = cur->next)
  643.            Things[ cur->objnum].angle = 180;
  644.         MadeChanges = TRUE;
  645.         break;
  646.      case 8:
  647.         for (cur = obj; cur; cur = cur->next)
  648.            Things[ cur->objnum].angle = 135;
  649.         MadeChanges = TRUE;
  650.         break;
  651.      }
  652.      break;
  653.  
  654.       case 3:
  655.      val = DisplayMenu( x0 + 42, y0 + 54, "Choose the difficulty level(s)",
  656.                 "D12          (Easy only)",
  657.                 "D3           (Medium only)",
  658.                 "D12, D3      (Easy and Medium)",
  659.                 "D45          (Hard only)",
  660.                 "D12, D45     (Easy and Hard)",
  661.                 "D3, D45      (Medium and Hard)",
  662.                 "D12, D3, D45 (Easy, Medium, Hard)",
  663.                 "Toggle \"Deaf/Ambush\" bit",
  664.                 "Toggle \"Multi-player only\" bit",
  665.                 "(Enter a decimal value)",
  666.                 NULL);
  667.      switch (val)
  668.      {
  669.      case 1:
  670.      case 2:
  671.      case 3:
  672.      case 4:
  673.      case 5:
  674.      case 6:
  675.      case 7:
  676.         for (cur = obj; cur; cur = cur->next)
  677.            Things[ cur->objnum].when = val;
  678.         MadeChanges = TRUE;
  679.         break;
  680.      case 8:
  681.         for (cur = obj; cur; cur = cur->next)
  682.            Things[ cur->objnum].when ^= 0x08;
  683.         MadeChanges = TRUE;
  684.         break;
  685.      case 9:
  686.         for (cur = obj; cur; cur = cur->next)
  687.            Things[ cur->objnum].when ^= 0x10;
  688.         MadeChanges = TRUE;
  689.         break;
  690.      case 10:
  691.         val = InputIntegerValue( x0 + 84, y0 + 158, 1, 31, Things[ obj->objnum].when);
  692.         if (val > 0)
  693.         {
  694.            for (cur = obj; cur; cur = cur->next)
  695.           Things[ cur->objnum].when = val;
  696.            MadeChanges = TRUE;
  697.         }
  698.         break;
  699.      }
  700.      break;
  701.  
  702.       case 4:
  703.      val = InputIntegerValue( x0 + 42, y0 + 64, MapMinX, MapMaxX, Things[ obj->objnum].xpos);
  704.      if (val >= MapMinX)
  705.      {
  706.         n = val - Things[ obj->objnum].xpos;
  707.         for (cur = obj; cur; cur = cur->next)
  708.            Things[ cur->objnum].xpos += n;
  709.         MadeChanges = TRUE;
  710.      }
  711.      break;
  712.  
  713.       case 5:
  714.      val = InputIntegerValue( x0 + 42, y0 + 74, MapMinY, MapMaxY, Things[ obj->objnum].ypos);
  715.      if (val >= MapMinY)
  716.      {
  717.         n = val - Things[ obj->objnum].ypos;
  718.         for (cur = obj; cur; cur = cur->next)
  719.            Things[ cur->objnum].ypos += n;
  720.         MadeChanges = TRUE;
  721.      }
  722.      break;
  723.       }
  724.       break;
  725.  
  726.    case OBJ_VERTEXES:
  727.       for (n = 0; n < 3; n++)
  728.      menustr[ n] = GetMemory( 60);
  729.       sprintf( menustr[ 2], "Edit Vertex #%d", obj->objnum);
  730.       sprintf( menustr[ 0], "Change X position (Current: %d)", Vertexes[ obj->objnum].x);
  731.       sprintf( menustr[ 1], "Change Y position (Current: %d)", Vertexes[ obj->objnum].y);
  732.       val = DisplayMenuArray( 0, 30, menustr[ 2], 2, NULL, menustr);
  733.       for (n = 0; n < 3; n++)
  734.      free( menustr[ n]);
  735.       switch (val)
  736.       {
  737.       case 1:
  738.      val = InputIntegerValue( x0 + 42, y0 + 34, MapMinX, MapMaxX, Vertexes[ obj->objnum].x);
  739.      if (val >= MapMinX)
  740.      {
  741.         n = val - Vertexes[ obj->objnum].x;
  742.         for (cur = obj; cur; cur = cur->next)
  743.            Vertexes[ cur->objnum].x += n;
  744.         MadeChanges = TRUE;
  745.         MadeMapChanges = TRUE;
  746.      }
  747.      break;
  748.  
  749.       case 2:
  750.      val = InputIntegerValue( x0 + 42, y0 + 44, MapMinY, MapMaxY, Vertexes[ obj->objnum].y);
  751.      if (val >= MapMinY)
  752.      {
  753.         n = val - Vertexes[ obj->objnum].y;
  754.         for (cur = obj; cur; cur = cur->next)
  755.            Vertexes[ cur->objnum].y += n;
  756.         MadeChanges = TRUE;
  757.         MadeMapChanges = TRUE;
  758.      }
  759.      break;
  760.       }
  761.       break;
  762.  
  763.    case OBJ_LINEDEFS:
  764.       switch (DisplayMenu( x0, y0, "Choose the object to edit:",
  765.                "Edit the LineDef",
  766.                (LineDefs[ obj->objnum].sidedef1 >= 0) ? "Edit the 1st SideDef" : "Add a 1st SideDef",
  767.                (LineDefs[ obj->objnum].sidedef2 >= 0) ? "Edit the 2nd SideDef" : "Add a 2nd SideDef",
  768.                NULL))
  769.       {
  770.       case 1:
  771.      for (n = 0; n < 8; n++)
  772.         menustr[ n] = GetMemory( 60);
  773.      sprintf( menustr[ 7], "Edit LineDef #%d", obj->objnum);
  774.      sprintf( menustr[ 0], "Change Flags            (Current: %d)", LineDefs[ obj->objnum].flags);
  775.      sprintf( menustr[ 1], "Change Type             (Current: %d)", LineDefs[ obj->objnum].type);
  776.      sprintf( menustr[ 2], "Change Sector tag       (Current: %d)", LineDefs[ obj->objnum].tag);
  777.      sprintf( menustr[ 3], "Change Starting Vertex  (Current: #%d)", LineDefs[ obj->objnum].start);
  778.      sprintf( menustr[ 4], "Change Ending Vertex    (Current: #%d)", LineDefs[ obj->objnum].end);
  779.      sprintf( menustr[ 5], "Change 1st SideDef ref. (Current: #%d)", LineDefs[ obj->objnum].sidedef1);
  780.      sprintf( menustr[ 6], "Change 2nd SideDef ref. (Current: #%d)", LineDefs[ obj->objnum].sidedef2);
  781.      val = DisplayMenuArray( x0 + 42, y0 + 34, menustr[ 7], 7, NULL, menustr);
  782.      for (n = 0; n < 8; n++)
  783.         free( menustr[ n]);
  784.      switch (val)
  785.      {
  786.      case 1:
  787.         val = DisplayMenu( x0 + 84, y0 + 68, "Toggle the flags:",
  788.                    GetLineDefFlagsLongName(0x01),
  789.                    GetLineDefFlagsLongName(0x02),
  790.                    GetLineDefFlagsLongName(0x04),
  791.                    GetLineDefFlagsLongName(0x08),
  792.                    GetLineDefFlagsLongName(0x10),
  793.                    GetLineDefFlagsLongName(0x20),
  794.                    GetLineDefFlagsLongName(0x40),
  795.                    GetLineDefFlagsLongName(0x80),
  796.                    GetLineDefFlagsLongName(0x100),
  797.                    "(Enter a decimal value)",
  798.                    NULL);
  799.         if (val >= 1 && val <= 9)
  800.         {
  801.            for (cur = obj; cur; cur = cur->next)
  802.           LineDefs[ cur->objnum].flags ^= 0x01 << (val - 1);
  803.            MadeChanges = TRUE;
  804.         }
  805.         else if (val == 10)
  806.         {
  807.            val = InputIntegerValue( x0 + 126, y0 + 182, 0, 511, LineDefs[ obj->objnum].flags);
  808.            if (val >= 0)
  809.            {
  810.           for (cur = obj; cur; cur = cur->next)
  811.              LineDefs[ cur->objnum].flags = val;
  812.           MadeChanges = TRUE;
  813.            }
  814.         }
  815.         break;
  816.      case 2:
  817.         switch (DisplayMenu( x0 + 84, y0 + 78, "Choose a LineDef type:",
  818.                  "Normal",
  819.                  "Doors...",
  820.                  "Ceilings...",
  821.                  "Floors...",
  822.                  "Lifts & Moving things...",
  823.                  "Special...",
  824.                  "(Enter a decimal value)",
  825.                  NULL))
  826.         {
  827.         case 1:
  828.            val = 0;
  829.            break;
  830.         case 2:
  831.            val = DisplayLineDefTypeMenu( x0 + 126, y0 + 122, NULL, /* Doors */
  832.                          1, 26, 27, 28, 63, 29, 90, 31, 32, 34, 33, 103, 86, 2, 46, 42, 75, 3, 76, 16,
  833.                          -1);
  834.            break;
  835.         case 3:
  836.            val = DisplayLineDefTypeMenu( x0 + 126, y0 + 132, NULL, /* Ceilings */
  837.                          41, 44, 40,
  838.                          -1);
  839.            break;
  840.         case 4:
  841.            val = DisplayLineDefTypeMenu( x0 + 126, y0 + 142, NULL, /* Floors */
  842.                          102, 70, 23, 9, 21, 82, 19, 38, 37, 98, 36, 18, 20, 14, 5, 22, 59, 30, 58, 91, 56,
  843.                          -1);
  844.            break;
  845.         case 5:
  846.            val = DisplayLineDefTypeMenu( x0 + 126, y0 + 152, NULL, /* Lifts & Moving things */
  847.                          62, 88, 10, 77, 73, 74, 87, 89, 7, 8,
  848.                          -1);
  849.            break;
  850.         case 6:
  851.            val = DisplayLineDefTypeMenu( x0 + 126, y0 + 162, NULL, /* Special */
  852.                          48, 11, 52, 51, 97, 39, 13, 35, 80, 104,
  853.                          -1);
  854.            break;
  855.         case 7:
  856.            val = InputIntegerValue( x0 + 126, y0 + 172, 0, 255, LineDefs[ obj->objnum].type);
  857.            break;
  858.         default:
  859.            val = -1;
  860.         }
  861.         if (val >= 0)
  862.         {
  863.            for (cur = obj; cur; cur = cur->next)
  864.           LineDefs[ cur->objnum].type = val;
  865.            MadeChanges = TRUE;
  866.         }
  867.         break;
  868.      case 3:
  869.         val = InputIntegerValue( x0 + 84, y0 + 88, 0, 255, LineDefs[ obj->objnum].tag);
  870.         if (val >= 0)
  871.         {
  872.            for (cur = obj; cur; cur = cur->next)
  873.           LineDefs[ cur->objnum].tag = val;
  874.            MadeChanges = TRUE;
  875.         }
  876.         break;
  877.      case 4:
  878.         val = InputObjectXRef( x0 + 84, y0 + 98, OBJ_VERTEXES, FALSE, LineDefs[ obj->objnum].start);
  879.         if (val >= 0)
  880.         {
  881.            for (cur = obj; cur; cur = cur->next)
  882.           LineDefs[ cur->objnum].start = val;
  883.            MadeChanges = TRUE;
  884.            MadeMapChanges = TRUE;
  885.         }
  886.         break;
  887.      case 5:
  888.         val = InputObjectXRef( x0 + 84, y0 + 108, OBJ_VERTEXES, FALSE, LineDefs[ obj->objnum].end);
  889.         if (val >= 0)
  890.         {
  891.            for (cur = obj; cur; cur = cur->next)
  892.           LineDefs[ cur->objnum].end = val;
  893.            MadeChanges = TRUE;
  894.            MadeMapChanges = TRUE;
  895.         }
  896.         break;
  897.      case 6:
  898.         val = InputObjectXRef( x0 + 84, y0 + 118, OBJ_SIDEDEFS, FALSE, LineDefs[ obj->objnum].sidedef1);
  899.         if (val >= 0)
  900.         {
  901.            for (cur = obj; cur; cur = cur->next)
  902.           LineDefs[ cur->objnum].sidedef1 = val;
  903.            MadeChanges = TRUE;
  904.            MadeMapChanges = TRUE;
  905.         }
  906.         break;
  907.      case 7:
  908.         val = InputObjectXRef( x0 + 84, y0 + 128, OBJ_SIDEDEFS, TRUE, LineDefs[ obj->objnum].sidedef2);
  909.         if (val >= -1)
  910.         {
  911.            for (cur = obj; cur; cur = cur->next)
  912.           LineDefs[ cur->objnum].sidedef2 = val;
  913.            MadeChanges = TRUE;
  914.            MadeMapChanges = TRUE;
  915.         }
  916.         break;
  917.      }
  918.      break;
  919.  
  920.       /* edit or add the first SideDef */
  921.       case 2:
  922.      if (LineDefs[ obj->objnum].sidedef1 >= 0)
  923.      {
  924.         /* build a new selection list with the first SideDefs */
  925.         objtype = OBJ_SIDEDEFS;
  926.         sdlist = NULL;
  927.         for (cur = obj; cur; cur = cur->next)
  928.            if (LineDefs[ cur->objnum].sidedef1 >= 0)
  929.           SelectObject( &sdlist, LineDefs[ cur->objnum].sidedef1);
  930.      }
  931.      else
  932.      {
  933.         /* add a new first SideDef */
  934.         for (cur = obj; cur; cur = cur->next)
  935.            if (LineDefs[ cur->objnum].sidedef1 == -1)
  936.            {
  937.           InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  938.           LineDefs[ cur->objnum].sidedef1 = NumSideDefs - 1;
  939.            }
  940.         break;
  941.      }
  942.      /* no break here */
  943.  
  944.       /* edit or add the second SideDef */
  945.       case 3:
  946.      if (objtype != OBJ_SIDEDEFS)
  947.      {
  948.         if (LineDefs[ obj->objnum].sidedef2 >= 0)
  949.         {
  950.            /* build a new selection list with the second (or first) SideDefs */
  951.            objtype = OBJ_SIDEDEFS;
  952.            sdlist = NULL;
  953.            for (cur = obj; cur; cur = cur->next)
  954.           if (LineDefs[ cur->objnum].sidedef2 >= 0)
  955.              SelectObject( &sdlist, LineDefs[ cur->objnum].sidedef2);
  956.           else if (LineDefs[ cur->objnum].sidedef1 >= 0)
  957.              SelectObject( &sdlist, LineDefs[ cur->objnum].sidedef1);
  958.         }
  959.         else
  960.         {
  961.            /* add a new second (or first) SideDef */
  962.            for (cur = obj; cur; cur = cur->next)
  963.           if (LineDefs[ cur->objnum].sidedef1 == -1)
  964.           {
  965.              InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  966.              LineDefs[ cur->objnum].sidedef1 = NumSideDefs - 1;
  967.           }
  968.           else if (LineDefs[ cur->objnum].sidedef2 == -1)
  969.           {
  970.              InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  971.              LineDefs[ cur->objnum].sidedef2 = NumSideDefs - 1;
  972.              LineDefs[ cur->objnum].flags = 4;
  973.              strncpy( SideDefs[ NumSideDefs - 1].tex3, "-", 8);
  974.              strncpy( SideDefs[ LineDefs[ cur->objnum].sidedef1].tex3, "-", 8);
  975.           }
  976.            break;
  977.         }
  978.      }
  979.      for (n = 0; n < 7; n++)
  980.         menustr[ n] = GetMemory( 60);
  981.      sprintf( menustr[ 6], "Edit SideDef #%d", sdlist->objnum);
  982.      texname[ 8] = '\0';
  983.      strncpy( texname, SideDefs[ sdlist->objnum].tex3, 8);
  984.      sprintf( menustr[ 0], "Change Normal Texture   (Current: %s)", texname);
  985.      strncpy( texname, SideDefs[ sdlist->objnum].tex1, 8);
  986.      sprintf( menustr[ 1], "Change Upper texture    (Current: %s)", texname);
  987.      strncpy( texname, SideDefs[ sdlist->objnum].tex2, 8);
  988.      sprintf( menustr[ 2], "Change Lower texture    (Current: %s)", texname);
  989.      sprintf( menustr[ 3], "Change Texture X offset (Current: %d)", SideDefs[ sdlist->objnum].xoff);
  990.      sprintf( menustr[ 4], "Change Texture Y offset (Current: %d)", SideDefs[ sdlist->objnum].yoff);
  991.      sprintf( menustr[ 5], "Change Sector ref.      (Current: #%d)", SideDefs[ sdlist->objnum].sector);
  992.      val = DisplayMenuArray( x0 + 42, y0 + 54, menustr[ 6], 6, NULL, menustr);
  993.      for (n = 0; n < 7; n++)
  994.         free( menustr[ n]);
  995.      switch (val)
  996.      {
  997.      case 1:
  998.         strncpy( texname, SideDefs[ sdlist->objnum].tex3, 8);
  999.         ChooseWallTexture( x0 + 84, y0 + 88, "Choose a wall texture", NumWTexture, WTexture, texname);
  1000.         if (strlen(texname) > 0)
  1001.         {
  1002.            for (cur = sdlist; cur; cur = cur->next)
  1003.           if (cur->objnum >= 0)
  1004.              strncpy( SideDefs[ cur->objnum].tex3, texname, 8);
  1005.            MadeChanges = TRUE;
  1006.         }
  1007.         break;
  1008.      case 2:
  1009.         strncpy( texname, SideDefs[ sdlist->objnum].tex1, 8);
  1010.         ChooseWallTexture( x0 + 84, y0 + 98, "Choose a wall texture", NumWTexture, WTexture, texname);
  1011.         if (strlen(texname) > 0)
  1012.         {
  1013.            for (cur = sdlist; cur; cur = cur->next)
  1014.           if (cur->objnum >= 0)
  1015.              strncpy( SideDefs[ cur->objnum].tex1, texname, 8);
  1016.            MadeChanges = TRUE;
  1017.         }
  1018.         break;
  1019.      case 3:
  1020.         strncpy( texname, SideDefs[ sdlist->objnum].tex2, 8);
  1021.         ChooseWallTexture( x0 + 84, y0 + 108, "Choose a wall texture", NumWTexture, WTexture, texname);
  1022.         if (strlen(texname) > 0)
  1023.         {
  1024.            for (cur = sdlist; cur; cur = cur->next)
  1025.           if (cur->objnum >= 0)
  1026.              strncpy( SideDefs[ cur->objnum].tex2, texname, 8);
  1027.            MadeChanges = TRUE;
  1028.         }
  1029.         break;
  1030.      case 4:
  1031.         val = InputIntegerValue( x0 + 84, y0 + 118, -100, 100, SideDefs[ sdlist->objnum].xoff);
  1032.         if (val >= -100)
  1033.         {
  1034.            for (cur = sdlist; cur; cur = cur->next)
  1035.           if (cur->objnum >= 0)
  1036.              SideDefs[ cur->objnum].xoff = val;
  1037.            MadeChanges = TRUE;
  1038.         }
  1039.         break;
  1040.      case 5:
  1041.         val = InputIntegerValue( x0 + 84, y0 + 128, -100, 100, SideDefs[ sdlist->objnum].yoff);
  1042.         if (val >= -100)
  1043.         {
  1044.            for (cur = sdlist; cur; cur = cur->next)
  1045.           if (cur->objnum >= 0)
  1046.              SideDefs[ cur->objnum].yoff = val;
  1047.            MadeChanges = TRUE;
  1048.         }
  1049.         break;
  1050.      case 6:
  1051.         val = InputObjectXRef( x0 + 84, y0 + 138, OBJ_SECTORS, FALSE, SideDefs[ sdlist->objnum].sector);
  1052.         if (val >= 0)
  1053.         {
  1054.            for (cur = sdlist; cur; cur = cur->next)
  1055.           if (cur->objnum >= 0)
  1056.              SideDefs[ cur->objnum].sector = val;
  1057.            MadeChanges = TRUE;
  1058.         }
  1059.         break;
  1060.      }
  1061.      ForgetSelection( &sdlist);
  1062.      break;
  1063.  
  1064.       }
  1065.       break;
  1066.  
  1067.    case OBJ_SECTORS:
  1068.       for (n = 0; n < 8; n++)
  1069.      menustr[ n] = GetMemory( 60);
  1070.       sprintf( menustr[ 7], "Edit Sector #%d", obj->objnum);
  1071.       sprintf( menustr[ 0], "Change Floor height     (Current: %d)", Sectors[ obj->objnum].floorh);
  1072.       sprintf( menustr[ 1], "Change Ceiling height   (Current: %d)", Sectors[ obj->objnum].ceilh);
  1073.       texname[ 8] = '\0';
  1074.       strncpy( texname, Sectors[ obj->objnum].floort, 8);
  1075.       sprintf( menustr[ 2], "Change Floor texture    (Current: %s)", texname);
  1076.       strncpy( texname, Sectors[ obj->objnum].ceilt, 8);
  1077.       sprintf( menustr[ 3], "Change Ceiling texture  (Current: %s)", texname);
  1078.       sprintf( menustr[ 4], "Change Light level      (Current: %d)", Sectors[ obj->objnum].light);
  1079.       sprintf( menustr[ 5], "Change Type             (Current: %d)", Sectors[ obj->objnum].special);
  1080.       sprintf( menustr[ 6], "Change LineDef tag      (Current: %d)", Sectors[ obj->objnum].tag);
  1081.       val = DisplayMenuArray( x0, y0, menustr[ 7], 7, NULL, menustr);
  1082.       for (n = 0; n < 8; n++)
  1083.      free( menustr[ n]);
  1084.       switch (val)
  1085.       {
  1086.       case 1:
  1087.      val = InputIntegerValue( x0 + 42, y0 + 34, -511, 511, Sectors[ obj->objnum].floorh);
  1088.      if (val >= -511)
  1089.      {
  1090.         for (cur = obj; cur; cur = cur->next)
  1091.            Sectors[ cur->objnum].floorh = val;
  1092.         MadeChanges = TRUE;
  1093.      }
  1094.      break;
  1095.       case 2:
  1096.      val = InputIntegerValue( x0 + 42, y0 + 44, -511, 511, Sectors[ obj->objnum].ceilh);
  1097.      if (val >= -511)
  1098.      {
  1099.         for (cur = obj; cur; cur = cur->next)
  1100.            Sectors[ cur->objnum].ceilh = val;
  1101.         MadeChanges = TRUE;
  1102.      }
  1103.      break;
  1104.       case 3:
  1105.      strncpy( texname, Sectors[ obj->objnum].floort, 8);
  1106.      ChooseFloorTexture( x0 + 42, y0 + 54, "Choose a floor texture", NumFTexture, FTexture, texname);
  1107.      if (strlen(texname) > 0)
  1108.      {
  1109.         for (cur = obj; cur; cur = cur->next)
  1110.            strncpy( Sectors[ cur->objnum].floort, texname, 8);
  1111.         MadeChanges = TRUE;
  1112.      }
  1113.      break;
  1114.       case 4:
  1115.      strncpy( texname, Sectors[ obj->objnum].ceilt, 8);
  1116.      ChooseFloorTexture( x0 + 42, y0 + 64, "Choose a ceiling texture", NumFTexture, FTexture, texname);
  1117.      if (strlen(texname) > 0)
  1118.      {
  1119.         for (cur = obj; cur; cur = cur->next)
  1120.            strncpy( Sectors[ cur->objnum].ceilt, texname, 8);
  1121.         MadeChanges = TRUE;
  1122.      }
  1123.      break;
  1124.       case 5:
  1125.      val = InputIntegerValue( x0 + 42, y0 + 74, 0, 255, Sectors[ obj->objnum].light);
  1126.      if (val >= 0)
  1127.      {
  1128.         for (cur = obj; cur; cur = cur->next)
  1129.            Sectors[ cur->objnum].light = val;
  1130.         MadeChanges = TRUE;
  1131.      }
  1132.      break;
  1133.       case 6:
  1134.      val = DisplayMenu( x0 + 42, y0 + 84, "Choose a special behaviour",
  1135.                 GetSectorTypeLongName(0),
  1136.                 GetSectorTypeLongName(1),
  1137.                 GetSectorTypeLongName(2),
  1138.                 GetSectorTypeLongName(3),
  1139.                 GetSectorTypeLongName(4),
  1140.                 GetSectorTypeLongName(5),
  1141.                 GetSectorTypeLongName(7),
  1142.                 GetSectorTypeLongName(8),
  1143.                 GetSectorTypeLongName(9),
  1144.                 GetSectorTypeLongName(10),
  1145.                 GetSectorTypeLongName(11),
  1146.                 GetSectorTypeLongName(12),
  1147.                 GetSectorTypeLongName(13),
  1148.                 GetSectorTypeLongName(14),
  1149.                 GetSectorTypeLongName(16),
  1150.                 "(Enter a decimal value)",
  1151.                 NULL);
  1152.      switch (val)
  1153.      {
  1154.      case 1:
  1155.      case 2:
  1156.      case 3:
  1157.      case 4:
  1158.      case 5:
  1159.      case 6:
  1160.         for (cur = obj; cur; cur = cur->next)
  1161.            Sectors[ cur->objnum].special = val - 1;
  1162.         MadeChanges = TRUE;
  1163.         break;
  1164.      case 7:
  1165.      case 8:
  1166.      case 9:
  1167.      case 10:
  1168.      case 11:
  1169.      case 12:
  1170.      case 13:
  1171.      case 14:
  1172.         for (cur = obj; cur; cur = cur->next)
  1173.            Sectors[ cur->objnum].special = val;
  1174.         MadeChanges = TRUE;
  1175.         break;
  1176.      case 15:
  1177.         for (cur = obj; cur; cur = cur->next)
  1178.            Sectors[ cur->objnum].special = 16;
  1179.         MadeChanges = TRUE;
  1180.         break;
  1181.      case 16:
  1182.         val = InputIntegerValue( x0 + 84, y0 + 208, 0, 255, Sectors[ obj->objnum].special);
  1183.         if (val >= 0)
  1184.         {
  1185.            for (cur = obj; cur; cur = cur->next)
  1186.           Sectors[ cur->objnum].special = val;
  1187.            MadeChanges = TRUE;
  1188.         }
  1189.         break;
  1190.      }
  1191.      break;
  1192.       case 7:
  1193.      val = InputIntegerValue( x0 + 42, y0 + 94, 0, 999, Sectors[ obj->objnum].tag);
  1194.      if (val >= 0)
  1195.      {
  1196.         for (cur = obj; cur; cur = cur->next)
  1197.            Sectors[ cur->objnum].tag = val;
  1198.         MadeChanges = TRUE;
  1199.      }
  1200.      break;
  1201.       }
  1202.       break;
  1203.    }
  1204. }
  1205.  
  1206.  
  1207.  
  1208. /*
  1209.    move a group of objects to a new position
  1210.    (must be called with obj = NULL before moving the objects)
  1211. */
  1212.  
  1213. Bool MoveObjectsToCoords( int objtype, SelPtr obj, int newx, int newy, int grid)
  1214. {
  1215.    int        n, m;
  1216.    int        dx, dy;
  1217.    SelPtr     cur, vertices;
  1218.    static int refx, refy;
  1219.  
  1220.    if (grid > 0)
  1221.    {
  1222.       newx = (newx + grid / 2) & ~(grid - 1);
  1223.       newy = (newy + grid / 2) & ~(grid - 1);
  1224.    }
  1225.    /* only update the reference point? */
  1226.    if (obj == NULL)
  1227.    {
  1228.       refx = newx;
  1229.       refy = newy;
  1230.       return TRUE;
  1231.    }
  1232.    /* compute the displacement */
  1233.    dx = newx - refx;
  1234.    dy = newy - refy;
  1235.    /* nothing to do? */
  1236.    if (dx == 0 && dy == 0)
  1237.       return FALSE;
  1238.  
  1239.    /* move the object(s) */
  1240.    switch (objtype)
  1241.    {
  1242.       case OBJ_THINGS:
  1243.      for (cur = obj; cur; cur = cur->next)
  1244.         Things[ cur->objnum].xpos += dx;
  1245.      for (cur = obj; cur; cur = cur->next)
  1246.         Things[ cur->objnum].ypos += dy;
  1247.      refx = newx;
  1248.      refy = newy;
  1249.      MadeChanges = TRUE;
  1250.      break;
  1251.       case OBJ_VERTEXES:
  1252.      for (cur = obj; cur; cur = cur->next)
  1253.         Vertexes[ cur->objnum].x += dx;
  1254.      for (cur = obj; cur; cur = cur->next)
  1255.         Vertexes[ cur->objnum].y += dy;
  1256.      refx = newx;
  1257.      refy = newy;
  1258.      MadeChanges = TRUE;
  1259.      MadeMapChanges = TRUE;
  1260.      break;
  1261.       case OBJ_LINEDEFS:
  1262.      vertices = NULL;
  1263.      for (cur = obj; cur; cur = cur->next)
  1264.      {
  1265.         if (!IsSelected( vertices, LineDefs[ cur->objnum].start))
  1266.            SelectObject( &vertices, LineDefs[ cur->objnum].start);
  1267.         if (!IsSelected( vertices, LineDefs[ cur->objnum].end))
  1268.            SelectObject( &vertices, LineDefs[ cur->objnum].end);
  1269.      }
  1270.      MoveObjectsToCoords( OBJ_VERTEXES, vertices, newx, newy, grid);
  1271.      ForgetSelection( &vertices);
  1272.      break;
  1273.       case OBJ_SECTORS:
  1274.      vertices = NULL;
  1275.      for (cur = obj; cur; cur = cur->next)
  1276.      {
  1277.         for (n = 0; n < NumLineDefs; n++)
  1278.            if (((m = LineDefs[ n].sidedef1) >= 0 && SideDefs[ m].sector == cur->objnum)
  1279.         || ((m = LineDefs[ n].sidedef2) >= 0 && SideDefs[ m].sector == cur->objnum))
  1280.            {
  1281.           if (!IsSelected( vertices, LineDefs[ n].start))
  1282.              SelectObject( &vertices, LineDefs[ n].start);
  1283.           if (!IsSelected( vertices, LineDefs[ n].end))
  1284.              SelectObject( &vertices, LineDefs[ n].end);
  1285.            }
  1286.      }
  1287.      MoveObjectsToCoords( OBJ_VERTEXES, vertices, newx, newy, grid);
  1288.      ForgetSelection( &vertices);
  1289.      break;
  1290.    }
  1291.    return TRUE;
  1292. }
  1293.  
  1294.  
  1295.  
  1296. /*
  1297.    ... Yuck!
  1298. */
  1299. int Input2Numbers( int x0, int y0, char *name1, char *name2, int v1max, int v2max, int *v1, int *v2)
  1300. {
  1301.    int  val, key;
  1302.    int  maxlen, first;
  1303.    Bool ok;
  1304.    char prompt[ 80];
  1305.  
  1306.    if (UseMouse)
  1307.       HideMousePointer();
  1308.    sprintf( prompt, "Give the %s and %s for the new Sector:", name1, name2);
  1309.    maxlen = strlen( prompt);
  1310.    if (x0 < 0)
  1311.       x0 = (ScrMaxX - 25 - 8 * maxlen) / 2;
  1312.    if (y0 < 0)
  1313.       y0 = (ScrMaxY - 75) / 2;
  1314.    DrawScreenBox3D( x0, y0, x0 + 25 + 8 * maxlen, y0 + 75);
  1315.    DrawScreenText( x0 + 10, y0 + 26, name1);
  1316.    DrawScreenText( x0 + 180, y0 + 26, name2);
  1317.    DrawScreenText( x0 + 10, y0 + 58, "(0-%d)", v1max);
  1318.    DrawScreenText( x0 + 180, y0 + 58, "(0-%d)", v2max);
  1319.    SetColor( WHITE);
  1320.    DrawScreenText( x0 + 10, y0 + 8, prompt);
  1321.    first = TRUE;
  1322.    key = 0;
  1323.    for (;;)
  1324.    {
  1325.       ok = TRUE;
  1326.       DrawScreenBox3D( x0 + 10, y0 + 38, x0 + 71, y0 + 51);
  1327.       if (*v1 < 0 || *v1 > v1max)
  1328.       {
  1329.      SetColor( DARKGRAY);
  1330.      ok = FALSE;
  1331.       }
  1332.       DrawScreenText( x0 + 14, y0 + 41, "%d", *v1);
  1333.       DrawScreenBox3D( x0 + 180, y0 + 38, x0 + 241, y0 + 51);
  1334.       if (*v2 < 0 || *v2 > v2max)
  1335.       {
  1336.      SetColor( DARKGRAY);
  1337.      ok = FALSE;
  1338.       }
  1339.       DrawScreenText( x0 + 184, y0 + 41, "%d", *v2);
  1340.       if (first)
  1341.      key = InputInteger( x0 + 10, y0 + 38, v1, 0, v1max);
  1342.       else
  1343.      key = InputInteger( x0 + 180, y0 + 38, v2, 0, v2max);
  1344.       if ((key & 0xFF00) == 0x4B00 || (key & 0xFF00) == 0x4D00 || (key & 0x00FF) == 0x0009 || (key & 0xFF00) == 0x0F00)
  1345.      first = !first;
  1346.       else if ((key & 0x00FF) == 0x001B)
  1347.      break;
  1348.       else if ((key & 0x00FF) == 0x000D)
  1349.       {
  1350.      if (first)
  1351.         first = FALSE;
  1352.      else if (ok)
  1353.         break;
  1354.      else
  1355.         Beep();
  1356.       }
  1357.       else
  1358.      Beep();
  1359.    }
  1360.    if (UseMouse)
  1361.       ShowMousePointer();
  1362.    return ((key & 0x00FF) == 0x000D);
  1363. }
  1364.  
  1365.  
  1366.  
  1367. /*
  1368.    find a free tag number
  1369. */
  1370.  
  1371. int FindFreeTag()
  1372. {
  1373.    int  tag, n;
  1374.    Bool ok;
  1375.  
  1376.    tag = 1;
  1377.    ok = FALSE;
  1378.    while (! ok)
  1379.    {
  1380.       ok = TRUE;
  1381.       for (n = 0; n < NumLineDefs; n++)
  1382.      if (LineDefs[ n].tag == tag)
  1383.      {
  1384.         ok = FALSE;
  1385.         break;
  1386.      }
  1387.       if (ok)
  1388.      for (n = 0; n < NumSectors; n++)
  1389.         if (Sectors[ n].tag == tag)
  1390.         {
  1391.            ok = FALSE;
  1392.            break;
  1393.         }
  1394.       tag++;
  1395.    }
  1396.    return tag;
  1397. }
  1398.  
  1399.  
  1400.  
  1401. /*
  1402.    insert a standard object at given position
  1403. */
  1404.  
  1405. void InsertStandardObject( int x0, int y0, int xpos, int ypos)
  1406. {
  1407.    int sector;
  1408.    int choice;
  1409.    int n;
  1410.    int a, b;
  1411.  
  1412.    sector = GetCurObject( OBJ_SECTORS, xpos, ypos, xpos, ypos);
  1413.    if (sector >= 0)
  1414.       choice = DisplayMenu( x0, y0, "Insert a pre-defined object (inside a Sector)",
  1415.                 "Rectangle",
  1416.                 "Polygon (N sides)",
  1417.                 "Door |",
  1418.                 "Door -",
  1419.                 "Stairs |",
  1420.                 "Stairs -",
  1421.                 "Hidden stairs |",
  1422.                 "Hidden stairs -",
  1423.                 NULL);
  1424.    else
  1425.       choice = DisplayMenu( x0, y0, "Insert a pre-defined object (outside)",
  1426.                 "Rectangle",
  1427.                 "Polygon (N sides)",
  1428.                 NULL);
  1429.    /* !!!! Should also check for overlapping objects (sectors) !!!! */
  1430.    switch (choice)
  1431.    {
  1432.    case 1:
  1433.       a = 256;
  1434.       b = 128;
  1435.       if (Input2Numbers( -1, -1, "Width", "Height", 2000, 2000, &a, &b))
  1436.       {
  1437.      xpos = xpos - a / 2;
  1438.      ypos = ypos - b / 2;
  1439.      InsertObject( OBJ_VERTEXES, -1, xpos, ypos);
  1440.      InsertObject( OBJ_VERTEXES, -1, xpos + a, ypos);
  1441.      InsertObject( OBJ_VERTEXES, -1, xpos + a, ypos + b);
  1442.      InsertObject( OBJ_VERTEXES, -1, xpos, ypos + b);
  1443.      if (sector < 0)
  1444.         InsertObject( OBJ_SECTORS, -1, 0, 0);
  1445.      for (n = 0; n < 4; n++)
  1446.      {
  1447.         InsertObject( OBJ_LINEDEFS, -1, 0, 0);
  1448.         InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  1449.         LineDefs[ NumLineDefs - 1].sidedef1 = NumSideDefs - 1;
  1450.         if (sector >= 0)
  1451.            SideDefs[ NumSideDefs - 1].sector = sector;
  1452.      }
  1453.      if (sector >= 0)
  1454.      {
  1455.         LineDefs[ NumLineDefs - 4].start = NumVertexes - 4;
  1456.         LineDefs[ NumLineDefs - 4].end = NumVertexes - 3;
  1457.         LineDefs[ NumLineDefs - 3].start = NumVertexes - 3;
  1458.         LineDefs[ NumLineDefs - 3].end = NumVertexes - 2;
  1459.         LineDefs[ NumLineDefs - 2].start = NumVertexes - 2;
  1460.         LineDefs[ NumLineDefs - 2].end = NumVertexes - 1;
  1461.         LineDefs[ NumLineDefs - 1].start = NumVertexes - 1;
  1462.         LineDefs[ NumLineDefs - 1].end = NumVertexes - 4;
  1463.      }
  1464.      else
  1465.      {
  1466.         LineDefs[ NumLineDefs - 4].start = NumVertexes - 1;
  1467.         LineDefs[ NumLineDefs - 4].end = NumVertexes - 2;
  1468.         LineDefs[ NumLineDefs - 3].start = NumVertexes - 2;
  1469.         LineDefs[ NumLineDefs - 3].end = NumVertexes - 3;
  1470.         LineDefs[ NumLineDefs - 2].start = NumVertexes - 3;
  1471.         LineDefs[ NumLineDefs - 2].end = NumVertexes - 4;
  1472.         LineDefs[ NumLineDefs - 1].start = NumVertexes - 4;
  1473.         LineDefs[ NumLineDefs - 1].end = NumVertexes - 1;
  1474.      }
  1475.       }
  1476.       break;
  1477.    case 2:
  1478.       a = 8;
  1479.       b = 128;
  1480.       if (Input2Numbers( -1, -1, "Number of sides", "Radius", 32, 2000, &a, &b))
  1481.       {
  1482.      InsertPolygonVertices( xpos, ypos, a, b);
  1483.      if (sector < 0)
  1484.         InsertObject( OBJ_SECTORS, -1, 0, 0);
  1485.      for (n = 0; n < a; n++)
  1486.      {
  1487.         InsertObject( OBJ_LINEDEFS, -1, 0, 0);
  1488.         InsertObject( OBJ_SIDEDEFS, -1, 0, 0);
  1489.         LineDefs[ NumLineDefs - 1].sidedef1 = NumSideDefs - 1;
  1490.         if (sector >= 0)
  1491.            SideDefs[ NumSideDefs - 1].sector = sector;
  1492.      }
  1493.      if (sector >= 0)
  1494.      {
  1495.         LineDefs[ NumLineDefs - 1].start = NumVertexes - 1;
  1496.         LineDefs[ NumLineDefs - 1].end = NumVertexes - a;
  1497.         for (n = 2; n <= a; n++)
  1498.         {
  1499.            LineDefs[ NumLineDefs - n].start = NumVertexes - n;
  1500.            LineDefs[ NumLineDefs - n].end = NumVertexes - n + 1;
  1501.         }
  1502.      }
  1503.      else
  1504.      {
  1505.         LineDefs[ NumLineDefs - 1].start = NumVertexes - a;
  1506.         LineDefs[ NumLineDefs - 1].end = NumVertexes - 1;
  1507.         for (n = 2; n <= a; n++)
  1508.         {
  1509.            LineDefs[ NumLineDefs - n].start = NumVertexes - n + 1;
  1510.            LineDefs[ NumLineDefs - n].end = NumVertexes - n;
  1511.         }
  1512.      }
  1513.       }
  1514.       break;
  1515.    case 3:
  1516.    case 4:
  1517.    case 5:
  1518.    case 6:
  1519.    case 7:
  1520.    case 8:
  1521.      NotImplemented();
  1522.      break;
  1523.    }
  1524. }
  1525.  
  1526.  
  1527.  
  1528. /*
  1529.    menu of miscellaneous operations
  1530. */
  1531.  
  1532. void MiscOperations( int x0, int y0, int objtype, SelPtr obj)
  1533. {
  1534.    char   temp[ 80];
  1535.    int    val, n, m;
  1536.    SelPtr cur;
  1537.  
  1538.    /* check if obj != NULL */
  1539.    if (obj && objtype == OBJ_VERTEXES)
  1540.    {
  1541.       val = DisplayMenu( x0, y0, "Misc. Operations",
  1542.              "Find first free tag number",
  1543.              "Check if all Sectors are closed",
  1544.              "Check all cross-references",
  1545.              "Delete Vertex and join LineDefs",
  1546.              NULL);
  1547.    }
  1548.    else if (obj && objtype == OBJ_LINEDEFS)
  1549.    {
  1550.       val = DisplayMenu( x0, y0, "Misc. Operations",
  1551.              "Find first free tag number",
  1552.              "Check if all Sectors are closed",
  1553.              "Check all cross-references",
  1554.              "Split LineDef (add new Vertex)",
  1555.              "Flip LineDef",
  1556.              "Align textures",
  1557.              NULL);
  1558.    }
  1559.    else
  1560.    {
  1561.       val = DisplayMenu( x0, y0, "Misc. Operations",
  1562.              "Find first free tag number",
  1563.              "Check if all Sectors are closed",
  1564.              "Check all cross-references",
  1565.              NULL);
  1566.    }
  1567.    switch (val)
  1568.    {
  1569.    case 1:
  1570.       sprintf( temp, "First free tag number: %d", FindFreeTag());
  1571.       Notify( -1, -1, temp, NULL);
  1572.       break;
  1573.    case 2:
  1574.       NotImplemented();
  1575.       break;
  1576.    case 3:
  1577.       for (n = 0; n < NumLineDefs; n++)
  1578.      if (LineDefs[ n].sidedef1 < 0)
  1579.      {
  1580.         Beep();
  1581.         sprintf( temp, "ERROR: LineDef %d has no first SideDef!", n);
  1582.         Notify( -1, -1, temp, "Doom will crash if you play with this level.");
  1583.         return;
  1584.      }
  1585.       cur = NULL;
  1586.       for (n = 0; n < NumVertexes; n++)
  1587.      SelectObject( &cur, n);
  1588.       for (n = 0; n < NumLineDefs; n++)
  1589.       {
  1590.      m = LineDefs[ n].start;
  1591.      if (m >= 0)
  1592.         UnSelectObject( &cur, m);
  1593.      m = LineDefs[ n].end;
  1594.      if (m >= 0)
  1595.         UnSelectObject( &cur, m);
  1596.      continue;
  1597.       }
  1598.       if (cur && (Expert || Confirm(-1, -1, "Some Vertices are not bound to any LineDef", "Do you want to delete these unused Vertices?")))
  1599.      DeleteObjects( OBJ_VERTEXES, &cur);
  1600.       cur = NULL;
  1601.       for (n = 0; n < NumSideDefs; n++)
  1602.      SelectObject( &cur, n);
  1603.       for (n = 0; n < NumLineDefs; n++)
  1604.       {
  1605.      m = LineDefs[ n].sidedef1;
  1606.      if (m >= 0)
  1607.         UnSelectObject( &cur, m);
  1608.      m = LineDefs[ n].sidedef2;
  1609.      if (m >= 0)
  1610.         UnSelectObject( &cur, m);
  1611.      continue;
  1612.       }
  1613.       if (cur && (Expert || Confirm(-1, -1, "Some SideDefs are not bound to any LineDef", "Do you want to delete these unused SideDefs?")))
  1614.      DeleteObjects( OBJ_SECTORS, &cur);
  1615.       cur = NULL;
  1616.       for (n = 0; n < NumSectors; n++)
  1617.      SelectObject( &cur, n);
  1618.       for (n = 0; n < NumLineDefs; n++)
  1619.       {
  1620.      m = LineDefs[ n].sidedef1;
  1621.      if (m >= 0 && SideDefs[ m].sector >= 0)
  1622.         UnSelectObject( &cur, SideDefs[ m].sector);
  1623.      m = LineDefs[ n].sidedef2;
  1624.      if (m >= 0 && SideDefs[ m].sector >= 0)
  1625.         UnSelectObject( &cur, SideDefs[ m].sector);
  1626.      continue;
  1627.       }
  1628.       if (cur && (Expert || Confirm(-1, -1, "Some Sectors are not bound to any SideDef", "Do you want to delete these unused Sectors?")))
  1629.      DeleteObjects( OBJ_SECTORS, &cur);
  1630.       break;
  1631.    case 4:
  1632.       if (objtype == OBJ_VERTEXES)
  1633.       {
  1634.      while (obj)
  1635.      {
  1636.         cur = obj;
  1637.         obj = obj->next;
  1638.         n = -1;
  1639.         m = -1;
  1640.         for (val = 0; val < NumLineDefs; val++)
  1641.         {
  1642.            if (LineDefs[ val].start == cur->objnum)
  1643.            {
  1644.           if (n == -1)
  1645.              n = val;
  1646.           else
  1647.              n = -2;
  1648.            }
  1649.            if (LineDefs[ val].end == cur->objnum)
  1650.            {
  1651.           if (m == -1)
  1652.              m = val;
  1653.           else
  1654.              m = -2;
  1655.            }
  1656.         }
  1657.         if (n < 0 || m < 0)
  1658.         {
  1659.            Beep();
  1660.            sprintf(temp, "Cannot delete Vertex %d and join the LineDefs", cur->objnum);
  1661.            Notify( -1, -1, temp, "The Vertex must be the start of one LineDef and the end of another one");
  1662.            continue;
  1663.         }
  1664.         LineDefs[ m].end = LineDefs[ n].end;
  1665.         DeleteObject( OBJ_LINEDEFS, n);
  1666.         DeleteObject( OBJ_VERTEXES, cur->objnum);
  1667.      }
  1668.       }
  1669.       else
  1670.       {
  1671.      for (cur = obj; cur; cur = cur->next)
  1672.      {
  1673.         n = LineDefs[ cur->objnum].start;
  1674.         m = LineDefs[ cur->objnum].end;
  1675.         InsertObject( OBJ_VERTEXES, -1, (Vertexes[ n].x + Vertexes[ m].x) / 2, (Vertexes[ n].y + Vertexes[ m].y) / 2);
  1676.         InsertObject( OBJ_LINEDEFS, cur->objnum, 0, 0);
  1677.         LineDefs[ cur->objnum].end = NumVertexes - 1;
  1678.         LineDefs[ NumLineDefs - 1].start = NumVertexes - 1;
  1679.         n = LineDefs[ cur->objnum].sidedef1;
  1680.         if (n >= 0)
  1681.         {
  1682.            InsertObject( OBJ_SIDEDEFS, n, 0, 0);
  1683.            LineDefs[ NumLineDefs - 1].sidedef1 = NumSideDefs - 1;
  1684.         }
  1685.         n = LineDefs[ cur->objnum].sidedef2;
  1686.         if (n >= 0)
  1687.         {
  1688.            InsertObject( OBJ_SIDEDEFS, n, 0, 0);
  1689.            LineDefs[ NumLineDefs - 1].sidedef2 = NumSideDefs - 1;
  1690.         }
  1691.      }
  1692.       }
  1693.       MadeChanges = TRUE;
  1694.       MadeMapChanges = TRUE;
  1695.       break;
  1696.    case 5:
  1697.       for (cur = obj; cur; cur = cur->next)
  1698.       {
  1699.      val = LineDefs[ cur->objnum].end;
  1700.      LineDefs[ cur->objnum].end = LineDefs[ cur->objnum].start;
  1701.      LineDefs[ cur->objnum].start = val;
  1702.      val = LineDefs[ cur->objnum].sidedef1;
  1703.      LineDefs[ cur->objnum].sidedef1 = LineDefs[ cur->objnum].sidedef2;
  1704.      LineDefs[ cur->objnum].sidedef2 = val;
  1705.       }
  1706.       MadeChanges = TRUE;
  1707.       MadeMapChanges = TRUE;
  1708.       break;
  1709.    case 6:
  1710.       NotImplemented();
  1711.       MadeChanges = TRUE;
  1712.       break;
  1713.    }
  1714. }
  1715.  
  1716.  
  1717.  
  1718. /* end of file */
  1719.