1 /* $Id: eobject.c,v 1.6 2005-03-31 09:38:53 chris Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Editor object functions.
22 static char rcsid[] = "$Id: eobject.c,v 1.6 2005-03-31 09:38:53 chris Exp $";
49 #include "3d.h" // For g3_point_to_vec
60 #define OBJ_SCALE (F1_0/2)
61 #define OBJ_DEL_SIZE (F1_0/2)
63 #define ROTATION_UNIT (4096/4)
65 //segment *Cur_object_seg = -1;
67 void show_objects_in_segment(segment *sp)
71 mprintf((0,"Objects in segment #%i: ",sp-Segments));
75 mprintf((0,"%2i ",objid));
76 objid = Objects[objid].next;
81 //returns the number of the first object in a segment, skipping the player
82 int get_first_object(segment *seg)
88 if (id == OBJECT_NUMBER(ConsoleObject))
89 id = Objects[id].next;
94 //returns the number of the next object in a segment, skipping the player
95 int get_next_object(segment *seg,int id)
97 if (id==-1 || (id=Objects[id].next)==-1)
98 return get_first_object(seg);
100 if (id == OBJECT_NUMBER(ConsoleObject))
101 return get_next_object(seg,id);
107 //@@// ------------------------------------------------------------------------------------------------------
108 //@@// this should be called whenever the current segment may have changed
109 //@@// If Cur_object_seg != Cursegp, then update various variables.
110 //@@// this used to be called update_due_to_new_segment()
111 //@@void ObjectUpdateCurrent(void)
113 //@@ if (Cur_object_seg != Cursegp) {
114 //@@ Cur_object_seg = Cursegp;
115 //@@ Cur_object_index = get_first_object(Cur_object_seg);
116 //@@ Update_flags |= UF_WORLD_CHANGED;
121 // ------------------------------------------------------------------------------------
122 int place_object(segment *segp, vms_vector *object_pos, short object_type, short object_id)
126 vms_matrix seg_matrix;
128 med_extract_matrix_from_segment(segp,&seg_matrix);
135 objnum = obj_create(OBJ_HOSTAGE, -1,
136 segp-Segments,object_pos,&seg_matrix,HOSTAGE_SIZE,
137 CT_NONE,MT_NONE,RT_HOSTAGE);
142 obj = &Objects[objnum];
144 // Fill in obj->id and other hostage info
145 // hostage_init_info( objnum ); //don't need to anymore
147 obj->control_type = CT_POWERUP;
149 obj->rtype.vclip_info.vclip_num = Hostage_vclip_num[object_id];
150 obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].frame_time;
151 obj->rtype.vclip_info.framenum = 0;
157 objnum = obj_create(OBJ_ROBOT, object_id, segp - Segments, object_pos,
158 &seg_matrix, Polygon_models[Robot_info[object_id].model_num].rad,
159 CT_AI, MT_PHYSICS, RT_POLYOBJ);
164 obj = &Objects[objnum];
166 //Set polygon-object-specific data
168 obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num;
169 obj->rtype.pobj_info.subobj_flags = 0;
173 obj->mtype.phys_info.mass = Robot_info[obj->id].mass;
174 obj->mtype.phys_info.drag = Robot_info[obj->id].drag;
176 obj->mtype.phys_info.flags |= (PF_LEVELLING);
178 obj->shields = Robot_info[obj->id].strength;
182 hide_segment = Markedsegp-Segments;
185 // robots which lunge forward to attack cannot have behavior type still.
186 if (Robot_info[obj->id].attack_type)
187 init_ai_object(OBJECT_NUMBER(obj), AIB_NORMAL, hide_segment);
189 init_ai_object(OBJECT_NUMBER(obj), AIB_STILL, hide_segment);
195 objnum = obj_create(OBJ_POWERUP, object_id,
196 segp - Segments, object_pos, &seg_matrix, Powerup_info[object_id].size,
197 CT_POWERUP, MT_NONE, RT_POWERUP);
202 obj = &Objects[objnum];
204 //set powerup-specific data
206 obj->rtype.vclip_info.vclip_num = Powerup_info[obj->id].vclip_num;
207 obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].play_time/Vclip[obj->rtype.vclip_info.vclip_num].num_frames;
208 obj->rtype.vclip_info.framenum = 0;
210 if (obj->id == POW_VULCAN_WEAPON)
211 obj->ctype.powerup_info.count = VULCAN_WEAPON_AMMO_AMOUNT;
213 obj->ctype.powerup_info.count = 1;
219 objnum = obj_create(OBJ_CNTRLCEN, object_id, segp - Segments, object_pos,
220 &seg_matrix, Polygon_models[object_id].rad,
221 CT_CNTRLCEN, MT_NONE, RT_POLYOBJ);
226 obj = &Objects[objnum];
228 //Set polygon-object-specific data
229 obj->shields = 0; // stored in Reactor_strength or calculated
230 obj->rtype.pobj_info.model_num = Reactors[object_id].model_num;
231 obj->rtype.pobj_info.subobj_flags = 0;
237 objnum = obj_create(OBJ_PLAYER, object_id, segp - Segments, object_pos,
238 &seg_matrix, Polygon_models[Player_ship->model_num].rad,
239 CT_NONE, MT_PHYSICS, RT_POLYOBJ);
244 obj = &Objects[objnum];
246 //Set polygon-object-specific data
248 obj->rtype.pobj_info.model_num = Player_ship->model_num;
249 obj->rtype.pobj_info.subobj_flags = 0;
250 //for (i=0;i<MAX_SUBMODELS;i++)
251 // vm_angvec_zero(&obj->rtype.pobj_info.anim_angles[i]);
255 vm_vec_zero(&obj->mtype.phys_info.velocity);
256 obj->mtype.phys_info.mass = Player_ship->mass;
257 obj->mtype.phys_info.drag = Player_ship->drag;
258 obj->mtype.phys_info.flags |= PF_TURNROLL | PF_LEVELLING | PF_WIGGLE;
259 obj->shields = i2f(100);
267 Cur_object_index = objnum;
268 //Cur_object_seg = Cursegp;
270 show_objects_in_segment(Cursegp); //mprintf the objects
272 Update_flags |= UF_WORLD_CHANGED;
277 // ------------------------------------------------------------------------------------------------------
278 // Count number of player objects, return value.
279 int compute_num_players(void)
283 for (i=0; i<=Highest_object_index; i++)
284 if (Objects[i].type == OBJ_PLAYER)
291 int ObjectMakeCoop(void)
293 Assert(Cur_object_index != -1);
294 Assert(Cur_object_index < MAX_OBJECTS);
295 // Assert(Objects[Cur_object_index.type == OBJ_PLAYER);
297 if (Objects[Cur_object_index].type == OBJ_PLAYER ) {
298 Objects[Cur_object_index].type = OBJ_COOP;
299 editor_status("You just made a player object COOPERATIVE");
301 editor_status("This is not a player object");
306 // ------------------------------------------------------------------------------------------------------
307 // Place current object at center of current segment.
308 int ObjectPlaceObject(void)
310 int old_cur_object_index;
313 vms_vector cur_object_loc;
316 if (Cur_object_type == OBJ_PLAYER)
318 int num_players = compute_num_players();
319 Assert(num_players <= MAX_PLAYERS);
320 if (num_players == MAX_PLAYERS) {
321 editor_status("Can't place player object. Already %i players.", MAX_PLAYERS);
328 if (Cur_object_type == OBJ_PLAYER)
330 int num_players = compute_num_players();
331 Assert(num_players <= MAX_MULTI_PLAYERS);
332 if (num_players > MAX_PLAYERS)
333 editor_status("You just placed a cooperative player object");
334 if (num_players == MAX_MULTI_PLAYERS) {
335 editor_status("Can't place player object. Already %i players.", MAX_MULTI_PLAYERS);
341 //update_due_to_new_segment();
342 compute_segment_center(&cur_object_loc, Cursegp);
344 old_cur_object_index = Cur_object_index;
345 rval = place_object(Cursegp, &cur_object_loc, Cur_object_type, Cur_object_id);
347 if (old_cur_object_index != Cur_object_index)
348 Objects[Cur_object_index].rtype.pobj_info.tmap_override = -1;
354 // ------------------------------------------------------------------------------------------------------
355 // Place current object at center of current segment.
356 int ObjectPlaceObjectTmap(void)
358 int rval, old_cur_object_index;
359 vms_vector cur_object_loc;
361 //update_due_to_new_segment();
362 compute_segment_center(&cur_object_loc, Cursegp);
364 old_cur_object_index = Cur_object_index;
365 rval = place_object(Cursegp, &cur_object_loc, Cur_object_type, Cur_object_id);
367 if ((Cur_object_index != old_cur_object_index) && (Objects[Cur_object_index].render_type == RT_POLYOBJ))
368 Objects[Cur_object_index].rtype.pobj_info.tmap_override = CurrentTexture;
370 editor_status("Unable to apply current texture map to this object.");
375 // ------------------------------------------------------------------------------------------------------
376 int ObjectSelectNextinSegment(void)
382 //update_due_to_new_segment();
384 //Assert(Cur_object_seg == Cursegp);
386 if (Cur_object_index == -1) {
388 Cur_object_index = objsegp->objects;
391 if (Objects[Cur_object_index].segnum != Cursegp-Segments)
392 Cur_object_index = objsegp->objects;
396 //Debug: make sure current object is in current segment
397 for (id=objsegp->objects;(id != Cur_object_index) && (id != -1);id=Objects[id].next);
398 Assert(id == Cur_object_index); //should have found object
400 // Select the next object, wrapping back to start if we are at the end of the linked list for this segment.
402 Cur_object_index = get_next_object(objsegp,Cur_object_index);
404 //mprintf((0,"Cur_object_index == %i\n", Cur_object_index));
406 Update_flags |= UF_WORLD_CHANGED;
412 //Moves to next object in the mine, skipping the player
413 int ObjectSelectNextInMine()
415 for (i=0;i<MAX_OBJECTS;i++) {
417 if (Cur_object_index>= MAX_OBJECTS ) Cur_object_index= 0;
419 if ( (Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != OBJECT_NUMBER(ConsoleObject)) ) {
420 Cursegp = &Segments[Objects[Cur_object_index ].segnum];
421 med_create_new_segment_from_cursegp();
422 //Cur_object_seg = Cursegp;
426 Cur_object_index = -1;
428 Update_flags |= UF_WORLD_CHANGED;
433 //Moves to next object in the mine, skipping the player
434 int ObjectSelectPrevInMine()
436 for (i=0;i<MAX_OBJECTS;i++) {
438 if (Cur_object_index < 0 )
439 Cur_object_index = MAX_OBJECTS-1;
441 if ( (Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != OBJECT_NUMBER(ConsoleObject)) ) {
442 Cursegp = &Segments[Objects[Cur_object_index ].segnum];
443 med_create_new_segment_from_cursegp();
444 //Cur_object_seg = Cursegp;
448 Cur_object_index = -1;
450 Update_flags |= UF_WORLD_CHANGED;
455 // ------------------------------------------------------------------------------------------------------
456 // Delete current object, if it exists.
457 // If it doesn't exist, reformat Matt's hard disk, even if he is in Boston.
458 int ObjectDelete(void)
461 if (Cur_object_index != -1) {
464 delete_objnum = Cur_object_index;
466 ObjectSelectNextinSegment();
468 obj_delete(delete_objnum);
470 if (delete_objnum == Cur_object_index)
471 Cur_object_index = -1;
473 Update_flags |= UF_WORLD_CHANGED;
479 // -----------------------------------------------------------------------------------------------------------------
480 // Object has moved to another segment, (or at least poked through).
481 // If still in mine, that is legal, so relink into new segment.
482 // Return value: 0 = in mine, 1 = not in mine
483 int move_object_within_mine(object * obj, vms_vector *newpos )
487 for (segnum=0;segnum <= Highest_segment_index; segnum++) {
488 segmasks result = get_seg_masks(&obj->pos, segnum, 0, __FILE__, __LINE__);
490 if (result.centermask == 0) {
495 // See if the radius pokes through any wall.
497 fq.startseg = obj->segnum;
501 fq.ignore_obj_list = NULL;
504 fate = find_vector_intersection(&fq,&hit_info);
506 if (fate != HIT_WALL) {
507 if ( segnum != obj->segnum )
508 obj_relink( OBJECT_NUMBER(obj), segnum );
512 //mprintf((0, "Hit wall seg:side = %i:%i\n", hit_info.hit_seg, hit_info.hit_side));
521 // Return 0 if object is in expected segment, else return 1
522 int verify_object_seg(object *objp, vms_vector *newpos)
524 segmasks result = get_seg_masks(newpos, objp->segnum, objp->size, __FILE__, __LINE__);
526 if (result.facemask == 0)
529 return move_object_within_mine(objp, newpos);
533 // ------------------------------------------------------------------------------------------------------
534 int ObjectMoveForward(void)
540 if (Cur_object_index == -1) {
541 editor_status("No current object, cannot move.");
545 obj = &Objects[Cur_object_index];
547 extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
548 vm_vec_normalize(&fvec);
550 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
552 if (!verify_object_seg(obj, &newpos))
555 Update_flags |= UF_WORLD_CHANGED;
560 // ------------------------------------------------------------------------------------------------------
561 int ObjectMoveBack(void)
567 if (Cur_object_index == -1) {
568 editor_status("No current object, cannot move.");
572 obj = &Objects[Cur_object_index];
574 extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
575 vm_vec_normalize(&fvec);
577 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
579 if (!verify_object_seg(obj, &newpos))
582 Update_flags |= UF_WORLD_CHANGED;
587 // ------------------------------------------------------------------------------------------------------
588 int ObjectMoveLeft(void)
594 if (Cur_object_index == -1) {
595 editor_status("No current object, cannot move.");
599 obj = &Objects[Cur_object_index];
601 extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
602 vm_vec_normalize(&rvec);
604 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
606 if (!verify_object_seg(obj, &newpos))
609 Update_flags |= UF_WORLD_CHANGED;
614 // ------------------------------------------------------------------------------------------------------
615 int ObjectMoveRight(void)
621 if (Cur_object_index == -1) {
622 editor_status("No current object, cannot move.");
626 obj = &Objects[Cur_object_index];
628 extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
629 vm_vec_normalize(&rvec);
631 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
633 if (!verify_object_seg(obj, &newpos))
636 Update_flags |= UF_WORLD_CHANGED;
641 // ------------------------------------------------------------------------------------------------------
642 int ObjectSetDefault(void)
644 //update_due_to_new_segment();
646 if (Cur_object_index == -1) {
647 editor_status("No current object, cannot move.");
651 compute_segment_center(&Objects[Cur_object_index].pos, &Segments[Objects[Cur_object_index].segnum]);
653 Update_flags |= UF_WORLD_CHANGED;
659 // ------------------------------------------------------------------------------------------------------
660 int ObjectMoveUp(void)
666 if (Cur_object_index == -1) {
667 editor_status("No current object, cannot move.");
671 obj = &Objects[Cur_object_index];
673 extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
674 vm_vec_normalize(&uvec);
676 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
678 if (!verify_object_seg(obj, &newpos))
681 Update_flags |= UF_WORLD_CHANGED;
686 // ------------------------------------------------------------------------------------------------------
687 int ObjectMoveDown(void)
693 if (Cur_object_index == -1) {
694 editor_status("No current object, cannot move.");
698 obj = &Objects[Cur_object_index];
700 extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
701 vm_vec_normalize(&uvec);
703 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
705 if (!verify_object_seg(obj, &newpos))
708 Update_flags |= UF_WORLD_CHANGED;
713 // ------------------------------------------------------------------------------------------------------
714 int ObjectMakeSmaller(void)
718 //update_due_to_new_segment();
720 cur_size = Objects[Cur_object_index].size;
722 cur_size -= OBJ_DEL_SIZE;
723 if (cur_size < OBJ_DEL_SIZE)
724 cur_size = OBJ_DEL_SIZE;
726 Objects[Cur_object_index].size = cur_size;
728 Update_flags |= UF_WORLD_CHANGED;
733 // ------------------------------------------------------------------------------------------------------
734 int ObjectMakeLarger(void)
738 //update_due_to_new_segment();
740 cur_size = Objects[Cur_object_index].size;
742 cur_size += OBJ_DEL_SIZE;
744 Objects[Cur_object_index].size = cur_size;
746 Update_flags |= UF_WORLD_CHANGED;
751 // ------------------------------------------------------------------------------------------------------
753 int rotate_object(short objnum, int p, int b, int h)
755 object *obj = &Objects[objnum];
757 vms_matrix rotmat,tempm;
759 // vm_extract_angles_matrix( &ang,&obj->orient);
769 vm_angles_2_matrix(&rotmat, &ang);
770 vm_matrix_x_matrix(&tempm, &obj->orient, &rotmat);
773 // vm_angles_2_matrix(&obj->orient, &ang);
775 Update_flags |= UF_WORLD_CHANGED;
781 void reset_object(short objnum)
783 object *obj = &Objects[objnum];
785 med_extract_matrix_from_segment(&Segments[obj->segnum],&obj->orient);
791 int ObjectResetObject()
793 reset_object(Cur_object_index);
795 Update_flags |= UF_WORLD_CHANGED;
801 int ObjectFlipObject()
803 vms_matrix *m=&Objects[Cur_object_index].orient;
805 vm_vec_negate(&m->uvec);
806 vm_vec_negate(&m->rvec);
808 Update_flags |= UF_WORLD_CHANGED;
813 int ObjectDecreaseBank() {return rotate_object(Cur_object_index, 0, -ROTATION_UNIT, 0);}
814 int ObjectIncreaseBank() {return rotate_object(Cur_object_index, 0, ROTATION_UNIT, 0);}
815 int ObjectDecreasePitch() {return rotate_object(Cur_object_index, -ROTATION_UNIT, 0, 0);}
816 int ObjectIncreasePitch() {return rotate_object(Cur_object_index, ROTATION_UNIT, 0, 0);}
817 int ObjectDecreaseHeading() {return rotate_object(Cur_object_index, 0, 0, -ROTATION_UNIT);}
818 int ObjectIncreaseHeading() {return rotate_object(Cur_object_index, 0, 0, ROTATION_UNIT);}
820 int ObjectDecreaseBankBig() {return rotate_object(Cur_object_index, 0, -(ROTATION_UNIT*4), 0);}
821 int ObjectIncreaseBankBig() {return rotate_object(Cur_object_index, 0, (ROTATION_UNIT*4), 0);}
822 int ObjectDecreasePitchBig() {return rotate_object(Cur_object_index, -(ROTATION_UNIT*4), 0, 0);}
823 int ObjectIncreasePitchBig() {return rotate_object(Cur_object_index, (ROTATION_UNIT*4), 0, 0);}
824 int ObjectDecreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, -(ROTATION_UNIT*4));}
825 int ObjectIncreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, (ROTATION_UNIT*4));}
827 // -----------------------------------------------------------------------------------------------------
828 // Move object around based on clicks in 2d screen.
829 // Slide an object parallel to the 2d screen, to a point on a vector.
830 // The vector is defined by a point on the 2d screen and the eye.
832 // V = vector from eye to 2d screen point.
834 // F = forward vector from eye
835 // O = 3-space location of object
837 // D = depth of object given forward vector F
838 // = (OE dot norm(F))
840 // Must solve intersection of:
841 // E + tV ( equation of vector from eye through point on 2d screen)
842 // Fs + D ( equation of plane parallel to 2d screen, at depth D)
843 // = Fx(Ex + tVx) + Fy(Ey + tVy) + Fz(Ez + tVz) + D = 0
845 // FxEx + FyEy + FzEz - D
846 // t = - ----------------------
847 // VxFx + VyFy + VzFz
850 //void print_vec(vms_vector *vec, char *text)
852 // mprintf((0, "%10s = %9.5f %9.5f %9.5f\n", text, f2fl(vec->x), f2fl(vec->y), f2fl(vec->z)));
855 // void solve(vms_vector *result, vms_vector *E, vms_vector *V, vms_vector *O, vms_vector *F)
858 // vms_vector Fnorm, Vnorm;
860 // // float test_plane;
862 // print_vec(E, "E");
863 // print_vec(V, "V");
864 // print_vec(O, "O");
865 // print_vec(F, "F");
867 // Fnorm = *F; vm_vec_normalize(&Fnorm);
868 // Vnorm = *V; vm_vec_normalize(&Vnorm);
870 // D = (fixmul(O->x, Fnorm.x) + fixmul(O->y, Fnorm.y) + fixmul(O->z, Fnorm.z));
871 // mprintf((0, "D = %9.5f\n", f2fl(D)));
873 // num = fixmul(Fnorm.x, E->x) + fixmul(Fnorm.y, E->y) + fixmul(Fnorm.z, E->z) - D;
874 // denom = vm_vec_dot(&Vnorm, &Fnorm);
877 // mprintf((0, "num = %9.5f, denom = %9.5f, t = %9.5f\n", f2fl(num), f2fl(denom), f2fl(t)));
879 // result->x = E->x + fixmul(t, Vnorm.x);
880 // result->y = E->y + fixmul(t, Vnorm.y);
881 // result->z = E->z + fixmul(t, Vnorm.z);
883 // print_vec(result, "result");
885 // // test_plane = fixmul(result->x, Fnorm.x) + fixmul(result->y, Fnorm.y) + fixmul(result->z, Fnorm.z) - D;
886 // // if (abs(test_plane) > .001)
887 // // printf("OOPS: test_plane = %9.5f\n", test_plane);
890 void move_object_to_position(int objnum, vms_vector *newpos)
892 object *objp = &Objects[objnum];
894 segmasks result = get_seg_masks(newpos, objp->segnum, objp->size, __FILE__, __LINE__);
896 if (result.facemask == 0) {
897 //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)));
900 if (verify_object_seg(&Objects[objnum], newpos)) {
903 object temp_viewer_obj;
906 vms_vector last_outside_pos;
907 vms_vector last_inside_pos;
909 temp_viewer_obj = *Viewer;
910 viewer_segnum = find_object_seg(&temp_viewer_obj);
911 temp_viewer_obj.segnum = viewer_segnum;
913 // If the viewer is outside the mine, get him in the mine!
914 if (viewer_segnum == -1) {
915 // While outside mine, move towards object
917 while (viewer_segnum == -1) {
920 //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)));
921 last_outside_pos = temp_viewer_obj.pos;
923 vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, newpos);
924 temp_viewer_obj.pos = temp_vec;
925 viewer_segnum = find_object_seg(&temp_viewer_obj);
926 temp_viewer_obj.segnum = viewer_segnum;
929 editor_status("Unable to move object, can't get viewer in mine. Aborting");
935 // While inside mine, move away from object.
936 while (viewer_segnum != -1) {
940 //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)));
941 last_inside_pos = temp_viewer_obj.pos;
943 vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, &last_outside_pos);
944 temp_viewer_obj.pos = temp_vec;
945 update_object_seg(&temp_viewer_obj);
946 viewer_segnum = find_object_seg(&temp_viewer_obj);
947 temp_viewer_obj.segnum = viewer_segnum;
950 editor_status("Unable to move object, can't get viewer back out of mine. Aborting");
956 fq.p0 = &temp_viewer_obj.pos;
957 fq.startseg = temp_viewer_obj.segnum;
959 fq.rad = temp_viewer_obj.size;
961 fq.ignore_obj_list = NULL;
964 fate = find_vector_intersection(&fq,&hit_info);
965 if (fate == HIT_WALL) {
968 //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)));
969 objp->pos = hit_info.hit_pnt;
970 new_segnum = find_object_seg(objp);
971 Assert(new_segnum != -1);
972 obj_relink(OBJECT_NUMBER(objp), new_segnum);
973 //mprintf((0, "Object moved from segment %i to %i\n", old_segnum, objp->segnum));
975 editor_status("Attempted to move object out of mine. Object not moved.");
976 //mprintf((0,"Attempted to move object out of mine. Object not moved."));
981 Update_flags |= UF_WORLD_CHANGED;
984 void move_object_to_vector(vms_vector *vec_through_screen, fix delta_distance)
988 vm_vec_scale_add(&result, &Viewer->pos, vec_through_screen, vm_vec_dist(&Viewer->pos,&Objects[Cur_object_index].pos)+delta_distance);
990 move_object_to_position(Cur_object_index, &result);
994 void move_object_to_mouse_click_delta(fix delta_distance)
997 vms_vector vec_through_screen;
999 if (Cur_object_index == -1) {
1000 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1004 xcrd = GameViewBox->b1_drag_x1;
1005 ycrd = GameViewBox->b1_drag_y1;
1007 med_point_2_vec(&_canv_editor_game, &vec_through_screen, xcrd, ycrd);
1009 //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)));
1011 move_object_to_vector(&vec_through_screen, delta_distance);
1015 void move_object_to_mouse_click(void)
1017 move_object_to_mouse_click_delta(0);
1020 int ObjectMoveNearer(void)
1024 if (Cur_object_index == -1) {
1025 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1029 // move_object_to_mouse_click_delta(-4*F1_0); // Move four units closer to eye
1031 vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
1032 vm_vec_normalize(&result);
1033 move_object_to_vector(&result, -4*F1_0);
1038 int ObjectMoveFurther(void)
1042 if (Cur_object_index == -1) {
1043 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1047 // move_object_to_mouse_click_delta(+4*F1_0); // Move four units further from eye
1049 vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
1050 vm_vec_normalize(&result);
1051 move_object_to_vector(&result, 4*F1_0);