void CGrid::OnGridXzPlane() { vec3d forward, right; vm_vec_make(&forward, 0.0f, 0.0f, 1.0f); vm_vec_make(&right, 1.0f, 0.0f, 0.0f); GridOrient(&forward, &right); }
// Create a nice grid -- centered at origin, 10x10, 10.0 size squares, in xz plane. grid *create_default_grid(void) { grid *rgrid; vector fvec, rvec, cvec; rgrid = create_grid(&Global_grid, vm_vec_make(&fvec, 0.0f, 0.0f, 1.0f), vm_vec_make(&rvec, 1.0f, 0.0f, 0.0f), vm_vec_make(&cvec, 0.0f, 0.0f, 0.0f), 100, 100, 5.0f); physics_init(&rgrid->physics); return rgrid; }
void GridOrient(vec3d *forward, vec3d *right) { vec3d center; int nrows, ncols; float square_size; if (The_grid != NULL) { center = The_grid->center; nrows = The_grid->nrows; ncols = The_grid->ncols; square_size = The_grid->square_size; } else { vm_vec_make(¢er, 0.0f, 0.0f, 0.0f); nrows = 20; ncols = 20; square_size = 2.0f; } The_grid = create_grid(The_grid, forward, right, ¢er, nrows, ncols, square_size); physics_init(&The_grid->physics); }
int CreateDefaultNewSegment() { // Create a default segment for New_segment. vms_vector tempvec; med_create_new_segment(vm_vec_make(&tempvec,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE)); mine_changed = 1; return 1; }
void physics_init( physics_info * pi ) { memset( pi, 0, sizeof(physics_info) ); pi->mass = 10.0f; // This ship weighs 10 units pi->side_slip_time_const = 0.05f; pi->rotdamp = 0.1f; pi->max_vel.xyz.x = 100.0f; //sideways pi->max_vel.xyz.y = 100.0f; //up/down pi->max_vel.xyz.z = 100.0f; //forward pi->max_rear_vel = 100.0f; //backward -- controlled seperately pi->max_rotvel.xyz.x = 2.0f; //pitch pi->max_rotvel.xyz.y = 1.0f; //heading pi->max_rotvel.xyz.z = 2.0f; //bank pi->prev_ramp_vel.xyz.x = 0.0f; pi->prev_ramp_vel.xyz.y = 0.0f; pi->prev_ramp_vel.xyz.z = 0.0f; pi->desired_vel.xyz.x = 0.0f; pi->desired_vel.xyz.y = 0.0f; pi->desired_vel.xyz.z = 0.0f; pi->slide_accel_time_const=pi->side_slip_time_const; // slide using max_vel.xyz.x & .xyz.y pi->slide_decel_time_const=pi->side_slip_time_const; // slide using max_vel.xyz.x & .xyz.y pi->afterburner_decay = 1; pi->forward_thrust = 0.0f; pi->vert_thrust = 0.0f; //added these two in order to get side and forward thrusters pi->side_thrust = 0.0f; //to glow brighter when the ship is moving in the right direction -Bobboau pi->flags = 0; // default values for moment of inertia vm_vec_make( &pi->I_body_inv.vec.rvec, 1e-5f, 0.0f, 0.0f ); vm_vec_make( &pi->I_body_inv.vec.uvec, 0.0f, 1e-5f, 0.0f ); vm_vec_make( &pi->I_body_inv.vec.fvec, 0.0f, 0.0f, 1e-5f ); }
object *object_create_debris(object *parent, int subobj_num) { int objnum; object *obj; polymodel *po; Assert((parent->type == OBJ_ROBOT) || (parent->type == OBJ_PLAYER) ); objnum = obj_create(OBJ_DEBRIS,0,parent->segnum,&parent->pos, &parent->orient,Polygon_models[parent->rtype.pobj_info.model_num].submodel_rads[subobj_num], CT_DEBRIS,MT_PHYSICS,RT_POLYOBJ); if ((objnum < 0 ) && (Highest_object_index >= MAX_OBJECTS-1)) { mprintf((1, "Can't create object in object_create_debris.\n")); Int3(); return NULL; } if ( objnum < 0 ) return NULL; // Not enough debris slots! obj = &Objects[objnum]; Assert(subobj_num < 32); //Set polygon-object-specific data obj->rtype.pobj_info.model_num = parent->rtype.pobj_info.model_num; obj->rtype.pobj_info.subobj_flags = 1<<subobj_num; obj->rtype.pobj_info.tmap_override = parent->rtype.pobj_info.tmap_override; //Set physics data for this object po = &Polygon_models[obj->rtype.pobj_info.model_num]; obj->mtype.phys_info.velocity.x = RAND_MAX/2 - rand(); obj->mtype.phys_info.velocity.y = RAND_MAX/2 - rand(); obj->mtype.phys_info.velocity.z = RAND_MAX/2 - rand(); vm_vec_normalize_quick(&obj->mtype.phys_info.velocity); vm_vec_scale(&obj->mtype.phys_info.velocity,i2f(10 + (30 * rand() / RAND_MAX))); vm_vec_add2(&obj->mtype.phys_info.velocity,&parent->mtype.phys_info.velocity); vm_vec_make(&obj->mtype.phys_info.rotvel,10*0x2000/3,10*0x4000/3,10*0x7000/3); vm_vec_zero(&obj->mtype.phys_info.rotthrust); obj->lifeleft = DEBRIS_LIFE; obj->mtype.phys_info.mass = fixmuldiv(parent->mtype.phys_info.mass,obj->size,parent->size); obj->mtype.phys_info.drag = 0; //fl2f(0.2); //parent->mtype.phys_info.drag; return obj; }
void HudGaugeRadarOrb::plotBlip(blip *b, vec3d *scaled_pos) { *scaled_pos = b->position; if (IS_VEC_NULL_SQ_SAFE(scaled_pos)) { vm_vec_make(scaled_pos, 1.0f, 0.0f, 0.0f); } else { vm_vec_normalize(scaled_pos); } float scale = b->dist / Radar_bright_range; if (scale > 1.25f) scale = 1.25f; if (scale < .75f) scale = .75f; vm_vec_scale(scaled_pos, scale); }
int CreateNewMine() { if (SafetyCheck()) { texpage_goto_first(); create_new_mine(); LargeView.ev_matrix = vmd_identity_matrix; //FrontView.ev_matrix; set_view_target_from_segment(Cursegp); vm_vec_make(&Seg_scale,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE); Update_flags = UF_WORLD_CHANGED; SetPlayerFromCurseg(); SetPlayerPosition(); //say default is permanant position mine_changed = 0; N_found_segs = 0; N_selected_segs = 0; med_compress_mine(); gamestate_not_restored = 0; init_info = 1; ResetFilename(); Game_mode = GM_UNKNOWN; Current_level_num = 0; //0 means not a real game } return 1; }
void physics_apply_shock(vec3d *direction_vec, float pressure, physics_info *pi, matrix *orient, vec3d *min, vec3d *max, float radius) { vec3d normal; vec3d local_torque, temp_torque, torque; vec3d impact_vec; vec3d area; vec3d sin; if (radius > MAX_RADIUS) { return; } vm_vec_normalize_safe ( direction_vec ); area.xyz.x = (max->xyz.y - min->xyz.z) * (max->xyz.z - min->xyz.z); area.xyz.y = (max->xyz.x - min->xyz.x) * (max->xyz.z - min->xyz.z); area.xyz.z = (max->xyz.x - min->xyz.x) * (max->xyz.y - min->xyz.y); normal.xyz.x = vm_vec_dotprod( direction_vec, &orient->vec.rvec ); normal.xyz.y = vm_vec_dotprod( direction_vec, &orient->vec.uvec ); normal.xyz.z = vm_vec_dotprod( direction_vec, &orient->vec.fvec ); sin.xyz.x = fl_sqrt( fl_abs(1.0f - normal.xyz.x*normal.xyz.x) ); sin.xyz.y = fl_sqrt( fl_abs(1.0f - normal.xyz.y*normal.xyz.y) ); sin.xyz.z = fl_sqrt( fl_abs(1.0f - normal.xyz.z*normal.xyz.z) ); vm_vec_make( &torque, 0.0f, 0.0f, 0.0f ); // find the torque exerted due to the shockwave hitting each face // model the effect of the shockwave as if the shockwave were a plane of projectiles, // all moving in the direction direction_vec. then find the torque as the cross prod // of the force (pressure * area * normal * sin * scale * mass) // normal takes account the fraction of the surface exposed to the shockwave // the sin term is not technically needed but "feels" better // scale factors out the increase in area with larger objects // more massive objects get less rotation // find torque due to forces on the right/left face if ( normal.xyz.x < 0.0f ) // normal < 0, hits the right face vm_vec_copy_scale( &impact_vec, &orient->vec.rvec, max->xyz.x * pressure * area.xyz.x * normal.xyz.x * sin.xyz.x / pi->mass ); else // normal > 0, hits the left face vm_vec_copy_scale( &impact_vec, &orient->vec.rvec, min->xyz.x * pressure * area.xyz.x * -normal.xyz.x * sin.xyz.x / pi->mass ); vm_vec_crossprod( &temp_torque, &impact_vec, direction_vec ); vm_vec_add2( &torque, &temp_torque ); // find torque due to forces on the up/down face if ( normal.xyz.y < 0.0f ) vm_vec_copy_scale( &impact_vec, &orient->vec.uvec, max->xyz.y * pressure * area.xyz.y * normal.xyz.y * sin.xyz.y / pi->mass ); else vm_vec_copy_scale( &impact_vec, &orient->vec.uvec, min->xyz.y * pressure * area.xyz.y * -normal.xyz.y * sin.xyz.y / pi->mass ); vm_vec_crossprod( &temp_torque, &impact_vec, direction_vec ); vm_vec_add2( &torque, &temp_torque ); // find torque due to forces on the forward/backward face if ( normal.xyz.z < 0.0f ) vm_vec_copy_scale( &impact_vec, &orient->vec.fvec, max->xyz.z * pressure * area.xyz.z * normal.xyz.z * sin.xyz.z / pi->mass ); else vm_vec_copy_scale( &impact_vec, &orient->vec.fvec, min->xyz.z * pressure * area.xyz.z * -normal.xyz.z * sin.xyz.z / pi->mass ); vm_vec_crossprod( &temp_torque, &impact_vec, direction_vec ); vm_vec_add2( &torque, &temp_torque ); // compute delta rotvel, scale according to blast and radius float scale; if (radius < MIN_RADIUS) { scale = 1.0f; } else { scale = (MAX_RADIUS - radius)/(MAX_RADIUS-MIN_RADIUS); } // set shockwave shake amplitude, duration, flag pi->shockwave_shake_amp = (float)(MAX_SHAKE*(pressure/STD_PRESSURE)*scale); pi->shockwave_decay = timestamp( SW_BLAST_DURATION ); pi->flags |= PF_IN_SHOCKWAVE; // safety dance if (!(IS_VEC_NULL_SQ_SAFE(&torque))) { vec3d delta_rotvel; vm_vec_rotate( &local_torque, &torque, orient ); vm_vec_copy_normalize(&delta_rotvel, &local_torque); vm_vec_scale(&delta_rotvel, (float)(MAX_ROTVEL*(pressure/STD_PRESSURE)*scale)); // nprintf(("Physics", "rotvel scale %f\n", (MAX_ROTVEL*(pressure/STD_PRESSURE)*scale))); vm_vec_add2(&pi->rotvel, &delta_rotvel); } // set reduced translational damping, set flags float velocity_scale = (float)MAX_VEL*scale; pi->flags |= PF_REDUCED_DAMP; update_reduced_damp_timestamp( pi, velocity_scale*pi->mass ); vm_vec_scale_add2( &pi->vel, direction_vec, velocity_scale ); vm_vec_rotate(&pi->prev_ramp_vel, &pi->vel, orient); // set so velocity will ramp starting from current speed // check that kick from shockwave is not too large if (!(pi->flags & PF_USE_VEL) && (vm_vec_mag_squared(&pi->vel) > MAX_SHIP_SPEED*MAX_SHIP_SPEED)) { // Get DaveA nprintf(("Physics", "speed reset in physics_apply_shock [speed: %f]\n", vm_vec_mag(&pi->vel))); vm_vec_normalize(&pi->vel); vm_vec_scale(&pi->vel, (float)RESET_SHIP_SPEED); } }
// Adds velocity to position // finds velocity and displacement in local coords void physics_sim_vel(vec3d * position, physics_info * pi, float sim_time, matrix *orient) { vec3d local_disp; // displacement in this frame vec3d local_v_in; // velocity in local coords at the start of this frame vec3d local_desired_vel; // desired velocity in local coords vec3d local_v_out; // velocity in local coords following this frame vec3d damp; // Maybe clear the reduced_damp flag. // This fixes the problem of the player getting near-instantaneous acceleration under unknown circumstances. // The larger problem is probably that PF_USE_VEL is getting stuck set. if ((pi->flags & PF_REDUCED_DAMP) && (timestamp_elapsed(pi->reduced_damp_decay))) { pi->flags &= ~PF_REDUCED_DAMP; } // Set up damping constants based on special conditions // ie. shockwave, collision, weapon, dead if (pi->flags & PF_DEAD_DAMP) { // side_slip_time_const is already quite large and now needs to be applied in all directions vm_vec_make( &damp, pi->side_slip_time_const, pi->side_slip_time_const, pi->side_slip_time_const ); } else if (pi->flags & PF_REDUCED_DAMP) { // case of shock, weapon, collide, etc. if ( timestamp_elapsed(pi->reduced_damp_decay) ) { vm_vec_make( &damp, pi->side_slip_time_const, pi->side_slip_time_const, 0.0f ); } else { // damp is multiplied by fraction and not fraction^2, gives better collision separation float reduced_damp_fraction_time_left = timestamp_until( pi->reduced_damp_decay ) / (float) REDUCED_DAMP_TIME; damp.xyz.x = pi->side_slip_time_const * ( 1 + (REDUCED_DAMP_FACTOR-1) * reduced_damp_fraction_time_left ); damp.xyz.y = pi->side_slip_time_const * ( 1 + (REDUCED_DAMP_FACTOR-1) * reduced_damp_fraction_time_left ); damp.xyz.z = pi->side_slip_time_const * reduced_damp_fraction_time_left * REDUCED_DAMP_FACTOR; } } else { // regular damping if (pi->use_newtonian_damp) { vm_vec_make( &damp, pi->side_slip_time_const, pi->side_slip_time_const, pi->side_slip_time_const ); } else { vm_vec_make( &damp, pi->side_slip_time_const, pi->side_slip_time_const, 0.0f ); } } // Note: CANNOT maintain a *local velocity* since a rotation can occur in this frame. // thus the local velocity of in the next frame can be different (this would require rotate to change local vel // and this is not desired // get local components of current velocity vm_vec_rotate (&local_v_in, &pi->vel, orient); // get local components of desired velocity vm_vec_rotate (&local_desired_vel, &pi->desired_vel, orient); // find updated LOCAL velocity and position in the local x direction apply_physics (damp.xyz.x, local_desired_vel.xyz.x, local_v_in.xyz.x, sim_time, &local_v_out.xyz.x, &local_disp.xyz.x); // find updated LOCAL velocity and position in the local y direction apply_physics (damp.xyz.y, local_desired_vel.xyz.y, local_v_in.xyz.y, sim_time, &local_v_out.xyz.y, &local_disp.xyz.y); // find updated LOCAL velocity and position in the local z direction // for player ship, damp should normally be zero, but may be altered in a shockwave // in death, shockwave,etc. we want damping time const large for all 3 axes // warp in test - make excessive speed drop exponentially from max allowed // become (0.01x in 3 sec) int special_warp_in = FALSE; float excess = local_v_in.xyz.z - pi->max_vel.xyz.z; if (excess > 5 && (pi->flags & PF_SPECIAL_WARP_IN)) { special_warp_in = TRUE; float exp_factor = float(exp(-sim_time / SPECIAL_WARP_T_CONST)); local_v_out.xyz.z = pi->max_vel.xyz.z + excess * exp_factor; local_disp.xyz.z = (pi->max_vel.xyz.z * sim_time) + excess * (float(SPECIAL_WARP_T_CONST) * (1.0f - exp_factor)); } else if (pi->flags & PF_SPECIAL_WARP_OUT) { float exp_factor = float(exp(-sim_time / SPECIAL_WARP_T_CONST)); vec3d temp; vm_vec_rotate(&temp, &pi->prev_ramp_vel, orient); float deficeit = temp.xyz.z - local_v_in.xyz.z; local_v_out.xyz.z = local_v_in.xyz.z + deficeit * (1.0f - exp_factor); local_disp.xyz.z = (local_v_in.xyz.z * sim_time) + deficeit * (sim_time - (float(SPECIAL_WARP_T_CONST) * (1.0f - exp_factor))); } else { apply_physics (damp.xyz.z, local_desired_vel.xyz.z, local_v_in.xyz.z, sim_time, &local_v_out.xyz.z, &local_disp.xyz.z); } // maybe turn off special warp in flag if ((pi->flags & PF_SPECIAL_WARP_IN) && (excess < 5)) { pi->flags &= ~(PF_SPECIAL_WARP_IN); } // update world position from local to world coords using orient vec3d world_disp; vm_vec_unrotate (&world_disp, &local_disp, orient); vm_vec_add2 (position, &world_disp); // update world velocity vm_vec_unrotate(&pi->vel, &local_v_out, orient); if (special_warp_in) { vm_vec_rotate(&pi->prev_ramp_vel, &pi->vel, orient); } }
// ----------------------------------------------------------------------------- //loads from an already-open file // returns 0=everything ok, 1=old version, -1=error int load_mine_data(CFILE *LoadFile) { int i, j; short tmap_xlate; int translate; char *temptr; int mine_start = cftell(LoadFile); fuelcen_reset(); for (i=0; i<MAX_TEXTURES; i++ ) tmap_times_used[i] = 0; #ifdef EDITOR // Create a new mine to initialize things. //texpage_goto_first(); create_new_mine(); #endif //===================== READ FILE INFO ======================== // These are the default values... version and fileinfo_sizeof // don't have defaults. mine_fileinfo.header_offset = -1; mine_fileinfo.header_size = sizeof(mine_header); mine_fileinfo.editor_offset = -1; mine_fileinfo.editor_size = sizeof(mine_editor); mine_fileinfo.vertex_offset = -1; mine_fileinfo.vertex_howmany = 0; mine_fileinfo.vertex_sizeof = sizeof(vms_vector); mine_fileinfo.segment_offset = -1; mine_fileinfo.segment_howmany = 0; mine_fileinfo.segment_sizeof = sizeof(segment); mine_fileinfo.newseg_verts_offset = -1; mine_fileinfo.newseg_verts_howmany = 0; mine_fileinfo.newseg_verts_sizeof = sizeof(vms_vector); mine_fileinfo.group_offset = -1; mine_fileinfo.group_howmany = 0; mine_fileinfo.group_sizeof = sizeof(group); mine_fileinfo.texture_offset = -1; mine_fileinfo.texture_howmany = 0; mine_fileinfo.texture_sizeof = 13; // num characters in a name mine_fileinfo.walls_offset = -1; mine_fileinfo.walls_howmany = 0; mine_fileinfo.walls_sizeof = sizeof(wall); mine_fileinfo.triggers_offset = -1; mine_fileinfo.triggers_howmany = 0; mine_fileinfo.triggers_sizeof = sizeof(trigger); mine_fileinfo.object_offset = -1; mine_fileinfo.object_howmany = 1; mine_fileinfo.object_sizeof = sizeof(object); // Read in mine_top_fileinfo to get size of saved fileinfo. memset( &mine_top_fileinfo, 0, sizeof(mine_top_fileinfo) ); if (cfseek( LoadFile, mine_start, SEEK_SET )) Error( "Error moving to top of file in gamemine.c" ); if (cfread( &mine_top_fileinfo, sizeof(mine_top_fileinfo), 1, LoadFile )!=1) Error( "Error reading mine_top_fileinfo in gamemine.c" ); if (mine_top_fileinfo.fileinfo_signature != 0x2884) return -1; // Check version number if (mine_top_fileinfo.fileinfo_version < COMPATIBLE_VERSION ) return -1; // Now, Read in the fileinfo if (cfseek( LoadFile, mine_start, SEEK_SET )) Error( "Error seeking to top of file in gamemine.c" ); if (cfread( &mine_fileinfo, mine_top_fileinfo.fileinfo_sizeof, 1, LoadFile )!=1) Error( "Error reading mine_fileinfo in gamemine.c" ); //===================== READ HEADER INFO ======================== // Set default values. mine_header.num_vertices = 0; mine_header.num_segments = 0; if (mine_fileinfo.header_offset > -1 ) { if (cfseek( LoadFile, mine_fileinfo.header_offset, SEEK_SET )) Error( "Error seeking to header_offset in gamemine.c" ); if (cfread( &mine_header, mine_fileinfo.header_size, 1, LoadFile )!=1) Error( "Error reading mine_header in gamemine.c" ); } //===================== READ EDITOR INFO ========================== // Set default values mine_editor.current_seg = 0; mine_editor.newsegment_offset = -1; // To be written mine_editor.newsegment_size = sizeof(segment); mine_editor.Curside = 0; mine_editor.Markedsegp = -1; mine_editor.Markedside = 0; if (mine_fileinfo.editor_offset > -1 ) { if (cfseek( LoadFile, mine_fileinfo.editor_offset, SEEK_SET )) Error( "Error seeking to editor_offset in gamemine.c" ); if (cfread( &mine_editor, mine_fileinfo.editor_size, 1, LoadFile )!=1) Error( "Error reading mine_editor in gamemine.c" ); } //===================== READ TEXTURE INFO ========================== if ( (mine_fileinfo.texture_offset > -1) && (mine_fileinfo.texture_howmany > 0)) { if (cfseek( LoadFile, mine_fileinfo.texture_offset, SEEK_SET )) Error( "Error seeking to texture_offset in gamemine.c" ); for (i=0; i< mine_fileinfo.texture_howmany; i++ ) { if (cfread( &old_tmap_list[i], mine_fileinfo.texture_sizeof, 1, LoadFile )!=1) Error( "Error reading old_tmap_list[i] in gamemine.c" ); } } //=============== GENERATE TEXTURE TRANSLATION TABLE =============== translate = 0; Assert (NumTextures < MAX_TEXTURES); { hashtable ht; hashtable_init( &ht, NumTextures ); // Remove all the file extensions in the textures list for (i=0;i<NumTextures;i++) { temptr = strchr(TmapInfo[i].filename, '.'); if (temptr) *temptr = '\0'; hashtable_insert( &ht, TmapInfo[i].filename, i ); } // For every texture, search through the texture list // to find a matching name. for (j=0;j<mine_fileinfo.texture_howmany;j++) { // Remove this texture name's extension temptr = strchr(old_tmap_list[j], '.'); if (temptr) *temptr = '\0'; tmap_xlate_table[j] = hashtable_search( &ht,old_tmap_list[j]); if (tmap_xlate_table[j] < 0 ) { //tmap_xlate_table[j] = 0; // mprintf( (0, "Couldn't find texture '%s'\n", old_tmap_list[j] )); ; } if (tmap_xlate_table[j] != j ) translate = 1; if (tmap_xlate_table[j] >= 0) tmap_times_used[tmap_xlate_table[j]]++; } { int count = 0; for (i=0; i<MAX_TEXTURES; i++ ) if (tmap_times_used[i]) count++; mprintf( (0, "This mine has %d unique textures in it (~%d KB)\n", count, (count*4096) /1024 )); } mprintf( (0, "Translate=%d\n", translate )); hashtable_free( &ht ); } //====================== READ VERTEX INFO ========================== // New check added to make sure we don't read in too many vertices. if ( mine_fileinfo.vertex_howmany > MAX_VERTICES ) { mprintf((0, "Num vertices exceeds maximum. Loading MAX %d vertices\n", MAX_VERTICES)); mine_fileinfo.vertex_howmany = MAX_VERTICES; } if ( (mine_fileinfo.vertex_offset > -1) && (mine_fileinfo.vertex_howmany > 0)) { if (cfseek( LoadFile, mine_fileinfo.vertex_offset, SEEK_SET )) Error( "Error seeking to vertex_offset in gamemine.c" ); for (i=0; i< mine_fileinfo.vertex_howmany; i++ ) { // Set the default values for this vertex Vertices[i].x = 1; Vertices[i].y = 1; Vertices[i].z = 1; if (cfread( &Vertices[i], mine_fileinfo.vertex_sizeof, 1, LoadFile )!=1) Error( "Error reading Vertices[i] in gamemine.c" ); } } //==================== READ SEGMENT INFO =========================== // New check added to make sure we don't read in too many segments. if ( mine_fileinfo.segment_howmany > MAX_SEGMENTS ) { mprintf((0, "Num segments exceeds maximum. Loading MAX %d segments\n", MAX_SEGMENTS)); mine_fileinfo.segment_howmany = MAX_SEGMENTS; } // [commented out by mk on 11/20/94 (weren't we supposed to hit final in October?) because it looks redundant. I think I'll test it now...] fuelcen_reset(); if ( (mine_fileinfo.segment_offset > -1) && (mine_fileinfo.segment_howmany > 0)) { if (cfseek( LoadFile, mine_fileinfo.segment_offset,SEEK_SET )) Error( "Error seeking to segment_offset in gamemine.c" ); Highest_segment_index = mine_fileinfo.segment_howmany-1; for (i=0; i< mine_fileinfo.segment_howmany; i++ ) { segment v16_seg; // Set the default values for this segment (clear to zero ) //memset( &Segments[i], 0, sizeof(segment) ); if (mine_top_fileinfo.fileinfo_version >= 16) { Assert(mine_fileinfo.segment_sizeof == sizeof(v16_seg)); if (cfread( &v16_seg, mine_fileinfo.segment_sizeof, 1, LoadFile )!=1) Error( "Error reading segments in gamemine.c" ); } else Error("Invalid mine version"); Segments[i] = v16_seg; Segments[i].objects = -1; #ifdef EDITOR Segments[i].group = -1; #endif if (mine_top_fileinfo.fileinfo_version < 15) { //used old uvl ranges int sn,uvln; for (sn=0;sn<MAX_SIDES_PER_SEGMENT;sn++) for (uvln=0;uvln<4;uvln++) { Segments[i].sides[sn].uvls[uvln].u /= 64; Segments[i].sides[sn].uvls[uvln].v /= 64; Segments[i].sides[sn].uvls[uvln].l /= 32; } } fuelcen_activate( &Segments[i], Segments[i].special ); if (translate == 1) for (j=0;j<MAX_SIDES_PER_SEGMENT;j++) { unsigned short orient; tmap_xlate = Segments[i].sides[j].tmap_num; Segments[i].sides[j].tmap_num = tmap_xlate_table[tmap_xlate]; if ((WALL_IS_DOORWAY(&Segments[i],j) & WID_RENDER_FLAG)) if (Segments[i].sides[j].tmap_num < 0) { mprintf( (0, "Couldn't find texture '%s' for Segment %d, side %d\n", old_tmap_list[tmap_xlate],i,j)); Int3(); Segments[i].sides[j].tmap_num = 0; } tmap_xlate = Segments[i].sides[j].tmap_num2 & 0x3FFF; orient = Segments[i].sides[j].tmap_num2 & (~0x3FFF); if (tmap_xlate != 0) { int xlated_tmap = tmap_xlate_table[tmap_xlate]; if ((WALL_IS_DOORWAY(&Segments[i],j) & WID_RENDER_FLAG)) if (xlated_tmap <= 0) { mprintf( (0, "Couldn't find texture '%s' for Segment %d, side %d\n", old_tmap_list[tmap_xlate],i,j)); Int3(); Segments[i].sides[j].tmap_num2 = 0; } Segments[i].sides[j].tmap_num2 = xlated_tmap | orient; } } } } //===================== READ NEWSEGMENT INFO ===================== #ifdef EDITOR { // Default segment created. vms_vector sizevec; med_create_new_segment(vm_vec_make(&sizevec,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE)); // New_segment = Segments[0]; //memset( &New_segment, 0, sizeof(segment) ); } if (mine_editor.newsegment_offset > -1) { if (cfseek( LoadFile, mine_editor.newsegment_offset,SEEK_SET )) Error( "Error seeking to newsegment_offset in gamemine.c" ); if (cfread( &New_segment, mine_editor.newsegment_size,1,LoadFile )!=1) Error( "Error reading new_segment in gamemine.c" ); } if ( (mine_fileinfo.newseg_verts_offset > -1) && (mine_fileinfo.newseg_verts_howmany > 0)) { if (cfseek( LoadFile, mine_fileinfo.newseg_verts_offset, SEEK_SET )) Error( "Error seeking to newseg_verts_offset in gamemine.c" ); for (i=0; i< mine_fileinfo.newseg_verts_howmany; i++ ) { // Set the default values for this vertex Vertices[NEW_SEGMENT_VERTICES+i].x = 1; Vertices[NEW_SEGMENT_VERTICES+i].y = 1; Vertices[NEW_SEGMENT_VERTICES+i].z = 1; if (cfread( &Vertices[NEW_SEGMENT_VERTICES+i], mine_fileinfo.newseg_verts_sizeof,1,LoadFile )!=1) Error( "Error reading Vertices[NEW_SEGMENT_VERTICES+i] in gamemine.c" ); New_segment.verts[i] = NEW_SEGMENT_VERTICES+i; } } #endif //========================= UPDATE VARIABLES ====================== #ifdef EDITOR // Setting to Markedsegp to NULL ignores Curside and Markedside, which // we want to do when reading in an old file. Markedside = mine_editor.Markedside; Curside = mine_editor.Curside; for (i=0;i<10;i++) Groupside[i] = mine_editor.Groupside[i]; if ( mine_editor.current_seg != -1 ) Cursegp = mine_editor.current_seg + Segments; else Cursegp = NULL; if (mine_editor.Markedsegp != -1 ) Markedsegp = mine_editor.Markedsegp + Segments; else Markedsegp = NULL; num_groups = 0; current_group = -1; #endif Num_vertices = mine_fileinfo.vertex_howmany; Num_segments = mine_fileinfo.segment_howmany; Highest_vertex_index = Num_vertices-1; Highest_segment_index = Num_segments-1; reset_objects(1); //one object, the player #ifdef EDITOR Highest_vertex_index = MAX_SEGMENT_VERTICES-1; Highest_segment_index = MAX_SEGMENTS-1; set_vertex_counts(); Highest_vertex_index = Num_vertices-1; Highest_segment_index = Num_segments-1; warn_if_concave_segments(); #endif #ifdef EDITOR validate_segment_all(); #endif //create_local_segment_data(); //gamemine_find_textures(); if (mine_top_fileinfo.fileinfo_version < MINE_VERSION ) return 1; //old version else return 0; }
// -------------------------------------------------------------------------------------- // Create a new mine, set global variables. int create_new_mine(void) { int s; vms_vector sizevec; vms_matrix m1 = IDENTITY_MATRIX; // initialize_mine_arrays(); // gamestate_not_restored = 1; // Clear refueling center code fuelcen_reset(); hostage_init_all(); init_all_vertices(); Current_level_num = 0; //0 means not a real level Current_level_name[0] = 0; Gamesave_current_version = LEVEL_FILE_VERSION; Cur_object_index = -1; reset_objects(1); //just one object, the player num_groups = 0; current_group = -1; Num_vertices = 0; // Number of vertices in global array. Highest_vertex_index = 0; Num_segments = 0; // Number of segments in global array, will get increased in med_create_segment Highest_segment_index = 0; Cursegp = Segments; // Say current segment is the only segment. Curside = WBACK; // The active side is the back side Markedsegp = 0; // Say there is no marked segment. Markedside = WBACK; // Shouldn't matter since Markedsegp == 0, but just in case... for (s=0;s<MAX_GROUPS+1;s++) { GroupList[s].num_segments = 0; GroupList[s].num_vertices = 0; Groupsegp[s] = NULL; Groupside[s] = 0; } Num_robot_centers = 0; Num_open_doors = 0; wall_init(); trigger_init(); // Create New_segment, which is the segment we will be adding at each instance. med_create_new_segment(vm_vec_make(&sizevec,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE)); // New_segment = Segments[0]; // med_create_segment(Segments,0,0,0,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE,vm_mat_make(&m1,F1_0,0,0,0,F1_0,0,0,0,F1_0)); med_create_segment(Segments,0,0,0,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE,&m1); N_found_segs = 0; N_selected_segs = 0; N_warning_segs = 0; //--repair-- create_local_segment_data(); ControlCenterTriggers.num_links = 0; create_new_mission(); //editor_status("New mine created."); return 0; // say no error }
// ----------------------------------------------------------------------------- //loads from an already-open file // returns 0=everything ok, 1=old version, -1=error int load_mine_data(PHYSFS_file *LoadFile) { int i, j; short tmap_xlate; int translate; char *temptr; int mine_start = PHYSFS_tell(LoadFile); fuelcen_reset(); for (i=0; i<sizeof(tmap_times_used)/sizeof(tmap_times_used[0]); i++ ) tmap_times_used[i] = 0; #ifdef EDITOR // Create a new mine to initialize things. //texpage_goto_first(); create_new_mine(); #endif //===================== READ FILE INFO ======================== // These are the default values... version and fileinfo_sizeof // don't have defaults. mine_fileinfo.header_offset = -1; mine_fileinfo.header_size = sizeof(mine_header); mine_fileinfo.editor_offset = -1; mine_fileinfo.editor_size = sizeof(mine_editor); mine_fileinfo.vertex_offset = -1; mine_fileinfo.vertex_howmany = 0; mine_fileinfo.vertex_sizeof = sizeof(vms_vector); mine_fileinfo.segment_offset = -1; mine_fileinfo.segment_howmany = 0; mine_fileinfo.segment_sizeof = sizeof(segment); mine_fileinfo.newseg_verts_offset = -1; mine_fileinfo.newseg_verts_howmany = 0; mine_fileinfo.newseg_verts_sizeof = sizeof(vms_vector); mine_fileinfo.group_offset = -1; mine_fileinfo.group_howmany = 0; mine_fileinfo.group_sizeof = sizeof(group); mine_fileinfo.texture_offset = -1; mine_fileinfo.texture_howmany = 0; mine_fileinfo.texture_sizeof = FILENAME_LEN; // num characters in a name mine_fileinfo.walls_offset = -1; mine_fileinfo.walls_howmany = 0; mine_fileinfo.walls_sizeof = sizeof(wall); mine_fileinfo.triggers_offset = -1; mine_fileinfo.triggers_howmany = 0; mine_fileinfo.triggers_sizeof = sizeof(trigger); mine_fileinfo.object_offset = -1; mine_fileinfo.object_howmany = 1; mine_fileinfo.object_sizeof = sizeof(object); mine_fileinfo.level_shake_frequency = 0; mine_fileinfo.level_shake_duration = 0; // Delta light stuff for blowing out light sources. // if (mine_top_fileinfo.fileinfo_version >= 19) { mine_fileinfo.dl_indices_offset = -1; mine_fileinfo.dl_indices_howmany = 0; mine_fileinfo.dl_indices_sizeof = sizeof(dl_index); mine_fileinfo.delta_light_offset = -1; mine_fileinfo.delta_light_howmany = 0; mine_fileinfo.delta_light_sizeof = sizeof(delta_light); // } mine_fileinfo.segment2_offset = -1; mine_fileinfo.segment2_howmany = 0; mine_fileinfo.segment2_sizeof = sizeof(segment2); // Read in mine_top_fileinfo to get size of saved fileinfo. memset( &mine_top_fileinfo, 0, sizeof(mine_top_fileinfo) ); if (PHYSFSX_fseek( LoadFile, mine_start, SEEK_SET )) Error( "Error moving to top of file in gamemine.c" ); if (PHYSFS_read( LoadFile, &mine_top_fileinfo, sizeof(mine_top_fileinfo), 1 )!=1) Error( "Error reading mine_top_fileinfo in gamemine.c" ); if (mine_top_fileinfo.fileinfo_signature != 0x2884) return -1; // Check version number if (mine_top_fileinfo.fileinfo_version < COMPATIBLE_VERSION ) return -1; // Now, Read in the fileinfo if (PHYSFSX_fseek( LoadFile, mine_start, SEEK_SET )) Error( "Error seeking to top of file in gamemine.c" ); if (PHYSFS_read( LoadFile, &mine_fileinfo, mine_top_fileinfo.fileinfo_sizeof, 1 )!=1) Error( "Error reading mine_fileinfo in gamemine.c" ); if (mine_top_fileinfo.fileinfo_version < 18) { Level_shake_frequency = 0; Level_shake_duration = 0; Secret_return_segment = 0; Secret_return_orient = vmd_identity_matrix; } else { Level_shake_frequency = mine_fileinfo.level_shake_frequency << 12; Level_shake_duration = mine_fileinfo.level_shake_duration << 12; Secret_return_segment = mine_fileinfo.secret_return_segment; Secret_return_orient = mine_fileinfo.secret_return_orient; } //===================== READ HEADER INFO ======================== // Set default values. mine_header.num_vertices = 0; mine_header.num_segments = 0; if (mine_fileinfo.header_offset > -1 ) { if (PHYSFSX_fseek( LoadFile, mine_fileinfo.header_offset, SEEK_SET )) Error( "Error seeking to header_offset in gamemine.c" ); if (PHYSFS_read( LoadFile, &mine_header, mine_fileinfo.header_size, 1 )!=1) Error( "Error reading mine_header in gamemine.c" ); } //===================== READ EDITOR INFO ========================== // Set default values mine_editor.current_seg = 0; mine_editor.newsegment_offset = -1; // To be written mine_editor.newsegment_size = sizeof(segment); mine_editor.Curside = 0; mine_editor.Markedsegp = -1; mine_editor.Markedside = 0; if (mine_fileinfo.editor_offset > -1 ) { if (PHYSFSX_fseek( LoadFile, mine_fileinfo.editor_offset, SEEK_SET )) Error( "Error seeking to editor_offset in gamemine.c" ); if (PHYSFS_read( LoadFile, &mine_editor, mine_fileinfo.editor_size, 1 )!=1) Error( "Error reading mine_editor in gamemine.c" ); } //===================== READ TEXTURE INFO ========================== if ( (mine_fileinfo.texture_offset > -1) && (mine_fileinfo.texture_howmany > 0)) { if (PHYSFSX_fseek( LoadFile, mine_fileinfo.texture_offset, SEEK_SET )) Error( "Error seeking to texture_offset in gamemine.c" ); for (i=0; i< mine_fileinfo.texture_howmany; i++ ) { if (PHYSFS_read( LoadFile, &old_tmap_list[i], mine_fileinfo.texture_sizeof, 1 )!=1) Error( "Error reading old_tmap_list[i] in gamemine.c" ); } } //=============== GENERATE TEXTURE TRANSLATION TABLE =============== translate = 0; Assert (NumTextures < MAX_TEXTURES); { hashtable ht; hashtable_init( &ht, NumTextures ); // Remove all the file extensions in the textures list for (i=0;i<NumTextures;i++) { temptr = strchr(TmapInfo[i].filename, '.'); if (temptr) *temptr = '\0'; hashtable_insert( &ht, TmapInfo[i].filename, i ); } // For every texture, search through the texture list // to find a matching name. for (j=0;j<mine_fileinfo.texture_howmany;j++) { // Remove this texture name's extension temptr = strchr(old_tmap_list[j], '.'); if (temptr) *temptr = '\0'; tmap_xlate_table[j] = hashtable_search( &ht,old_tmap_list[j]); if (tmap_xlate_table[j] < 0 ) { ; } if (tmap_xlate_table[j] != j ) translate = 1; if (tmap_xlate_table[j] >= 0) tmap_times_used[tmap_xlate_table[j]]++; } { int count = 0; for (i=0; i<MAX_TEXTURES; i++ ) if (tmap_times_used[i]) count++; } hashtable_free( &ht ); } //====================== READ VERTEX INFO ========================== // New check added to make sure we don't read in too many vertices. if ( mine_fileinfo.vertex_howmany > MAX_VERTICES ) { mine_fileinfo.vertex_howmany = MAX_VERTICES; } if ( (mine_fileinfo.vertex_offset > -1) && (mine_fileinfo.vertex_howmany > 0)) { if (PHYSFSX_fseek( LoadFile, mine_fileinfo.vertex_offset, SEEK_SET )) Error( "Error seeking to vertex_offset in gamemine.c" ); for (i=0; i< mine_fileinfo.vertex_howmany; i++ ) { // Set the default values for this vertex Vertices[i].x = 1; Vertices[i].y = 1; Vertices[i].z = 1; if (PHYSFS_read( LoadFile, &Vertices[i], mine_fileinfo.vertex_sizeof, 1 )!=1) Error( "Error reading Vertices[i] in gamemine.c" ); } } //==================== READ SEGMENT INFO =========================== // New check added to make sure we don't read in too many segments. if ( mine_fileinfo.segment_howmany > MAX_SEGMENTS ) { mine_fileinfo.segment_howmany = MAX_SEGMENTS; mine_fileinfo.segment2_howmany = MAX_SEGMENTS; } // [commented out by mk on 11/20/94 (weren't we supposed to hit final in October?) because it looks redundant. I think I'll test it now...] fuelcen_reset(); if ( (mine_fileinfo.segment_offset > -1) && (mine_fileinfo.segment_howmany > 0)) { if (PHYSFSX_fseek( LoadFile, mine_fileinfo.segment_offset,SEEK_SET )) Error( "Error seeking to segment_offset in gamemine.c" ); Highest_segment_index = mine_fileinfo.segment_howmany-1; for (i=0; i< mine_fileinfo.segment_howmany; i++ ) { // Set the default values for this segment (clear to zero ) //memset( &Segments[i], 0, sizeof(segment) ); if (mine_top_fileinfo.fileinfo_version < 20) { v16_segment v16_seg; Assert(mine_fileinfo.segment_sizeof == sizeof(v16_seg)); if (PHYSFS_read( LoadFile, &v16_seg, mine_fileinfo.segment_sizeof, 1 )!=1) Error( "Error reading segments in gamemine.c" ); #ifdef EDITOR Segments[i].segnum = v16_seg.segnum; // -- Segments[i].pad = v16_seg.pad; #endif for (j=0; j<MAX_SIDES_PER_SEGMENT; j++) Segments[i].sides[j] = v16_seg.sides[j]; for (j=0; j<MAX_SIDES_PER_SEGMENT; j++) Segments[i].children[j] = v16_seg.children[j]; for (j=0; j<MAX_VERTICES_PER_SEGMENT; j++) Segments[i].verts[j] = v16_seg.verts[j]; Segment2s[i].special = v16_seg.special; Segment2s[i].value = v16_seg.value; Segment2s[i].s2_flags = 0; Segment2s[i].matcen_num = v16_seg.matcen_num; Segment2s[i].static_light = v16_seg.static_light; fuelcen_activate( &Segments[i], Segment2s[i].special ); } else { if (PHYSFS_read( LoadFile, &Segments[i], mine_fileinfo.segment_sizeof, 1 )!=1) Error("Unable to read segment %i\n", i); } Segments[i].objects = -1; #ifdef EDITOR Segments[i].group = -1; #endif if (mine_top_fileinfo.fileinfo_version < 15) { //used old uvl ranges int sn,uvln; for (sn=0;sn<MAX_SIDES_PER_SEGMENT;sn++) for (uvln=0;uvln<4;uvln++) { Segments[i].sides[sn].uvls[uvln].u /= 64; Segments[i].sides[sn].uvls[uvln].v /= 64; Segments[i].sides[sn].uvls[uvln].l /= 32; } } if (translate == 1) for (j=0;j<MAX_SIDES_PER_SEGMENT;j++) { unsigned short orient; tmap_xlate = Segments[i].sides[j].tmap_num; Segments[i].sides[j].tmap_num = tmap_xlate_table[tmap_xlate]; if ((WALL_IS_DOORWAY(&Segments[i],j) & WID_RENDER_FLAG)) if (Segments[i].sides[j].tmap_num < 0) { Int3(); Segments[i].sides[j].tmap_num = NumTextures-1; } tmap_xlate = Segments[i].sides[j].tmap_num2 & TMAP_NUM_MASK; orient = Segments[i].sides[j].tmap_num2 & (~TMAP_NUM_MASK); if (tmap_xlate != 0) { int xlated_tmap = tmap_xlate_table[tmap_xlate]; if ((WALL_IS_DOORWAY(&Segments[i],j) & WID_RENDER_FLAG)) if (xlated_tmap <= 0) { Int3(); Segments[i].sides[j].tmap_num2 = NumTextures-1; } Segments[i].sides[j].tmap_num2 = xlated_tmap | orient; } } } if (mine_top_fileinfo.fileinfo_version >= 20) for (i=0; i<=Highest_segment_index; i++) { PHYSFS_read(LoadFile, &Segment2s[i], sizeof(segment2), 1); fuelcen_activate( &Segments[i], Segment2s[i].special ); } } //===================== READ NEWSEGMENT INFO ===================== #ifdef EDITOR { // Default segment created. vms_vector sizevec; med_create_new_segment(vm_vec_make(&sizevec,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE)); // New_segment = Segments[0]; //memset( &New_segment, 0, sizeof(segment) ); } if (mine_editor.newsegment_offset > -1) { if (PHYSFSX_fseek( LoadFile, mine_editor.newsegment_offset,SEEK_SET )) Error( "Error seeking to newsegment_offset in gamemine.c" ); if (PHYSFS_read( LoadFile, &New_segment, mine_editor.newsegment_size,1 )!=1) Error( "Error reading new_segment in gamemine.c" ); } if ( (mine_fileinfo.newseg_verts_offset > -1) && (mine_fileinfo.newseg_verts_howmany > 0)) { if (PHYSFSX_fseek( LoadFile, mine_fileinfo.newseg_verts_offset, SEEK_SET )) Error( "Error seeking to newseg_verts_offset in gamemine.c" ); for (i=0; i< mine_fileinfo.newseg_verts_howmany; i++ ) { // Set the default values for this vertex Vertices[NEW_SEGMENT_VERTICES+i].x = 1; Vertices[NEW_SEGMENT_VERTICES+i].y = 1; Vertices[NEW_SEGMENT_VERTICES+i].z = 1; if (PHYSFS_read( LoadFile, &Vertices[NEW_SEGMENT_VERTICES+i], mine_fileinfo.newseg_verts_sizeof,1 )!=1) Error( "Error reading Vertices[NEW_SEGMENT_VERTICES+i] in gamemine.c" ); New_segment.verts[i] = NEW_SEGMENT_VERTICES+i; } } #endif //========================= UPDATE VARIABLES ====================== #ifdef EDITOR // Setting to Markedsegp to NULL ignores Curside and Markedside, which // we want to do when reading in an old file. Markedside = mine_editor.Markedside; Curside = mine_editor.Curside; for (i=0;i<10;i++) Groupside[i] = mine_editor.Groupside[i]; if ( mine_editor.current_seg != -1 ) Cursegp = mine_editor.current_seg + Segments; else Cursegp = NULL; if (mine_editor.Markedsegp != -1 ) Markedsegp = mine_editor.Markedsegp + Segments; else Markedsegp = NULL; num_groups = 0; current_group = -1; #endif Num_vertices = mine_fileinfo.vertex_howmany; Num_segments = mine_fileinfo.segment_howmany; Highest_vertex_index = Num_vertices-1; Highest_segment_index = Num_segments-1; reset_objects(1); //one object, the player #ifdef EDITOR Highest_vertex_index = MAX_SEGMENT_VERTICES-1; Highest_segment_index = MAX_SEGMENTS-1; set_vertex_counts(); Highest_vertex_index = Num_vertices-1; Highest_segment_index = Num_segments-1; warn_if_concave_segments(); #endif #ifdef EDITOR validate_segment_all(); #endif //create_local_segment_data(); //gamemine_find_textures(); if (mine_top_fileinfo.fileinfo_version < MINE_VERSION ) return 1; //old version else return 0; }
void briefing_editor_dlg::OnMakeIcon() { char *name; int z, len, team, ship, waypoint, count = -1; int cargo = 0, cargo_count = 0, freighter_count = 0; object *ptr; vec3d min, max, pos; brief_icon *iconp; if (Briefing->stages[m_cur_stage].num_icons >= MAX_STAGE_ICONS) return; m_cur_icon = Briefing->stages[m_cur_stage].num_icons++; iconp = &Briefing->stages[m_cur_stage].icons[m_cur_icon]; ship = waypoint = -1; team = 0; jump_node *jnp = NULL; vm_vec_make(&min, 9e19f, 9e19f, 9e19f); vm_vec_make(&max, -9e19f, -9e19f, -9e19f); ptr = GET_FIRST(&obj_used_list); while (ptr != END_OF_LIST(&obj_used_list)) { if (ptr->flags & OF_MARKED) { if (ptr->pos.xyz.x < min.xyz.x) min.xyz.x = ptr->pos.xyz.x; if (ptr->pos.xyz.x > max.xyz.x) max.xyz.x = ptr->pos.xyz.x; if (ptr->pos.xyz.y < min.xyz.y) min.xyz.y = ptr->pos.xyz.y; if (ptr->pos.xyz.y > max.xyz.y) max.xyz.y = ptr->pos.xyz.y; if (ptr->pos.xyz.z < min.xyz.z) min.xyz.z = ptr->pos.xyz.z; if (ptr->pos.xyz.z > max.xyz.z) max.xyz.z = ptr->pos.xyz.z; switch (ptr->type) { case OBJ_SHIP: case OBJ_START: ship = ptr->instance; break; case OBJ_WAYPOINT: waypoint = ptr->instance; break; case OBJ_JUMP_NODE: jnp = ptr->jnp; break; default: Int3(); } if (ship >= 0) { team = Ships[ship].team; z = ship_query_general_type(ship); if (Ship_info[Ships[ship].ship_info_index].flags & SIF_CARGO) cargo_count++; if (Ship_info[Ships[ship].ship_info_index].flags & SIF_FREIGHTER) { // direct docked with any marked cargo? for (dock_instance *dock_ptr = ptr->dock_list; dock_ptr != NULL; dock_ptr = dock_ptr->next) { if (dock_ptr->docked_objp->flags & OF_MARKED) { if (Ship_info[Ships[dock_ptr->docked_objp->instance].ship_info_index].flags & SIF_CARGO) freighter_count++; } } } } count++; } ptr = GET_NEXT(ptr); } if (cargo_count && cargo_count == freighter_count) cargo = 1; vm_vec_avg(&pos, &min, &max); if (ship >= 0) name = Ships[ship].ship_name; else if (waypoint >= 0) name = Waypoint_lists[waypoint / 65536].name; else if (jnp != NULL) name = jnp->get_name_ptr(); else return; len = strlen(name); if (len >= MAX_LABEL_LEN - 1) len = MAX_LABEL_LEN - 1; strncpy(iconp->label, name, len); iconp->label[len] = 0; // iconp->text[0] = 0; iconp->type = 0; iconp->team = team; iconp->pos = pos; iconp->flags = 0; iconp->id = Cur_brief_id++; if (ship >= 0) { iconp->ship_class = Ships[ship].ship_info_index; switch (Ship_info[Ships[ship].ship_info_index].flags & SIF_ALL_SHIP_TYPES) { case SIF_KNOSSOS_DEVICE: iconp->type = ICON_KNOSSOS_DEVICE; break; case SIF_CORVETTE: iconp->type = ICON_CORVETTE; break; case SIF_GAS_MINER: iconp->type = ICON_GAS_MINER; break; case SIF_SUPERCAP: iconp->type = ICON_SUPERCAP; break; case SIF_SENTRYGUN: iconp->type = ICON_SENTRYGUN; break; case SIF_AWACS: iconp->type = ICON_AWACS; break; case SIF_CARGO: if (cargo) iconp->type = (count == 1) ? ICON_FREIGHTER_WITH_CARGO : ICON_FREIGHTER_WING_WITH_CARGO; else iconp->type = count ? ICON_CARGO_WING : ICON_CARGO; break; case SIF_SUPPORT: iconp->type = ICON_SUPPORT_SHIP; break; case SIF_FIGHTER: iconp->type = count ? ICON_FIGHTER_WING : ICON_FIGHTER; break; case SIF_BOMBER: iconp->type = count ? ICON_BOMBER_WING : ICON_BOMBER; break; case SIF_FREIGHTER: if (cargo) iconp->type = (count == 1) ? ICON_FREIGHTER_WITH_CARGO : ICON_FREIGHTER_WING_WITH_CARGO; else iconp->type = count ? ICON_FREIGHTER_WING_NO_CARGO : ICON_FREIGHTER_NO_CARGO; break; case SIF_CRUISER: iconp->type = count ? ICON_CRUISER_WING : ICON_CRUISER; break; case SIF_TRANSPORT: iconp->type = count ? ICON_TRANSPORT_WING : ICON_TRANSPORT; break; case SIF_CAPITAL: case SIF_DRYDOCK: iconp->type = ICON_CAPITAL; break; case SIF_NAVBUOY: iconp->type = ICON_WAYPOINT; break; default: iconp->type = ICON_ASTEROID_FIELD; break; } } // jumpnodes else if(jnp != NULL){ // find the first navbuoy iconp->ship_class = -1; for (int i = 0; i < Num_ship_classes; i++) { if (Ship_info[i].flags & SIF_NAVBUOY) { iconp->ship_class = i; break; } } iconp->type = ICON_JUMP_NODE; } // everything else else { // find the first navbuoy iconp->ship_class = -1; for (int i = 0; i < Num_ship_classes; i++) { if (Ship_info[i].flags & SIF_NAVBUOY) { iconp->ship_class = i; break; } } iconp->type = ICON_WAYPOINT; } if (!m_change_local){ propagate_icon(m_cur_icon); } icon_obj[m_cur_icon] = obj_create(OBJ_POINT, -1, m_cur_icon, NULL, &pos, 0.0f, OF_RENDERS); Assert(icon_obj[m_cur_icon] >= 0); obj_merge_created_list(); unmark_all(); set_cur_object_index(icon_obj[m_cur_icon]); GetDlgItem(IDC_MAKE_ICON) -> EnableWindow(FALSE); GetDlgItem(IDC_PROPAGATE_ICONS) -> EnableWindow(TRUE); update_data(1); }
//make a series of photographs do_photos() { FILE *vfile,*upvfile; int photo_num=0; char savename[13]; grs_canvas *photo_canvas; vms_vector viewer_pos; vms_matrix viewer_orient; vfile=fopen("vectors.lst","rt"); upvfile=fopen("upvecs.c","wt"); Assert(vfile!=NULL && upvfile!=NULL); fprintf(upvfile,"\n\n#include \"vecmat.h\"\n\nvms_vector up_vecs[] = {\n"); photo_canvas = gr_create_canvas(64,64); gr_set_current_canvas(photo_canvas); while (!feof(vfile)) { vms_vector v; vms_matrix m; float x,y,z; int nf; nf = fscanf(vfile,"%f %f %f",&x,&y,&z); if (nf!=3) break; vm_vec_make(&v,fl2f(x),fl2f(y),fl2f(z)); vm_vector_2_matrix(&m,&v,NULL,NULL); fprintf(upvfile,"\t\t\t{%#x,%#x,%#x},\n",m.uvec.x,m.uvec.y,m.uvec.z); vm_vec_scale(&v,PHOTO_DIST); vm_vec_add(&viewer_pos,&cube_position,&v); viewer_orient = m; vm_vec_negate(&viewer_orient.fvec); vm_vec_negate(&viewer_orient.rvec); gr_clear_canvas(129); g3_start_frame(); g3_set_view_matrix(&viewer_pos,&viewer_orient,0x9000); draw_cube(); g3_end_frame(); gr_set_current_canvas(Canv_game); gr_ubitmap(0,0,&photo_canvas->cv_bitmap); gr_set_current_canvas(photo_canvas); sprintf(savename,"cube_%02d.bbm",photo_num); iff_write_bitmap(savename,&photo_canvas->cv_bitmap,gr_palette); photo_num++; } gr_free_canvas(photo_canvas); fprintf(upvfile,"\t\t};\n"); fclose(vfile); fclose(upvfile); }