1 /* $Id: eobject.c,v 1.2 2004-12-19 14:52:48 btb 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.
23 static char rcsid[] = "$Id: eobject.c,v 1.2 2004-12-19 14:52:48 btb Exp $";
46 #include "3d.h" // For g3_point_to_vec
56 #define OBJ_SCALE (F1_0/2)
57 #define OBJ_DEL_SIZE (F1_0/2)
59 #define ROTATION_UNIT (4096/4)
61 //segment *Cur_object_seg = -1;
63 void show_objects_in_segment(segment *sp)
67 mprintf((0,"Objects in segment #%i: ",sp-Segments));
71 mprintf((0,"%2i ",objid));
72 objid = Objects[objid].next;
77 //returns the number of the first object in a segment, skipping the player
78 int get_first_object(segment *seg)
84 if (id == (ConsoleObject-Objects))
85 id = Objects[id].next;
90 //returns the number of the next object in a segment, skipping the player
91 int get_next_object(segment *seg,int id)
93 if (id==-1 || (id=Objects[id].next)==-1)
94 return get_first_object(seg);
96 if (id == (ConsoleObject-Objects))
97 return get_next_object(seg,id);
103 //@@// ------------------------------------------------------------------------------------------------------
104 //@@// this should be called whenever the current segment may have changed
105 //@@// If Cur_object_seg != Cursegp, then update various variables.
106 //@@// this used to be called update_due_to_new_segment()
107 //@@void ObjectUpdateCurrent(void)
109 //@@ if (Cur_object_seg != Cursegp) {
110 //@@ Cur_object_seg = Cursegp;
111 //@@ Cur_object_index = get_first_object(Cur_object_seg);
112 //@@ Update_flags |= UF_WORLD_CHANGED;
117 // ------------------------------------------------------------------------------------
118 int place_object(segment *segp, vms_vector *object_pos, int object_type)
122 vms_matrix seg_matrix;
124 med_extract_matrix_from_segment(segp,&seg_matrix);
126 switch(ObjType[object_type]) {
130 objnum = obj_create(OBJ_HOSTAGE, -1,
131 segp-Segments,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 );
142 obj->control_type = CT_POWERUP;
144 obj->rtype.vclip_info.vclip_num = Hostage_vclip_num[ObjId[object_type]];
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,ObjId[object_type],segp-Segments,object_pos,
153 &seg_matrix,Polygon_models[Robot_info[ObjId[object_type]].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 = Markedsegp-Segments;
180 // robots which lunge forward to attack cannot have behavior type still.
181 if (Robot_info[obj->id].attack_type)
182 init_ai_object(obj-Objects, AIB_NORMAL, hide_segment);
184 init_ai_object(obj-Objects, AIB_STILL, hide_segment);
190 objnum = obj_create(OBJ_POWERUP,ObjId[object_type],
191 segp-Segments,object_pos,&seg_matrix,Powerup_info[ObjId[object_type]].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;
213 case OL_CONTROL_CENTER:
215 int obj_type,control_type;
217 if (ObjType[object_type]==OL_CONTROL_CENTER) {
218 obj_type = OBJ_CNTRLCEN;
219 control_type = CT_CNTRLCEN;
222 obj_type = OBJ_CLUTTER;
223 control_type = CT_NONE;
226 objnum = obj_create(obj_type,object_type,segp-Segments,object_pos,
227 &seg_matrix,Polygon_models[ObjId[object_type]].rad,
228 control_type,MT_NONE,RT_POLYOBJ);
233 obj = &Objects[objnum];
235 obj->shields = ObjStrength[object_type];
237 //Set polygon-object-specific data
238 obj->shields = ObjStrength[object_type];
239 obj->rtype.pobj_info.model_num = ObjId[object_type];
240 obj->rtype.pobj_info.subobj_flags = 0;
246 objnum = obj_create(OBJ_PLAYER,ObjId[object_type],segp-Segments,object_pos,
247 &seg_matrix,Polygon_models[Player_ship->model_num].rad,
248 CT_NONE,MT_PHYSICS,RT_POLYOBJ);
253 obj = &Objects[objnum];
255 //Set polygon-object-specific data
257 obj->rtype.pobj_info.model_num = Player_ship->model_num;
258 obj->rtype.pobj_info.subobj_flags = 0;
259 //for (i=0;i<MAX_SUBMODELS;i++)
260 // vm_angvec_zero(&obj->rtype.pobj_info.anim_angles[i]);
264 vm_vec_zero(&obj->mtype.phys_info.velocity);
265 obj->mtype.phys_info.mass = Player_ship->mass;
266 obj->mtype.phys_info.drag = Player_ship->drag;
267 obj->mtype.phys_info.flags |= PF_TURNROLL | PF_LEVELLING | PF_WIGGLE;
268 obj->shields = i2f(100);
276 Cur_object_index = objnum;
277 //Cur_object_seg = Cursegp;
279 show_objects_in_segment(Cursegp); //mprintf the objects
281 Update_flags |= UF_WORLD_CHANGED;
286 // ------------------------------------------------------------------------------------------------------
287 // Count number of player objects, return value.
288 int compute_num_players(void)
292 for (i=0; i<=Highest_object_index; i++)
293 if (Objects[i].type == OBJ_PLAYER)
300 int ObjectMakeCoop(void)
302 Assert(Cur_object_index != -1);
303 Assert(Cur_object_index < MAX_OBJECTS);
304 // Assert(Objects[Cur_object_index.type == OBJ_PLAYER);
306 if (Objects[Cur_object_index].type == OBJ_PLAYER ) {
307 Objects[Cur_object_index].type = OBJ_COOP;
308 editor_status("You just made a player object COOPERATIVE");
310 editor_status("This is not a player object");
315 // ------------------------------------------------------------------------------------------------------
316 // Place current object at center of current segment.
317 int ObjectPlaceObject(void)
319 int old_cur_object_index;
322 vms_vector cur_object_loc;
325 if (ObjType[Cur_robot_type] == OL_PLAYER) {
326 int num_players = compute_num_players();
327 Assert(num_players <= MAX_PLAYERS);
328 if (num_players == MAX_PLAYERS) {
329 editor_status("Can't place player object. Already %i players.", MAX_PLAYERS);
336 if (ObjType[Cur_robot_type] == OL_PLAYER) {
337 int num_players = compute_num_players();
338 Assert(num_players <= MAX_MULTI_PLAYERS);
339 if (num_players > MAX_PLAYERS)
340 editor_status("You just placed a cooperative player object");
341 if (num_players == MAX_MULTI_PLAYERS) {
342 editor_status("Can't place player object. Already %i players.", MAX_MULTI_PLAYERS);
348 //update_due_to_new_segment();
349 compute_segment_center(&cur_object_loc, Cursegp);
351 old_cur_object_index = Cur_object_index;
352 rval = place_object(Cursegp, &cur_object_loc, Cur_robot_type);
354 if (old_cur_object_index != Cur_object_index)
355 Objects[Cur_object_index].rtype.pobj_info.tmap_override = -1;
361 // ------------------------------------------------------------------------------------------------------
362 // Place current object at center of current segment.
363 int ObjectPlaceObjectTmap(void)
365 int rval, old_cur_object_index;
366 vms_vector cur_object_loc;
368 //update_due_to_new_segment();
369 compute_segment_center(&cur_object_loc, Cursegp);
371 old_cur_object_index = Cur_object_index;
372 rval = place_object(Cursegp, &cur_object_loc, Cur_robot_type);
374 if ((Cur_object_index != old_cur_object_index) && (Objects[Cur_object_index].render_type == RT_POLYOBJ))
375 Objects[Cur_object_index].rtype.pobj_info.tmap_override = CurrentTexture;
377 editor_status("Unable to apply current texture map to this object.");
382 // ------------------------------------------------------------------------------------------------------
383 int ObjectSelectNextinSegment(void)
389 //update_due_to_new_segment();
391 //Assert(Cur_object_seg == Cursegp);
393 if (Cur_object_index == -1) {
395 Cur_object_index = objsegp->objects;
398 if (Objects[Cur_object_index].segnum != Cursegp-Segments)
399 Cur_object_index = objsegp->objects;
403 //Debug: make sure current object is in current segment
404 for (id=objsegp->objects;(id != Cur_object_index) && (id != -1);id=Objects[id].next);
405 Assert(id == Cur_object_index); //should have found object
407 // Select the next object, wrapping back to start if we are at the end of the linked list for this segment.
409 Cur_object_index = get_next_object(objsegp,Cur_object_index);
411 //mprintf((0,"Cur_object_index == %i\n", Cur_object_index));
413 Update_flags |= UF_WORLD_CHANGED;
419 //Moves to next object in the mine, skipping the player
420 int ObjectSelectNextInMine()
422 for (i=0;i<MAX_OBJECTS;i++) {
424 if (Cur_object_index>= MAX_OBJECTS ) Cur_object_index= 0;
426 if ((Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != (ConsoleObject-Objects)) ) {
427 Cursegp = &Segments[Objects[Cur_object_index ].segnum];
428 med_create_new_segment_from_cursegp();
429 //Cur_object_seg = Cursegp;
433 Cur_object_index = -1;
435 Update_flags |= UF_WORLD_CHANGED;
440 //Moves to next object in the mine, skipping the player
441 int ObjectSelectPrevInMine()
443 for (i=0;i<MAX_OBJECTS;i++) {
445 if (Cur_object_index < 0 )
446 Cur_object_index = MAX_OBJECTS-1;
448 if ((Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != (ConsoleObject-Objects)) ) {
449 Cursegp = &Segments[Objects[Cur_object_index ].segnum];
450 med_create_new_segment_from_cursegp();
451 //Cur_object_seg = Cursegp;
455 Cur_object_index = -1;
457 Update_flags |= UF_WORLD_CHANGED;
462 // ------------------------------------------------------------------------------------------------------
463 // Delete current object, if it exists.
464 // If it doesn't exist, reformat Matt's hard disk, even if he is in Boston.
465 int ObjectDelete(void)
468 if (Cur_object_index != -1) {
471 delete_objnum = Cur_object_index;
473 ObjectSelectNextinSegment();
475 obj_delete(delete_objnum);
477 if (delete_objnum == Cur_object_index)
478 Cur_object_index = -1;
480 Update_flags |= UF_WORLD_CHANGED;
486 // -----------------------------------------------------------------------------------------------------------------
487 // Object has moved to another segment, (or at least poked through).
488 // If still in mine, that is legal, so relink into new segment.
489 // Return value: 0 = in mine, 1 = not in mine
490 int move_object_within_mine(object * obj, vms_vector *newpos )
494 for (segnum=0;segnum <= Highest_segment_index; segnum++) {
495 segmasks result = get_seg_masks(&obj->pos,segnum,0);
496 if (result.centermask == 0) {
501 // See if the radius pokes through any wall.
503 fq.startseg = obj->segnum;
507 fq.ignore_obj_list = NULL;
510 fate = find_vector_intersection(&fq,&hit_info);
512 if (fate != HIT_WALL) {
513 if ( segnum != obj->segnum )
514 obj_relink( obj-Objects, segnum);
518 //mprintf((0, "Hit wall seg:side = %i:%i\n", hit_info.hit_seg, hit_info.hit_side));
527 // Return 0 if object is in expected segment, else return 1
528 int verify_object_seg(object *objp, vms_vector *newpos)
530 segmasks result = get_seg_masks(newpos, objp->segnum, objp->size);
532 if (result.facemask == 0)
535 return move_object_within_mine(objp, newpos);
539 // ------------------------------------------------------------------------------------------------------
540 int ObjectMoveForward(void)
546 if (Cur_object_index == -1) {
547 editor_status("No current object, cannot move.");
551 obj = &Objects[Cur_object_index];
553 extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
554 vm_vec_normalize(&fvec);
556 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
558 if (!verify_object_seg(obj, &newpos))
561 Update_flags |= UF_WORLD_CHANGED;
566 // ------------------------------------------------------------------------------------------------------
567 int ObjectMoveBack(void)
573 if (Cur_object_index == -1) {
574 editor_status("No current object, cannot move.");
578 obj = &Objects[Cur_object_index];
580 extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
581 vm_vec_normalize(&fvec);
583 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
585 if (!verify_object_seg(obj, &newpos))
588 Update_flags |= UF_WORLD_CHANGED;
593 // ------------------------------------------------------------------------------------------------------
594 int ObjectMoveLeft(void)
600 if (Cur_object_index == -1) {
601 editor_status("No current object, cannot move.");
605 obj = &Objects[Cur_object_index];
607 extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
608 vm_vec_normalize(&rvec);
610 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
612 if (!verify_object_seg(obj, &newpos))
615 Update_flags |= UF_WORLD_CHANGED;
620 // ------------------------------------------------------------------------------------------------------
621 int ObjectMoveRight(void)
627 if (Cur_object_index == -1) {
628 editor_status("No current object, cannot move.");
632 obj = &Objects[Cur_object_index];
634 extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
635 vm_vec_normalize(&rvec);
637 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
639 if (!verify_object_seg(obj, &newpos))
642 Update_flags |= UF_WORLD_CHANGED;
647 // ------------------------------------------------------------------------------------------------------
648 int ObjectSetDefault(void)
650 //update_due_to_new_segment();
652 if (Cur_object_index == -1) {
653 editor_status("No current object, cannot move.");
657 compute_segment_center(&Objects[Cur_object_index].pos, &Segments[Objects[Cur_object_index].segnum]);
659 Update_flags |= UF_WORLD_CHANGED;
665 // ------------------------------------------------------------------------------------------------------
666 int ObjectMoveUp(void)
672 if (Cur_object_index == -1) {
673 editor_status("No current object, cannot move.");
677 obj = &Objects[Cur_object_index];
679 extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
680 vm_vec_normalize(&uvec);
682 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
684 if (!verify_object_seg(obj, &newpos))
687 Update_flags |= UF_WORLD_CHANGED;
692 // ------------------------------------------------------------------------------------------------------
693 int ObjectMoveDown(void)
699 if (Cur_object_index == -1) {
700 editor_status("No current object, cannot move.");
704 obj = &Objects[Cur_object_index];
706 extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
707 vm_vec_normalize(&uvec);
709 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
711 if (!verify_object_seg(obj, &newpos))
714 Update_flags |= UF_WORLD_CHANGED;
719 // ------------------------------------------------------------------------------------------------------
720 int ObjectMakeSmaller(void)
724 //update_due_to_new_segment();
726 cur_size = Objects[Cur_object_index].size;
728 cur_size -= OBJ_DEL_SIZE;
729 if (cur_size < OBJ_DEL_SIZE)
730 cur_size = OBJ_DEL_SIZE;
732 Objects[Cur_object_index].size = cur_size;
734 Update_flags |= UF_WORLD_CHANGED;
739 // ------------------------------------------------------------------------------------------------------
740 int ObjectMakeLarger(void)
744 //update_due_to_new_segment();
746 cur_size = Objects[Cur_object_index].size;
748 cur_size += OBJ_DEL_SIZE;
750 Objects[Cur_object_index].size = cur_size;
752 Update_flags |= UF_WORLD_CHANGED;
757 // ------------------------------------------------------------------------------------------------------
759 int rotate_object(short objnum, int p, int b, int h)
761 object *obj = &Objects[objnum];
763 vms_matrix rotmat,tempm;
765 // vm_extract_angles_matrix( &ang,&obj->orient);
775 vm_angles_2_matrix(&rotmat, &ang);
776 vm_matrix_x_matrix(&tempm, &obj->orient, &rotmat);
779 // vm_angles_2_matrix(&obj->orient, &ang);
781 Update_flags |= UF_WORLD_CHANGED;
787 void reset_object(short objnum)
789 object *obj = &Objects[objnum];
791 med_extract_matrix_from_segment(&Segments[obj->segnum],&obj->orient);
797 int ObjectResetObject()
799 reset_object(Cur_object_index);
801 Update_flags |= UF_WORLD_CHANGED;
807 int ObjectFlipObject()
809 vms_matrix *m=&Objects[Cur_object_index].orient;
811 vm_vec_negate(&m->uvec);
812 vm_vec_negate(&m->rvec);
814 Update_flags |= UF_WORLD_CHANGED;
819 int ObjectDecreaseBank() {return rotate_object(Cur_object_index, 0, -ROTATION_UNIT, 0);}
820 int ObjectIncreaseBank() {return rotate_object(Cur_object_index, 0, ROTATION_UNIT, 0);}
821 int ObjectDecreasePitch() {return rotate_object(Cur_object_index, -ROTATION_UNIT, 0, 0);}
822 int ObjectIncreasePitch() {return rotate_object(Cur_object_index, ROTATION_UNIT, 0, 0);}
823 int ObjectDecreaseHeading() {return rotate_object(Cur_object_index, 0, 0, -ROTATION_UNIT);}
824 int ObjectIncreaseHeading() {return rotate_object(Cur_object_index, 0, 0, ROTATION_UNIT);}
826 int ObjectDecreaseBankBig() {return rotate_object(Cur_object_index, 0, -(ROTATION_UNIT*4), 0);}
827 int ObjectIncreaseBankBig() {return rotate_object(Cur_object_index, 0, (ROTATION_UNIT*4), 0);}
828 int ObjectDecreasePitchBig() {return rotate_object(Cur_object_index, -(ROTATION_UNIT*4), 0, 0);}
829 int ObjectIncreasePitchBig() {return rotate_object(Cur_object_index, (ROTATION_UNIT*4), 0, 0);}
830 int ObjectDecreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, -(ROTATION_UNIT*4));}
831 int ObjectIncreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, (ROTATION_UNIT*4));}
833 // -----------------------------------------------------------------------------------------------------
834 // Move object around based on clicks in 2d screen.
835 // Slide an object parallel to the 2d screen, to a point on a vector.
836 // The vector is defined by a point on the 2d screen and the eye.
838 // V = vector from eye to 2d screen point.
840 // F = forward vector from eye
841 // O = 3-space location of object
843 // D = depth of object given forward vector F
844 // = (OE dot norm(F))
846 // Must solve intersection of:
847 // E + tV ( equation of vector from eye through point on 2d screen)
848 // Fs + D ( equation of plane parallel to 2d screen, at depth D)
849 // = Fx(Ex + tVx) + Fy(Ey + tVy) + Fz(Ez + tVz) + D = 0
851 // FxEx + FyEy + FzEz - D
852 // t = - ----------------------
853 // VxFx + VyFy + VzFz
856 //void print_vec(vms_vector *vec, char *text)
858 // mprintf((0, "%10s = %9.5f %9.5f %9.5f\n", text, f2fl(vec->x), f2fl(vec->y), f2fl(vec->z)));
861 // void solve(vms_vector *result, vms_vector *E, vms_vector *V, vms_vector *O, vms_vector *F)
864 // vms_vector Fnorm, Vnorm;
866 // // float test_plane;
868 // print_vec(E, "E");
869 // print_vec(V, "V");
870 // print_vec(O, "O");
871 // print_vec(F, "F");
873 // Fnorm = *F; vm_vec_normalize(&Fnorm);
874 // Vnorm = *V; vm_vec_normalize(&Vnorm);
876 // D = (fixmul(O->x, Fnorm.x) + fixmul(O->y, Fnorm.y) + fixmul(O->z, Fnorm.z));
877 // mprintf((0, "D = %9.5f\n", f2fl(D)));
879 // num = fixmul(Fnorm.x, E->x) + fixmul(Fnorm.y, E->y) + fixmul(Fnorm.z, E->z) - D;
880 // denom = vm_vec_dot(&Vnorm, &Fnorm);
883 // mprintf((0, "num = %9.5f, denom = %9.5f, t = %9.5f\n", f2fl(num), f2fl(denom), f2fl(t)));
885 // result->x = E->x + fixmul(t, Vnorm.x);
886 // result->y = E->y + fixmul(t, Vnorm.y);
887 // result->z = E->z + fixmul(t, Vnorm.z);
889 // print_vec(result, "result");
891 // // test_plane = fixmul(result->x, Fnorm.x) + fixmul(result->y, Fnorm.y) + fixmul(result->z, Fnorm.z) - D;
892 // // if (abs(test_plane) > .001)
893 // // printf("OOPS: test_plane = %9.5f\n", test_plane);
896 void move_object_to_position(int objnum, vms_vector *newpos)
898 object *objp = &Objects[objnum];
900 segmasks result = get_seg_masks(newpos, objp->segnum, objp->size);
902 if (result.facemask == 0) {
903 //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)));
906 if (verify_object_seg(&Objects[objnum], newpos)) {
909 object temp_viewer_obj;
912 vms_vector last_outside_pos;
913 vms_vector last_inside_pos;
915 temp_viewer_obj = *Viewer;
916 viewer_segnum = find_object_seg(&temp_viewer_obj);
917 temp_viewer_obj.segnum = viewer_segnum;
919 // If the viewer is outside the mine, get him in the mine!
920 if (viewer_segnum == -1) {
921 // While outside mine, move towards object
923 while (viewer_segnum == -1) {
926 //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)));
927 last_outside_pos = temp_viewer_obj.pos;
929 vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, newpos);
930 temp_viewer_obj.pos = temp_vec;
931 viewer_segnum = find_object_seg(&temp_viewer_obj);
932 temp_viewer_obj.segnum = viewer_segnum;
935 editor_status("Unable to move object, can't get viewer in mine. Aborting");
941 // While inside mine, move away from object.
942 while (viewer_segnum != -1) {
946 //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)));
947 last_inside_pos = temp_viewer_obj.pos;
949 vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, &last_outside_pos);
950 temp_viewer_obj.pos = temp_vec;
951 update_object_seg(&temp_viewer_obj);
952 viewer_segnum = find_object_seg(&temp_viewer_obj);
953 temp_viewer_obj.segnum = viewer_segnum;
956 editor_status("Unable to move object, can't get viewer back out of mine. Aborting");
962 fq.p0 = &temp_viewer_obj.pos;
963 fq.startseg = temp_viewer_obj.segnum;
965 fq.rad = temp_viewer_obj.size;
967 fq.ignore_obj_list = NULL;
970 fate = find_vector_intersection(&fq,&hit_info);
971 if (fate == HIT_WALL) {
974 //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)));
975 objp->pos = hit_info.hit_pnt;
976 new_segnum = find_object_seg(objp);
977 Assert(new_segnum != -1);
978 obj_relink(objp-Objects, new_segnum);
979 //mprintf((0, "Object moved from segment %i to %i\n", old_segnum, objp->segnum));
981 editor_status("Attempted to move object out of mine. Object not moved.");
982 //mprintf((0,"Attempted to move object out of mine. Object not moved."));
987 Update_flags |= UF_WORLD_CHANGED;
990 void move_object_to_vector(vms_vector *vec_through_screen, fix delta_distance)
994 vm_vec_scale_add(&result, &Viewer->pos, vec_through_screen, vm_vec_dist(&Viewer->pos,&Objects[Cur_object_index].pos)+delta_distance);
996 move_object_to_position(Cur_object_index, &result);
1000 void move_object_to_mouse_click_delta(fix delta_distance)
1003 vms_vector vec_through_screen;
1005 if (Cur_object_index == -1) {
1006 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1010 xcrd = GameViewBox->b1_drag_x1;
1011 ycrd = GameViewBox->b1_drag_y1;
1013 med_point_2_vec(&_canv_editor_game, &vec_through_screen, xcrd, ycrd);
1015 //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)));
1017 move_object_to_vector(&vec_through_screen, delta_distance);
1021 void move_object_to_mouse_click(void)
1023 move_object_to_mouse_click_delta(0);
1026 int ObjectMoveNearer(void)
1030 if (Cur_object_index == -1) {
1031 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1035 // move_object_to_mouse_click_delta(-4*F1_0); // Move four units closer to eye
1037 vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
1038 vm_vec_normalize(&result);
1039 move_object_to_vector(&result, -4*F1_0);
1044 int ObjectMoveFurther(void)
1048 if (Cur_object_index == -1) {
1049 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1053 // move_object_to_mouse_click_delta(+4*F1_0); // Move four units further from eye
1055 vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
1056 vm_vec_normalize(&result);
1057 move_object_to_vector(&result, 4*F1_0);