1 /* $Id: eobject.c,v 1.4 2004-12-20 06:28:10 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.
22 static char rcsid[] = "$Id: eobject.c,v 1.4 2004-12-20 06:28:10 btb Exp $";
49 #include "3d.h" // For g3_point_to_vec
59 #define OBJ_SCALE (F1_0/2)
60 #define OBJ_DEL_SIZE (F1_0/2)
62 #define ROTATION_UNIT (4096/4)
64 //segment *Cur_object_seg = -1;
66 void show_objects_in_segment(segment *sp)
70 mprintf((0,"Objects in segment #%i: ",sp-Segments));
74 mprintf((0,"%2i ",objid));
75 objid = Objects[objid].next;
80 //returns the number of the first object in a segment, skipping the player
81 int get_first_object(segment *seg)
87 if (id == (ConsoleObject-Objects))
88 id = Objects[id].next;
93 //returns the number of the next object in a segment, skipping the player
94 int get_next_object(segment *seg,int id)
96 if (id==-1 || (id=Objects[id].next)==-1)
97 return get_first_object(seg);
99 if (id == (ConsoleObject-Objects))
100 return get_next_object(seg,id);
106 //@@// ------------------------------------------------------------------------------------------------------
107 //@@// this should be called whenever the current segment may have changed
108 //@@// If Cur_object_seg != Cursegp, then update various variables.
109 //@@// this used to be called update_due_to_new_segment()
110 //@@void ObjectUpdateCurrent(void)
112 //@@ if (Cur_object_seg != Cursegp) {
113 //@@ Cur_object_seg = Cursegp;
114 //@@ Cur_object_index = get_first_object(Cur_object_seg);
115 //@@ Update_flags |= UF_WORLD_CHANGED;
120 // ------------------------------------------------------------------------------------
121 int place_object(segment *segp, vms_vector *object_pos, int object_type)
125 vms_matrix seg_matrix;
127 med_extract_matrix_from_segment(segp,&seg_matrix);
129 switch(ObjType[object_type]) {
133 objnum = obj_create(OBJ_HOSTAGE, -1,
134 segp-Segments,object_pos,&seg_matrix,HOSTAGE_SIZE,
135 CT_NONE,MT_NONE,RT_HOSTAGE);
140 obj = &Objects[objnum];
142 // Fill in obj->id and other hostage info
143 hostage_init_info( objnum );
145 obj->control_type = CT_POWERUP;
147 obj->rtype.vclip_info.vclip_num = Hostage_vclip_num[ObjId[object_type]];
148 obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].frame_time;
149 obj->rtype.vclip_info.framenum = 0;
155 objnum = obj_create(OBJ_ROBOT,ObjId[object_type],segp-Segments,object_pos,
156 &seg_matrix,Polygon_models[Robot_info[ObjId[object_type]].model_num].rad,
157 CT_AI,MT_PHYSICS,RT_POLYOBJ);
162 obj = &Objects[objnum];
164 //Set polygon-object-specific data
166 obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num;
167 obj->rtype.pobj_info.subobj_flags = 0;
171 obj->mtype.phys_info.mass = Robot_info[obj->id].mass;
172 obj->mtype.phys_info.drag = Robot_info[obj->id].drag;
174 obj->mtype.phys_info.flags |= (PF_LEVELLING);
176 obj->shields = Robot_info[obj->id].strength;
180 hide_segment = Markedsegp-Segments;
183 // robots which lunge forward to attack cannot have behavior type still.
184 if (Robot_info[obj->id].attack_type)
185 init_ai_object(obj-Objects, AIB_NORMAL, hide_segment);
187 init_ai_object(obj-Objects, AIB_STILL, hide_segment);
193 objnum = obj_create(OBJ_POWERUP,ObjId[object_type],
194 segp-Segments,object_pos,&seg_matrix,Powerup_info[ObjId[object_type]].size,
195 CT_POWERUP,MT_NONE,RT_POWERUP);
200 obj = &Objects[objnum];
202 //set powerup-specific data
204 obj->rtype.vclip_info.vclip_num = Powerup_info[obj->id].vclip_num;
205 obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].play_time/Vclip[obj->rtype.vclip_info.vclip_num].num_frames;
206 obj->rtype.vclip_info.framenum = 0;
208 if (obj->id == POW_VULCAN_WEAPON)
209 obj->ctype.powerup_info.count = VULCAN_WEAPON_AMMO_AMOUNT;
211 obj->ctype.powerup_info.count = 1;
216 case OL_CONTROL_CENTER:
218 int obj_type,control_type;
220 if (ObjType[object_type]==OL_CONTROL_CENTER) {
221 obj_type = OBJ_CNTRLCEN;
222 control_type = CT_CNTRLCEN;
225 obj_type = OBJ_CLUTTER;
226 control_type = CT_NONE;
229 objnum = obj_create(obj_type,object_type,segp-Segments,object_pos,
230 &seg_matrix,Polygon_models[ObjId[object_type]].rad,
231 control_type,MT_NONE,RT_POLYOBJ);
236 obj = &Objects[objnum];
238 obj->shields = ObjStrength[object_type];
240 //Set polygon-object-specific data
241 obj->shields = ObjStrength[object_type];
242 obj->rtype.pobj_info.model_num = ObjId[object_type];
243 obj->rtype.pobj_info.subobj_flags = 0;
249 objnum = obj_create(OBJ_PLAYER,ObjId[object_type],segp-Segments,object_pos,
250 &seg_matrix,Polygon_models[Player_ship->model_num].rad,
251 CT_NONE,MT_PHYSICS,RT_POLYOBJ);
256 obj = &Objects[objnum];
258 //Set polygon-object-specific data
260 obj->rtype.pobj_info.model_num = Player_ship->model_num;
261 obj->rtype.pobj_info.subobj_flags = 0;
262 //for (i=0;i<MAX_SUBMODELS;i++)
263 // vm_angvec_zero(&obj->rtype.pobj_info.anim_angles[i]);
267 vm_vec_zero(&obj->mtype.phys_info.velocity);
268 obj->mtype.phys_info.mass = Player_ship->mass;
269 obj->mtype.phys_info.drag = Player_ship->drag;
270 obj->mtype.phys_info.flags |= PF_TURNROLL | PF_LEVELLING | PF_WIGGLE;
271 obj->shields = i2f(100);
279 Cur_object_index = objnum;
280 //Cur_object_seg = Cursegp;
282 show_objects_in_segment(Cursegp); //mprintf the objects
284 Update_flags |= UF_WORLD_CHANGED;
289 // ------------------------------------------------------------------------------------------------------
290 // Count number of player objects, return value.
291 int compute_num_players(void)
295 for (i=0; i<=Highest_object_index; i++)
296 if (Objects[i].type == OBJ_PLAYER)
303 int ObjectMakeCoop(void)
305 Assert(Cur_object_index != -1);
306 Assert(Cur_object_index < MAX_OBJECTS);
307 // Assert(Objects[Cur_object_index.type == OBJ_PLAYER);
309 if (Objects[Cur_object_index].type == OBJ_PLAYER ) {
310 Objects[Cur_object_index].type = OBJ_COOP;
311 editor_status("You just made a player object COOPERATIVE");
313 editor_status("This is not a player object");
318 // ------------------------------------------------------------------------------------------------------
319 // Place current object at center of current segment.
320 int ObjectPlaceObject(void)
322 int old_cur_object_index;
325 vms_vector cur_object_loc;
328 if (ObjType[Cur_robot_type] == OL_PLAYER) {
329 int num_players = compute_num_players();
330 Assert(num_players <= MAX_PLAYERS);
331 if (num_players == MAX_PLAYERS) {
332 editor_status("Can't place player object. Already %i players.", MAX_PLAYERS);
339 if (ObjType[Cur_robot_type] == OL_PLAYER) {
340 int num_players = compute_num_players();
341 Assert(num_players <= MAX_MULTI_PLAYERS);
342 if (num_players > MAX_PLAYERS)
343 editor_status("You just placed a cooperative player object");
344 if (num_players == MAX_MULTI_PLAYERS) {
345 editor_status("Can't place player object. Already %i players.", MAX_MULTI_PLAYERS);
351 //update_due_to_new_segment();
352 compute_segment_center(&cur_object_loc, Cursegp);
354 old_cur_object_index = Cur_object_index;
355 rval = place_object(Cursegp, &cur_object_loc, Cur_robot_type);
357 if (old_cur_object_index != Cur_object_index)
358 Objects[Cur_object_index].rtype.pobj_info.tmap_override = -1;
364 // ------------------------------------------------------------------------------------------------------
365 // Place current object at center of current segment.
366 int ObjectPlaceObjectTmap(void)
368 int rval, old_cur_object_index;
369 vms_vector cur_object_loc;
371 //update_due_to_new_segment();
372 compute_segment_center(&cur_object_loc, Cursegp);
374 old_cur_object_index = Cur_object_index;
375 rval = place_object(Cursegp, &cur_object_loc, Cur_robot_type);
377 if ((Cur_object_index != old_cur_object_index) && (Objects[Cur_object_index].render_type == RT_POLYOBJ))
378 Objects[Cur_object_index].rtype.pobj_info.tmap_override = CurrentTexture;
380 editor_status("Unable to apply current texture map to this object.");
385 // ------------------------------------------------------------------------------------------------------
386 int ObjectSelectNextinSegment(void)
392 //update_due_to_new_segment();
394 //Assert(Cur_object_seg == Cursegp);
396 if (Cur_object_index == -1) {
398 Cur_object_index = objsegp->objects;
401 if (Objects[Cur_object_index].segnum != Cursegp-Segments)
402 Cur_object_index = objsegp->objects;
406 //Debug: make sure current object is in current segment
407 for (id=objsegp->objects;(id != Cur_object_index) && (id != -1);id=Objects[id].next);
408 Assert(id == Cur_object_index); //should have found object
410 // Select the next object, wrapping back to start if we are at the end of the linked list for this segment.
412 Cur_object_index = get_next_object(objsegp,Cur_object_index);
414 //mprintf((0,"Cur_object_index == %i\n", Cur_object_index));
416 Update_flags |= UF_WORLD_CHANGED;
422 //Moves to next object in the mine, skipping the player
423 int ObjectSelectNextInMine()
425 for (i=0;i<MAX_OBJECTS;i++) {
427 if (Cur_object_index>= MAX_OBJECTS ) Cur_object_index= 0;
429 if ((Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != (ConsoleObject-Objects)) ) {
430 Cursegp = &Segments[Objects[Cur_object_index ].segnum];
431 med_create_new_segment_from_cursegp();
432 //Cur_object_seg = Cursegp;
436 Cur_object_index = -1;
438 Update_flags |= UF_WORLD_CHANGED;
443 //Moves to next object in the mine, skipping the player
444 int ObjectSelectPrevInMine()
446 for (i=0;i<MAX_OBJECTS;i++) {
448 if (Cur_object_index < 0 )
449 Cur_object_index = MAX_OBJECTS-1;
451 if ((Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != (ConsoleObject-Objects)) ) {
452 Cursegp = &Segments[Objects[Cur_object_index ].segnum];
453 med_create_new_segment_from_cursegp();
454 //Cur_object_seg = Cursegp;
458 Cur_object_index = -1;
460 Update_flags |= UF_WORLD_CHANGED;
465 // ------------------------------------------------------------------------------------------------------
466 // Delete current object, if it exists.
467 // If it doesn't exist, reformat Matt's hard disk, even if he is in Boston.
468 int ObjectDelete(void)
471 if (Cur_object_index != -1) {
474 delete_objnum = Cur_object_index;
476 ObjectSelectNextinSegment();
478 obj_delete(delete_objnum);
480 if (delete_objnum == Cur_object_index)
481 Cur_object_index = -1;
483 Update_flags |= UF_WORLD_CHANGED;
489 // -----------------------------------------------------------------------------------------------------------------
490 // Object has moved to another segment, (or at least poked through).
491 // If still in mine, that is legal, so relink into new segment.
492 // Return value: 0 = in mine, 1 = not in mine
493 int move_object_within_mine(object * obj, vms_vector *newpos )
497 for (segnum=0;segnum <= Highest_segment_index; segnum++) {
498 segmasks result = get_seg_masks(&obj->pos, segnum, 0, __FILE__, __LINE__);
500 if (result.centermask == 0) {
505 // See if the radius pokes through any wall.
507 fq.startseg = obj->segnum;
511 fq.ignore_obj_list = NULL;
514 fate = find_vector_intersection(&fq,&hit_info);
516 if (fate != HIT_WALL) {
517 if ( segnum != obj->segnum )
518 obj_relink( obj-Objects, segnum);
522 //mprintf((0, "Hit wall seg:side = %i:%i\n", hit_info.hit_seg, hit_info.hit_side));
531 // Return 0 if object is in expected segment, else return 1
532 int verify_object_seg(object *objp, vms_vector *newpos)
534 segmasks result = get_seg_masks(newpos, objp->segnum, objp->size, __FILE__, __LINE__);
536 if (result.facemask == 0)
539 return move_object_within_mine(objp, newpos);
543 // ------------------------------------------------------------------------------------------------------
544 int ObjectMoveForward(void)
550 if (Cur_object_index == -1) {
551 editor_status("No current object, cannot move.");
555 obj = &Objects[Cur_object_index];
557 extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
558 vm_vec_normalize(&fvec);
560 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
562 if (!verify_object_seg(obj, &newpos))
565 Update_flags |= UF_WORLD_CHANGED;
570 // ------------------------------------------------------------------------------------------------------
571 int ObjectMoveBack(void)
577 if (Cur_object_index == -1) {
578 editor_status("No current object, cannot move.");
582 obj = &Objects[Cur_object_index];
584 extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
585 vm_vec_normalize(&fvec);
587 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
589 if (!verify_object_seg(obj, &newpos))
592 Update_flags |= UF_WORLD_CHANGED;
597 // ------------------------------------------------------------------------------------------------------
598 int ObjectMoveLeft(void)
604 if (Cur_object_index == -1) {
605 editor_status("No current object, cannot move.");
609 obj = &Objects[Cur_object_index];
611 extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
612 vm_vec_normalize(&rvec);
614 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
616 if (!verify_object_seg(obj, &newpos))
619 Update_flags |= UF_WORLD_CHANGED;
624 // ------------------------------------------------------------------------------------------------------
625 int ObjectMoveRight(void)
631 if (Cur_object_index == -1) {
632 editor_status("No current object, cannot move.");
636 obj = &Objects[Cur_object_index];
638 extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
639 vm_vec_normalize(&rvec);
641 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
643 if (!verify_object_seg(obj, &newpos))
646 Update_flags |= UF_WORLD_CHANGED;
651 // ------------------------------------------------------------------------------------------------------
652 int ObjectSetDefault(void)
654 //update_due_to_new_segment();
656 if (Cur_object_index == -1) {
657 editor_status("No current object, cannot move.");
661 compute_segment_center(&Objects[Cur_object_index].pos, &Segments[Objects[Cur_object_index].segnum]);
663 Update_flags |= UF_WORLD_CHANGED;
669 // ------------------------------------------------------------------------------------------------------
670 int ObjectMoveUp(void)
676 if (Cur_object_index == -1) {
677 editor_status("No current object, cannot move.");
681 obj = &Objects[Cur_object_index];
683 extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
684 vm_vec_normalize(&uvec);
686 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
688 if (!verify_object_seg(obj, &newpos))
691 Update_flags |= UF_WORLD_CHANGED;
696 // ------------------------------------------------------------------------------------------------------
697 int ObjectMoveDown(void)
703 if (Cur_object_index == -1) {
704 editor_status("No current object, cannot move.");
708 obj = &Objects[Cur_object_index];
710 extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
711 vm_vec_normalize(&uvec);
713 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
715 if (!verify_object_seg(obj, &newpos))
718 Update_flags |= UF_WORLD_CHANGED;
723 // ------------------------------------------------------------------------------------------------------
724 int ObjectMakeSmaller(void)
728 //update_due_to_new_segment();
730 cur_size = Objects[Cur_object_index].size;
732 cur_size -= OBJ_DEL_SIZE;
733 if (cur_size < OBJ_DEL_SIZE)
734 cur_size = OBJ_DEL_SIZE;
736 Objects[Cur_object_index].size = cur_size;
738 Update_flags |= UF_WORLD_CHANGED;
743 // ------------------------------------------------------------------------------------------------------
744 int ObjectMakeLarger(void)
748 //update_due_to_new_segment();
750 cur_size = Objects[Cur_object_index].size;
752 cur_size += OBJ_DEL_SIZE;
754 Objects[Cur_object_index].size = cur_size;
756 Update_flags |= UF_WORLD_CHANGED;
761 // ------------------------------------------------------------------------------------------------------
763 int rotate_object(short objnum, int p, int b, int h)
765 object *obj = &Objects[objnum];
767 vms_matrix rotmat,tempm;
769 // vm_extract_angles_matrix( &ang,&obj->orient);
779 vm_angles_2_matrix(&rotmat, &ang);
780 vm_matrix_x_matrix(&tempm, &obj->orient, &rotmat);
783 // vm_angles_2_matrix(&obj->orient, &ang);
785 Update_flags |= UF_WORLD_CHANGED;
791 void reset_object(short objnum)
793 object *obj = &Objects[objnum];
795 med_extract_matrix_from_segment(&Segments[obj->segnum],&obj->orient);
801 int ObjectResetObject()
803 reset_object(Cur_object_index);
805 Update_flags |= UF_WORLD_CHANGED;
811 int ObjectFlipObject()
813 vms_matrix *m=&Objects[Cur_object_index].orient;
815 vm_vec_negate(&m->uvec);
816 vm_vec_negate(&m->rvec);
818 Update_flags |= UF_WORLD_CHANGED;
823 int ObjectDecreaseBank() {return rotate_object(Cur_object_index, 0, -ROTATION_UNIT, 0);}
824 int ObjectIncreaseBank() {return rotate_object(Cur_object_index, 0, ROTATION_UNIT, 0);}
825 int ObjectDecreasePitch() {return rotate_object(Cur_object_index, -ROTATION_UNIT, 0, 0);}
826 int ObjectIncreasePitch() {return rotate_object(Cur_object_index, ROTATION_UNIT, 0, 0);}
827 int ObjectDecreaseHeading() {return rotate_object(Cur_object_index, 0, 0, -ROTATION_UNIT);}
828 int ObjectIncreaseHeading() {return rotate_object(Cur_object_index, 0, 0, ROTATION_UNIT);}
830 int ObjectDecreaseBankBig() {return rotate_object(Cur_object_index, 0, -(ROTATION_UNIT*4), 0);}
831 int ObjectIncreaseBankBig() {return rotate_object(Cur_object_index, 0, (ROTATION_UNIT*4), 0);}
832 int ObjectDecreasePitchBig() {return rotate_object(Cur_object_index, -(ROTATION_UNIT*4), 0, 0);}
833 int ObjectIncreasePitchBig() {return rotate_object(Cur_object_index, (ROTATION_UNIT*4), 0, 0);}
834 int ObjectDecreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, -(ROTATION_UNIT*4));}
835 int ObjectIncreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, (ROTATION_UNIT*4));}
837 // -----------------------------------------------------------------------------------------------------
838 // Move object around based on clicks in 2d screen.
839 // Slide an object parallel to the 2d screen, to a point on a vector.
840 // The vector is defined by a point on the 2d screen and the eye.
842 // V = vector from eye to 2d screen point.
844 // F = forward vector from eye
845 // O = 3-space location of object
847 // D = depth of object given forward vector F
848 // = (OE dot norm(F))
850 // Must solve intersection of:
851 // E + tV ( equation of vector from eye through point on 2d screen)
852 // Fs + D ( equation of plane parallel to 2d screen, at depth D)
853 // = Fx(Ex + tVx) + Fy(Ey + tVy) + Fz(Ez + tVz) + D = 0
855 // FxEx + FyEy + FzEz - D
856 // t = - ----------------------
857 // VxFx + VyFy + VzFz
860 //void print_vec(vms_vector *vec, char *text)
862 // mprintf((0, "%10s = %9.5f %9.5f %9.5f\n", text, f2fl(vec->x), f2fl(vec->y), f2fl(vec->z)));
865 // void solve(vms_vector *result, vms_vector *E, vms_vector *V, vms_vector *O, vms_vector *F)
868 // vms_vector Fnorm, Vnorm;
870 // // float test_plane;
872 // print_vec(E, "E");
873 // print_vec(V, "V");
874 // print_vec(O, "O");
875 // print_vec(F, "F");
877 // Fnorm = *F; vm_vec_normalize(&Fnorm);
878 // Vnorm = *V; vm_vec_normalize(&Vnorm);
880 // D = (fixmul(O->x, Fnorm.x) + fixmul(O->y, Fnorm.y) + fixmul(O->z, Fnorm.z));
881 // mprintf((0, "D = %9.5f\n", f2fl(D)));
883 // num = fixmul(Fnorm.x, E->x) + fixmul(Fnorm.y, E->y) + fixmul(Fnorm.z, E->z) - D;
884 // denom = vm_vec_dot(&Vnorm, &Fnorm);
887 // mprintf((0, "num = %9.5f, denom = %9.5f, t = %9.5f\n", f2fl(num), f2fl(denom), f2fl(t)));
889 // result->x = E->x + fixmul(t, Vnorm.x);
890 // result->y = E->y + fixmul(t, Vnorm.y);
891 // result->z = E->z + fixmul(t, Vnorm.z);
893 // print_vec(result, "result");
895 // // test_plane = fixmul(result->x, Fnorm.x) + fixmul(result->y, Fnorm.y) + fixmul(result->z, Fnorm.z) - D;
896 // // if (abs(test_plane) > .001)
897 // // printf("OOPS: test_plane = %9.5f\n", test_plane);
900 void move_object_to_position(int objnum, vms_vector *newpos)
902 object *objp = &Objects[objnum];
904 segmasks result = get_seg_masks(newpos, objp->segnum, objp->size, __FILE__, __LINE__);
906 if (result.facemask == 0) {
907 //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)));
910 if (verify_object_seg(&Objects[objnum], newpos)) {
913 object temp_viewer_obj;
916 vms_vector last_outside_pos;
917 vms_vector last_inside_pos;
919 temp_viewer_obj = *Viewer;
920 viewer_segnum = find_object_seg(&temp_viewer_obj);
921 temp_viewer_obj.segnum = viewer_segnum;
923 // If the viewer is outside the mine, get him in the mine!
924 if (viewer_segnum == -1) {
925 // While outside mine, move towards object
927 while (viewer_segnum == -1) {
930 //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)));
931 last_outside_pos = temp_viewer_obj.pos;
933 vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, newpos);
934 temp_viewer_obj.pos = temp_vec;
935 viewer_segnum = find_object_seg(&temp_viewer_obj);
936 temp_viewer_obj.segnum = viewer_segnum;
939 editor_status("Unable to move object, can't get viewer in mine. Aborting");
945 // While inside mine, move away from object.
946 while (viewer_segnum != -1) {
950 //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)));
951 last_inside_pos = temp_viewer_obj.pos;
953 vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, &last_outside_pos);
954 temp_viewer_obj.pos = temp_vec;
955 update_object_seg(&temp_viewer_obj);
956 viewer_segnum = find_object_seg(&temp_viewer_obj);
957 temp_viewer_obj.segnum = viewer_segnum;
960 editor_status("Unable to move object, can't get viewer back out of mine. Aborting");
966 fq.p0 = &temp_viewer_obj.pos;
967 fq.startseg = temp_viewer_obj.segnum;
969 fq.rad = temp_viewer_obj.size;
971 fq.ignore_obj_list = NULL;
974 fate = find_vector_intersection(&fq,&hit_info);
975 if (fate == HIT_WALL) {
978 //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)));
979 objp->pos = hit_info.hit_pnt;
980 new_segnum = find_object_seg(objp);
981 Assert(new_segnum != -1);
982 obj_relink(objp-Objects, new_segnum);
983 //mprintf((0, "Object moved from segment %i to %i\n", old_segnum, objp->segnum));
985 editor_status("Attempted to move object out of mine. Object not moved.");
986 //mprintf((0,"Attempted to move object out of mine. Object not moved."));
991 Update_flags |= UF_WORLD_CHANGED;
994 void move_object_to_vector(vms_vector *vec_through_screen, fix delta_distance)
998 vm_vec_scale_add(&result, &Viewer->pos, vec_through_screen, vm_vec_dist(&Viewer->pos,&Objects[Cur_object_index].pos)+delta_distance);
1000 move_object_to_position(Cur_object_index, &result);
1004 void move_object_to_mouse_click_delta(fix delta_distance)
1007 vms_vector vec_through_screen;
1009 if (Cur_object_index == -1) {
1010 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1014 xcrd = GameViewBox->b1_drag_x1;
1015 ycrd = GameViewBox->b1_drag_y1;
1017 med_point_2_vec(&_canv_editor_game, &vec_through_screen, xcrd, ycrd);
1019 //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)));
1021 move_object_to_vector(&vec_through_screen, delta_distance);
1025 void move_object_to_mouse_click(void)
1027 move_object_to_mouse_click_delta(0);
1030 int ObjectMoveNearer(void)
1034 if (Cur_object_index == -1) {
1035 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1039 // move_object_to_mouse_click_delta(-4*F1_0); // Move four units closer to eye
1041 vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
1042 vm_vec_normalize(&result);
1043 move_object_to_vector(&result, -4*F1_0);
1048 int ObjectMoveFurther(void)
1052 if (Cur_object_index == -1) {
1053 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1057 // move_object_to_mouse_click_delta(+4*F1_0); // Move four units further from eye
1059 vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
1060 vm_vec_normalize(&result);
1061 move_object_to_vector(&result, 4*F1_0);