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.
16 * Editor object functions.
35 #include "3d.h" // For g3_point_to_vec
38 #define OBJ_SCALE (F1_0/2)
39 #define OBJ_DEL_SIZE (F1_0/2)
41 #define ROTATION_UNIT (4096/4)
43 //segment *Cur_object_seg = -1;
45 void show_objects_in_segment(segment *sp)
49 mprintf((0, "Objects in segment #%i: ", SEGMENT_NUMBER(sp)));
53 mprintf((0,"%2i ",objid));
54 objid = Objects[objid].next;
59 //returns the number of the first object in a segment, skipping the player
60 int get_first_object(segment *seg)
66 if (id == OBJECT_NUMBER(ConsoleObject))
67 id = Objects[id].next;
72 //returns the number of the next object in a segment, skipping the player
73 int get_next_object(segment *seg,int id)
75 if (id==-1 || (id=Objects[id].next)==-1)
76 return get_first_object(seg);
78 if (id == OBJECT_NUMBER(ConsoleObject))
79 return get_next_object(seg,id);
85 //@@// ------------------------------------------------------------------------------------------------------
86 //@@// this should be called whenever the current segment may have changed
87 //@@// If Cur_object_seg != Cursegp, then update various variables.
88 //@@// this used to be called update_due_to_new_segment()
89 //@@void ObjectUpdateCurrent(void)
91 //@@ if (Cur_object_seg != Cursegp) {
92 //@@ Cur_object_seg = Cursegp;
93 //@@ Cur_object_index = get_first_object(Cur_object_seg);
94 //@@ Update_flags |= UF_WORLD_CHANGED;
99 // ------------------------------------------------------------------------------------
100 int place_object(segment *segp, vms_vector *object_pos, short object_type, short object_id)
104 vms_matrix seg_matrix;
106 med_extract_matrix_from_segment(segp,&seg_matrix);
113 objnum = obj_create(OBJ_HOSTAGE, -1,
114 SEGMENT_NUMBER(segp), object_pos, &seg_matrix, HOSTAGE_SIZE,
115 CT_NONE, MT_NONE, RT_HOSTAGE);
120 obj = &Objects[objnum];
122 // Fill in obj->id and other hostage info
123 // hostage_init_info( objnum ); //don't need to anymore
125 obj->control_type = CT_POWERUP;
127 obj->rtype.vclip_info.vclip_num = Hostage_vclip_num[object_id];
128 obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].frame_time;
129 obj->rtype.vclip_info.framenum = 0;
135 objnum = obj_create(OBJ_ROBOT, object_id, SEGMENT_NUMBER(segp), object_pos,
136 &seg_matrix, Polygon_models[Robot_info[object_id].model_num].rad,
137 CT_AI, MT_PHYSICS, RT_POLYOBJ);
142 obj = &Objects[objnum];
144 //Set polygon-object-specific data
146 obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num;
147 obj->rtype.pobj_info.subobj_flags = 0;
151 obj->mtype.phys_info.mass = Robot_info[obj->id].mass;
152 obj->mtype.phys_info.drag = Robot_info[obj->id].drag;
154 obj->mtype.phys_info.flags |= (PF_LEVELLING);
156 obj->shields = Robot_info[obj->id].strength;
160 hide_segment = SEGMENT_NUMBER(Markedsegp);
163 // robots which lunge forward to attack cannot have behavior type still.
164 if (Robot_info[obj->id].attack_type)
165 init_ai_object(OBJECT_NUMBER(obj), AIB_NORMAL, hide_segment);
167 init_ai_object(OBJECT_NUMBER(obj), AIB_STILL, hide_segment);
173 objnum = obj_create(OBJ_POWERUP, object_id,
174 SEGMENT_NUMBER(segp), object_pos, &seg_matrix, Powerup_info[object_id].size,
175 CT_POWERUP, MT_NONE, RT_POWERUP);
180 obj = &Objects[objnum];
182 //set powerup-specific data
184 obj->rtype.vclip_info.vclip_num = Powerup_info[obj->id].vclip_num;
185 obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].play_time/Vclip[obj->rtype.vclip_info.vclip_num].num_frames;
186 obj->rtype.vclip_info.framenum = 0;
188 if (obj->id == POW_VULCAN_WEAPON)
189 obj->ctype.powerup_info.count = VULCAN_WEAPON_AMMO_AMOUNT;
191 obj->ctype.powerup_info.count = 1;
197 objnum = obj_create(OBJ_CNTRLCEN, object_id, SEGMENT_NUMBER(segp), object_pos,
198 &seg_matrix, Polygon_models[object_id].rad,
199 CT_CNTRLCEN, MT_NONE, RT_POLYOBJ);
204 obj = &Objects[objnum];
206 //Set polygon-object-specific data
207 obj->shields = 0; // stored in Reactor_strength or calculated
208 obj->rtype.pobj_info.model_num = Reactors[object_id].model_num;
209 obj->rtype.pobj_info.subobj_flags = 0;
215 objnum = obj_create(OBJ_PLAYER, object_id, SEGMENT_NUMBER(segp), object_pos,
216 &seg_matrix, Polygon_models[Player_ship->model_num].rad,
217 CT_NONE, MT_PHYSICS, RT_POLYOBJ);
222 obj = &Objects[objnum];
224 //Set polygon-object-specific data
226 obj->rtype.pobj_info.model_num = Player_ship->model_num;
227 obj->rtype.pobj_info.subobj_flags = 0;
228 //for (i=0;i<MAX_SUBMODELS;i++)
229 // vm_angvec_zero(&obj->rtype.pobj_info.anim_angles[i]);
233 vm_vec_zero(&obj->mtype.phys_info.velocity);
234 obj->mtype.phys_info.mass = Player_ship->mass;
235 obj->mtype.phys_info.drag = Player_ship->drag;
236 obj->mtype.phys_info.flags |= PF_TURNROLL | PF_LEVELLING | PF_WIGGLE;
237 obj->shields = i2f(100);
245 Cur_object_index = objnum;
246 //Cur_object_seg = Cursegp;
248 show_objects_in_segment(Cursegp); //mprintf the objects
250 Update_flags |= UF_WORLD_CHANGED;
255 // ------------------------------------------------------------------------------------------------------
256 // Count number of player objects, return value.
257 int compute_num_players(void)
261 for (i=0; i<=Highest_object_index; i++)
262 if (Objects[i].type == OBJ_PLAYER)
269 int ObjectMakeCoop(void)
271 Assert(Cur_object_index != -1);
272 Assert(Cur_object_index < MAX_OBJECTS);
273 // Assert(Objects[Cur_object_index.type == OBJ_PLAYER);
275 if (Objects[Cur_object_index].type == OBJ_PLAYER ) {
276 Objects[Cur_object_index].type = OBJ_COOP;
277 editor_status("You just made a player object COOPERATIVE");
279 editor_status("This is not a player object");
284 // ------------------------------------------------------------------------------------------------------
285 // Place current object at center of current segment.
286 int ObjectPlaceObject(void)
288 int old_cur_object_index;
291 vms_vector cur_object_loc;
294 if (Cur_object_type == OBJ_PLAYER)
296 int num_players = compute_num_players();
297 Assert(num_players <= MAX_PLAYERS);
298 if (num_players == MAX_PLAYERS) {
299 editor_status("Can't place player object. Already %i players.", MAX_PLAYERS);
306 if (Cur_object_type == OBJ_PLAYER)
308 int num_players = compute_num_players();
309 Assert(num_players <= MAX_MULTI_PLAYERS);
310 if (num_players > MAX_PLAYERS)
311 editor_status("You just placed a cooperative player object");
312 if (num_players == MAX_MULTI_PLAYERS) {
313 editor_status("Can't place player object. Already %i players.", MAX_MULTI_PLAYERS);
319 //update_due_to_new_segment();
320 compute_segment_center(&cur_object_loc, Cursegp);
322 old_cur_object_index = Cur_object_index;
323 rval = place_object(Cursegp, &cur_object_loc, Cur_object_type, Cur_object_id);
325 if (old_cur_object_index != Cur_object_index)
326 Objects[Cur_object_index].rtype.pobj_info.tmap_override = -1;
332 // ------------------------------------------------------------------------------------------------------
333 // Place current object at center of current segment.
334 int ObjectPlaceObjectTmap(void)
336 int rval, old_cur_object_index;
337 vms_vector cur_object_loc;
339 //update_due_to_new_segment();
340 compute_segment_center(&cur_object_loc, Cursegp);
342 old_cur_object_index = Cur_object_index;
343 rval = place_object(Cursegp, &cur_object_loc, Cur_object_type, Cur_object_id);
345 if ((Cur_object_index != old_cur_object_index) && (Objects[Cur_object_index].render_type == RT_POLYOBJ))
346 Objects[Cur_object_index].rtype.pobj_info.tmap_override = CurrentTexture;
348 editor_status("Unable to apply current texture map to this object.");
353 // ------------------------------------------------------------------------------------------------------
354 int ObjectSelectNextinSegment(void)
360 //update_due_to_new_segment();
362 //Assert(Cur_object_seg == Cursegp);
364 if (Cur_object_index == -1) {
366 Cur_object_index = objsegp->objects;
369 if (Objects[Cur_object_index].segnum != SEGMENT_NUMBER(Cursegp))
370 Cur_object_index = objsegp->objects;
374 //Debug: make sure current object is in current segment
375 for (id=objsegp->objects;(id != Cur_object_index) && (id != -1);id=Objects[id].next);
376 Assert(id == Cur_object_index); //should have found object
378 // Select the next object, wrapping back to start if we are at the end of the linked list for this segment.
380 Cur_object_index = get_next_object(objsegp,Cur_object_index);
382 //mprintf((0,"Cur_object_index == %i\n", Cur_object_index));
384 Update_flags |= UF_WORLD_CHANGED;
390 //Moves to next object in the mine, skipping the player
391 int ObjectSelectNextInMine()
393 for (i=0;i<MAX_OBJECTS;i++) {
395 if (Cur_object_index>= MAX_OBJECTS ) Cur_object_index= 0;
397 if ( (Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != OBJECT_NUMBER(ConsoleObject)) ) {
398 Cursegp = &Segments[Objects[Cur_object_index ].segnum];
399 med_create_new_segment_from_cursegp();
400 //Cur_object_seg = Cursegp;
404 Cur_object_index = -1;
406 Update_flags |= UF_WORLD_CHANGED;
411 //Moves to next object in the mine, skipping the player
412 int ObjectSelectPrevInMine()
414 for (i=0;i<MAX_OBJECTS;i++) {
416 if (Cur_object_index < 0 )
417 Cur_object_index = MAX_OBJECTS-1;
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 // ------------------------------------------------------------------------------------------------------
434 // Delete current object, if it exists.
435 // If it doesn't exist, reformat Matt's hard disk, even if he is in Boston.
436 int ObjectDelete(void)
439 if (Cur_object_index != -1) {
442 delete_objnum = Cur_object_index;
444 ObjectSelectNextinSegment();
446 obj_delete(delete_objnum);
448 if (delete_objnum == Cur_object_index)
449 Cur_object_index = -1;
451 Update_flags |= UF_WORLD_CHANGED;
457 // -----------------------------------------------------------------------------------------------------------------
458 // Object has moved to another segment, (or at least poked through).
459 // If still in mine, that is legal, so relink into new segment.
460 // Return value: 0 = in mine, 1 = not in mine
461 int move_object_within_mine(object * obj, vms_vector *newpos )
465 for (segnum=0;segnum <= Highest_segment_index; segnum++) {
466 segmasks result = get_seg_masks(&obj->pos, segnum, 0, __FILE__, __LINE__);
468 if (result.centermask == 0) {
473 // See if the radius pokes through any wall.
475 fq.startseg = obj->segnum;
479 fq.ignore_obj_list = NULL;
482 fate = find_vector_intersection(&fq,&hit_info);
484 if (fate != HIT_WALL) {
485 if ( segnum != obj->segnum )
486 obj_relink( OBJECT_NUMBER(obj), segnum );
490 //mprintf((0, "Hit wall seg:side = %i:%i\n", hit_info.hit_seg, hit_info.hit_side));
499 // Return 0 if object is in expected segment, else return 1
500 int verify_object_seg(object *objp, vms_vector *newpos)
502 segmasks result = get_seg_masks(newpos, objp->segnum, objp->size, __FILE__, __LINE__);
504 if (result.facemask == 0)
507 return move_object_within_mine(objp, newpos);
511 // ------------------------------------------------------------------------------------------------------
512 int ObjectMoveForward(void)
518 if (Cur_object_index == -1) {
519 editor_status("No current object, cannot move.");
523 obj = &Objects[Cur_object_index];
525 extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
526 vm_vec_normalize(&fvec);
528 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
530 if (!verify_object_seg(obj, &newpos))
533 Update_flags |= UF_WORLD_CHANGED;
538 // ------------------------------------------------------------------------------------------------------
539 int ObjectMoveBack(void)
545 if (Cur_object_index == -1) {
546 editor_status("No current object, cannot move.");
550 obj = &Objects[Cur_object_index];
552 extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
553 vm_vec_normalize(&fvec);
555 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
557 if (!verify_object_seg(obj, &newpos))
560 Update_flags |= UF_WORLD_CHANGED;
565 // ------------------------------------------------------------------------------------------------------
566 int ObjectMoveLeft(void)
572 if (Cur_object_index == -1) {
573 editor_status("No current object, cannot move.");
577 obj = &Objects[Cur_object_index];
579 extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
580 vm_vec_normalize(&rvec);
582 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
584 if (!verify_object_seg(obj, &newpos))
587 Update_flags |= UF_WORLD_CHANGED;
592 // ------------------------------------------------------------------------------------------------------
593 int ObjectMoveRight(void)
599 if (Cur_object_index == -1) {
600 editor_status("No current object, cannot move.");
604 obj = &Objects[Cur_object_index];
606 extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
607 vm_vec_normalize(&rvec);
609 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
611 if (!verify_object_seg(obj, &newpos))
614 Update_flags |= UF_WORLD_CHANGED;
619 // ------------------------------------------------------------------------------------------------------
620 int ObjectSetDefault(void)
622 //update_due_to_new_segment();
624 if (Cur_object_index == -1) {
625 editor_status("No current object, cannot move.");
629 compute_segment_center(&Objects[Cur_object_index].pos, &Segments[Objects[Cur_object_index].segnum]);
631 Update_flags |= UF_WORLD_CHANGED;
637 // ------------------------------------------------------------------------------------------------------
638 int ObjectMoveUp(void)
644 if (Cur_object_index == -1) {
645 editor_status("No current object, cannot move.");
649 obj = &Objects[Cur_object_index];
651 extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
652 vm_vec_normalize(&uvec);
654 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
656 if (!verify_object_seg(obj, &newpos))
659 Update_flags |= UF_WORLD_CHANGED;
664 // ------------------------------------------------------------------------------------------------------
665 int ObjectMoveDown(void)
671 if (Cur_object_index == -1) {
672 editor_status("No current object, cannot move.");
676 obj = &Objects[Cur_object_index];
678 extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
679 vm_vec_normalize(&uvec);
681 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
683 if (!verify_object_seg(obj, &newpos))
686 Update_flags |= UF_WORLD_CHANGED;
691 // ------------------------------------------------------------------------------------------------------
692 int ObjectMakeSmaller(void)
696 //update_due_to_new_segment();
698 cur_size = Objects[Cur_object_index].size;
700 cur_size -= OBJ_DEL_SIZE;
701 if (cur_size < OBJ_DEL_SIZE)
702 cur_size = OBJ_DEL_SIZE;
704 Objects[Cur_object_index].size = cur_size;
706 Update_flags |= UF_WORLD_CHANGED;
711 // ------------------------------------------------------------------------------------------------------
712 int ObjectMakeLarger(void)
716 //update_due_to_new_segment();
718 cur_size = Objects[Cur_object_index].size;
720 cur_size += OBJ_DEL_SIZE;
722 Objects[Cur_object_index].size = cur_size;
724 Update_flags |= UF_WORLD_CHANGED;
729 // ------------------------------------------------------------------------------------------------------
731 int rotate_object(short objnum, int p, int b, int h)
733 object *obj = &Objects[objnum];
735 vms_matrix rotmat,tempm;
737 // vm_extract_angles_matrix( &ang,&obj->orient);
747 vm_angles_2_matrix(&rotmat, &ang);
748 vm_matrix_x_matrix(&tempm, &obj->orient, &rotmat);
751 // vm_angles_2_matrix(&obj->orient, &ang);
753 Update_flags |= UF_WORLD_CHANGED;
759 void reset_object(short objnum)
761 object *obj = &Objects[objnum];
763 med_extract_matrix_from_segment(&Segments[obj->segnum],&obj->orient);
769 int ObjectResetObject()
771 reset_object(Cur_object_index);
773 Update_flags |= UF_WORLD_CHANGED;
779 int ObjectFlipObject()
781 vms_matrix *m=&Objects[Cur_object_index].orient;
783 vm_vec_negate(&m->uvec);
784 vm_vec_negate(&m->rvec);
786 Update_flags |= UF_WORLD_CHANGED;
791 int ObjectDecreaseBank() {return rotate_object(Cur_object_index, 0, -ROTATION_UNIT, 0);}
792 int ObjectIncreaseBank() {return rotate_object(Cur_object_index, 0, ROTATION_UNIT, 0);}
793 int ObjectDecreasePitch() {return rotate_object(Cur_object_index, -ROTATION_UNIT, 0, 0);}
794 int ObjectIncreasePitch() {return rotate_object(Cur_object_index, ROTATION_UNIT, 0, 0);}
795 int ObjectDecreaseHeading() {return rotate_object(Cur_object_index, 0, 0, -ROTATION_UNIT);}
796 int ObjectIncreaseHeading() {return rotate_object(Cur_object_index, 0, 0, ROTATION_UNIT);}
798 int ObjectDecreaseBankBig() {return rotate_object(Cur_object_index, 0, -(ROTATION_UNIT*4), 0);}
799 int ObjectIncreaseBankBig() {return rotate_object(Cur_object_index, 0, (ROTATION_UNIT*4), 0);}
800 int ObjectDecreasePitchBig() {return rotate_object(Cur_object_index, -(ROTATION_UNIT*4), 0, 0);}
801 int ObjectIncreasePitchBig() {return rotate_object(Cur_object_index, (ROTATION_UNIT*4), 0, 0);}
802 int ObjectDecreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, -(ROTATION_UNIT*4));}
803 int ObjectIncreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, (ROTATION_UNIT*4));}
805 // -----------------------------------------------------------------------------------------------------
806 // Move object around based on clicks in 2d screen.
807 // Slide an object parallel to the 2d screen, to a point on a vector.
808 // The vector is defined by a point on the 2d screen and the eye.
810 // V = vector from eye to 2d screen point.
812 // F = forward vector from eye
813 // O = 3-space location of object
815 // D = depth of object given forward vector F
816 // = (OE dot norm(F))
818 // Must solve intersection of:
819 // E + tV ( equation of vector from eye through point on 2d screen)
820 // Fs + D ( equation of plane parallel to 2d screen, at depth D)
821 // = Fx(Ex + tVx) + Fy(Ey + tVy) + Fz(Ez + tVz) + D = 0
823 // FxEx + FyEy + FzEz - D
824 // t = - ----------------------
825 // VxFx + VyFy + VzFz
828 //void print_vec(vms_vector *vec, char *text)
830 // mprintf((0, "%10s = %9.5f %9.5f %9.5f\n", text, f2fl(vec->x), f2fl(vec->y), f2fl(vec->z)));
833 // void solve(vms_vector *result, vms_vector *E, vms_vector *V, vms_vector *O, vms_vector *F)
836 // vms_vector Fnorm, Vnorm;
838 // // float test_plane;
840 // print_vec(E, "E");
841 // print_vec(V, "V");
842 // print_vec(O, "O");
843 // print_vec(F, "F");
845 // Fnorm = *F; vm_vec_normalize(&Fnorm);
846 // Vnorm = *V; vm_vec_normalize(&Vnorm);
848 // D = (fixmul(O->x, Fnorm.x) + fixmul(O->y, Fnorm.y) + fixmul(O->z, Fnorm.z));
849 // mprintf((0, "D = %9.5f\n", f2fl(D)));
851 // num = fixmul(Fnorm.x, E->x) + fixmul(Fnorm.y, E->y) + fixmul(Fnorm.z, E->z) - D;
852 // denom = vm_vec_dot(&Vnorm, &Fnorm);
855 // mprintf((0, "num = %9.5f, denom = %9.5f, t = %9.5f\n", f2fl(num), f2fl(denom), f2fl(t)));
857 // result->x = E->x + fixmul(t, Vnorm.x);
858 // result->y = E->y + fixmul(t, Vnorm.y);
859 // result->z = E->z + fixmul(t, Vnorm.z);
861 // print_vec(result, "result");
863 // // test_plane = fixmul(result->x, Fnorm.x) + fixmul(result->y, Fnorm.y) + fixmul(result->z, Fnorm.z) - D;
864 // // if (abs(test_plane) > .001)
865 // // printf("OOPS: test_plane = %9.5f\n", test_plane);
868 void move_object_to_position(int objnum, vms_vector *newpos)
870 object *objp = &Objects[objnum];
872 segmasks result = get_seg_masks(newpos, objp->segnum, objp->size, __FILE__, __LINE__);
874 if (result.facemask == 0) {
875 //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)));
878 if (verify_object_seg(&Objects[objnum], newpos)) {
881 object temp_viewer_obj;
884 vms_vector last_outside_pos;
885 vms_vector last_inside_pos;
887 temp_viewer_obj = *Viewer;
888 viewer_segnum = find_object_seg(&temp_viewer_obj);
889 temp_viewer_obj.segnum = viewer_segnum;
891 // If the viewer is outside the mine, get him in the mine!
892 if (viewer_segnum == -1) {
893 // While outside mine, move towards object
895 while (viewer_segnum == -1) {
898 //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)));
899 last_outside_pos = temp_viewer_obj.pos;
901 vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, newpos);
902 temp_viewer_obj.pos = temp_vec;
903 viewer_segnum = find_object_seg(&temp_viewer_obj);
904 temp_viewer_obj.segnum = viewer_segnum;
907 editor_status("Unable to move object, can't get viewer in mine. Aborting");
913 // While inside mine, move away from object.
914 while (viewer_segnum != -1) {
918 //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)));
919 last_inside_pos = temp_viewer_obj.pos;
921 vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, &last_outside_pos);
922 temp_viewer_obj.pos = temp_vec;
923 update_object_seg(&temp_viewer_obj);
924 viewer_segnum = find_object_seg(&temp_viewer_obj);
925 temp_viewer_obj.segnum = viewer_segnum;
928 editor_status("Unable to move object, can't get viewer back out of mine. Aborting");
934 fq.p0 = &temp_viewer_obj.pos;
935 fq.startseg = temp_viewer_obj.segnum;
937 fq.rad = temp_viewer_obj.size;
939 fq.ignore_obj_list = NULL;
942 fate = find_vector_intersection(&fq,&hit_info);
943 if (fate == HIT_WALL) {
946 //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)));
947 objp->pos = hit_info.hit_pnt;
948 new_segnum = find_object_seg(objp);
949 Assert(new_segnum != -1);
950 obj_relink(OBJECT_NUMBER(objp), new_segnum);
951 //mprintf((0, "Object moved from segment %i to %i\n", old_segnum, objp->segnum));
953 editor_status("Attempted to move object out of mine. Object not moved.");
954 //mprintf((0,"Attempted to move object out of mine. Object not moved."));
959 Update_flags |= UF_WORLD_CHANGED;
962 void move_object_to_vector(vms_vector *vec_through_screen, fix delta_distance)
966 vm_vec_scale_add(&result, &Viewer->pos, vec_through_screen, vm_vec_dist(&Viewer->pos,&Objects[Cur_object_index].pos)+delta_distance);
968 move_object_to_position(Cur_object_index, &result);
972 void move_object_to_mouse_click_delta(fix delta_distance)
975 vms_vector vec_through_screen;
977 if (Cur_object_index == -1) {
978 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
982 xcrd = GameViewBox->b1_drag_x1;
983 ycrd = GameViewBox->b1_drag_y1;
985 med_point_2_vec(&_canv_editor_game, &vec_through_screen, xcrd, ycrd);
987 //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)));
989 move_object_to_vector(&vec_through_screen, delta_distance);
993 void move_object_to_mouse_click(void)
995 move_object_to_mouse_click_delta(0);
998 int ObjectMoveNearer(void)
1002 if (Cur_object_index == -1) {
1003 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1007 // move_object_to_mouse_click_delta(-4*F1_0); // Move four units closer to eye
1009 vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
1010 vm_vec_normalize(&result);
1011 move_object_to_vector(&result, -4*F1_0);
1016 int ObjectMoveFurther(void)
1020 if (Cur_object_index == -1) {
1021 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1025 // move_object_to_mouse_click_delta(+4*F1_0); // Move four units further from eye
1027 vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
1028 vm_vec_normalize(&result);
1029 move_object_to_vector(&result, 4*F1_0);