home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / editor / eobject.c < prev    next >
Text File  |  1998-06-08  |  32KB  |  1,137 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: f:/miner/source/main/editor/rcs/eobject.c $
  15.  * $Revision: 2.0 $
  16.  * $Author: john $
  17.  * $Date: 1995/02/27 11:35:14 $
  18.  * 
  19.  * Editor object functions.
  20.  * 
  21.  * $Log: eobject.c $
  22.  * Revision 2.0  1995/02/27  11:35:14  john
  23.  * Version 2.0! No anonymous unions, Watcom 10.0, with no need
  24.  * for bitmaps.tbl.
  25.  * 
  26.  * Revision 1.93  1995/02/22  15:09:04  allender
  27.  * remove anonymous unions from object structure
  28.  * 
  29.  * Revision 1.92  1995/01/12  12:10:32  yuan
  30.  * Added coop object capability.
  31.  * 
  32.  * Revision 1.91  1994/12/20  17:57:02  yuan
  33.  * Multiplayer object stuff.
  34.  * 
  35.  * Revision 1.90  1994/11/27  23:17:49  matt
  36.  * Made changes for new mprintf calling convention
  37.  * 
  38.  * Revision 1.89  1994/11/17  14:48:06  mike
  39.  * validation functions moved from editor to game.
  40.  * 
  41.  * Revision 1.88  1994/11/14  11:40:03  mike
  42.  * fix default robot behavior.
  43.  * 
  44.  * Revision 1.87  1994/10/25  10:51:31  matt
  45.  * Vulcan cannon powerups now contain ammo count
  46.  * 
  47.  * Revision 1.86  1994/10/23  02:11:40  matt
  48.  * Got rid of obsolete hostage_info stuff
  49.  * 
  50.  * Revision 1.85  1994/10/17  21:35:32  matt
  51.  * Added support for new Control Center/Main Reactor
  52.  * 
  53.  * Revision 1.84  1994/10/10  17:23:13  mike
  54.  * Verify that not placing too many player objects.
  55.  * 
  56.  * Revision 1.83  1994/09/24  14:15:35  mike
  57.  * Custom colored object support.
  58.  * 
  59.  * Revision 1.82  1994/09/15  22:58:12  matt
  60.  * Made new objects be oriented to their segment
  61.  * Added keypad function to flip an object upside-down
  62.  * 
  63.  * Revision 1.81  1994/09/01  10:58:41  matt
  64.  * Sizes for powerups now specified in bitmaps.tbl; blob bitmaps now plot
  65.  * correctly if width & height of bitmap are different.
  66.  * 
  67.  * Revision 1.80  1994/08/25  21:58:14  mike
  68.  * Write ObjectSelectPrevInMine and something else, I think...
  69.  * 
  70.  * Revision 1.79  1994/08/16  20:19:54  mike
  71.  * Make STILL default (from CHASE_OBJECT).
  72.  * 
  73.  * Revision 1.78  1994/08/14  23:15:45  matt
  74.  * Added animating bitmap hostages, and cleaned up vclips a bit
  75.  * 
  76.  * Revision 1.77  1994/08/13  14:58:43  matt
  77.  * Finished adding support for miscellaneous objects
  78.  * 
  79.  * Revision 1.76  1994/08/12  22:24:58  matt
  80.  * Generalized polygon objects (such as control center)
  81.  * 
  82.  * Revision 1.75  1994/08/09  16:06:11  john
  83.  * Added the ability to place players.  Made old
  84.  * Player variable be ConsoleObject.
  85.  * 
  86.  * Revision 1.74  1994/08/05  18:18:55  matt
  87.  * Made object rotation have 4x resolution, and SHIFT+rotate do old resolution.
  88.  * 
  89.  * Revision 1.73  1994/08/01  13:30:56  matt
  90.  * Made fvi() check holes in transparent walls, and changed fvi() calling
  91.  * parms to take all input data in query structure.
  92.  * 
  93.  */
  94.  
  95.  
  96. #pragma off (unreferenced)
  97. static char rcsid[] = "$Id: eobject.c 2.0 1995/02/27 11:35:14 john Exp $";
  98. #pragma on (unreferenced)
  99.  
  100. #include <stdio.h>
  101. #include <stdlib.h>
  102. #include <stdarg.h>
  103. #include <math.h>
  104. #include <string.h>
  105.  
  106. #include "inferno.h"
  107. #include "segment.h"
  108. #include "editor.h"
  109.  
  110. #include "objpage.h"
  111. #include "fix.h"
  112. #include "mono.h"
  113. #include "error.h"
  114. #include "kdefs.h"
  115. #include    "object.h"
  116. #include "polyobj.h"
  117. #include "game.h"
  118. #include "ai.h"
  119. #include "bm.h"
  120. #include "3d.h"        //    For g3_point_to_vec
  121. #include    "fvi.h"
  122.  
  123. #include "powerup.h"
  124. #include "fuelcen.h"
  125. #include "hostage.h"
  126. #include "medrobot.h"
  127. #include "player.h"
  128. #include "gameseg.h"
  129.  
  130. #define    OBJ_SCALE        (F1_0/2)
  131. #define    OBJ_DEL_SIZE    (F1_0/2)
  132.  
  133. #define ROTATION_UNIT (4096/4)
  134.  
  135. //segment        *Cur_object_seg = -1;
  136.  
  137. void show_objects_in_segment(segment *sp)
  138. {
  139.     short        objid;
  140.  
  141.     mprintf((0,"Objects in segment #%i: ",sp-Segments));
  142.  
  143.     objid = sp->objects;
  144.     while (objid != -1) {
  145.         mprintf((0,"%2i ",objid));
  146.         objid = Objects[objid].next;
  147.     }
  148.     mprintf((0,"\n"));
  149. }
  150.  
  151. //returns the number of the first object in a segment, skipping the player
  152. int get_first_object(segment *seg)
  153. {
  154.     int id;
  155.  
  156.     id = seg->objects;
  157.  
  158.     if (id == (ConsoleObject-Objects))
  159.         id = Objects[id].next;
  160.  
  161.     return id;
  162. }
  163.  
  164. //returns the number of the next object in a segment, skipping the player
  165. int get_next_object(segment *seg,int id)
  166. {
  167.     if (id==-1 || (id=Objects[id].next)==-1)
  168.         return get_first_object(seg);
  169.  
  170.     if (id == (ConsoleObject-Objects))
  171.         return get_next_object(seg,id);
  172.  
  173.     return id;
  174. }
  175.  
  176.  
  177. //@@//    ------------------------------------------------------------------------------------------------------
  178. //@@// this should be called whenever the current segment may have changed
  179. //@@//    If Cur_object_seg != Cursegp, then update various variables.
  180. //@@// this used to be called update_due_to_new_segment()
  181. //@@void ObjectUpdateCurrent(void)
  182. //@@{
  183. //@@    if (Cur_object_seg != Cursegp) {
  184. //@@        Cur_object_seg = Cursegp;
  185. //@@        Cur_object_index = get_first_object(Cur_object_seg);
  186. //@@        Update_flags |= UF_WORLD_CHANGED;
  187. //@@    }
  188. //@@
  189. //@@}
  190.  
  191. //    ------------------------------------------------------------------------------------
  192. int place_object(segment *segp, vms_vector *object_pos, int object_type)
  193. {
  194.     short objnum;
  195.     object *obj;
  196.     vms_matrix seg_matrix;
  197.  
  198.     med_extract_matrix_from_segment(segp,&seg_matrix);
  199.  
  200.     switch(ObjType[object_type]) {
  201.  
  202.         case OL_HOSTAGE:
  203.  
  204.             objnum = obj_create(OBJ_HOSTAGE, -1, 
  205.                     segp-Segments,object_pos,&seg_matrix,HOSTAGE_SIZE,
  206.                     CT_NONE,MT_NONE,RT_HOSTAGE);
  207.  
  208.             if ( objnum < 0 )
  209.                 return 0;
  210.  
  211.             obj = &Objects[objnum];
  212.  
  213.             // Fill in obj->id and other hostage info
  214.             hostage_init_info( objnum );
  215.         
  216.             obj->control_type = CT_POWERUP;
  217.             
  218.             obj->rtype.vclip_info.vclip_num = Hostage_vclip_num[ObjId[object_type]];
  219.             obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].frame_time;
  220.             obj->rtype.vclip_info.framenum = 0;
  221.  
  222.             break;
  223.  
  224.         case OL_ROBOT:
  225.  
  226.             objnum = obj_create(OBJ_ROBOT,ObjId[object_type],segp-Segments,object_pos,
  227.                 &seg_matrix,Polygon_models[Robot_info[ObjId[object_type]].model_num].rad,
  228.                 CT_AI,MT_PHYSICS,RT_POLYOBJ);
  229.  
  230.             if ( objnum < 0 )
  231.                 return 0;
  232.  
  233.             obj = &Objects[objnum];
  234.  
  235.             //Set polygon-object-specific data 
  236.  
  237.             obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num;
  238.             obj->rtype.pobj_info.subobj_flags = 0;
  239.  
  240.             //set Physics info
  241.         
  242.             obj->mtype.phys_info.mass = Robot_info[obj->id].mass;
  243.             obj->mtype.phys_info.drag = Robot_info[obj->id].drag;
  244.  
  245.             obj->mtype.phys_info.flags |= (PF_LEVELLING);
  246.  
  247.             obj->shields = Robot_info[obj->id].strength;
  248.  
  249.             {    int    hide_segment;
  250.             if (Markedsegp)
  251.                 hide_segment = Markedsegp-Segments;
  252.             else
  253.                 hide_segment = -1;
  254.             //    robots which lunge forward to attack cannot have behavior type still.
  255.             if (Robot_info[obj->id].attack_type)
  256.                 init_ai_object(obj-Objects, AIB_NORMAL, hide_segment);
  257.             else
  258.                 init_ai_object(obj-Objects, AIB_STILL, hide_segment);
  259.             }
  260.             break;
  261.  
  262.         case OL_POWERUP:
  263.  
  264.             objnum = obj_create(OBJ_POWERUP,ObjId[object_type],
  265.                     segp-Segments,object_pos,&seg_matrix,Powerup_info[ObjId[object_type]].size,
  266.                     CT_POWERUP,MT_NONE,RT_POWERUP);
  267.  
  268.             if ( objnum < 0 )
  269.                 return 0;
  270.  
  271.             obj = &Objects[objnum];
  272.  
  273.             //set powerup-specific data
  274.  
  275.             obj->rtype.vclip_info.vclip_num = Powerup_info[obj->id].vclip_num;
  276.             obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].play_time/Vclip[obj->rtype.vclip_info.vclip_num].num_frames;
  277.             obj->rtype.vclip_info.framenum = 0;
  278.  
  279.             if (obj->id == POW_VULCAN_WEAPON)
  280.                 obj->ctype.powerup_info.count = VULCAN_WEAPON_AMMO_AMOUNT;
  281.             else
  282.                 obj->ctype.powerup_info.count = 1;
  283.  
  284.             break;
  285.  
  286.         case OL_CLUTTER:
  287.         case OL_CONTROL_CENTER: 
  288.         {
  289.             int obj_type,control_type;
  290.  
  291.             if (ObjType[object_type]==OL_CONTROL_CENTER) {
  292.                 obj_type = OBJ_CNTRLCEN;
  293.                 control_type = CT_CNTRLCEN;
  294.             }
  295.             else {
  296.                 obj_type = OBJ_CLUTTER;
  297.                 control_type = CT_NONE;
  298.             }
  299.  
  300.             objnum = obj_create(obj_type,object_type,segp-Segments,object_pos,
  301.                     &seg_matrix,Polygon_models[ObjId[object_type]].rad,
  302.                     control_type,MT_NONE,RT_POLYOBJ);
  303.  
  304.             if ( objnum < 0 )
  305.                 return 0;
  306.  
  307.             obj = &Objects[objnum];
  308.  
  309.             obj->shields = ObjStrength[object_type];
  310.  
  311.             //Set polygon-object-specific data 
  312.             obj->shields = ObjStrength[object_type];
  313.             obj->rtype.pobj_info.model_num = ObjId[object_type];
  314.             obj->rtype.pobj_info.subobj_flags = 0;
  315.  
  316.             break;
  317.         }
  318.  
  319.         case OL_PLAYER:    {
  320.             objnum = obj_create(OBJ_PLAYER,ObjId[object_type],segp-Segments,object_pos,
  321.                 &seg_matrix,Polygon_models[Player_ship->model_num].rad,
  322.                 CT_NONE,MT_PHYSICS,RT_POLYOBJ);
  323.  
  324.             if ( objnum < 0 )
  325.                 return 0;
  326.  
  327.             obj = &Objects[objnum];
  328.  
  329.             //Set polygon-object-specific data 
  330.  
  331.             obj->rtype.pobj_info.model_num = Player_ship->model_num;
  332.             obj->rtype.pobj_info.subobj_flags = 0;
  333.             //for (i=0;i<MAX_SUBMODELS;i++)
  334.             //    vm_angvec_zero(&obj->rtype.pobj_info.anim_angles[i]);
  335.  
  336.             //set Physics info
  337.  
  338.             vm_vec_zero(&obj->mtype.phys_info.velocity);
  339.             obj->mtype.phys_info.mass = Player_ship->mass;
  340.             obj->mtype.phys_info.drag = Player_ship->drag;
  341.             obj->mtype.phys_info.flags |= PF_TURNROLL | PF_LEVELLING | PF_WIGGLE;
  342.             obj->shields = i2f(100);
  343.  
  344.             break;
  345.         }
  346.         default:
  347.             break;    
  348.         }
  349.  
  350.     Cur_object_index = objnum;
  351.     //Cur_object_seg = Cursegp;
  352.  
  353.     show_objects_in_segment(Cursegp);        //mprintf the objects
  354.  
  355.     Update_flags |= UF_WORLD_CHANGED;
  356.  
  357.     return 1;
  358. }
  359.  
  360. //    ------------------------------------------------------------------------------------------------------
  361. //    Count number of player objects, return value.
  362. int compute_num_players(void)
  363. {
  364.     int    i, count = 0;
  365.  
  366.     for (i=0; i<=Highest_object_index; i++)
  367.         if (Objects[i].type == OBJ_PLAYER)
  368.             count++;
  369.  
  370.     return count;
  371.  
  372. }
  373.  
  374. int ObjectMakeCoop(void)
  375. {
  376.     Assert(Cur_object_index != -1);
  377.     Assert(Cur_object_index < MAX_OBJECTS);
  378. //    Assert(Objects[Cur_object_index.type == OBJ_PLAYER);
  379.  
  380.     if (Objects[Cur_object_index].type == OBJ_PLAYER ) {
  381.         Objects[Cur_object_index].type = OBJ_COOP;
  382.         editor_status("You just made a player object COOPERATIVE");
  383.     } else
  384.         editor_status("This is not a player object");
  385.  
  386.     return 1;
  387. }
  388.  
  389. //    ------------------------------------------------------------------------------------------------------
  390. //    Place current object at center of current segment.
  391. int ObjectPlaceObject(void)
  392. {
  393.     int    old_cur_object_index;
  394.     int    rval;
  395.  
  396.     vms_vector    cur_object_loc;
  397.  
  398. #ifdef SHAREWARE
  399.     if (ObjType[Cur_robot_type] == OL_PLAYER) {
  400.         int num_players = compute_num_players();
  401.         Assert(num_players <= MAX_PLAYERS);
  402.         if (num_players == MAX_PLAYERS) {
  403.             editor_status("Can't place player object.  Already %i players.", MAX_PLAYERS);
  404.             return -1;
  405.         }
  406.     }
  407. #endif
  408.  
  409. #ifndef SHAREWARE
  410.     if (ObjType[Cur_robot_type] == OL_PLAYER) {
  411.         int num_players = compute_num_players();
  412.         Assert(num_players <= MAX_MULTI_PLAYERS);
  413.         if (num_players > MAX_PLAYERS)
  414.             editor_status("You just placed a cooperative player object");
  415.         if (num_players == MAX_MULTI_PLAYERS) {
  416.             editor_status("Can't place player object.  Already %i players.", MAX_MULTI_PLAYERS);
  417.             return -1;
  418.         }
  419.     }
  420. #endif
  421.  
  422.     //update_due_to_new_segment();
  423.     compute_segment_center(&cur_object_loc, Cursegp);
  424.  
  425.     old_cur_object_index = Cur_object_index;
  426.     rval = place_object(Cursegp, &cur_object_loc, Cur_robot_type);
  427.  
  428.     if (old_cur_object_index != Cur_object_index)
  429.         Objects[Cur_object_index].rtype.pobj_info.tmap_override = -1;
  430.  
  431.     return rval;
  432.  
  433. }
  434.  
  435. //    ------------------------------------------------------------------------------------------------------
  436. //    Place current object at center of current segment.
  437. int ObjectPlaceObjectTmap(void)
  438. {
  439.     int    rval, old_cur_object_index;
  440.     vms_vector    cur_object_loc;
  441.  
  442.     //update_due_to_new_segment();
  443.     compute_segment_center(&cur_object_loc, Cursegp);
  444.  
  445.     old_cur_object_index = Cur_object_index;
  446.     rval = place_object(Cursegp, &cur_object_loc, Cur_robot_type);
  447.  
  448.     if ((Cur_object_index != old_cur_object_index) && (Objects[Cur_object_index].render_type == RT_POLYOBJ))
  449.         Objects[Cur_object_index].rtype.pobj_info.tmap_override = CurrentTexture;
  450.     else
  451.         editor_status("Unable to apply current texture map to this object.");
  452.     
  453.     return rval;
  454. }
  455.  
  456. //    ------------------------------------------------------------------------------------------------------
  457. int ObjectSelectNextinSegment(void)
  458. {
  459.     int    id;
  460.     segment *objsegp;
  461.  
  462.  
  463.     //update_due_to_new_segment();
  464.  
  465.     //Assert(Cur_object_seg == Cursegp);
  466.  
  467.     if (Cur_object_index == -1) {
  468.         objsegp = Cursegp;
  469.         Cur_object_index = objsegp->objects;
  470.     } else {
  471.         objsegp = Cursegp;
  472.         if (Objects[Cur_object_index].segnum != Cursegp-Segments)
  473.             Cur_object_index = objsegp->objects;
  474.     }
  475.  
  476.  
  477.     //Debug: make sure current object is in current segment
  478.     for (id=objsegp->objects;(id != Cur_object_index)  && (id != -1);id=Objects[id].next);
  479.     Assert(id == Cur_object_index);        //should have found object
  480.  
  481.     //    Select the next object, wrapping back to start if we are at the end of the linked list for this segment.
  482.     if (id != -1)
  483.         Cur_object_index = get_next_object(objsegp,Cur_object_index);
  484.  
  485.     //mprintf((0,"Cur_object_index == %i\n", Cur_object_index));
  486.  
  487.     Update_flags |= UF_WORLD_CHANGED;
  488.  
  489.     return 1;
  490.  
  491. }
  492.  
  493. //Moves to next object in the mine, skipping the player
  494. int ObjectSelectNextInMine()
  495. {    int i;
  496.     for (i=0;i<MAX_OBJECTS;i++) {
  497.         Cur_object_index++;
  498.         if (Cur_object_index>= MAX_OBJECTS ) Cur_object_index= 0;
  499.  
  500.         if ((Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != (ConsoleObject-Objects)) )    {
  501.             Cursegp = &Segments[Objects[Cur_object_index ].segnum];
  502.             med_create_new_segment_from_cursegp();
  503.             //Cur_object_seg = Cursegp;
  504.             return 1;
  505.         }
  506.     }
  507.     Cur_object_index = -1;
  508.  
  509.     Update_flags |= UF_WORLD_CHANGED;
  510.  
  511.     return 0;
  512. }
  513.  
  514. //Moves to next object in the mine, skipping the player
  515. int ObjectSelectPrevInMine()
  516. {    int i;
  517.     for (i=0;i<MAX_OBJECTS;i++) {
  518.         Cur_object_index--;
  519.         if (Cur_object_index < 0 )
  520.             Cur_object_index = MAX_OBJECTS-1;
  521.  
  522.         if ((Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != (ConsoleObject-Objects)) )    {
  523.             Cursegp = &Segments[Objects[Cur_object_index ].segnum];
  524.             med_create_new_segment_from_cursegp();
  525.             //Cur_object_seg = Cursegp;
  526.             return 1;
  527.         }
  528.     }
  529.     Cur_object_index = -1;
  530.  
  531.     Update_flags |= UF_WORLD_CHANGED;
  532.  
  533.     return 0;
  534. }
  535.  
  536. //    ------------------------------------------------------------------------------------------------------
  537. //    Delete current object, if it exists.
  538. //    If it doesn't exist, reformat Matt's hard disk, even if he is in Boston.
  539. int ObjectDelete(void)
  540. {
  541.  
  542.     if (Cur_object_index != -1) {
  543.         int delete_objnum;
  544.  
  545.         delete_objnum = Cur_object_index;
  546.  
  547.         ObjectSelectNextinSegment();
  548.  
  549.         obj_delete(delete_objnum);
  550.  
  551.         if (delete_objnum == Cur_object_index)
  552.             Cur_object_index = -1;
  553.  
  554.         Update_flags |= UF_WORLD_CHANGED;
  555.     }
  556.  
  557.     return 1;
  558. }
  559.  
  560. //    -----------------------------------------------------------------------------------------------------------------
  561. //    Object has moved to another segment, (or at least poked through).
  562. //    If still in mine, that is legal, so relink into new segment.
  563. //    Return value:    0 = in mine, 1 = not in mine
  564. int move_object_within_mine(object * obj, vms_vector *newpos )
  565. {
  566.     int segnum;
  567.  
  568.     for (segnum=0;segnum <= Highest_segment_index; segnum++) {
  569.         segmasks    result = get_seg_masks(&obj->pos,segnum,0);
  570.         if (result.centermask == 0) {
  571.             int    fate;
  572.             fvi_info    hit_info;
  573.             fvi_query fq;
  574.  
  575.             //    See if the radius pokes through any wall.
  576.             fq.p0                        = &obj->pos;
  577.             fq.startseg                = obj->segnum;
  578.             fq.p1                        = newpos;
  579.             fq.rad                    = obj->size;
  580.             fq.thisobjnum            = -1;
  581.             fq.ignore_obj_list    = NULL;
  582.             fq.flags                    = 0;
  583.  
  584.             fate = find_vector_intersection(&fq,&hit_info);
  585.  
  586.             if (fate != HIT_WALL) {
  587.                 if ( segnum != obj->segnum )
  588.                     obj_relink( obj-Objects, segnum);
  589.                 obj->pos = *newpos;
  590.                 return 0;
  591.             } //else
  592.                 //mprintf((0, "Hit wall seg:side = %i:%i\n", hit_info.hit_seg, hit_info.hit_side));
  593.         }
  594.     }
  595.  
  596.     return 1;
  597.  
  598. }
  599.  
  600.  
  601. //    Return 0 if object is in expected segment, else return 1
  602. int verify_object_seg(object *objp, vms_vector *newpos)
  603. {
  604.     segmasks    result = get_seg_masks(newpos, objp->segnum, objp->size);
  605.  
  606.     if (result.facemask == 0)
  607.         return 0;
  608.     else
  609.         return move_object_within_mine(objp, newpos);
  610.  
  611. }
  612.  
  613. //    ------------------------------------------------------------------------------------------------------
  614. int    ObjectMoveForward(void)
  615. {
  616.     object *obj;
  617.     vms_vector    fvec;
  618.     vms_vector    newpos;
  619.  
  620.     if (Cur_object_index == -1) {
  621.         editor_status("No current object, cannot move.");
  622.         return 1;
  623.     }
  624.  
  625.     obj = &Objects[Cur_object_index];
  626.  
  627.     extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
  628.     vm_vec_normalize(&fvec);
  629.  
  630.     vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
  631.  
  632.     if (!verify_object_seg(obj, &newpos))
  633.         obj->pos = newpos;
  634.  
  635.     Update_flags |= UF_WORLD_CHANGED;
  636.  
  637.     return 1;
  638. }
  639.  
  640. //    ------------------------------------------------------------------------------------------------------
  641. int    ObjectMoveBack(void)
  642. {
  643.     object *obj;
  644.     vms_vector    fvec;
  645.     vms_vector    newpos;
  646.  
  647.     if (Cur_object_index == -1) {
  648.         editor_status("No current object, cannot move.");
  649.         return 1;
  650.     }
  651.  
  652.     obj = &Objects[Cur_object_index];
  653.  
  654.     extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
  655.     vm_vec_normalize(&fvec);
  656.  
  657.     vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
  658.  
  659.     if (!verify_object_seg(obj, &newpos))
  660.         obj->pos = newpos;
  661.  
  662.     Update_flags |= UF_WORLD_CHANGED;
  663.  
  664.     return 1;
  665. }
  666.  
  667. //    ------------------------------------------------------------------------------------------------------
  668. int    ObjectMoveLeft(void)
  669. {
  670.     object *obj;
  671.     vms_vector    rvec;
  672.     vms_vector    newpos;
  673.  
  674.     if (Cur_object_index == -1) {
  675.         editor_status("No current object, cannot move.");
  676.         return 1;
  677.     }
  678.  
  679.     obj = &Objects[Cur_object_index];
  680.  
  681.     extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
  682.     vm_vec_normalize(&rvec);
  683.  
  684.     vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
  685.  
  686.     if (!verify_object_seg(obj, &newpos))
  687.         obj->pos = newpos;
  688.  
  689.     Update_flags |= UF_WORLD_CHANGED;
  690.  
  691.     return 1;
  692. }
  693.  
  694. //    ------------------------------------------------------------------------------------------------------
  695. int    ObjectMoveRight(void)
  696. {
  697.     object *obj;
  698.     vms_vector    rvec;
  699.     vms_vector    newpos;
  700.  
  701.     if (Cur_object_index == -1) {
  702.         editor_status("No current object, cannot move.");
  703.         return 1;
  704.     }
  705.  
  706.     obj = &Objects[Cur_object_index];
  707.  
  708.     extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
  709.     vm_vec_normalize(&rvec);
  710.  
  711.     vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
  712.  
  713.     if (!verify_object_seg(obj, &newpos))
  714.         obj->pos = newpos;
  715.  
  716.     Update_flags |= UF_WORLD_CHANGED;
  717.  
  718.     return 1;
  719. }
  720.  
  721. //    ------------------------------------------------------------------------------------------------------
  722. int    ObjectSetDefault(void)
  723. {
  724.     //update_due_to_new_segment();
  725.  
  726.     if (Cur_object_index == -1) {
  727.         editor_status("No current object, cannot move.");
  728.         return 1;
  729.     }
  730.  
  731.     compute_segment_center(&Objects[Cur_object_index].pos, &Segments[Objects[Cur_object_index].segnum]);
  732.  
  733.     Update_flags |= UF_WORLD_CHANGED;
  734.  
  735.     return 1;
  736. }
  737.  
  738.  
  739. //    ------------------------------------------------------------------------------------------------------
  740. int    ObjectMoveUp(void)
  741. {
  742.     object *obj;
  743.     vms_vector    uvec;
  744.     vms_vector    newpos;
  745.  
  746.     if (Cur_object_index == -1) {
  747.         editor_status("No current object, cannot move.");
  748.         return 1;
  749.     }
  750.  
  751.     obj = &Objects[Cur_object_index];
  752.  
  753.     extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
  754.     vm_vec_normalize(&uvec);
  755.  
  756.     vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
  757.  
  758.     if (!verify_object_seg(obj, &newpos))
  759.         obj->pos = newpos;
  760.  
  761.     Update_flags |= UF_WORLD_CHANGED;
  762.  
  763.     return 1;
  764. }
  765.  
  766. //    ------------------------------------------------------------------------------------------------------
  767. int    ObjectMoveDown(void)
  768. {
  769.     object *obj;
  770.     vms_vector    uvec;
  771.     vms_vector    newpos;
  772.  
  773.     if (Cur_object_index == -1) {
  774.         editor_status("No current object, cannot move.");
  775.         return 1;
  776.     }
  777.  
  778.     obj = &Objects[Cur_object_index];
  779.  
  780.     extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
  781.     vm_vec_normalize(&uvec);
  782.  
  783.     vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
  784.  
  785.     if (!verify_object_seg(obj, &newpos))
  786.         obj->pos = newpos;
  787.  
  788.     Update_flags |= UF_WORLD_CHANGED;
  789.  
  790.     return 1;
  791. }
  792.  
  793. //    ------------------------------------------------------------------------------------------------------
  794. int    ObjectMakeSmaller(void)
  795. {
  796.     fix    cur_size;
  797.  
  798.     //update_due_to_new_segment();
  799.  
  800.     cur_size = Objects[Cur_object_index].size;
  801.  
  802.     cur_size -= OBJ_DEL_SIZE;
  803.     if (cur_size < OBJ_DEL_SIZE)
  804.         cur_size = OBJ_DEL_SIZE;
  805.  
  806.     Objects[Cur_object_index].size = cur_size;
  807.     
  808.     Update_flags |= UF_WORLD_CHANGED;
  809.  
  810.     return 1;
  811. }
  812.  
  813. //    ------------------------------------------------------------------------------------------------------
  814. int    ObjectMakeLarger(void)
  815. {
  816.     fix    cur_size;
  817.  
  818.     //update_due_to_new_segment();
  819.  
  820.     cur_size = Objects[Cur_object_index].size;
  821.  
  822.     cur_size += OBJ_DEL_SIZE;
  823.  
  824.     Objects[Cur_object_index].size = cur_size;
  825.     
  826.     Update_flags |= UF_WORLD_CHANGED;
  827.  
  828.     return 1;
  829. }
  830.  
  831. //    ------------------------------------------------------------------------------------------------------
  832.  
  833. int rotate_object(short objnum, int p, int b, int h)
  834. {
  835.     object *obj = &Objects[objnum];
  836.     vms_angvec ang;
  837.     vms_matrix rotmat,tempm;
  838.     
  839. //    vm_extract_angles_matrix( &ang,&obj->orient);
  840.  
  841. //    ang.p += p;
  842. //    ang.b += b;
  843. //    ang.h += h;
  844.  
  845.     ang.p = p;
  846.     ang.b = b;
  847.     ang.h = h;
  848.  
  849.     vm_angles_2_matrix(&rotmat, &ang);
  850.     vm_matrix_x_matrix(&tempm, &obj->orient, &rotmat);
  851.     obj->orient = tempm;
  852.  
  853. //   vm_angles_2_matrix(&obj->orient, &ang);
  854.  
  855.     Update_flags |= UF_WORLD_CHANGED;
  856.  
  857.     return 1;
  858. }
  859.  
  860.  
  861. void reset_object(short objnum)
  862. {
  863.     object *obj = &Objects[objnum];
  864.  
  865.     med_extract_matrix_from_segment(&Segments[obj->segnum],&obj->orient);
  866.  
  867. }
  868.  
  869.  
  870.  
  871. int ObjectResetObject()
  872. {
  873.     reset_object(Cur_object_index);
  874.  
  875.     Update_flags |= UF_WORLD_CHANGED;
  876.  
  877.     return 1;
  878. }
  879.  
  880.  
  881. int ObjectFlipObject()
  882. {
  883.     vms_matrix *m=&Objects[Cur_object_index].orient;
  884.  
  885.     vm_vec_negate(&m->uvec);
  886.     vm_vec_negate(&m->rvec);
  887.  
  888.     Update_flags |= UF_WORLD_CHANGED;
  889.  
  890.     return 1;
  891. }
  892.  
  893. int ObjectDecreaseBank()        {return rotate_object(Cur_object_index, 0, -ROTATION_UNIT, 0);}
  894. int ObjectIncreaseBank()        {return rotate_object(Cur_object_index, 0, ROTATION_UNIT, 0);}
  895. int ObjectDecreasePitch()        {return rotate_object(Cur_object_index, -ROTATION_UNIT, 0, 0);}
  896. int ObjectIncreasePitch()        {return rotate_object(Cur_object_index, ROTATION_UNIT, 0, 0);}
  897. int ObjectDecreaseHeading()    {return rotate_object(Cur_object_index, 0, 0, -ROTATION_UNIT);}
  898. int ObjectIncreaseHeading()    {return rotate_object(Cur_object_index, 0, 0, ROTATION_UNIT);}
  899.  
  900. int ObjectDecreaseBankBig()        {return rotate_object(Cur_object_index, 0, -(ROTATION_UNIT*4), 0);}
  901. int ObjectIncreaseBankBig()        {return rotate_object(Cur_object_index, 0, (ROTATION_UNIT*4), 0);}
  902. int ObjectDecreasePitchBig()        {return rotate_object(Cur_object_index, -(ROTATION_UNIT*4), 0, 0);}
  903. int ObjectIncreasePitchBig()        {return rotate_object(Cur_object_index, (ROTATION_UNIT*4), 0, 0);}
  904. int ObjectDecreaseHeadingBig()    {return rotate_object(Cur_object_index, 0, 0, -(ROTATION_UNIT*4));}
  905. int ObjectIncreaseHeadingBig()    {return rotate_object(Cur_object_index, 0, 0, (ROTATION_UNIT*4));}
  906.  
  907. //    -----------------------------------------------------------------------------------------------------
  908. //    Move object around based on clicks in 2d screen.
  909. //    Slide an object parallel to the 2d screen, to a point on a vector.
  910. //    The vector is defined by a point on the 2d screen and the eye.
  911.  
  912. //    V    =    vector from eye to 2d screen point.
  913. //    E    =    eye
  914. //    F    =    forward vector from eye
  915. //    O    =    3-space location of object
  916.  
  917. //    D    =    depth of object given forward vector F
  918. //        =    (OE dot norm(F))
  919.  
  920. //    Must solve intersection of:
  921. //        E + tV        ( equation of vector from eye through point on 2d screen)
  922. //        Fs + D        ( equation of plane parallel to 2d screen, at depth D)
  923. //        =    Fx(Ex + tVx) + Fy(Ey + tVy) + Fz(Ez + tVz) + D = 0
  924. //
  925. //                  FxEx + FyEy + FzEz - D
  926. //            t = - ----------------------
  927. //                      VxFx + VyFy + VzFz
  928.  
  929.  
  930. //void print_vec(vms_vector *vec, char *text)
  931. //{
  932. //    mprintf((0, "%10s = %9.5f %9.5f %9.5f\n", text, f2fl(vec->x), f2fl(vec->y), f2fl(vec->z)));
  933. //}
  934. //
  935. // void solve(vms_vector *result, vms_vector *E, vms_vector *V, vms_vector *O, vms_vector *F)
  936. // {
  937. //     fix    t, D;
  938. //     vms_vector    Fnorm, Vnorm;
  939. //     fix            num, denom;
  940. //     // float            test_plane;
  941. // 
  942. //     print_vec(E, "E");
  943. //     print_vec(V, "V");
  944. //     print_vec(O, "O");
  945. //     print_vec(F, "F");
  946. // 
  947. //     Fnorm = *F;    vm_vec_normalize(&Fnorm);
  948. //     Vnorm = *V;    vm_vec_normalize(&Vnorm);
  949. // 
  950. //     D = (fixmul(O->x, Fnorm.x) + fixmul(O->y, Fnorm.y) + fixmul(O->z, Fnorm.z));
  951. //     mprintf((0, "D = %9.5f\n", f2fl(D)));
  952. // 
  953. //     num = fixmul(Fnorm.x, E->x) + fixmul(Fnorm.y, E->y) + fixmul(Fnorm.z, E->z) - D;
  954. //     denom = vm_vec_dot(&Vnorm, &Fnorm);
  955. //     t = - num/denom;
  956. // 
  957. //     mprintf((0, "num = %9.5f, denom = %9.5f, t = %9.5f\n", f2fl(num), f2fl(denom), f2fl(t)));
  958. // 
  959. //     result->x = E->x + fixmul(t, Vnorm.x);
  960. //     result->y = E->y + fixmul(t, Vnorm.y);
  961. //     result->z = E->z + fixmul(t, Vnorm.z);
  962. // 
  963. //     print_vec(result, "result");
  964. // 
  965. //     // test_plane = fixmul(result->x, Fnorm.x) + fixmul(result->y, Fnorm.y) + fixmul(result->z, Fnorm.z) - D;
  966. //     // if (abs(test_plane) > .001)
  967. //     //     printf("OOPS: test_plane = %9.5f\n", test_plane);
  968. // }
  969.  
  970. void move_object_to_position(int objnum, vms_vector *newpos)
  971. {
  972.     object    *objp = &Objects[objnum];
  973.  
  974.     segmasks    result = get_seg_masks(newpos, objp->segnum, objp->size);
  975.  
  976.     if (result.facemask == 0) {
  977.         //mprintf((0, "Object #%i moved from (%7.3f %7.3f %7.3f) to (%7.3f %7.3f %7.3f)\n", objnum, f2fl(objp->pos.x), f2fl(objp->pos.y), f2fl(objp->pos.z), f2fl(newpos->x), f2fl(newpos->y), f2fl(newpos->z)));
  978.         objp->pos = *newpos;
  979.     } else {
  980.         if (verify_object_seg(&Objects[objnum], newpos)) {
  981.             int        fate, count;
  982.             int        viewer_segnum;
  983.             object    temp_viewer_obj;
  984.             fvi_query fq;
  985.             fvi_info    hit_info;
  986.             vms_vector    last_outside_pos;
  987.             vms_vector    last_inside_pos;
  988.  
  989.             temp_viewer_obj = *Viewer;
  990.             viewer_segnum = find_object_seg(&temp_viewer_obj);
  991.             temp_viewer_obj.segnum = viewer_segnum;
  992.  
  993.             //    If the viewer is outside the mine, get him in the mine!
  994.             if (viewer_segnum == -1) {
  995.                 //    While outside mine, move towards object
  996.                 count = 0;
  997.                 while (viewer_segnum == -1) {
  998.                     vms_vector    temp_vec;
  999.  
  1000.                     //mprintf((0, "[towards %7.3f %7.3f %7.3f]\n", f2fl(temp_viewer_obj.pos.x), f2fl(temp_viewer_obj.pos.y), f2fl(temp_viewer_obj.pos.z)));
  1001.                     last_outside_pos = temp_viewer_obj.pos;
  1002.  
  1003.                     vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, newpos);
  1004.                     temp_viewer_obj.pos = temp_vec;
  1005.                     viewer_segnum = find_object_seg(&temp_viewer_obj);
  1006.                     temp_viewer_obj.segnum = viewer_segnum;
  1007.  
  1008.                     if (count > 5) {
  1009.                         editor_status("Unable to move object, can't get viewer in mine.  Aborting");
  1010.                         return;
  1011.                     }
  1012.                 }
  1013.  
  1014.                 count = 0;
  1015.                 //    While inside mine, move away from object.
  1016.                 while (viewer_segnum != -1) {
  1017.  
  1018.                     vms_vector    temp_vec;
  1019.  
  1020.                     //mprintf((0, "[away %7.3f %7.3f %7.3f]\n", f2fl(temp_viewer_obj.pos.x), f2fl(temp_viewer_obj.pos.y), f2fl(temp_viewer_obj.pos.z)));
  1021.                     last_inside_pos = temp_viewer_obj.pos;
  1022.  
  1023.                     vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, &last_outside_pos);
  1024.                     temp_viewer_obj.pos = temp_vec;
  1025.                     update_object_seg(&temp_viewer_obj);
  1026.                     viewer_segnum = find_object_seg(&temp_viewer_obj);
  1027.                     temp_viewer_obj.segnum = viewer_segnum;
  1028.  
  1029.                     if (count > 5) {
  1030.                         editor_status("Unable to move object, can't get viewer back out of mine.  Aborting");
  1031.                         return;
  1032.                     }
  1033.                 }
  1034.             }
  1035.  
  1036.             fq.p0                        = &temp_viewer_obj.pos;
  1037.             fq.startseg                = temp_viewer_obj.segnum;
  1038.             fq.p1                        = newpos;
  1039.             fq.rad                    = temp_viewer_obj.size;
  1040.             fq.thisobjnum            = -1;
  1041.             fq.ignore_obj_list    = NULL;
  1042.             fq.flags                    = 0;
  1043.  
  1044.             fate = find_vector_intersection(&fq,&hit_info);
  1045.             if (fate == HIT_WALL) {
  1046.                 int    new_segnum;
  1047.  
  1048.                 //mprintf((0, "Hit wall seg:side = %i:%i, point = (%7.3f %7.3f %7.3f)\n", hit_info.hit_seg, hit_info.hit_side, f2fl(hit_info.hit_pnt.x), f2fl(hit_info.hit_pnt.y), f2fl(hit_info.hit_pnt.z)));
  1049.                 objp->pos = hit_info.hit_pnt;
  1050.                 new_segnum = find_object_seg(objp);
  1051.                 Assert(new_segnum != -1);
  1052.                 obj_relink(objp-Objects, new_segnum);
  1053.                 //mprintf((0, "Object moved from segment %i to %i\n", old_segnum, objp->segnum));
  1054.             } else {
  1055.                 editor_status("Attempted to move object out of mine.  Object not moved.");
  1056.                 //mprintf((0,"Attempted to move object out of mine.  Object not moved."));
  1057.             }
  1058.         }
  1059.     }
  1060.  
  1061.     Update_flags |= UF_WORLD_CHANGED;
  1062. }
  1063.  
  1064. void move_object_to_vector(vms_vector *vec_through_screen, fix delta_distance)
  1065. {
  1066.     vms_vector    result;
  1067.  
  1068.     vm_vec_scale_add(&result, &Viewer->pos, vec_through_screen, vm_vec_dist(&Viewer->pos,&Objects[Cur_object_index].pos)+delta_distance);
  1069.  
  1070.     move_object_to_position(Cur_object_index, &result);
  1071.  
  1072. }
  1073.  
  1074. void move_object_to_mouse_click_delta(fix delta_distance)
  1075. {
  1076.     short            xcrd,ycrd;
  1077.     vms_vector    vec_through_screen;
  1078.  
  1079.     if (Cur_object_index == -1) {
  1080.         editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
  1081.         return;
  1082.     }
  1083.  
  1084.     xcrd = GameViewBox->b1_drag_x1;
  1085.     ycrd = GameViewBox->b1_drag_y1;
  1086.  
  1087.     med_point_2_vec(&_canv_editor_game, &vec_through_screen, xcrd, ycrd);
  1088.  
  1089.     //mprintf((0, "Mouse click at %i %i, vector = %7.3f %7.3f %7.3f\n", xcrd, ycrd, f2fl(vec_through_screen.x), f2fl(vec_through_screen.y), f2fl(vec_through_screen.z)));
  1090.  
  1091.     move_object_to_vector(&vec_through_screen, delta_distance);
  1092.  
  1093. }
  1094.  
  1095. void move_object_to_mouse_click(void)
  1096. {
  1097.     move_object_to_mouse_click_delta(0);
  1098. }
  1099.  
  1100. int    ObjectMoveNearer(void)
  1101. {
  1102.     vms_vector    result;
  1103.  
  1104.     if (Cur_object_index == -1) {
  1105.         editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
  1106.         return 1;
  1107.     }
  1108.  
  1109. //    move_object_to_mouse_click_delta(-4*F1_0);        //    Move four units closer to eye
  1110.  
  1111.     vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
  1112.     vm_vec_normalize(&result);
  1113.     move_object_to_vector(&result, -4*F1_0);
  1114.  
  1115.     return 1;    
  1116. }
  1117.  
  1118. int    ObjectMoveFurther(void)
  1119. {
  1120.     vms_vector    result;
  1121.  
  1122.     if (Cur_object_index == -1) {
  1123.         editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
  1124.         return 1;
  1125.     }
  1126.  
  1127. //    move_object_to_mouse_click_delta(+4*F1_0);        //    Move four units further from eye
  1128.  
  1129.     vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
  1130.     vm_vec_normalize(&result);
  1131.     move_object_to_vector(&result, 4*F1_0);
  1132.  
  1133.     return 1;    
  1134. }
  1135.  
  1136. 
  1137.