//find which side to fly out of find_exit_side(object *obj) { int i; vms_vector prefvec,segcenter,sidevec; fix best_val=-f2_0; int best_side; segment *pseg = &Segments[obj->segnum]; //find exit side vm_vec_normalized_dir_quick(&prefvec,&obj->pos,&obj->last_pos); compute_segment_center(&segcenter,pseg); best_side=-1; for (i=MAX_SIDES_PER_SEGMENT;--i >= 0;) { fix d; if (pseg->children[i]!=-1) { compute_center_point_on_side(&sidevec,pseg,i); vm_vec_normalized_dir_quick(&sidevec,&sidevec,&segcenter); d = vm_vec_dotprod(&sidevec,&prefvec); if (labs(d) < MIN_D) d=0; if (d > best_val) {best_val=d; best_side=i;} } } Assert(best_side!=-1); return best_side; }
void digi_get_sound_loc( vms_matrix * listener, vms_vector * listener_pos, int listener_seg, vms_vector * sound_pos, int sound_seg, fix max_volume, int *volume, int *pan, fix max_distance ) { vms_vector vector_to_sound; fix angle_from_ear, cosang,sinang; fix distance; fix path_distance; *volume = 0; *pan = 0; max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far. // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation. distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos ); if (distance < max_distance ) { int num_search_segs = f2i(max_distance/20); if ( num_search_segs < 1 ) num_search_segs = 1; path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG ); if ( path_distance > -1 ) { *volume = max_volume - fixdiv(path_distance,max_distance); //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume )); if (*volume > 0 ) { angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec); fix_sincos(angle_from_ear,&sinang,&cosang); //mprintf( (0, "volume is %.2f\n", f2fl(*volume) )); if (Config_channels_reversed) cosang *= -1; *pan = (cosang + F1_0)/2; } else { *volume = 0; } } } }
do_endlevel_frame() { static fix timer; vms_vector save_last_pos; static fix explosion_wait1=0; static fix explosion_wait2=0; static fix bank_rate; static fix ext_expl_halflife; save_last_pos = ConsoleObject->last_pos; //don't let move code change this object_move_all(); ConsoleObject->last_pos = save_last_pos; if (ext_expl_playing) { external_explosion.lifeleft -= FrameTime; do_explosion_sequence(&external_explosion); if (external_explosion.lifeleft < ext_expl_halflife) mine_destroyed = 1; if (external_explosion.flags & OF_SHOULD_BE_DEAD) ext_expl_playing = 0; } if (cur_fly_speed != desired_fly_speed) { fix delta = desired_fly_speed - cur_fly_speed; fix frame_accel = fixmul(FrameTime,FLY_ACCEL); if (abs(delta) < frame_accel) cur_fly_speed = desired_fly_speed; else if (delta > 0) cur_fly_speed += frame_accel; else cur_fly_speed -= frame_accel; } //do big explosions if (!outside_mine) { if (Endlevel_sequence==EL_OUTSIDE) { vms_vector tvec; vm_vec_sub(&tvec,&ConsoleObject->pos,&mine_side_exit_point); if (vm_vec_dot(&tvec,&mine_exit_orient.fvec) > 0) { object *tobj; outside_mine = 1; tobj = object_create_explosion(exit_segnum,&mine_side_exit_point,i2f(50),VCLIP_BIG_PLAYER_EXPLOSION); if (tobj) { external_explosion = *tobj; tobj->flags |= OF_SHOULD_BE_DEAD; flash_scale = 0; //kill lights in mine ext_expl_halflife = tobj->lifeleft; ext_expl_playing = 1; } digi_link_sound_to_pos( SOUND_BIG_ENDLEVEL_EXPLOSION, exit_segnum, 0, &mine_side_exit_point, 0, i2f(3)/4 ); } } //do explosions chasing player if ((explosion_wait1-=FrameTime) < 0) { vms_vector tpnt; int segnum; object *expl; static int sound_count; vm_vec_scale_add(&tpnt,&ConsoleObject->pos,&ConsoleObject->orient.fvec,-ConsoleObject->size*5); vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.rvec,(rand()-RAND_MAX/2)*15); vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.uvec,(rand()-RAND_MAX/2)*15); segnum = find_point_seg(&tpnt,ConsoleObject->segnum); if (segnum != -1) { expl = object_create_explosion(segnum,&tpnt,i2f(20),VCLIP_BIG_PLAYER_EXPLOSION); if (rand()<10000 || ++sound_count==7) { //pseudo-random digi_link_sound_to_pos( SOUND_TUNNEL_EXPLOSION, segnum, 0, &tpnt, 0, F1_0 ); sound_count=0; } } explosion_wait1 = 0x2000 + rand()/4; } } //do little explosions on walls if (Endlevel_sequence >= EL_FLYTHROUGH && Endlevel_sequence < EL_OUTSIDE) if ((explosion_wait2-=FrameTime) < 0) { vms_vector tpnt; fvi_query fq; fvi_info hit_data; //create little explosion on wall vm_vec_copy_scale(&tpnt,&ConsoleObject->orient.rvec,(rand()-RAND_MAX/2)*100); vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.uvec,(rand()-RAND_MAX/2)*100); vm_vec_add2(&tpnt,&ConsoleObject->pos); if (Endlevel_sequence == EL_FLYTHROUGH) vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.fvec,rand()*200); else vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.fvec,rand()*60); //find hit point on wall fq.p0 = &ConsoleObject->pos; fq.p1 = &tpnt; fq.startseg = ConsoleObject->segnum; fq.rad = 0; fq.thisobjnum = 0; fq.ignore_obj_list = NULL; fq.flags = 0; find_vector_intersection(&fq,&hit_data); if (hit_data.hit_type==HIT_WALL && hit_data.hit_seg!=-1) object_create_explosion(hit_data.hit_seg,&hit_data.hit_pnt,i2f(3)+rand()*6,VCLIP_SMALL_EXPLOSION); explosion_wait2 = (0xa00 + rand()/8)/2; } switch (Endlevel_sequence) { case EL_OFF: return; case EL_FLYTHROUGH: { do_endlevel_flythrough(0); if (ConsoleObject->segnum == transition_segnum) { int objnum; Endlevel_sequence = EL_LOOKBACK; objnum = obj_create(OBJ_CAMERA, 0, ConsoleObject->segnum,&ConsoleObject->pos,&ConsoleObject->orient,0, CT_NONE,MT_NONE,RT_NONE); if (objnum == -1) { //can't get object, so abort mprintf((1, "Can't get object for endlevel sequence. Aborting endlevel sequence.\n")); stop_endlevel_sequence(); return; } Viewer = endlevel_camera = &Objects[objnum]; select_cockpit(CM_LETTERBOX); fly_objects[1] = fly_objects[0]; fly_objects[1].obj = endlevel_camera; fly_objects[1].speed = (5*cur_fly_speed)/4; fly_objects[1].offset_frac = 0x4000; vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,i2f(7)); timer=0x20000; } break; } case EL_LOOKBACK: { do_endlevel_flythrough(0); do_endlevel_flythrough(1); if (timer>0) { timer -= FrameTime; if (timer < 0) //reduce speed fly_objects[1].speed = fly_objects[0].speed; } if (endlevel_camera->segnum == exit_segnum) { vms_angvec cam_angles,exit_seg_angles; Endlevel_sequence = EL_OUTSIDE; timer = i2f(2); vm_vec_negate(&endlevel_camera->orient.fvec); vm_vec_negate(&endlevel_camera->orient.rvec); vm_extract_angles_matrix(&cam_angles,&endlevel_camera->orient); vm_extract_angles_matrix(&exit_seg_angles,&mine_exit_orient); bank_rate = (-exit_seg_angles.b - cam_angles.b)/2; ConsoleObject->control_type = endlevel_camera->control_type = CT_NONE; //_MARK_("Starting outside");//Commented out by KRB #ifdef SLEW_ON slew_obj = endlevel_camera; #endif } break; } case EL_OUTSIDE: { #ifndef SLEW_ON vms_angvec cam_angles; #endif vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed)); #ifndef SLEW_ON vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,fixmul(FrameTime,-2*cur_fly_speed)); vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.uvec,fixmul(FrameTime,-cur_fly_speed/10)); vm_extract_angles_matrix(&cam_angles,&endlevel_camera->orient); cam_angles.b += fixmul(bank_rate,FrameTime); vm_angles_2_matrix(&endlevel_camera->orient,&cam_angles); #endif timer -= FrameTime; if (timer < 0) { Endlevel_sequence = EL_STOPPED; vm_extract_angles_matrix(&player_angles,&ConsoleObject->orient); timer = i2f(3); } break; } case EL_STOPPED: { get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos); chase_angles(&player_angles,&player_dest_angles); vm_angles_2_matrix(&ConsoleObject->orient,&player_angles); vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed)); timer -= FrameTime; if (timer < 0) { #ifdef SLEW_ON slew_obj = endlevel_camera; _do_slew_movement(endlevel_camera,1,1); timer += FrameTime; //make time stop break; #else #ifdef SHORT_SEQUENCE stop_endlevel_sequence(); #else Endlevel_sequence = EL_PANNING; vm_extract_angles_matrix(&camera_cur_angles,&endlevel_camera->orient); timer = i2f(3); if (Game_mode & GM_MULTI) { // try to skip part of the seq if multiplayer stop_endlevel_sequence(); return; } //mprintf((0,"Switching to pan...\n")); #endif //SHORT_SEQUENCE #endif //SLEW_ON } break; } #ifndef SHORT_SEQUENCE case EL_PANNING: { #ifndef SLEW_ON int mask; #endif get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos); chase_angles(&player_angles,&player_dest_angles); vm_angles_2_matrix(&ConsoleObject->orient,&player_angles); vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed)); #ifdef SLEW_ON _do_slew_movement(endlevel_camera,1,1); #else get_angs_to_object(&camera_desired_angles,&ConsoleObject->pos,&endlevel_camera->pos); mask = chase_angles(&camera_cur_angles,&camera_desired_angles); vm_angles_2_matrix(&endlevel_camera->orient,&camera_cur_angles); if ((mask&5) == 5) { vms_vector tvec; Endlevel_sequence = EL_CHASING; //_MARK_("Done outside");//Commented out -KRB vm_vec_normalized_dir_quick(&tvec,&station_pos,&ConsoleObject->pos); vm_vector_2_matrix(&ConsoleObject->orient,&tvec,&surface_orient.uvec,NULL); desired_fly_speed *= 2; //mprintf((0,"Switching to chase...\n")); } #endif break; } case EL_CHASING: { fix d,speed_scale; #ifdef SLEW_ON _do_slew_movement(endlevel_camera,1,1); #endif get_angs_to_object(&camera_desired_angles,&ConsoleObject->pos,&endlevel_camera->pos); chase_angles(&camera_cur_angles,&camera_desired_angles); #ifndef SLEW_ON vm_angles_2_matrix(&endlevel_camera->orient,&camera_cur_angles); #endif d = vm_vec_dist_quick(&ConsoleObject->pos,&endlevel_camera->pos); speed_scale = fixdiv(d,i2f(0x20)); if (d<f1_0) d=f1_0; get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos); chase_angles(&player_angles,&player_dest_angles); vm_angles_2_matrix(&ConsoleObject->orient,&player_angles); vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed)); #ifndef SLEW_ON vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,fixmul(FrameTime,fixmul(speed_scale,cur_fly_speed))); if (vm_vec_dist(&ConsoleObject->pos,&station_pos) < i2f(10)) stop_endlevel_sequence(); #endif break; } #endif //ifdef SHORT_SEQUENCE } }
// ----------------------------------------------------------------------------------------------------------- //Simulate a physics object for this frame do_physics_sim(object *obj) { int ignore_obj_list[MAX_IGNORE_OBJS],n_ignore_objs; int iseg; int try_again; int fate; vms_vector frame_vec; //movement in this frame vms_vector new_pos,ipos; //position after this frame int count=0; int objnum; int WallHitSeg, WallHitSide; fvi_info hit_info; fvi_query fq; vms_vector save_pos; int save_seg; fix drag; fix sim_time; vms_vector start_pos; int obj_stopped=0; fix moved_time; //how long objected moved before hit something vms_vector save_p0,save_p1; physics_info *pi; int orig_segnum = obj->segnum; Assert(obj->type != OBJ_NONE); Assert(obj->movement_type == MT_PHYSICS); #ifndef NDEBUG if (Dont_move_ai_objects) if (obj->control_type == CT_AI) return; #endif pi = &obj->mtype.phys_info; do_physics_sim_rot(obj); if (!(pi->velocity.x || pi->velocity.y || pi->velocity.z || pi->thrust.x || pi->thrust.y || pi->thrust.z)) return; objnum = obj-Objects; n_phys_segs = 0; disable_new_fvi_stuff = (obj->type != OBJ_PLAYER); sim_time = FrameTime; //debug_obj = obj; #ifdef EXTRA_DEBUG if (obj == debug_obj) { printf("object %d:\n start pos = %x %x %x\n",objnum,XYZ(&obj->pos)); printf(" thrust = %x %x %x\n",XYZ(&obj->mtype.phys_info.thrust)); printf(" sim_time = %x\n",sim_time); } //check for correct object segment if(!get_seg_masks(&obj->pos,obj->segnum,0).centermask==0) { #ifndef NDEBUG mprintf((0,"Warning: object %d not in given seg!\n",objnum)); #endif //Int3(); Removed by Rob 10/5/94 if (!update_object_seg(obj)) { #ifndef NDEBUG mprintf((0,"Warning: can't find seg for object %d - moving\n",objnum)); #endif if (!(Game_mode & GM_MULTI)) Int3(); compute_segment_center(&obj->pos,&Segments[obj->segnum]); obj->pos.x += objnum; } } #endif start_pos = obj->pos; n_ignore_objs = 0; Assert(obj->mtype.phys_info.brakes==0); //brakes not used anymore? //if uses thrust, cannot have zero drag Assert(!(obj->mtype.phys_info.flags&PF_USES_THRUST) || obj->mtype.phys_info.drag!=0); //mprintf((0,"thrust=%x speed=%x\n",vm_vec_mag(&obj->mtype.phys_info.thrust),vm_vec_mag(&obj->mtype.phys_info.velocity))); //do thrust & drag if ((drag = obj->mtype.phys_info.drag) != 0) { int count; vms_vector accel; fix r,k; count = sim_time / FT; r = sim_time % FT; k = fixdiv(r,FT); if (obj->mtype.phys_info.flags & PF_USES_THRUST) { vm_vec_copy_scale(&accel,&obj->mtype.phys_info.thrust,fixdiv(f1_0,obj->mtype.phys_info.mass)); while (count--) { vm_vec_add2(&obj->mtype.phys_info.velocity,&accel); vm_vec_scale(&obj->mtype.phys_info.velocity,f1_0-drag); } //do linear scale on remaining bit of time vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&accel,k); vm_vec_scale(&obj->mtype.phys_info.velocity,f1_0-fixmul(k,drag)); } else { fix total_drag=f1_0; while (count--) total_drag = fixmul(total_drag,f1_0-drag); //do linear scale on remaining bit of time total_drag = fixmul(total_drag,f1_0-fixmul(k,drag)); vm_vec_scale(&obj->mtype.phys_info.velocity,total_drag); } } #ifdef EXTRA_DEBUG if (obj == debug_obj) printf(" velocity = %x %x %x\n",XYZ(&obj->mtype.phys_info.velocity)); #endif do { try_again = 0; //Move the object vm_vec_copy_scale(&frame_vec, &obj->mtype.phys_info.velocity, sim_time); #ifdef EXTRA_DEBUG if (obj == debug_obj) printf(" pass %d, frame_vec = %x %x %x\n",count,XYZ(&frame_vec)); #endif if ( (frame_vec.x==0) && (frame_vec.y==0) && (frame_vec.z==0) ) break; count++; // If retry count is getting large, then we are trying to do something stupid. if ( count > 3) { if (obj->type == OBJ_PLAYER) { if (count > 8) break; } else break; } vm_vec_add(&new_pos,&obj->pos,&frame_vec); #ifdef EXTRA_DEBUG if (obj == debug_obj) printf(" desired_pos = %x %x %x\n",XYZ(&new_pos)); #endif ignore_obj_list[n_ignore_objs] = -1; #ifdef EXTRA_DEBUG if (obj == debug_obj) { printf(" FVI parms: p0 = %8x %8x %8x, segnum=%x, size=%x\n",XYZ(&obj->pos),obj->segnum,obj->size); printf(" p1 = %8x %8x %8x\n",XYZ(&new_pos)); } #endif fq.p0 = &obj->pos; fq.startseg = obj->segnum; fq.p1 = &new_pos; fq.rad = obj->size; fq.thisobjnum = objnum; fq.ignore_obj_list = ignore_obj_list; fq.flags = FQ_CHECK_OBJS; if (obj->type == OBJ_WEAPON) fq.flags |= FQ_TRANSPOINT; if (obj->type == OBJ_PLAYER) fq.flags |= FQ_GET_SEGLIST; //@@ if (get_seg_masks(&obj->pos,obj->segnum,0).centermask!=0) //@@ Int3(); save_p0 = *fq.p0; save_p1 = *fq.p1; fate = find_vector_intersection(&fq,&hit_info); // Matt: Mike's hack. if (fate == HIT_OBJECT) { object *objp = &Objects[hit_info.hit_object]; if ((objp->type == OBJ_WEAPON) && (objp->id == PROXIMITY_ID)) count--; } #ifndef NDEBUG if (fate == HIT_BAD_P0) { mprintf((0,"Warning: Bad p0 in physics! Object = %i, type = %i [%s]\n", obj-Objects, obj->type, Object_type_names[obj->type])); Int3(); } #endif if (obj->type == OBJ_PLAYER) { int i; if (n_phys_segs && phys_seglist[n_phys_segs-1]==hit_info.seglist[0]) n_phys_segs--; for (i=0;(i<hit_info.n_segs) && (n_phys_segs<MAX_FVI_SEGS-1); ) phys_seglist[n_phys_segs++] = hit_info.seglist[i++]; } #ifdef EXTRA_DEBUG if (obj == debug_obj) printf(" fate = %d, hit_pnt = %8x %8x %8x\n",fate,XYZ(&hit_info.hit_pnt));; #endif ipos = hit_info.hit_pnt; iseg = hit_info.hit_seg; WallHitSide = hit_info.hit_side; WallHitSeg = hit_info.hit_side_seg; if (iseg==-1) { //some sort of horrible error #ifndef NDEBUG mprintf((1,"iseg==-1 in physics! Object = %i, type = %i (%s)\n", obj-Objects, obj->type, Object_type_names[obj->type])); #endif //Int3(); //compute_segment_center(&ipos,&Segments[obj->segnum]); //ipos.x += objnum; //iseg = obj->segnum; //fate = HIT_NONE; if (obj->type == OBJ_WEAPON) obj->flags |= OF_SHOULD_BE_DEAD; break; } Assert(!((fate==HIT_WALL) && ((WallHitSeg == -1) || (WallHitSeg > Highest_segment_index)))); //if(!get_seg_masks(&hit_info.hit_pnt,hit_info.hit_seg,0).centermask==0) // Int3(); save_pos = obj->pos; //save the object's position save_seg = obj->segnum; // update object's position and segment number obj->pos = ipos; #ifdef EXTRA_DEBUG if (obj == debug_obj) printf(" new pos = %x %x %x\n",XYZ(&obj->pos)); #endif if ( iseg != obj->segnum ) obj_relink(objnum, iseg ); //if start point not in segment, move object to center of segment if (get_seg_masks(&obj->pos,obj->segnum,0).centermask!=0) { int n; if ((n=find_object_seg(obj))==-1) { //Int3(); if (obj->type==OBJ_PLAYER && (n=find_point_seg(&obj->last_pos,obj->segnum))!=-1) { obj->pos = obj->last_pos; obj_relink(objnum, n ); } else { compute_segment_center(&obj->pos,&Segments[obj->segnum]); obj->pos.x += objnum; } if (obj->type == OBJ_WEAPON) obj->flags |= OF_SHOULD_BE_DEAD; } return; } //calulate new sim time { //vms_vector moved_vec; vms_vector moved_vec_n; fix attempted_dist,actual_dist; actual_dist = vm_vec_normalized_dir(&moved_vec_n,&obj->pos,&save_pos); if (fate==HIT_WALL && vm_vec_dot(&moved_vec_n,&frame_vec) < 0) { //moved backwards //don't change position or sim_time //******* mprintf((0,"Obj %d moved backwards\n",obj-Objects)); #ifdef EXTRA_DEBUG if (obj == debug_obj) printf(" Warning: moved backwards!\n"); #endif obj->pos = save_pos; //iseg = obj->segnum; //don't change segment obj_relink(objnum, save_seg ); moved_time = 0; } else { fix old_sim_time; //if (obj == debug_obj) // printf(" moved_vec = %x %x %x\n",XYZ(&moved_vec)); attempted_dist = vm_vec_mag(&frame_vec); old_sim_time = sim_time; sim_time = fixmuldiv(sim_time,attempted_dist-actual_dist,attempted_dist); moved_time = old_sim_time - sim_time; if (sim_time < 0 || sim_time>old_sim_time) { #ifndef NDEBUG mprintf((0,"Bogus sim_time = %x, old = %x\n",sim_time,old_sim_time)); if (obj == debug_obj) printf(" Bogus sim_time = %x, old = %x, attempted_dist = %x, actual_dist = %x\n",sim_time,old_sim_time,attempted_dist,actual_dist); //Int3(); Removed by Rob #endif sim_time = old_sim_time; //WHY DOES THIS HAPPEN?? moved_time = 0; } } #ifdef EXTRA_DEBUG if (obj == debug_obj) printf(" new sim_time = %x\n",sim_time); #endif } switch( fate ) { case HIT_WALL: { vms_vector moved_v; //@@fix total_d,moved_d; fix hit_speed,wall_part; // Find hit speed vm_vec_sub(&moved_v,&obj->pos,&save_pos); wall_part = vm_vec_dot(&moved_v,&hit_info.hit_wallnorm); if (wall_part != 0 && moved_time>0 && (hit_speed=-fixdiv(wall_part,moved_time))>0) collide_object_with_wall( obj, hit_speed, WallHitSeg, WallHitSide, &hit_info.hit_pnt ); else scrape_object_on_wall(obj, WallHitSeg, WallHitSide, &hit_info.hit_pnt ); Assert( WallHitSeg > -1 ); Assert( WallHitSide > -1 ); if ( !(obj->flags&OF_SHOULD_BE_DEAD) ) { Assert(! (obj->mtype.phys_info.flags & PF_STICK && obj->mtype.phys_info.flags & PF_BOUNCE)); //can't be bounce and stick if (obj->mtype.phys_info.flags & PF_STICK) { //stop moving // mprintf((0, "Object %i stuck at %i:%i\n", obj-Objects, WallHitSeg, WallHitSide)); add_stuck_object(obj, WallHitSeg, WallHitSide); vm_vec_zero(&obj->mtype.phys_info.velocity); obj_stopped = 1; try_again = 0; } else { // Slide object along wall //We're constrained by wall, so subtract wall part from //velocity vector wall_part = vm_vec_dot(&hit_info.hit_wallnorm,&obj->mtype.phys_info.velocity); if (obj->mtype.phys_info.flags & PF_BOUNCE) //bounce off wall wall_part *= 2; //Subtract out wall part twice to achieve bounce vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&hit_info.hit_wallnorm,-wall_part); #ifdef EXTRA_DEBUG if (obj == debug_obj) { printf(" sliding - wall_norm %x %x %x\n",wall_part,XYZ(&hit_info.hit_wallnorm)); printf(" wall_part %x, new velocity = %x %x %x\n",wall_part,XYZ(&obj->mtype.phys_info.velocity)); } #endif try_again = 1; } } break; } case HIT_OBJECT: { vms_vector old_vel; // Mark the hit object so that on a retry the fvi code // ignores this object. Assert(hit_info.hit_object != -1); // Calculcate the hit point between the two objects. { vms_vector *ppos0, *ppos1, pos_hit; fix size0, size1; ppos0 = &Objects[hit_info.hit_object].pos; ppos1 = &obj->pos; size0 = Objects[hit_info.hit_object].size; size1 = obj->size; Assert(size0+size1 != 0); // Error, both sizes are 0, so how did they collide, anyway?!? //vm_vec_scale(vm_vec_sub(&pos_hit, ppos1, ppos0), fixdiv(size0, size0 + size1)); //vm_vec_add2(&pos_hit, ppos0); vm_vec_sub(&pos_hit, ppos1, ppos0); vm_vec_scale_add(&pos_hit,ppos0,&pos_hit,fixdiv(size0, size0 + size1)); old_vel = obj->mtype.phys_info.velocity; collide_two_objects( obj, &Objects[hit_info.hit_object], &pos_hit); } // Let object continue its movement if ( !(obj->flags&OF_SHOULD_BE_DEAD) ) { //obj->pos = save_pos; if (obj->mtype.phys_info.flags&PF_PERSISTENT || (old_vel.x == obj->mtype.phys_info.velocity.x && old_vel.y == obj->mtype.phys_info.velocity.y && old_vel.z == obj->mtype.phys_info.velocity.z)) { //if (Objects[hit_info.hit_object].type == OBJ_POWERUP) ignore_obj_list[n_ignore_objs++] = hit_info.hit_object; try_again = 1; } } break; } case HIT_NONE: break; #ifndef NDEBUG case HIT_BAD_P0: Int3(); // Unexpected collision type: start point not in specified segment. mprintf((0,"Warning: Bad p0 in physics!!!\n")); break; default: // Unknown collision type returned from find_vector_intersection!! Int3(); break; #endif } } while ( try_again ); // Pass retry count info to AI. if (obj->control_type == CT_AI) { if (count > 0) { Ai_local_info[objnum].retry_count = count-1; Total_retries += count-1; Total_sims++; } } if (! obj_stopped) { //Set velocity from actual movement vms_vector moved_vec; vm_vec_sub(&moved_vec,&obj->pos,&start_pos); vm_vec_copy_scale(&obj->mtype.phys_info.velocity,&moved_vec,fixdiv(f1_0,FrameTime)); #ifdef BUMP_HACK if (obj==ConsoleObject && (obj->mtype.phys_info.velocity.x==0 && obj->mtype.phys_info.velocity.y==0 && obj->mtype.phys_info.velocity.z==0) && !(obj->mtype.phys_info.thrust.x==0 && obj->mtype.phys_info.thrust.y==0 && obj->mtype.phys_info.thrust.z==0)) { vms_vector center,bump_vec; //bump player a little towards center of segment to unstick compute_segment_center(¢er,&Segments[obj->segnum]); vm_vec_normalized_dir_quick(&bump_vec,¢er,&obj->pos); vm_vec_scale_add2(&obj->pos,&bump_vec,obj->size/5); } #endif } //Assert(check_point_in_seg(&obj->pos,obj->segnum,0).centermask==0); //if (obj->control_type == CT_FLYING) if (obj->mtype.phys_info.flags & PF_LEVELLING) do_physics_align_object( obj ); //hack to keep player from going through closed doors if (obj->type==OBJ_PLAYER && obj->segnum!=orig_segnum && (Physics_cheat_flag!=0xBADA55) ) { int sidenum; sidenum = find_connect_side(&Segments[obj->segnum],&Segments[orig_segnum]); if (sidenum != -1) { if (! (WALL_IS_DOORWAY(&Segments[orig_segnum],sidenum) & WID_FLY_FLAG)) { side *s; int vertnum,num_faces,i; fix dist; int vertex_list[6]; //bump object back s = &Segments[orig_segnum].sides[sidenum]; create_abs_vertex_lists( &num_faces, vertex_list, orig_segnum, sidenum); //let's pretend this wall is not triangulated vertnum = vertex_list[0]; for (i=1;i<4;i++) if (vertex_list[i] < vertnum) vertnum = vertex_list[i]; #ifdef COMPACT_SEGS { vms_vector _vn; get_side_normal(&Segments[orig_segnum], sidenum, 0, &_vn ); dist = vm_dist_to_plane(&start_pos, &_vn, &Vertices[vertnum]); vm_vec_scale_add(&obj->pos,&start_pos,&_vn,obj->size-dist); } #else dist = vm_dist_to_plane(&start_pos, &s->normals[0], &Vertices[vertnum]); vm_vec_scale_add(&obj->pos,&start_pos,&s->normals[0],obj->size-dist); #endif update_object_seg(obj); } } } //--WE ALWYS WANT THIS IN, MATT AND MIKE DECISION ON 12/10/94, TWO MONTHS AFTER FINAL #ifndef NDEBUG //if end point not in segment, move object to last pos, or segment center if (get_seg_masks(&obj->pos,obj->segnum,0).centermask!=0) { if (find_object_seg(obj)==-1) { int n; //Int3(); if (obj->type==OBJ_PLAYER && (n=find_point_seg(&obj->last_pos,obj->segnum))!=-1) { obj->pos = obj->last_pos; obj_relink(objnum, n ); } else { compute_segment_center(&obj->pos,&Segments[obj->segnum]); obj->pos.x += objnum; } if (obj->type == OBJ_WEAPON) obj->flags |= OF_SHOULD_BE_DEAD; } } //--WE ALWYS WANT THIS IN, MATT AND MIKE DECISION ON 12/10/94, TWO MONTHS AFTER FINAL #endif }
void init_points(polymodel *pm,vms_vector *box_size,int submodel_num,morph_data *md) { ushort nverts; vms_vector *vp; ushort *data,type; int i; //printf("initing %d ",submodel_num); data = (ushort *) &pm->model_data[pm->submodel_ptrs[submodel_num]]; type = *data++; Assert(type == 7 || type == 1); nverts = *data++; md->n_morphing_points[submodel_num] = 0; if (type==7) { i = *data++; //get start point number data++; //skip pad } else i = 0; //start at zero Assert(i+nverts < MAX_VECS); md->submodel_startpoints[submodel_num] = i; vp = (vms_vector *) data; while (nverts--) { fix k,dist; if (box_size) { fix t; k = 0x7fffffff; if (vp->x && f2i(box_size->x)<abs(vp->x)/2 && (t = fixdiv(box_size->x,abs(vp->x))) < k) k=t; if (vp->y && f2i(box_size->y)<abs(vp->y)/2 && (t = fixdiv(box_size->y,abs(vp->y))) < k) k=t; if (vp->z && f2i(box_size->z)<abs(vp->z)/2 && (t = fixdiv(box_size->z,abs(vp->z))) < k) k=t; if (k==0x7fffffff) k=0; } else k=0; vm_vec_copy_scale(&md->morph_vecs[i],vp,k); dist = vm_vec_normalized_dir_quick(&md->morph_deltas[i],vp,&md->morph_vecs[i]); md->morph_times[i] = fixdiv(dist,morph_rate); if (md->morph_times[i] != 0) md->n_morphing_points[submodel_num]++; vm_vec_scale(&md->morph_deltas[i],morph_rate); vp++; i++; } //printf("npoints = %d\n",n_morphing_points[submodel_num]); }