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.
44 #include "3d.h" // For g3_point_to_vec
55 #define OBJ_SCALE (F1_0/2)
56 #define OBJ_DEL_SIZE (F1_0/2)
58 #define ROTATION_UNIT (4096/4)
60 //segment *Cur_object_seg = -1;
62 void show_objects_in_segment(segment *sp)
66 mprintf((0, "Objects in segment #%i: ", SEGMENT_NUMBER(sp)));
70 mprintf((0,"%2i ",objid));
71 objid = Objects[objid].next;
76 //returns the number of the first object in a segment, skipping the player
77 int get_first_object(segment *seg)
83 if (id == OBJECT_NUMBER(ConsoleObject))
84 id = Objects[id].next;
89 //returns the number of the next object in a segment, skipping the player
90 int get_next_object(segment *seg,int id)
92 if (id==-1 || (id=Objects[id].next)==-1)
93 return get_first_object(seg);
95 if (id == OBJECT_NUMBER(ConsoleObject))
96 return get_next_object(seg,id);
102 //@@// ------------------------------------------------------------------------------------------------------
103 //@@// this should be called whenever the current segment may have changed
104 //@@// If Cur_object_seg != Cursegp, then update various variables.
105 //@@// this used to be called update_due_to_new_segment()
106 //@@void ObjectUpdateCurrent(void)
108 //@@ if (Cur_object_seg != Cursegp) {
109 //@@ Cur_object_seg = Cursegp;
110 //@@ Cur_object_index = get_first_object(Cur_object_seg);
111 //@@ Update_flags |= UF_WORLD_CHANGED;
116 // ------------------------------------------------------------------------------------
117 int place_object(segment *segp, vms_vector *object_pos, short object_type, short object_id)
121 vms_matrix seg_matrix;
123 med_extract_matrix_from_segment(segp,&seg_matrix);
130 objnum = obj_create(OBJ_HOSTAGE, -1,
131 SEGMENT_NUMBER(segp), object_pos, &seg_matrix, HOSTAGE_SIZE,
132 CT_NONE, MT_NONE, RT_HOSTAGE);
137 obj = &Objects[objnum];
139 // Fill in obj->id and other hostage info
140 // hostage_init_info( objnum ); //don't need to anymore
142 obj->control_type = CT_POWERUP;
144 obj->rtype.vclip_info.vclip_num = Hostage_vclip_num[object_id];
145 obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].frame_time;
146 obj->rtype.vclip_info.framenum = 0;
152 objnum = obj_create(OBJ_ROBOT, object_id, SEGMENT_NUMBER(segp), object_pos,
153 &seg_matrix, Polygon_models[Robot_info[object_id].model_num].rad,
154 CT_AI, MT_PHYSICS, RT_POLYOBJ);
159 obj = &Objects[objnum];
161 //Set polygon-object-specific data
163 obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num;
164 obj->rtype.pobj_info.subobj_flags = 0;
168 obj->mtype.phys_info.mass = Robot_info[obj->id].mass;
169 obj->mtype.phys_info.drag = Robot_info[obj->id].drag;
171 obj->mtype.phys_info.flags |= (PF_LEVELLING);
173 obj->shields = Robot_info[obj->id].strength;
177 hide_segment = SEGMENT_NUMBER(Markedsegp);
180 // robots which lunge forward to attack cannot have behavior type still.
181 if (Robot_info[obj->id].attack_type)
182 init_ai_object(OBJECT_NUMBER(obj), AIB_NORMAL, hide_segment);
184 init_ai_object(OBJECT_NUMBER(obj), AIB_STILL, hide_segment);
190 objnum = obj_create(OBJ_POWERUP, object_id,
191 SEGMENT_NUMBER(segp), object_pos, &seg_matrix, Powerup_info[object_id].size,
192 CT_POWERUP, MT_NONE, RT_POWERUP);
197 obj = &Objects[objnum];
199 //set powerup-specific data
201 obj->rtype.vclip_info.vclip_num = Powerup_info[obj->id].vclip_num;
202 obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].play_time/Vclip[obj->rtype.vclip_info.vclip_num].num_frames;
203 obj->rtype.vclip_info.framenum = 0;
205 if (obj->id == POW_VULCAN_WEAPON)
206 obj->ctype.powerup_info.count = VULCAN_WEAPON_AMMO_AMOUNT;
208 obj->ctype.powerup_info.count = 1;
214 objnum = obj_create(OBJ_CNTRLCEN, object_id, SEGMENT_NUMBER(segp), object_pos,
215 &seg_matrix, Polygon_models[object_id].rad,
216 CT_CNTRLCEN, MT_NONE, RT_POLYOBJ);
221 obj = &Objects[objnum];
223 //Set polygon-object-specific data
224 obj->shields = 0; // stored in Reactor_strength or calculated
225 obj->rtype.pobj_info.model_num = Reactors[object_id].model_num;
226 obj->rtype.pobj_info.subobj_flags = 0;
232 objnum = obj_create(OBJ_PLAYER, object_id, SEGMENT_NUMBER(segp), object_pos,
233 &seg_matrix, Polygon_models[Player_ship->model_num].rad,
234 CT_NONE, MT_PHYSICS, RT_POLYOBJ);
239 obj = &Objects[objnum];
241 //Set polygon-object-specific data
243 obj->rtype.pobj_info.model_num = Player_ship->model_num;
244 obj->rtype.pobj_info.subobj_flags = 0;
245 //for (i=0;i<MAX_SUBMODELS;i++)
246 // vm_angvec_zero(&obj->rtype.pobj_info.anim_angles[i]);
250 vm_vec_zero(&obj->mtype.phys_info.velocity);
251 obj->mtype.phys_info.mass = Player_ship->mass;
252 obj->mtype.phys_info.drag = Player_ship->drag;
253 obj->mtype.phys_info.flags |= PF_TURNROLL | PF_LEVELLING | PF_WIGGLE;
254 obj->shields = i2f(100);
262 Cur_object_index = objnum;
263 //Cur_object_seg = Cursegp;
265 show_objects_in_segment(Cursegp); //mprintf the objects
267 Update_flags |= UF_WORLD_CHANGED;
272 // ------------------------------------------------------------------------------------------------------
273 // Count number of player objects, return value.
274 int compute_num_players(void)
278 for (i=0; i<=Highest_object_index; i++)
279 if (Objects[i].type == OBJ_PLAYER)
286 int ObjectMakeCoop(void)
288 Assert(Cur_object_index != -1);
289 Assert(Cur_object_index < MAX_OBJECTS);
290 // Assert(Objects[Cur_object_index.type == OBJ_PLAYER);
292 if (Objects[Cur_object_index].type == OBJ_PLAYER ) {
293 Objects[Cur_object_index].type = OBJ_COOP;
294 editor_status("You just made a player object COOPERATIVE");
296 editor_status("This is not a player object");
301 // ------------------------------------------------------------------------------------------------------
302 // Place current object at center of current segment.
303 int ObjectPlaceObject(void)
305 int old_cur_object_index;
308 vms_vector cur_object_loc;
311 if (Cur_object_type == OBJ_PLAYER)
313 int num_players = compute_num_players();
314 Assert(num_players <= MAX_PLAYERS);
315 if (num_players == MAX_PLAYERS) {
316 editor_status("Can't place player object. Already %i players.", MAX_PLAYERS);
323 if (Cur_object_type == OBJ_PLAYER)
325 int num_players = compute_num_players();
326 Assert(num_players <= MAX_MULTI_PLAYERS);
327 if (num_players > MAX_PLAYERS)
328 editor_status("You just placed a cooperative player object");
329 if (num_players == MAX_MULTI_PLAYERS) {
330 editor_status("Can't place player object. Already %i players.", MAX_MULTI_PLAYERS);
336 //update_due_to_new_segment();
337 compute_segment_center(&cur_object_loc, Cursegp);
339 old_cur_object_index = Cur_object_index;
340 rval = place_object(Cursegp, &cur_object_loc, Cur_object_type, Cur_object_id);
342 if (old_cur_object_index != Cur_object_index)
343 Objects[Cur_object_index].rtype.pobj_info.tmap_override = -1;
349 // ------------------------------------------------------------------------------------------------------
350 // Place current object at center of current segment.
351 int ObjectPlaceObjectTmap(void)
353 int rval, old_cur_object_index;
354 vms_vector cur_object_loc;
356 //update_due_to_new_segment();
357 compute_segment_center(&cur_object_loc, Cursegp);
359 old_cur_object_index = Cur_object_index;
360 rval = place_object(Cursegp, &cur_object_loc, Cur_object_type, Cur_object_id);
362 if ((Cur_object_index != old_cur_object_index) && (Objects[Cur_object_index].render_type == RT_POLYOBJ))
363 Objects[Cur_object_index].rtype.pobj_info.tmap_override = CurrentTexture;
365 editor_status("Unable to apply current texture map to this object.");
370 // ------------------------------------------------------------------------------------------------------
371 int ObjectSelectNextinSegment(void)
377 //update_due_to_new_segment();
379 //Assert(Cur_object_seg == Cursegp);
381 if (Cur_object_index == -1) {
383 Cur_object_index = objsegp->objects;
386 if (Objects[Cur_object_index].segnum != SEGMENT_NUMBER(Cursegp))
387 Cur_object_index = objsegp->objects;
391 //Debug: make sure current object is in current segment
392 for (id=objsegp->objects;(id != Cur_object_index) && (id != -1);id=Objects[id].next);
393 Assert(id == Cur_object_index); //should have found object
395 // Select the next object, wrapping back to start if we are at the end of the linked list for this segment.
397 Cur_object_index = get_next_object(objsegp,Cur_object_index);
399 //mprintf((0,"Cur_object_index == %i\n", Cur_object_index));
401 Update_flags |= UF_WORLD_CHANGED;
407 //Moves to next object in the mine, skipping the player
408 int ObjectSelectNextInMine()
410 for (i=0;i<MAX_OBJECTS;i++) {
412 if (Cur_object_index>= MAX_OBJECTS ) Cur_object_index= 0;
414 if ( (Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != OBJECT_NUMBER(ConsoleObject)) ) {
415 Cursegp = &Segments[Objects[Cur_object_index ].segnum];
416 med_create_new_segment_from_cursegp();
417 //Cur_object_seg = Cursegp;
421 Cur_object_index = -1;
423 Update_flags |= UF_WORLD_CHANGED;
428 //Moves to next object in the mine, skipping the player
429 int ObjectSelectPrevInMine()
431 for (i=0;i<MAX_OBJECTS;i++) {
433 if (Cur_object_index < 0 )
434 Cur_object_index = MAX_OBJECTS-1;
436 if ( (Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != OBJECT_NUMBER(ConsoleObject)) ) {
437 Cursegp = &Segments[Objects[Cur_object_index ].segnum];
438 med_create_new_segment_from_cursegp();
439 //Cur_object_seg = Cursegp;
443 Cur_object_index = -1;
445 Update_flags |= UF_WORLD_CHANGED;
450 // ------------------------------------------------------------------------------------------------------
451 // Delete current object, if it exists.
452 // If it doesn't exist, reformat Matt's hard disk, even if he is in Boston.
453 int ObjectDelete(void)
456 if (Cur_object_index != -1) {
459 delete_objnum = Cur_object_index;
461 ObjectSelectNextinSegment();
463 obj_delete(delete_objnum);
465 if (delete_objnum == Cur_object_index)
466 Cur_object_index = -1;
468 Update_flags |= UF_WORLD_CHANGED;
474 // -----------------------------------------------------------------------------------------------------------------
475 // Object has moved to another segment, (or at least poked through).
476 // If still in mine, that is legal, so relink into new segment.
477 // Return value: 0 = in mine, 1 = not in mine
478 int move_object_within_mine(object * obj, vms_vector *newpos )
482 for (segnum=0;segnum <= Highest_segment_index; segnum++) {
483 segmasks result = get_seg_masks(&obj->pos, segnum, 0, __FILE__, __LINE__);
485 if (result.centermask == 0) {
490 // See if the radius pokes through any wall.
492 fq.startseg = obj->segnum;
496 fq.ignore_obj_list = NULL;
499 fate = find_vector_intersection(&fq,&hit_info);
501 if (fate != HIT_WALL) {
502 if ( segnum != obj->segnum )
503 obj_relink( OBJECT_NUMBER(obj), segnum );
507 //mprintf((0, "Hit wall seg:side = %i:%i\n", hit_info.hit_seg, hit_info.hit_side));
516 // Return 0 if object is in expected segment, else return 1
517 int verify_object_seg(object *objp, vms_vector *newpos)
519 segmasks result = get_seg_masks(newpos, objp->segnum, objp->size, __FILE__, __LINE__);
521 if (result.facemask == 0)
524 return move_object_within_mine(objp, newpos);
528 // ------------------------------------------------------------------------------------------------------
529 int ObjectMoveForward(void)
535 if (Cur_object_index == -1) {
536 editor_status("No current object, cannot move.");
540 obj = &Objects[Cur_object_index];
542 extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
543 vm_vec_normalize(&fvec);
545 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
547 if (!verify_object_seg(obj, &newpos))
550 Update_flags |= UF_WORLD_CHANGED;
555 // ------------------------------------------------------------------------------------------------------
556 int ObjectMoveBack(void)
562 if (Cur_object_index == -1) {
563 editor_status("No current object, cannot move.");
567 obj = &Objects[Cur_object_index];
569 extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
570 vm_vec_normalize(&fvec);
572 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
574 if (!verify_object_seg(obj, &newpos))
577 Update_flags |= UF_WORLD_CHANGED;
582 // ------------------------------------------------------------------------------------------------------
583 int ObjectMoveLeft(void)
589 if (Cur_object_index == -1) {
590 editor_status("No current object, cannot move.");
594 obj = &Objects[Cur_object_index];
596 extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
597 vm_vec_normalize(&rvec);
599 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
601 if (!verify_object_seg(obj, &newpos))
604 Update_flags |= UF_WORLD_CHANGED;
609 // ------------------------------------------------------------------------------------------------------
610 int ObjectMoveRight(void)
616 if (Cur_object_index == -1) {
617 editor_status("No current object, cannot move.");
621 obj = &Objects[Cur_object_index];
623 extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
624 vm_vec_normalize(&rvec);
626 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
628 if (!verify_object_seg(obj, &newpos))
631 Update_flags |= UF_WORLD_CHANGED;
636 // ------------------------------------------------------------------------------------------------------
637 int ObjectSetDefault(void)
639 //update_due_to_new_segment();
641 if (Cur_object_index == -1) {
642 editor_status("No current object, cannot move.");
646 compute_segment_center(&Objects[Cur_object_index].pos, &Segments[Objects[Cur_object_index].segnum]);
648 Update_flags |= UF_WORLD_CHANGED;
654 // ------------------------------------------------------------------------------------------------------
655 int ObjectMoveUp(void)
661 if (Cur_object_index == -1) {
662 editor_status("No current object, cannot move.");
666 obj = &Objects[Cur_object_index];
668 extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
669 vm_vec_normalize(&uvec);
671 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
673 if (!verify_object_seg(obj, &newpos))
676 Update_flags |= UF_WORLD_CHANGED;
681 // ------------------------------------------------------------------------------------------------------
682 int ObjectMoveDown(void)
688 if (Cur_object_index == -1) {
689 editor_status("No current object, cannot move.");
693 obj = &Objects[Cur_object_index];
695 extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
696 vm_vec_normalize(&uvec);
698 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
700 if (!verify_object_seg(obj, &newpos))
703 Update_flags |= UF_WORLD_CHANGED;
708 // ------------------------------------------------------------------------------------------------------
709 int ObjectMakeSmaller(void)
713 //update_due_to_new_segment();
715 cur_size = Objects[Cur_object_index].size;
717 cur_size -= OBJ_DEL_SIZE;
718 if (cur_size < OBJ_DEL_SIZE)
719 cur_size = OBJ_DEL_SIZE;
721 Objects[Cur_object_index].size = cur_size;
723 Update_flags |= UF_WORLD_CHANGED;
728 // ------------------------------------------------------------------------------------------------------
729 int ObjectMakeLarger(void)
733 //update_due_to_new_segment();
735 cur_size = Objects[Cur_object_index].size;
737 cur_size += OBJ_DEL_SIZE;
739 Objects[Cur_object_index].size = cur_size;
741 Update_flags |= UF_WORLD_CHANGED;
746 // ------------------------------------------------------------------------------------------------------
748 int rotate_object(short objnum, int p, int b, int h)
750 object *obj = &Objects[objnum];
752 vms_matrix rotmat,tempm;
754 // vm_extract_angles_matrix( &ang,&obj->orient);
764 vm_angles_2_matrix(&rotmat, &ang);
765 vm_matrix_x_matrix(&tempm, &obj->orient, &rotmat);
768 // vm_angles_2_matrix(&obj->orient, &ang);
770 Update_flags |= UF_WORLD_CHANGED;
776 void reset_object(short objnum)
778 object *obj = &Objects[objnum];
780 med_extract_matrix_from_segment(&Segments[obj->segnum],&obj->orient);
786 int ObjectResetObject()
788 reset_object(Cur_object_index);
790 Update_flags |= UF_WORLD_CHANGED;
796 int ObjectFlipObject()
798 vms_matrix *m=&Objects[Cur_object_index].orient;
800 vm_vec_negate(&m->uvec);
801 vm_vec_negate(&m->rvec);
803 Update_flags |= UF_WORLD_CHANGED;
808 int ObjectDecreaseBank() {return rotate_object(Cur_object_index, 0, -ROTATION_UNIT, 0);}
809 int ObjectIncreaseBank() {return rotate_object(Cur_object_index, 0, ROTATION_UNIT, 0);}
810 int ObjectDecreasePitch() {return rotate_object(Cur_object_index, -ROTATION_UNIT, 0, 0);}
811 int ObjectIncreasePitch() {return rotate_object(Cur_object_index, ROTATION_UNIT, 0, 0);}
812 int ObjectDecreaseHeading() {return rotate_object(Cur_object_index, 0, 0, -ROTATION_UNIT);}
813 int ObjectIncreaseHeading() {return rotate_object(Cur_object_index, 0, 0, ROTATION_UNIT);}
815 int ObjectDecreaseBankBig() {return rotate_object(Cur_object_index, 0, -(ROTATION_UNIT*4), 0);}
816 int ObjectIncreaseBankBig() {return rotate_object(Cur_object_index, 0, (ROTATION_UNIT*4), 0);}
817 int ObjectDecreasePitchBig() {return rotate_object(Cur_object_index, -(ROTATION_UNIT*4), 0, 0);}
818 int ObjectIncreasePitchBig() {return rotate_object(Cur_object_index, (ROTATION_UNIT*4), 0, 0);}
819 int ObjectDecreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, -(ROTATION_UNIT*4));}
820 int ObjectIncreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, (ROTATION_UNIT*4));}
822 // -----------------------------------------------------------------------------------------------------
823 // Move object around based on clicks in 2d screen.
824 // Slide an object parallel to the 2d screen, to a point on a vector.
825 // The vector is defined by a point on the 2d screen and the eye.
827 // V = vector from eye to 2d screen point.
829 // F = forward vector from eye
830 // O = 3-space location of object
832 // D = depth of object given forward vector F
833 // = (OE dot norm(F))
835 // Must solve intersection of:
836 // E + tV ( equation of vector from eye through point on 2d screen)
837 // Fs + D ( equation of plane parallel to 2d screen, at depth D)
838 // = Fx(Ex + tVx) + Fy(Ey + tVy) + Fz(Ez + tVz) + D = 0
840 // FxEx + FyEy + FzEz - D
841 // t = - ----------------------
842 // VxFx + VyFy + VzFz
845 //void print_vec(vms_vector *vec, char *text)
847 // mprintf((0, "%10s = %9.5f %9.5f %9.5f\n", text, f2fl(vec->x), f2fl(vec->y), f2fl(vec->z)));
850 // void solve(vms_vector *result, vms_vector *E, vms_vector *V, vms_vector *O, vms_vector *F)
853 // vms_vector Fnorm, Vnorm;
855 // // float test_plane;
857 // print_vec(E, "E");
858 // print_vec(V, "V");
859 // print_vec(O, "O");
860 // print_vec(F, "F");
862 // Fnorm = *F; vm_vec_normalize(&Fnorm);
863 // Vnorm = *V; vm_vec_normalize(&Vnorm);
865 // D = (fixmul(O->x, Fnorm.x) + fixmul(O->y, Fnorm.y) + fixmul(O->z, Fnorm.z));
866 // mprintf((0, "D = %9.5f\n", f2fl(D)));
868 // num = fixmul(Fnorm.x, E->x) + fixmul(Fnorm.y, E->y) + fixmul(Fnorm.z, E->z) - D;
869 // denom = vm_vec_dot(&Vnorm, &Fnorm);
872 // mprintf((0, "num = %9.5f, denom = %9.5f, t = %9.5f\n", f2fl(num), f2fl(denom), f2fl(t)));
874 // result->x = E->x + fixmul(t, Vnorm.x);
875 // result->y = E->y + fixmul(t, Vnorm.y);
876 // result->z = E->z + fixmul(t, Vnorm.z);
878 // print_vec(result, "result");
880 // // test_plane = fixmul(result->x, Fnorm.x) + fixmul(result->y, Fnorm.y) + fixmul(result->z, Fnorm.z) - D;
881 // // if (abs(test_plane) > .001)
882 // // printf("OOPS: test_plane = %9.5f\n", test_plane);
885 void move_object_to_position(int objnum, vms_vector *newpos)
887 object *objp = &Objects[objnum];
889 segmasks result = get_seg_masks(newpos, objp->segnum, objp->size, __FILE__, __LINE__);
891 if (result.facemask == 0) {
892 //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)));
895 if (verify_object_seg(&Objects[objnum], newpos)) {
898 object temp_viewer_obj;
901 vms_vector last_outside_pos;
902 vms_vector last_inside_pos;
904 temp_viewer_obj = *Viewer;
905 viewer_segnum = find_object_seg(&temp_viewer_obj);
906 temp_viewer_obj.segnum = viewer_segnum;
908 // If the viewer is outside the mine, get him in the mine!
909 if (viewer_segnum == -1) {
910 // While outside mine, move towards object
912 while (viewer_segnum == -1) {
915 //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)));
916 last_outside_pos = temp_viewer_obj.pos;
918 vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, newpos);
919 temp_viewer_obj.pos = temp_vec;
920 viewer_segnum = find_object_seg(&temp_viewer_obj);
921 temp_viewer_obj.segnum = viewer_segnum;
924 editor_status("Unable to move object, can't get viewer in mine. Aborting");
930 // While inside mine, move away from object.
931 while (viewer_segnum != -1) {
935 //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)));
936 last_inside_pos = temp_viewer_obj.pos;
938 vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, &last_outside_pos);
939 temp_viewer_obj.pos = temp_vec;
940 update_object_seg(&temp_viewer_obj);
941 viewer_segnum = find_object_seg(&temp_viewer_obj);
942 temp_viewer_obj.segnum = viewer_segnum;
945 editor_status("Unable to move object, can't get viewer back out of mine. Aborting");
951 fq.p0 = &temp_viewer_obj.pos;
952 fq.startseg = temp_viewer_obj.segnum;
954 fq.rad = temp_viewer_obj.size;
956 fq.ignore_obj_list = NULL;
959 fate = find_vector_intersection(&fq,&hit_info);
960 if (fate == HIT_WALL) {
963 //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)));
964 objp->pos = hit_info.hit_pnt;
965 new_segnum = find_object_seg(objp);
966 Assert(new_segnum != -1);
967 obj_relink(OBJECT_NUMBER(objp), new_segnum);
968 //mprintf((0, "Object moved from segment %i to %i\n", old_segnum, objp->segnum));
970 editor_status("Attempted to move object out of mine. Object not moved.");
971 //mprintf((0,"Attempted to move object out of mine. Object not moved."));
976 Update_flags |= UF_WORLD_CHANGED;
979 void move_object_to_vector(vms_vector *vec_through_screen, fix delta_distance)
983 vm_vec_scale_add(&result, &Viewer->pos, vec_through_screen, vm_vec_dist(&Viewer->pos,&Objects[Cur_object_index].pos)+delta_distance);
985 move_object_to_position(Cur_object_index, &result);
989 void move_object_to_mouse_click_delta(fix delta_distance)
992 vms_vector vec_through_screen;
994 if (Cur_object_index == -1) {
995 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
999 xcrd = GameViewBox->b1_drag_x1;
1000 ycrd = GameViewBox->b1_drag_y1;
1002 med_point_2_vec(&_canv_editor_game, &vec_through_screen, xcrd, ycrd);
1004 //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)));
1006 move_object_to_vector(&vec_through_screen, delta_distance);
1010 void move_object_to_mouse_click(void)
1012 move_object_to_mouse_click_delta(0);
1015 int ObjectMoveNearer(void)
1019 if (Cur_object_index == -1) {
1020 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1024 // move_object_to_mouse_click_delta(-4*F1_0); // Move four units closer to eye
1026 vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
1027 vm_vec_normalize(&result);
1028 move_object_to_vector(&result, -4*F1_0);
1033 int ObjectMoveFurther(void)
1037 if (Cur_object_index == -1) {
1038 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1042 // move_object_to_mouse_click_delta(+4*F1_0); // Move four units further from eye
1044 vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
1045 vm_vec_normalize(&result);
1046 move_object_to_vector(&result, 4*F1_0);