diff --git a/src/Core/Entity.m b/src/Core/Entity.m index 54529bce..6c757a2d 100644 --- a/src/Core/Entity.m +++ b/src/Core/Entity.m @@ -781,11 +781,14 @@ static Universe *data_store_universe; #ifdef WIN32 int fi; + //NSLog(@"Entity::reloadTextures called on [%@]", [self description]); + + // Force the entity to reload the textures for each face by clearing the face's texture name. for (fi = 0; fi < n_faces; fi++) faces[fi].texName = 0; - [self initialiseTextures]; - [self generateDisplayList]; + // Force the display list to be regenerated next time a frame is drawn. + [self regenerateDisplayList]; #endif } @@ -795,19 +798,16 @@ static Universe *data_store_universe; // roll out each face and texture in turn // int fi,ti ; - // + for (fi = 0; fi < n_faces; fi++) { - // texture NSString* texture = [NSString stringWithUTF8String:(char*)faces[fi].textureFileStr255]; -// if ((faces[fi].texName == 0)&&(faces[fi].textureFile)) if ((faces[fi].texName == 0)&&(texture)) { // load texture into Universe texturestore -// NSLog(@"Off to load %@",faces[fi].textureFile); + //NSLog(@"Off to load %@", texture); if (universe) { -// faces[fi].texName = [[universe textureStore] getTextureNameFor:faces[fi].textureFile]; faces[fi].texName = [[universe textureStore] getTextureNameFor: texture]; } } @@ -817,7 +817,6 @@ static Universe *data_store_universe; { if (!texture_name[ti]) { -// texture_name[ti] = [[universe textureStore] getTextureNameFor: texture_file[ti]]; texture_name[ti] = [[universe textureStore] getTextureNameFor: [NSString stringWithUTF8String: (char*)texture_file[ti]]]; // NSLog(@"DEBUG (initialiseTextures) Processed textureFile : %@ to texName : %d", entityData[ti].textureFile, entityData[ti].texName); } diff --git a/src/Core/ParticleEntity.m b/src/Core/ParticleEntity.m index 790abc2f..9eac1142 100644 --- a/src/Core/ParticleEntity.m +++ b/src/Core/ParticleEntity.m @@ -51,7 +51,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle @implementation ParticleEntity - (id) init -{ +{ self = [super init]; // quaternion_set_identity(&q_rotation); @@ -172,9 +172,9 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle Vector v_right = vector_right_from_quaternion(q_rotation); GLfloat fs = [ship flight_speed]; velocity = make_vector( v_forward.x * fs, v_forward.y * fs, v_forward.z * fs); - + // NSLog(@"DEBUG firing laser with offset [ %.3f, %.3f, %.3f]", offset.x, offset.y, offset.z); - + position.x += offset.x * v_right.x + offset.y * v_up.x + offset.z * v_forward.x; position.y += offset.x * v_right.y + offset.y * v_up.y + offset.z * v_forward.y; position.z += offset.x * v_right.z + offset.y * v_up.z + offset.z * v_forward.z; @@ -279,17 +279,17 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle } - (id) initExhaustFromShip:(ShipEntity *) ship offsetVector:(Vector) offset scaleVector:(Vector) scale -{ +{ self = [super init]; // sets rotMatrix and q_rotation to initial identities // status = STATUS_EFFECT; exhaustScale = scale; - + position.x = offset.x; // position is relative to owner position.y = offset.y; position.z = offset.z; - + particle_type = PARTICLE_EXHAUST; // [self setOwner:ship]; @@ -314,22 +314,22 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle scale.x = [(NSString *)[values objectAtIndex:3] floatValue]; scale.y = [(NSString *)[values objectAtIndex:4] floatValue]; scale.z = [(NSString *)[values objectAtIndex:5] floatValue]; - + self = [super init]; // status = STATUS_EFFECT; - + exhaustScale = scale; // NSLog(@"Adding an exhaust to %@ >>%@<< scale: ( %3.1f, %3.1f, %3.1f)", ship, details, exhaustScale.x, exhaustScale.y, exhaustScale.z); - + position.x = offset.x; // position is relative to owner position.y = offset.y; position.z = offset.z; - + particle_type = PARTICLE_EXHAUST; // [self setOwner:ship]; - // + // isParticle = YES; // return self; @@ -673,9 +673,9 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle isParticle = YES; // [self setVelocity: make_vector( 0.0f, 0.0f, 0.0f)]; - + // NSLog(@"DEBUG *FLASH* initialised at [ %.2f, %.2f, %.2f]", fragPos.x, fragPos.y, fragPos.z); - + return self; } @@ -713,9 +713,9 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle isParticle = YES; // [self setVelocity: make_vector( 0.0f, 0.0f, 0.0f)]; - + // NSLog(@"DEBUG *FLASH* initialised at [ %.2f, %.2f, %.2f]", fragPos.x, fragPos.y, fragPos.z); - + return self; } @@ -769,7 +769,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle /* ------------------------------------------------------------------- */ - + // size = billSize; // @@ -791,7 +791,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle isParticle = YES; // [self setVelocity: make_vector( 0.0f, 0.0f, 0.0f)]; - + return self; } @@ -902,7 +902,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle return; // OOColor *rgbColor = [a_color colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; OOColor *rgbColor = a_color; - + if (color) [color release]; color = [rgbColor retain]; @@ -955,9 +955,9 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle { // NSLog(@"DEBUG update for %@",self); [super update:delta_t]; - + time_counter += delta_t; - + if (universe) { switch (particle_type) @@ -993,55 +993,55 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle case PARTICLE_TEST : alpha = (sin(time_counter) + 2.0) / 3.0; break; - + case PARTICLE_EXPLOSION : [self updateExplosion:delta_t]; break; - + case PARTICLE_HYPERRING : [self updateHyperring:delta_t]; break; - + case PARTICLE_LASER_BEAM_RED : case PARTICLE_LASER_BEAM : [self updateLaser:delta_t]; break; - + case PARTICLE_EXHAUST : [self updateExhaust2:delta_t]; break; - + case PARTICLE_ECM_MINE : [self updateECMMine:delta_t]; break; - + case PARTICLE_ENERGY_MINE : [self updateEnergyMine:delta_t]; break; - + case PARTICLE_FLASHER : [self updateFlasher:delta_t]; break; - + case PARTICLE_SPARK : [self updateSpark:delta_t]; break; - + case PARTICLE_FRAGBURST : [self updateFragburst:delta_t]; break; - + case PARTICLE_BURST2 : [self updateBurst2:delta_t]; break; - + case PARTICLE_FLASH : [self updateFlash:delta_t]; break; - + case PARTICLE_BILLBOARD : break; - + case PARTICLE_SHOT_EXPIRED : case PARTICLE_SHOT_YELLOW_PLASMA : case PARTICLE_SHOT_GREEN_PLASMA : @@ -1107,7 +1107,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle else v0.z = 1.0; //equivalent of v_forward - + Vector arb1; if ((v0.x == 0.0)&&(v0.y == 0.0)) { @@ -1117,17 +1117,17 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle { arb1.x = 0.0; arb1.y = 0.0; arb1.z = 1.0; } - + Vector v1 = cross_product( v0, arb1 ); // 90 degrees to (v0 x arb1) //equivalent of v_right - + Vector v2 = cross_product( v0, v1 ); // 90 degrees to (v0 x v1) //equivalent of v_up - + vectors_into_gl_matrix( v0, v1, v2, rotMatrix); // // end of new billboard routine - + GLfloat tf = time_counter / duration; GLfloat stf = tf * tf; GLfloat expansion_speed = 0.0; @@ -1135,12 +1135,12 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle expansion_speed = 240 + 10 / (tf * tf); if (expansion_speed > 1000.0) expansion_speed = 1000.0; - + velocity.z = expansion_speed; - + collision_radius += delta_t * expansion_speed; // expand energy = 10000 - 9000 * tf; // 10000 -> 1000 - + alpha = 0.5 * ((0.025 / tf) + 1.0 - stf); if (alpha > 1.0) alpha = 1.0; color_fv[0] = 1.0 - 5.0 * tf; @@ -1149,7 +1149,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle color_fv[1] = 1.0 - 5.0 * tf; if (color_fv[1] > 1.0) color_fv[1] = 1.0; if (color_fv[1] < 0.0) color_fv[1] = 0.0; - + // manageCollisions if ([collidingEntities count] > 0) { @@ -1160,7 +1160,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle [e takeEnergyDamage:energy from:self becauseOf:[self owner]]; } } - + // expire after ttl if (time_counter > duration) // until the timer runs out! [universe removeEntity:self]; @@ -1206,12 +1206,12 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle alpha = (duration - time_counter) / duration; if (alpha < 0.0) alpha = 0.0; if (alpha > 1.0) alpha = 1.0; - + // fade towards transparent red color_fv[0] = alpha * [color redComponent] + (1.0 - alpha) * 1.0; color_fv[1] = alpha * [color greenComponent];// + (1.0 - alpha) * 0.0; color_fv[2] = alpha * [color blueComponent];// + (1.0 - alpha) * 0.0; - + // disappear eventually if (time_counter > duration) [universe removeEntity:self]; @@ -1254,7 +1254,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle vertices[i].y += vertex_normal[i].y * delta_t; vertices[i].z += vertex_normal[i].z * delta_t; } - + // disappear eventually if (time_counter > duration) [universe removeEntity:self]; @@ -1277,7 +1277,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle vertices[i].y += vertex_normal[i].y * delta_t; vertices[i].z += vertex_normal[i].z * delta_t; } - + // disappear eventually if (time_counter > duration) [universe removeEntity:self]; @@ -1287,7 +1287,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle { GLfloat tf = duration * 0.667; GLfloat tf1 = duration - tf; - + // move as necessary position.x += velocity.x * delta_t; position.y += velocity.y * delta_t; @@ -1296,19 +1296,19 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle // scale up size.width += delta_t * growth_rate; size.height = size.width; - + // fade up if ((time_counter)&&(time_counter < tf)) alpha = time_counter/tf; - + // fade out if (time_counter > tf) alpha = (duration - time_counter)/tf1; - + // disappear eventually if (time_counter > duration) [universe removeEntity:self]; - + // NSLog(@"DEBUG *FLASH* time: %.2f size: %.2f alpha: %.2f", time_counter, size.width, alpha); } @@ -1319,13 +1319,13 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle GLfloat s1[8] = { 0.0, 0.707, 1.0, 0.707, 0.0, -0.707, -1.0, -0.707}; GLfloat c1[8] = { 1.0, 0.707, 0.0, -0.707, -1.0, -0.707, 0.0, 0.707}; ShipEntity *ship =(ShipEntity *)[universe entityForUniversalID:owner]; - + if (!ship) return; - + Quaternion shipQrotation = ship->q_rotation; if (ship->isPlayer) shipQrotation.w = -shipQrotation.w; - + Frame zero; zero.q_rotation = shipQrotation; int dam = [ship damage]; @@ -1345,15 +1345,15 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle red_factor = 1.5; flare_length = 1.0 + 0.25 * flare_length; } - + if ((ranrot_rand() % 50) < dam - 50) // flicker the damaged engines red_factor = 0.0; if ((ranrot_rand() % 40) < dam - 60) green_factor = 0.0; if ((ranrot_rand() % 25) < dam - 75) flare_factor = 0.0; - - if (flare_length < 0.1) flare_length = 0.1; + + if (flare_length < 0.1) flare_length = 0.1; Vector currentPos = ship->position; Vector vfwd = vector_forward_from_quaternion(shipQrotation); GLfloat spd = 0.5 * [ship flight_speed]; @@ -1368,7 +1368,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle zero.position = make_vector( currentPos.x + vi.x * position.x + vj.x * position.y + vk.x * position.z, currentPos.y + vi.y * position.x + vj.y * position.y + vk.y * position.z, currentPos.z + vi.z * position.x + vj.z * position.y + vk.z * position.z); - + GLfloat i01 = -0.03;// * flare_length; GLfloat i03 = -0.12;// * flare_length; GLfloat i06 = -0.25;// * flare_length; @@ -1383,13 +1383,13 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle GLfloat r06 = 1.0 - q06; GLfloat r08 = 1.0 - q08; Frame f01 = [self frameAtTime: i01 fromFrame: zero]; - Vector b01 = make_vector( r01 * i01 * vfwd.x, r01 * i01 * vfwd.y, r01 * i01 * vfwd.z); + Vector b01 = make_vector( r01 * i01 * vfwd.x, r01 * i01 * vfwd.y, r01 * i01 * vfwd.z); Frame f03 = [self frameAtTime: i03 fromFrame: zero]; - Vector b03 = make_vector( r03 * i03 * vfwd.x, r03 * i03 * vfwd.y, r03 * i03 * vfwd.z); + Vector b03 = make_vector( r03 * i03 * vfwd.x, r03 * i03 * vfwd.y, r03 * i03 * vfwd.z); Frame f06 = [self frameAtTime: i06 fromFrame: zero]; - Vector b06 = make_vector( r06 * i06 * vfwd.x, r06 * i06 * vfwd.y, r06 * i06 * vfwd.z); + Vector b06 = make_vector( r06 * i06 * vfwd.x, r06 * i06 * vfwd.y, r06 * i06 * vfwd.z); Frame f08 = [self frameAtTime: i08 fromFrame: zero]; - Vector b08 = make_vector( r08 * i08 * vfwd.x, r08 * i08 * vfwd.y, r08 * i08 * vfwd.z); + Vector b08 = make_vector( r08 * i08 * vfwd.x, r08 * i08 * vfwd.y, r08 * i08 * vfwd.z); Frame f10 = [self frameAtTime: i10 fromFrame: zero]; int ci = 0; @@ -1414,11 +1414,11 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle Vector k1 = f01.k; Vector j1 = cross_product( master_i, k1); Vector i1 = cross_product( j1, k1); - + f01.position = make_vector(zero.position.x - vk.x, zero.position.y - vk.y, zero.position.z - vk.z);// 1m out from zero // i1 = vi; // j1 = vj; // initial vars - + i1.x *= exhaustScale.x; i1.y *= exhaustScale.x; i1.z *= exhaustScale.x; j1.x *= exhaustScale.y; j1.y *= exhaustScale.y; j1.z *= exhaustScale.y; for (i = 0; i < 8; i++) @@ -1507,15 +1507,15 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle - (void) drawEntity:(BOOL) immediate :(BOOL) translucent; { NSString* debug_type = @"PLAIN"; - + if (!universe) return; - + if ([universe breakPatternHide]) return; // DON'T DRAW DURING BREAK PATTERN - + if ((particle_type == PARTICLE_FLASHER)&&(zero_distance > no_draw_distance)) return; // TOO FAR AWAY TO SEE - + if (translucent) { switch (particle_type) @@ -1524,22 +1524,22 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle [self drawLaser]; debug_type = @"PARTICLE_LASER_BEAM_RED"; break; - + case PARTICLE_EXHAUST : [self drawExhaust2]; debug_type = @"PARTICLE_EXHAUST"; break; - + case PARTICLE_HYPERRING : [self drawHyperring]; debug_type = @"PARTICLE_HYPERRING"; break; - + case PARTICLE_ECM_MINE : // not a visible entity debug_type = @"PARTICLE_ECM_MINE"; break; - + case PARTICLE_ENERGY_MINE : [self drawEnergyMine]; debug_type = @"PARTICLE_ENERGY_MINE"; @@ -1549,22 +1549,22 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle [self drawFragburst]; debug_type = @"PARTICLE_FRAGBURST"; break; - + case PARTICLE_BURST2 : [self drawBurst2]; debug_type = @"PARTICLE_BURST2"; break; - + case PARTICLE_FLASH : - debug_type = @"PARTICLE_FLASH"; + debug_type = @"PARTICLE_FLASH"; [self drawParticle]; break; - + case PARTICLE_BILLBOARD : - debug_type = @"PARTICLE_BILLBOARD"; + debug_type = @"PARTICLE_BILLBOARD"; [self drawBillboard]; break; - + default : [self drawParticle]; break; @@ -1578,7 +1578,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle // NSLog(@"DEBUG drawing subentity %@ for %@", self, [universe entityForUniversalID:owner]); if (particle_type == PARTICLE_EXHAUST) - { + { if (translucent) [self drawExhaust2]; return; @@ -1594,12 +1594,12 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle if (zero_distance > no_draw_distance) return; // TOO FAR AWAY TO DRAW } - + if ((particle_type == PARTICLE_FLASHER)&&(status != STATUS_INACTIVE)) { gl_matrix temp_matrix; glGetFloatv(GL_MODELVIEW_MATRIX, temp_matrix); - + Vector abspos = position; // in control of it's own orientation Entity* father = my_owner; GLfloat* r_mat = [father drawRotationMatrix]; @@ -1614,15 +1614,15 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle father = nil; r_mat = [father drawRotationMatrix]; } - + glPopMatrix(); // restore zero! glPushMatrix(); // position and orientation is absolute glTranslatef( abspos.x, abspos.y, abspos.z); glMultMatrixf([[universe entityZero] drawRotationMatrix]); - + [self drawEntity:immediate :translucent]; - + glLoadMatrixf( temp_matrix); } } @@ -1631,33 +1631,33 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle - (void) drawParticle { int viewdir; - + GLfloat xx = 0.5 * size.width; GLfloat yy = 0.5 * size.height; - + if (alpha < 0.0) alpha = 0.0; // clamp the alpha value if (alpha > 1.0) alpha = 1.0; // clamp the alpha value color_fv[3] = alpha; - + // movies: // draw data required xx, yy, color_fv[0], color_fv[1], color_fv[2] - + glEnable(GL_TEXTURE_2D); - + glColor4f( color_fv[0], color_fv[1], color_fv[2], alpha); - + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color_fv); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); glBindTexture(GL_TEXTURE_2D, texName); glBegin(GL_QUADS); - + viewdir = [universe viewDir]; - + switch (viewdir) { case VIEW_AFT : @@ -1669,11 +1669,11 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle glTexCoord2f(1.0, 0.0); glVertex3f(-xx, yy, xx); - + glTexCoord2f(0.0, 0.0); glVertex3f(xx, yy, xx); break; - + case VIEW_STARBOARD : glTexCoord2f(0.0, 1.0); glVertex3f(-xx, -yy, xx); @@ -1683,11 +1683,11 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle glTexCoord2f(1.0, 0.0); glVertex3f(-xx, yy, -xx); - + glTexCoord2f(0.0, 0.0); glVertex3f(-xx, yy, xx); break; - + case VIEW_PORT : glTexCoord2f(0.0, 1.0); glVertex3f(xx, -yy, -xx); @@ -1697,11 +1697,11 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle glTexCoord2f(1.0, 0.0); glVertex3f(xx, yy, xx); - + glTexCoord2f(0.0, 0.0); glVertex3f(xx, yy, -xx); break; - + default : glTexCoord2f(0.0, 1.0); glVertex3f(-xx, -yy, -xx); @@ -1711,7 +1711,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle glTexCoord2f(1.0, 0.0); glVertex3f(xx, yy, -xx); - + glTexCoord2f(0.0, 0.0); glVertex3f(-xx, yy, -xx); break; @@ -1723,30 +1723,30 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle - (void) drawLaser { color_fv[3] = 0.75; // set alpha - + glDisable(GL_CULL_FACE); // face culling - + // movies: // draw data required collision_radius, color_fv[0], color_fv[1], color_fv[2] - + glDisable(GL_TEXTURE_2D); glColor4fv(color_fv); glBegin(GL_QUADS); - + glVertex3f(0.25, 0.0, 0.0); glVertex3f(0.25, 0.0, collision_radius); glVertex3f(-0.25, 0.0, collision_radius); glVertex3f(-0.25, 0.0, 0.0); - + glVertex3f(0.0, 0.25, 0.0); glVertex3f(0.0, 0.25, collision_radius); glVertex3f(0.0, -0.25, collision_radius); glVertex3f(0.0, -0.25, 0.0); - + glEnd(); - + glEnable(GL_CULL_FACE); // face culling } @@ -1757,12 +1757,12 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle GLuint qstrip2[18] = { 9, 17, 10, 18, 11, 19, 12, 20, 13, 21, 14, 22, 15, 23, 16, 24, 9, 17}; // second quadstrip 28..45 GLuint qstrip3[18] = { 17, 25, 18, 26, 19, 27, 20, 28, 21, 29, 22, 30, 23, 31, 24, 32, 17, 25}; // third quadstrip 46..63 GLuint tfan2[10] = { 33, 25, 26, 27, 28, 29, 30, 31, 32, 25}; // final fan 64..73 - + ShipEntity *ship =(ShipEntity *)[universe entityForUniversalID:owner]; - + if (!ship) return; - + if ([ship speed_factor] <= 0.0) // don't draw if there's no fire! return; @@ -1772,7 +1772,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle glDisable( GL_TEXTURE_2D); glDisable( GL_CULL_FACE); // face culling glShadeModel( GL_SMOOTH); - + glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer( 3, GL_FLOAT, 0, verts); glEnableClientState(GL_COLOR_ARRAY); @@ -1787,7 +1787,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle glDrawElements( GL_QUAD_STRIP, 18, GL_UNSIGNED_INT, qstrip2); glDrawElements( GL_QUAD_STRIP, 18, GL_UNSIGNED_INT, qstrip3); glDrawElements( GL_TRIANGLE_FAN, 10, GL_UNSIGNED_INT, tfan2); - + glEnable( GL_CULL_FACE); // face culling glEnable( GL_TEXTURE_2D); } @@ -1796,20 +1796,20 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle { int i; GLfloat aleph = (alpha < 2.0) ? alpha*0.5 : 1.0; - + GLfloat ex_em_hi[4] = {0.6, 0.8, 1.0, aleph}; // pale blue GLfloat ex_em_lo[4] = {0.2, 0.0, 1.0, 0.0}; // purplish-blue-black - + glPushMatrix(); glDisable(GL_CULL_FACE); // face culling glDisable(GL_TEXTURE_2D); glShadeModel(GL_SMOOTH); //NSLog(@"... drawing hyppering inner_radius:%.1f alpha:%.2f", ring_inner_radius, aleph); - + // movies: // draw data required ring_inner_radius, ring_outer_radius - + glBegin(GL_TRIANGLE_STRIP); for (i = 0; i < 65; i++) { @@ -1827,12 +1827,12 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle - (void) drawEnergyMine { double szd = sqrt(zero_distance); - + color_fv[3] = alpha; // set alpha - + glDisable(GL_CULL_FACE); // face culling glDisable(GL_TEXTURE_2D); - + int step = 4; glColor4fv( color_fv); @@ -1841,23 +1841,23 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle drawBallVertices( collision_radius, step, szd); // glEnd(); - + // NSLog(@"DEBUG ENERGY BOMB radius: %.3f, expansion: %.3f, color: [ %.3f, %.3f, %.3f, %.3f]", collision_radius, velocity.z, color_fv[0], color_fv[1], color_fv[2], alpha); - + glEnable(GL_CULL_FACE); // face culling } - (void) drawFragburst { int i; - + int viewdir = universe->viewDirection; - + glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBindTexture(GL_TEXTURE_2D, texName); glPushMatrix(); - + glBegin(GL_QUADS); for (i = 0; i < n_vertices; i++) { @@ -1865,7 +1865,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle drawQuadForView( viewdir, vertices[i].x, vertices[i].y, vertices[i].z, faces[i].normal.x, faces[i].normal.x); } glEnd(); - + glPopMatrix(); glDisable(GL_TEXTURE_2D); } @@ -1873,9 +1873,9 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle - (void) drawBurst2 { int i; - + int viewdir = universe->viewDirection; - + glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBindTexture(GL_TEXTURE_2D, texName); @@ -1888,7 +1888,7 @@ static Vector circleVertex[65]; // holds vector coordinates for a unit circle drawQuadForView( viewdir, vertices[i].x, vertices[i].y, vertices[i].z, size.width, size.width); } glEnd(); - + glPopMatrix(); glDisable(GL_TEXTURE_2D); } @@ -1930,4 +1930,21 @@ void drawQuadForView(int viewdir, GLfloat x, GLfloat y, GLfloat z, GLfloat xx, G } } +#ifdef WIN32 +// No over-ride of Entity's version of the method is required for non-Win32 platforms. +- (void) reloadTextures +{ + //NSLog(@"ParticleEntity::reloadTextures called, calling super and resetTextureNames"); + + // Force the sky textures to be reloaded next time a frame is drawn. + texName = 0; + faces[0].texName = 0; + faces[1].texName = 0; + + // Reset the entity display list. + [super reloadTextures]; +} + +#endif + @end diff --git a/src/Core/PlanetEntity.m b/src/Core/PlanetEntity.m index 49ac9a23..9678467f 100644 --- a/src/Core/PlanetEntity.m +++ b/src/Core/PlanetEntity.m @@ -189,11 +189,11 @@ void setUpSinTable() [sun_color getHue:&hue saturation:&sat brightness:&bri alpha:&alf]; // float hue_drift = 0.34 * (randf() - randf()); - + // set the lighting color for the sun GLfloat r,g,b,a; [sun_color getRed:&r green:&g blue:&b alpha:&a]; - + GLfloat sun_ambient[] = { 0.0, 0.0, 0.0, 1.0}; // ambient light about 5% sun_diffuse[0] = 0.5 * (1.0 + r); // paler sun_diffuse[1] = 0.5 * (1.0 + g); // paler @@ -207,7 +207,7 @@ void setUpSinTable() glLightfv(GL_LIGHT1, GL_AMBIENT, sun_ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, sun_diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, sun_specular); - + // // main disc less saturation more brightness color = [OOColor colorWithCalibratedHue: hue saturation: sat * 0.333 brightness: 1.0 alpha: alf]; @@ -257,7 +257,7 @@ void setUpSinTable() } - (id) initAsAtmosphereForPlanet:(PlanetEntity *) planet -{ +{ int i; int percent_land; double aleph = 1.0 / sqrt(2.0); @@ -279,7 +279,7 @@ void setUpSinTable() shuttles_on_ground = 0; last_launch_time = 0.0; shuttle_launch_interval = 60 * 60; - + scan_class = CLASS_NO_DRAW; // q_rotation.w = aleph; // represents a 90 degree rotation around x axis @@ -319,9 +319,9 @@ void setUpSinTable() amb_polar_sea[1] = 0.9 + gen_rnd_number() / 2560.0; amb_polar_sea[2] = 0.9 + gen_rnd_number() / 2560.0; amb_polar_sea[3] = 0.75; // 75% clouds - + atmosphere = nil; - + // NSLog(@"DEBUG atmosphere testing [PlanetEntity initialiseBaseVertexArray]"); [self initialiseBaseVertexArray]; @@ -337,7 +337,7 @@ void setUpSinTable() // set speed of rotation rotational_velocity = 0.01 + 0.02 * randf(); // 0.01 .. 0.03 avr 0.02; - + // usingVAR = [self OGL_InitVAR]; // @@ -350,7 +350,7 @@ void setUpSinTable() } - (id) initAsCoronaForPlanet:(PlanetEntity *) planet -{ +{ self = [super init]; // isTextured = NO; @@ -377,9 +377,9 @@ void setUpSinTable() amb_land[1] = 0.85; amb_land[2] = 1.0; amb_land[3] = 1.0; // blue color - + atmosphere = nil; - + [self setOwner:planet]; // isPlanet = YES; @@ -388,7 +388,7 @@ void setUpSinTable() } - (id) initWithSeed:(Random_Seed) p_seed fromUniverse:(Universe *) uni -{ +{ int i; int percent_land; double aleph = 1.0 / sqrt(2.0); @@ -411,15 +411,15 @@ void setUpSinTable() textureName = [[uni textureStore] getTextureNameFor:(NSString*)[planetinfo objectForKey:@"texture"]]; isTextured = (textureName != 0); } - + shuttles_on_ground = 1 + floor(techlevel * 0.5); last_launch_time = 0.0; shuttle_launch_interval = 3600.0 / shuttles_on_ground; // all are launched in an hour last_launch_time = -(ranrot_rand() % 60) * shuttle_launch_interval/60.0; last_launch_time = 30.0 - shuttle_launch_interval; // debug - launch 30s after player enters universe - + //NSLog(@"shuttles on ground:%d launch_interval:%.1f minutes", shuttles_on_ground, shuttle_launch_interval/60); - + //collision_radius = 25000.0; // 25km across collision_radius = radius_km * 10.0; // scale down by a factor of 100 ! // @@ -439,19 +439,19 @@ void setUpSinTable() // [self rescaleTo:1.0]; // - + percent_land = (gen_rnd_number() % 48); - + //// possibly get percent_land from planetinfo.plist entry // if ([planetinfo objectForKey:@"percent_land"]) { percent_land = [(NSNumber *)[planetinfo objectForKey:@"percent_land"] intValue]; } - + // save the current random number generator seed RNG_Seed saved_seed = currentRandomSeed(); - + //NSLog(@"Planet surface is %d percent land.",percent_land); for (i = 0; i < n_vertices; i++) { @@ -464,14 +464,14 @@ void setUpSinTable() polar_color_factor = 1.0; // Vector land_hsb, sea_hsb, land_polar_hsb, sea_polar_hsb; - - land_hsb.x = gen_rnd_number() / 256.0; land_hsb.y = gen_rnd_number() / 256.0; land_hsb.z = 0.5 + gen_rnd_number() / 512.0; - sea_hsb.x = gen_rnd_number() / 256.0; sea_hsb.y = gen_rnd_number() / 256.0; sea_hsb.z = 0.5 + gen_rnd_number() / 512.0; + + land_hsb.x = gen_rnd_number() / 256.0; land_hsb.y = gen_rnd_number() / 256.0; land_hsb.z = 0.5 + gen_rnd_number() / 512.0; + sea_hsb.x = gen_rnd_number() / 256.0; sea_hsb.y = gen_rnd_number() / 256.0; sea_hsb.z = 0.5 + gen_rnd_number() / 512.0; while (dot_product(land_hsb,sea_hsb) > .80) // make sure land and sea colors differ significantly { - sea_hsb.x = gen_rnd_number() / 256.0; sea_hsb.y = gen_rnd_number() / 256.0; sea_hsb.z = 0.5 + gen_rnd_number() / 512.0; + sea_hsb.x = gen_rnd_number() / 256.0; sea_hsb.y = gen_rnd_number() / 256.0; sea_hsb.z = 0.5 + gen_rnd_number() / 512.0; } - + //// possibly get land_hsb and sea_hsb from planetinfo.plist entry // if ([planetinfo objectForKey:@"land_hsb_color"]) @@ -480,11 +480,11 @@ void setUpSinTable() sea_hsb = [Entity vectorFromString:(NSString *)[planetinfo objectForKey:@"sea_hsb_color"]]; // //// - + // polar areas are brighter but have less color (closer to white) // - land_polar_hsb.x = land_hsb.x; land_polar_hsb.y = (land_hsb.y / 5.0); land_polar_hsb.z = 1.0 - (land_hsb.z / 10.0); - sea_polar_hsb.x = sea_hsb.x; sea_polar_hsb.y = (sea_hsb.y / 5.0); sea_polar_hsb.z = 1.0 - (sea_hsb.z / 10.0); + land_polar_hsb.x = land_hsb.x; land_polar_hsb.y = (land_hsb.y / 5.0); land_polar_hsb.z = 1.0 - (land_hsb.z / 10.0); + sea_polar_hsb.x = sea_hsb.x; sea_polar_hsb.y = (sea_hsb.y / 5.0); sea_polar_hsb.z = 1.0 - (sea_hsb.z / 10.0); amb_land[0] = [[OOColor colorWithCalibratedHue:land_hsb.x saturation:land_hsb.y brightness:land_hsb.z alpha:1.0] redComponent]; amb_land[1] = [[OOColor colorWithCalibratedHue:land_hsb.x saturation:land_hsb.y brightness:land_hsb.z alpha:1.0] blueComponent]; @@ -502,24 +502,24 @@ void setUpSinTable() amb_polar_sea[1] = [[OOColor colorWithCalibratedHue:sea_polar_hsb.x saturation:sea_polar_hsb.y brightness:sea_polar_hsb.z alpha:1.0] blueComponent]; amb_polar_sea[2] = [[OOColor colorWithCalibratedHue:sea_polar_hsb.x saturation:sea_polar_hsb.y brightness:sea_polar_hsb.z alpha:1.0] greenComponent]; amb_polar_sea[3] = 1.0; - + // NSLog(@"DEBUG testing [PlanetEntity initialiseBaseVertexArray]"); [self initialiseBaseVertexArray]; - + // NSLog(@"DEBUG testing [PlanetEntity initialiseBaseTerrainArray:%d]", percent_land); setRandomSeed(saved_seed); [self initialiseBaseTerrainArray:percent_land]; - + // NSLog(@"DEBUG painting %d vertices", next_free_vertex); for (i = 0; i < next_free_vertex; i++) [self paintVertex:i :planet_seed]; - + // NSLog(@"DEBUG scaling %d vertices", next_free_vertex); [self scaleVertices]; - + // set speed of rotation rotational_velocity = 0.01 * randf(); // 0.0 .. 0.01 avr 0.005; - + // do atmosphere // atmosphere = [[PlanetEntity alloc] initAsAtmosphereForPlanet:self]; @@ -538,7 +538,7 @@ void setUpSinTable() } - (id) initPlanetFromDictionary:(NSDictionary*) dict inUniverse:(Universe *) uni -{ +{ int i; int percent_land; double aleph = 1.0 / sqrt(2.0); @@ -584,14 +584,14 @@ void setUpSinTable() { radius_km = [[dict objectForKey:@"radius"] intValue]; } - + shuttles_on_ground = 0; last_launch_time = 0.0; shuttle_launch_interval = 3600.0 / shuttles_on_ground; // all are launched in an hour last_launch_time = 3600.0; - + //NSLog(@"shuttles on ground:%d launch_interval:%.1f minutes", shuttles_on_ground, shuttle_launch_interval/60); - + collision_radius = radius_km * 10.0; // scale down by a factor of 100 ! // scan_class = CLASS_NO_DRAW; @@ -610,7 +610,7 @@ void setUpSinTable() // [self rescaleTo:1.0]; // - + percent_land = (gen_rnd_number() % 48); if ([dict objectForKey:@"percent_land"]) { @@ -618,10 +618,10 @@ void setUpSinTable() } if (isTextured) percent_land = 0; - + // save the current random number generator seed RNG_Seed saved_seed = currentRandomSeed(); - + //NSLog(@"Planet surface is %d percent land.",percent_land); for (i = 0; i < n_vertices; i++) { @@ -636,14 +636,14 @@ void setUpSinTable() polar_color_factor = [[dict objectForKey:@"polar_color_factor"] doubleValue]; // Vector land_hsb, sea_hsb, land_polar_hsb, sea_polar_hsb; - + if (!isTextured) { - land_hsb.x = gen_rnd_number() / 256.0; land_hsb.y = gen_rnd_number() / 256.0; land_hsb.z = 0.5 + gen_rnd_number() / 512.0; - sea_hsb.x = gen_rnd_number() / 256.0; sea_hsb.y = gen_rnd_number() / 256.0; sea_hsb.z = 0.5 + gen_rnd_number() / 512.0; + land_hsb.x = gen_rnd_number() / 256.0; land_hsb.y = gen_rnd_number() / 256.0; land_hsb.z = 0.5 + gen_rnd_number() / 512.0; + sea_hsb.x = gen_rnd_number() / 256.0; sea_hsb.y = gen_rnd_number() / 256.0; sea_hsb.z = 0.5 + gen_rnd_number() / 512.0; while (dot_product(land_hsb,sea_hsb) > .80) // make sure land and sea colors differ significantly { - sea_hsb.x = gen_rnd_number() / 256.0; sea_hsb.y = gen_rnd_number() / 256.0; sea_hsb.z = 0.5 + gen_rnd_number() / 512.0; + sea_hsb.x = gen_rnd_number() / 256.0; sea_hsb.y = gen_rnd_number() / 256.0; sea_hsb.z = 0.5 + gen_rnd_number() / 512.0; } } else @@ -651,7 +651,7 @@ void setUpSinTable() land_hsb.x = 0.0; land_hsb.y = 0.0; land_hsb.z = 1.0; // non-saturated fully bright (white) sea_hsb.x = 0.0; sea_hsb.y = 1.0; sea_hsb.z = 1.0; // fully-saturated fully bright (red) } - + //// possibly get land_hsb and sea_hsb from planetinfo.plist entry // if ([dict objectForKey:@"land_hsb_color"]) @@ -664,11 +664,11 @@ void setUpSinTable() } // //// - + // polar areas are brighter but have less color (closer to white) // - land_polar_hsb.x = land_hsb.x; land_polar_hsb.y = (land_hsb.y / 5.0); land_polar_hsb.z = 1.0 - (land_hsb.z / 10.0); - sea_polar_hsb.x = sea_hsb.x; sea_polar_hsb.y = (sea_hsb.y / 5.0); sea_polar_hsb.z = 1.0 - (sea_hsb.z / 10.0); + land_polar_hsb.x = land_hsb.x; land_polar_hsb.y = (land_hsb.y / 5.0); land_polar_hsb.z = 1.0 - (land_hsb.z / 10.0); + sea_polar_hsb.x = sea_hsb.x; sea_polar_hsb.y = (sea_hsb.y / 5.0); sea_polar_hsb.z = 1.0 - (sea_hsb.z / 10.0); amb_land[0] = [[OOColor colorWithCalibratedHue:land_hsb.x saturation:land_hsb.y brightness:land_hsb.z alpha:1.0] redComponent]; amb_land[1] = [[OOColor colorWithCalibratedHue:land_hsb.x saturation:land_hsb.y brightness:land_hsb.z alpha:1.0] blueComponent]; @@ -686,26 +686,26 @@ void setUpSinTable() amb_polar_sea[1] = [[OOColor colorWithCalibratedHue:sea_polar_hsb.x saturation:sea_polar_hsb.y brightness:sea_polar_hsb.z alpha:1.0] blueComponent]; amb_polar_sea[2] = [[OOColor colorWithCalibratedHue:sea_polar_hsb.x saturation:sea_polar_hsb.y brightness:sea_polar_hsb.z alpha:1.0] greenComponent]; amb_polar_sea[3] = 1.0; - + // NSLog(@"DEBUG testing [PlanetEntity initialiseBaseVertexArray]"); [self initialiseBaseVertexArray]; - + // NSLog(@"DEBUG testing [PlanetEntity initialiseBaseTerrainArray:%d]", percent_land); setRandomSeed(saved_seed); [self initialiseBaseTerrainArray:percent_land]; - + // NSLog(@"DEBUG painting %d vertices", next_free_vertex); for (i = 0; i < next_free_vertex; i++) [self paintVertex:i :planet_seed]; - + // NSLog(@"DEBUG scaling %d vertices", next_free_vertex); [self scaleVertices]; - + // set speed of rotation rotational_velocity = 0.01 * randf(); // 0.0 .. 0.01 avr 0.005; if ([dict objectForKey:@"rotational_velocity"]) rotational_velocity = [[dict objectForKey:@"rotational_velocity"] doubleValue]; - + // do atmosphere // atmosphere = [[PlanetEntity alloc] initAsAtmosphereForPlanet:self]; @@ -713,7 +713,7 @@ void setUpSinTable() // set energy energy = collision_radius * 1000.0; - + // usingVAR = [self OGL_InitVAR]; // @@ -726,7 +726,7 @@ void setUpSinTable() } - (id) initMoonFromDictionary:(NSDictionary*) dict inUniverse:(Universe *) uni -{ +{ int i; int percent_land; double aleph = 1.0 / sqrt(2.0); @@ -772,14 +772,14 @@ void setUpSinTable() { radius_km = [[dict objectForKey:@"radius"] intValue]; } - + shuttles_on_ground = 0; last_launch_time = 0.0; shuttle_launch_interval = 3600.0 / shuttles_on_ground; // all are launched in an hour last_launch_time = 3600.0; - + //NSLog(@"shuttles on ground:%d launch_interval:%.1f minutes", shuttles_on_ground, shuttle_launch_interval/60); - + collision_radius = radius_km * 10.0; // scale down by a factor of 100 ! // scan_class = CLASS_NO_DRAW; @@ -798,7 +798,7 @@ void setUpSinTable() // [self rescaleTo:1.0]; // - + percent_land = (gen_rnd_number() % 48); if ([dict objectForKey:@"percent_land"]) { @@ -806,10 +806,10 @@ void setUpSinTable() } if (isTextured) percent_land = 100; - + // save the current random number generator seed RNG_Seed saved_seed = currentRandomSeed(); - + //NSLog(@"Planet surface is %d percent land.",percent_land); for (i = 0; i < n_vertices; i++) { @@ -824,14 +824,14 @@ void setUpSinTable() polar_color_factor = [[dict objectForKey:@"polar_color_factor"] doubleValue]; // Vector land_hsb, sea_hsb, land_polar_hsb, sea_polar_hsb; - + if (!isTextured) { - land_hsb.x = gen_rnd_number() / 256.0; land_hsb.y = gen_rnd_number() / 256.0; land_hsb.z = 0.5 + gen_rnd_number() / 512.0; - sea_hsb.x = gen_rnd_number() / 256.0; sea_hsb.y = gen_rnd_number() / 256.0; sea_hsb.z = 0.5 + gen_rnd_number() / 512.0; + land_hsb.x = gen_rnd_number() / 256.0; land_hsb.y = gen_rnd_number() / 256.0; land_hsb.z = 0.5 + gen_rnd_number() / 512.0; + sea_hsb.x = gen_rnd_number() / 256.0; sea_hsb.y = gen_rnd_number() / 256.0; sea_hsb.z = 0.5 + gen_rnd_number() / 512.0; while (dot_product(land_hsb,sea_hsb) > .80) // make sure land and sea colors differ significantly { - sea_hsb.x = gen_rnd_number() / 256.0; sea_hsb.y = gen_rnd_number() / 256.0; sea_hsb.z = 0.5 + gen_rnd_number() / 512.0; + sea_hsb.x = gen_rnd_number() / 256.0; sea_hsb.y = gen_rnd_number() / 256.0; sea_hsb.z = 0.5 + gen_rnd_number() / 512.0; } } else @@ -839,7 +839,7 @@ void setUpSinTable() land_hsb.x = 0.0; land_hsb.y = 0.0; land_hsb.z = 1.0; // non-saturated fully bright (white) sea_hsb.x = 0.0; sea_hsb.y = 1.0; sea_hsb.z = 1.0; // fully-saturated fully bright (red) } - + //// possibly get land_hsb and sea_hsb from planetinfo.plist entry // if ([dict objectForKey:@"land_hsb_color"]) @@ -852,11 +852,11 @@ void setUpSinTable() } // //// - + // polar areas are brighter but have less color (closer to white) // - land_polar_hsb.x = land_hsb.x; land_polar_hsb.y = (land_hsb.y / 5.0); land_polar_hsb.z = 1.0 - (land_hsb.z / 10.0); - sea_polar_hsb.x = sea_hsb.x; sea_polar_hsb.y = (sea_hsb.y / 5.0); sea_polar_hsb.z = 1.0 - (sea_hsb.z / 10.0); + land_polar_hsb.x = land_hsb.x; land_polar_hsb.y = (land_hsb.y / 5.0); land_polar_hsb.z = 1.0 - (land_hsb.z / 10.0); + sea_polar_hsb.x = sea_hsb.x; sea_polar_hsb.y = (sea_hsb.y / 5.0); sea_polar_hsb.z = 1.0 - (sea_hsb.z / 10.0); amb_land[0] = [[OOColor colorWithCalibratedHue:land_hsb.x saturation:land_hsb.y brightness:land_hsb.z alpha:1.0] redComponent]; amb_land[1] = [[OOColor colorWithCalibratedHue:land_hsb.x saturation:land_hsb.y brightness:land_hsb.z alpha:1.0] blueComponent]; @@ -874,30 +874,30 @@ void setUpSinTable() amb_polar_sea[1] = [[OOColor colorWithCalibratedHue:sea_polar_hsb.x saturation:sea_polar_hsb.y brightness:sea_polar_hsb.z alpha:1.0] blueComponent]; amb_polar_sea[2] = [[OOColor colorWithCalibratedHue:sea_polar_hsb.x saturation:sea_polar_hsb.y brightness:sea_polar_hsb.z alpha:1.0] greenComponent]; amb_polar_sea[3] = 1.0; - + // NSLog(@"DEBUG testing [PlanetEntity initialiseBaseVertexArray]"); [self initialiseBaseVertexArray]; - + // NSLog(@"DEBUG testing [PlanetEntity initialiseBaseTerrainArray:%d]", percent_land); setRandomSeed(saved_seed); [self initialiseBaseTerrainArray:percent_land]; - + // NSLog(@"DEBUG painting %d vertices", next_free_vertex); for (i = 0; i < next_free_vertex; i++) [self paintVertex:i :planet_seed]; - + // NSLog(@"DEBUG scaling %d vertices", next_free_vertex); [self scaleVertices]; - + // set speed of rotation rotational_velocity = 0.01 * randf(); // 0.0 .. 0.01 avr 0.005; if ([dict objectForKey:@"rotational_velocity"]) rotational_velocity = [[dict objectForKey:@"rotational_velocity"] doubleValue]; - + // do NO atmosphere // atmosphere = nil; - + energy = collision_radius * 1000.0; // @@ -982,19 +982,19 @@ void setUpSinTable() NSLog(@"DEBUG %@ %d collided with planet at (%.1f,%.1f,%.1f)",[ship name], [ship universal_id], p1.x,p1.y,p1.z); } } - + return YES; } - (void) update:(double) delta_t -{ +{ if (usingVAR) [self OGL_UpdateVAR]; - + [super update:delta_t]; sqrt_zero_distance = sqrt(zero_distance); - + switch (planet_type) { case PLANET_TYPE_GREEN : @@ -1007,18 +1007,18 @@ void setUpSinTable() shuttles_on_ground--; last_launch_time = ugt; } - + // normal planetary rotation quaternion_rotate_about_y( &q_rotation, rotational_velocity * delta_t); quaternion_normalise(&q_rotation); quaternion_into_gl_matrix(q_rotation, rotMatrix); - + if (atmosphere) { [atmosphere update:delta_t]; double alt = sqrt_zero_distance - collision_radius; double atmo = 10.0 * (atmosphere->collision_radius - collision_radius); // effect starts at 10x the height of the clouds - + if ((alt > 0)&&(alt <= atmo)) { double aleph = (atmo - alt) / atmo; @@ -1038,7 +1038,7 @@ void setUpSinTable() quaternion_into_gl_matrix(q_rotation, rotMatrix); } break; - + case PLANET_TYPE_CORONA : case PLANET_TYPE_SUN : { @@ -1047,13 +1047,13 @@ void setUpSinTable() Vector v0 = position; Vector p0 = (player)? player->position: make_vector( 0.0f, 0.0f, 0.0f); v0.x -= p0.x; v0.y -= p0.y; v0.z -= p0.z; // vector from player to position - + if (v0.x||v0.y||v0.z) v0 = unit_vector(&v0); else v0.z = 1.0; //equivalent of v_forward - + Vector arb1; if ((v0.x == 0.0)&&(v0.y == 0.0)) { @@ -1063,13 +1063,13 @@ void setUpSinTable() { arb1.x = 0.0; arb1.y = 0.0; arb1.z = 1.0; } - + Vector v1 = cross_product( v0, arb1 ); // 90 degrees to (v0 x arb1) //equivalent of v_right - + Vector v2 = cross_product( v0, v1 ); // 90 degrees to (v0 x v1) //equivalent of v_up - + vectors_into_gl_matrix( v0, v1, v2, rotMatrix); if (planet_type == PLANET_TYPE_CORONA) @@ -1083,7 +1083,7 @@ void setUpSinTable() v_sun.z = 1.0; polar_color_factor = dot_product( v_sun, v0); } - + if (throw_sparks&&(planet_type == PLANET_TYPE_SUN)&&(velocity.z > 0)) // going NOVA! { if (velocity.x >= 0.0) // countdown @@ -1116,7 +1116,7 @@ void setUpSinTable() } } } - + // update corona if (![universe reducedDetail]) { @@ -1132,7 +1132,7 @@ void setUpSinTable() } } } - + } break; } @@ -1179,20 +1179,20 @@ void setUpSinTable() if (subdivideLevel > 4) subdivideLevel = 4; } - - + + glFrontFace(GL_CW); // face culling - front faces are AntiClockwise! - + /* - + The depth test gets disabled in parts of this and instead we rely on the painters algorithm instead. - + The depth buffer isn't granular enough to cope with huge objects at vast distances. - + */ - + switch (planet_type) { case PLANET_TYPE_ATMOSPHERE : @@ -1201,7 +1201,7 @@ void setUpSinTable() if (!translucent) { GLfloat mat1[] = { 1.0, 1.0, 1.0, 1.0 }; // opaque white - + if (!isTextured) glDisable(GL_TEXTURE_2D); // stop any problems from this being left on! else @@ -1209,7 +1209,7 @@ void setUpSinTable() glEnable(GL_TEXTURE_2D); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //wrap around horizontally } - + glShadeModel(GL_SMOOTH); glColor4fv(mat1); @@ -1296,13 +1296,13 @@ void setUpSinTable() } } glFrontFace(GL_CW); - + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat1); if (atmosphere) { glDisable(GL_DEPTH_TEST); - + glPopMatrix(); // get old draw matrix back glPushMatrix(); // and store it again glTranslatef(position.x,position.y,position.z); // centre on the planet @@ -1310,18 +1310,18 @@ void setUpSinTable() glMultMatrixf([atmosphere rotationMatrix]); // draw atmosphere entity [atmosphere drawEntity:immediate :translucent]; - + glEnable(GL_DEPTH_TEST); } - + } break; - + case PLANET_TYPE_SUN : if (!translucent) { int steps = 2 * (MAX_SUBDIVIDE - subdivideLevel); - + glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glColor4fv( amb_land); @@ -1329,7 +1329,7 @@ void setUpSinTable() glBegin(GL_TRIANGLE_FAN); drawBallVertices( collision_radius, steps, sqrt_zero_distance); glEnd(); - + if (![universe reducedDetail]) { glDisable(GL_DEPTH_TEST); @@ -1353,7 +1353,7 @@ void setUpSinTable() glEnable(GL_LIGHTING); } break; - + case PLANET_TYPE_CORONA : if (!translucent) { @@ -1362,19 +1362,19 @@ void setUpSinTable() GLfloat r = 0.42 * bri; GLfloat g = 0.42 * bri; GLfloat b = 0.5 * bri; - + GLfloat amb_1[4] = {1.0, 1.0, 1.0, 1.0 }; double r0 = (my_owner)? my_owner->collision_radius: 5000; GLfloat col1[4] = { r, g, b, 1.0}; GLfloat col2[4] = { r, g, b, 0.0}; - + glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, amb_1); - + drawCorona( r0, collision_radius, 6 - subdivideLevel, sqrt_zero_distance, col1, col2); - + glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); } @@ -1392,7 +1392,7 @@ void drawBall (double radius, int step, double z_distance) return; int i; double s, c; - double r = radius * z_distance / sqrt( z_distance * z_distance - radius * radius); + double r = radius * z_distance / sqrt( z_distance * z_distance - radius * radius); glBegin(GL_TRIANGLE_FAN); glVertex3i( 0, 0, 0); for ( i = 0; i < 360; i += step ) @@ -1413,7 +1413,7 @@ void drawBallVertices (double radius, int step, double z_distance) return; int i; GLfloat s, c; - GLfloat r = radius * z_distance / sqrt( z_distance * z_distance - radius * radius); + GLfloat r = radius * z_distance / sqrt( z_distance * z_distance - radius * radius); glVertex3i( 0, 0, 0); for ( i = 0; i < 360; i += step ) { @@ -1430,20 +1430,20 @@ void drawCorona (double inner_radius, double outer_radius, int step, double z_di return; int i; GLfloat s0, c0, s1, c1; - + double r = inner_radius; double c = outer_radius; double z = z_distance; double x = sqrt( z * z - r * r); - + GLfloat r1 = r * x / z; GLfloat z1 = r * r / z; - + GLfloat r0 = c * x / z; GLfloat z0 = c * r / z; - + // NSLog(@"DEBUG r1 = %.4f z1 = %.4f r0 = %.4f z0 = %.4f", r1, z1, r0, z0); - + glBegin(GL_TRIANGLE_STRIP); for ( i = 0; i < 360; i += step ) { @@ -1468,38 +1468,38 @@ void drawActiveCorona (double inner_radius, double outer_radius, int step, doubl if (inner_radius >= z_distance) // inside the sphere return; int i; - + NSRange activity = NSMakeRange(0.34, 1.0); - + GLfloat s0, c0, s1, c1; - + double r = inner_radius; double c = outer_radius; double z = z_distance; double x = sqrt( z * z - r * r); - + GLfloat r1 = r * x / z; GLfloat z1 = r * r / z; - + GLfloat r0 = c * x / z; GLfloat z0 = c * r / z; - + // NSLog(@"DEBUG r1 = %.4f z1 = %.4f r0 = %.4f z0 = %.4f", r1, z1, r0, z0); GLfloat rv0, rv1, rv2; - + glBegin(GL_TRIANGLE_STRIP); for ( i = 0; i < 360; i += step ) { rv0 = (1.0 - corona_stage) * rvalue[i + rv] + corona_stage * rvalue[i + rv + 360]; rv1 = (1.0 - corona_stage) * rvalue[i + rv + 1] + corona_stage * rvalue[i + rv + 361]; rv2 = (1.0 - corona_stage) * rvalue[i + rv + 2] + corona_stage * rvalue[i + rv + 362]; - + s1 = r1 * sin_value[i]; c1 = r1 * cos_value[i]; glColor4f( col4v1[0] * (activity.location + rv0*activity.length), col4v1[1] * (activity.location + rv1*activity.length), col4v1[2] * (activity.location + rv2*activity.length), col4v1[3]); glVertex3f( s1, c1, -z1); - + s0 = r0 * sin_value[i]; c0 = r0 * cos_value[i]; glColor4f( col4v1[0], col4v1[1], col4v1[2], 0); @@ -1509,7 +1509,7 @@ void drawActiveCorona (double inner_radius, double outer_radius, int step, doubl rv0 = (1.0 - corona_stage) * rvalue[rv] + corona_stage * rvalue[360 + rv]; rv1 = (1.0 - corona_stage) * rvalue[1 + rv] + corona_stage * rvalue[361 + rv]; rv2 = (1.0 - corona_stage) * rvalue[2 + rv] + corona_stage * rvalue[362 + rv]; - + glColor4f( col4v1[0] * (activity.location + rv0*activity.length), col4v1[1] * (activity.location + rv1*activity.length), col4v1[2] * (activity.location + rv2*activity.length), col4v1[3]); glVertex3f( 0.0, r1, -z1); //repeat the zero value to close glColor4f( col4v1[0], col4v1[1], col4v1[2], 0); @@ -1570,7 +1570,7 @@ void drawActiveCorona (double inner_radius, double outer_radius, int step, doubl { int i; Vector vert; - + for (i = 0; i < n_vertices; i++) { vert = vertices[i]; // not guaranteed non-zero @@ -1588,11 +1588,11 @@ void drawActiveCorona (double inner_radius, double outer_radius, int step, doubl { #ifdef GNUSTEP // TODO: Find a suitable replacement fn for APPLE -#else +#else if (usingVAR) glBindVertexArrayAPPLE(gVertexArrayRangeObjects[0]); #endif - + glDrawElements( GL_TRIANGLES, 3 * n_triangles[subdivide], GL_UNSIGNED_INT, &vertexdata.index_array[triangle_start[subdivide]]); } @@ -1602,34 +1602,34 @@ void drawActiveCorona (double inner_radius, double outer_radius, int step, doubl Quaternion q1; Vector launch_pos = position; double start_distance = collision_radius + 125.0; - + quaternion_set_random(&q1); - + Vector vf = vector_forward_from_quaternion(q1); - + launch_pos.x += start_distance * vf.x; launch_pos.y += start_distance * vf.y; launch_pos.z += start_distance * vf.z; - + shuttle_ship = [universe getShipWithRole:@"shuttle"]; // retain count = 1 if (shuttle_ship) { [shuttle_ship setPosition:launch_pos]; [shuttle_ship setQRotation:q1]; - + [shuttle_ship setScanClass: CLASS_NEUTRAL]; - + [shuttle_ship setCargoFlag:CARGO_FLAG_FULL_PLENTIFUL]; - + [shuttle_ship setStatus:STATUS_IN_FLIGHT]; - + //[shuttle_ship setReportAImessages:YES]; // debug [universe addEntity:shuttle_ship]; [[shuttle_ship getAI] setStateMachine:@"risingShuttleAI.plist"]; // must happen after adding to the universe! //NSLog(@"Planet %@ in universe %@ Launching shuttle: %@ %d", self, universe, [shuttle_ship name], [shuttle_ship universal_id]); - + [shuttle_ship release]; } } @@ -1652,7 +1652,7 @@ static BOOL last_one_was_textured; { int i; NSAutoreleasePool* mypool = [[NSAutoreleasePool alloc] init]; // use our own pool since this routine is quite hard on memory - + if (last_one_was_textured != isTextured) { [PlanetEntity resetBaseVertexArray]; @@ -1663,11 +1663,11 @@ static BOOL last_one_was_textured; // NSLog(@"DEBUG %@ creating textured vertex data texture_uv_array = <%x>", self, texture_uv_array); // else // NSLog(@"DEBUG %@ creating plain vertex data", self); - + if (edge_to_vertex == nil) { edge_to_vertex = [[NSMutableDictionary dictionaryWithCapacity:7680] retain]; // make a new one - + int vi,fi; next_free_vertex = 0; // @@ -1705,9 +1705,9 @@ static BOOL last_one_was_textured; triangle_start[newlevel] = triangle_start[sublevel] + n_triangles[sublevel] * 3; n_triangles[newlevel] = n_triangles[sublevel] * 4; // - + // NSLog(@"Building new level of subdivision - level %d.", newlevel); - + int tri; for (tri = 0; tri < n_triangles[sublevel]; tri++) { @@ -1734,20 +1734,20 @@ static BOOL last_one_was_textured; vertex_index_array[triangle_start[newlevel] + tri * 12 + 9] = v01; vertex_index_array[triangle_start[newlevel] + tri * 12 +10] = v12; vertex_index_array[triangle_start[newlevel] + tri * 12 +11] = v20; - + } // NSLog(@"Current total number of vertices %d.", next_free_vertex); } } - + // NSLog(@"edge_to_vertex %@", edge_to_vertex); - + // all done - copy the indices to the instance // for (i = 0; i < MAX_TRI_INDICES; i++) vertexdata.index_array[i] = vertex_index_array[i]; - + [mypool release]; } @@ -1763,14 +1763,14 @@ int baseVertexIndexForEdge(int va, int vb, BOOL textured) else { int vindex = next_free_vertex++; - + // calculate position of new vertex base_vertex_array[vindex] = base_vertex_array[va]; base_vertex_array[vindex].x += base_vertex_array[vb].x; base_vertex_array[vindex].y += base_vertex_array[vb].y; base_vertex_array[vindex].z += base_vertex_array[vb].z; base_vertex_array[vindex] = unit_vector(&base_vertex_array[vindex]); // guaranteed non-zero - + // NSLog(@"%d [%@]= (%.3f,%.3f,%.3f)", vindex, key, base_vertex_array[vindex].x, base_vertex_array[vindex].y, base_vertex_array[vindex].z); if (textured) @@ -1898,7 +1898,7 @@ int baseVertexIndexForEdge(int va, int vb, BOOL textured) for (i = 0; i < 4; i++) { paint_color[i] = (r * paint_sea[i])*0.01 + ((100 - r) * paint_land[i])*0.01; - + // finally initialise the color array entry vertexdata.color_array[vi*4 + i] = paint_color[i]; } @@ -1959,5 +1959,25 @@ double longitudeFromVector(Vector v) velocity.z = 10000; } +#ifdef WIN32 +// No over-ride of Entity's version of the method is required for non-Win32 platforms. +- (void) reloadTextures +{ + //NSLog(@"PlanetEntity::reloadTextures called, clearing planet draw lists and calling super"); + + int i; + // Clear out the planet's various detail level display lists. + for (i = 0; i < MAX_SUBDIVIDE; i++) + { + glDeleteLists(displayListNames[i], 1); + displayListNames[i] = 0; + } + + // Don't know if this will help for planets, but it shouldn't hurt. + [super reloadTextures]; +} + +#endif + @end diff --git a/src/Core/ShipEntity.m b/src/Core/ShipEntity.m index a0feeb21..f54920a5 100644 --- a/src/Core/ShipEntity.m +++ b/src/Core/ShipEntity.m @@ -55,7 +55,7 @@ Your fair use and other rights are in no way affected by the above. @implementation ShipEntity - (id) init -{ +{ self = [super init]; // // scripting @@ -217,9 +217,9 @@ Your fair use and other rights are in no way affected by the above. if (launch_actions) [launch_actions release]; if (script_actions) [script_actions release]; if (death_actions) [death_actions release]; - + if (previousCondition) [previousCondition release]; - + if (collisionInfoForEntity) [collisionInfoForEntity release]; @@ -227,7 +227,7 @@ Your fair use and other rights are in no way affected by the above. [dockingInstructions release]; if (crew) [crew release]; - + if (lastRadioMessage) [lastRadioMessage autorelease]; [super dealloc]; @@ -366,7 +366,7 @@ static NSMutableDictionary* smallOctreeDict = nil; - (void) setUniverse:(Universe *)univ { [super setUniverse: univ]; - + // // if we have a universal id then we can proceed to set up any // stuff that happens when we get added to the universe @@ -385,7 +385,7 @@ static NSMutableDictionary* smallOctreeDict = nil; escortsAreSetUp = YES; // we don't do this ourself! } } - + // // set subentities universe // @@ -436,93 +436,93 @@ static NSMutableDictionary* smallOctreeDict = nil; nextBeaconID = NO_TARGET; else nextBeaconID = [beaconShip universal_id]; -} +} - (void) setUpEscorts { NSString *escortRole = @"escort"; NSString *escortShipKey = nil; - + if ([roles isEqual:@"trader"]) escortRole = @"escort"; - + if ([roles isEqual:@"police"]) escortRole = @"wingman"; - + if ([shipinfoDictionary objectForKey:@"escort-role"]) { escortRole = (NSString*)[shipinfoDictionary objectForKey:@"escort-role"]; if (![[universe getShipWithRole:escortRole] autorelease]) escortRole = @"escort"; } - + if ([shipinfoDictionary objectForKey:@"escort-ship"]) { escortShipKey = (NSString*)[shipinfoDictionary objectForKey:@"escort-ship"]; if (![[universe getShip:escortShipKey] autorelease]) escortShipKey = nil; } - + // NSLog(@"DEBUG Setting up escorts for %@", self); - + while (n_escorts > 0) { Vector ex_pos = [self getCoordinatesForEscortPosition:n_escorts - 1]; - + ShipEntity *escorter; - + if (escortShipKey) escorter = [universe getShip:escortShipKey]; // retained else escorter = [universe getShipWithRole:escortRole]; // retained - + if (!escorter) break; - + // spread them around a little randomly double dd = escorter->collision_radius; ex_pos.x += dd * 6.0 * (randf() - 0.5); ex_pos.y += dd * 6.0 * (randf() - 0.5); ex_pos.z += dd * 6.0 * (randf() - 0.5); - - + + [escorter setScanClass: CLASS_NEUTRAL]; [escorter setPosition:ex_pos]; - + [escorter setStatus:STATUS_IN_FLIGHT]; - + [escorter setRoles:escortRole]; - + [escorter setScanClass:scan_class]; // you are the same as I - + //[escorter setReportAImessages: (i == 0) ? YES:NO ]; // debug [universe addEntity:escorter]; [[escorter getAI] setStateMachine:@"escortAI.plist"]; // must happen after adding to the universe! - + [escorter setGroup_id:universal_id]; [self setGroup_id:universal_id]; // make self part of same group - + [escorter setOwner: self]; // make self group leader - + [[escorter getAI] setState:@"FLYING_ESCORT"]; // begin immediately - + if (bounty) { int extra = 1 | (ranrot_rand() & 15); bounty += extra; // obviously we're dodgier than we thought! [escorter setBounty: extra]; // NSLog(@"DEBUG setting bounty for %@ escorting %@ to %d", escorter, self, extra); - + // [escorter setReportAImessages: YES ]; // debug } else { [escorter setBounty:0]; } - + // NSLog(@"DEBUG set up escort ship %@ for %@", escorter, self); - + [escorter release]; n_escorts--; } @@ -747,15 +747,15 @@ static NSMutableDictionary* smallOctreeDict = nil; NSString* cargo_type_string; NSString* weapon_type_string; NSMutableDictionary* shipdict = [NSMutableDictionary dictionaryWithDictionary:dict]; - + // reset all settings [self reinit]; - + if (collisionInfoForEntity) [collisionInfoForEntity removeAllObjects]; else collisionInfoForEntity = [(NSMutableDictionary *)[NSMutableDictionary alloc] initWithCapacity:12]; - + // check if this is based upon a different ship while ([shipdict objectForKey:@"like_ship"]) { @@ -765,7 +765,7 @@ static NSMutableDictionary* smallOctreeDict = nil; NSDictionary* other_shipdict = nil; if (other_shipdesc) { - NS_DURING + NS_DURING other_shipdict = [universe getDictionaryForShip:other_shipdesc]; // handle OOLITE_EXCEPTION_SHIP_NOT_FOUND NS_HANDLER if ([[localException name] isEqual: OOLITE_EXCEPTION_SHIP_NOT_FOUND]) @@ -780,20 +780,20 @@ static NSMutableDictionary* smallOctreeDict = nil; if (other_shipdict) { [shipdict removeObjectForKey:@"like_ship"]; // so it may inherit a new one from the like_ship - + // NSLog(@"DEBUG setting up ship alike unto : %@", other_shipdesc); - + NSMutableDictionary* this_shipdict = [NSMutableDictionary dictionaryWithDictionary:other_shipdict]; // basics from that one [this_shipdict addEntriesFromDictionary:shipdict]; // overrides from this one shipdict = [NSMutableDictionary dictionaryWithDictionary:this_shipdict]; // synthesis' - + // NSLog(@"DEBUG resulting shipdict is :\n%@", shipdict); } } } - + shipinfoDictionary = [[NSDictionary alloc] initWithDictionary:shipdict]; // retained - + // // set things from dictionary from here out // @@ -870,8 +870,8 @@ static NSMutableDictionary* smallOctreeDict = nil; // if ([shipdict objectForKey:@"missiles"]) missiles = [(NSNumber *)[shipdict objectForKey:@"missiles"] intValue]; - - // upgrades: + + // upgrades: // did use [NSNumber boolValue], but now have a random chance instead // if ([shipdict objectForKey:@"has_ecm"]) @@ -907,10 +907,10 @@ static NSMutableDictionary* smallOctreeDict = nil; has_military_scanner_filter = (randf() < [(NSNumber *)[shipdict objectForKey:@"has_military_scanner_filter"] floatValue]); // // /upgrades - + if ([shipdict objectForKey:@"fuel"]) fuel = [(NSNumber *)[shipdict objectForKey:@"fuel"] intValue]; - + // if ([shipdict objectForKey:@"bounty"]) bounty = [(NSNumber *)[shipdict objectForKey:@"bounty"] intValue]; @@ -937,7 +937,7 @@ static NSMutableDictionary* smallOctreeDict = nil; if ([shipdict objectForKey:@"cargo_carried"]) { cargo_flag = CARGO_FLAG_FULL_UNIFORM; - + [self setCommodity:NSNotFound andAmount:0]; int c_commodity = NSNotFound; int c_amount = 1; @@ -952,7 +952,7 @@ static NSMutableDictionary* smallOctreeDict = nil; c_amount = 1; c_commodity = [universe commodityForName: (NSString*)[shipdict objectForKey:@"cargo_carried"]]; } - + if (c_commodity != NSNotFound) [self setCommodity:c_commodity andAmount:c_amount]; } @@ -1015,8 +1015,8 @@ static NSMutableDictionary* smallOctreeDict = nil; [self addExhaust:exhaust]; [exhaust release]; } - } - // + } + // if ([shipdict objectForKey:@"subentities"]) { if (universe) @@ -1028,7 +1028,7 @@ static NSMutableDictionary* smallOctreeDict = nil; { // NSArray* details = [(NSString *)[subs objectAtIndex:i] componentsSeparatedByString:@" "]; NSArray* details = [Entity scanTokensFromString:(NSString *)[subs objectAtIndex:i]]; - + if ([details count] == 8) { //NSLog(@"DEBUG adding subentity..."); @@ -1043,7 +1043,7 @@ static NSMutableDictionary* smallOctreeDict = nil; sub_q.x = [(NSString *)[details objectAtIndex:5] floatValue]; sub_q.y = [(NSString *)[details objectAtIndex:6] floatValue]; sub_q.z = [(NSString *)[details objectAtIndex:7] floatValue]; - + // NSLog(@"DEBUG adding subentity... %@ %f %f %f - %f %f %f %f", subdesc, sub_pos.x, sub_pos.y, sub_pos.z, sub_q.w, sub_q.x, sub_q.y, sub_q.z); if ([subdesc isEqual:@"*FLASHER*"]) @@ -1061,14 +1061,14 @@ static NSMutableDictionary* smallOctreeDict = nil; else { quaternion_normalise(&sub_q); - + // NSLog(@"DEBUG universe = %@", universe); - + subent = [universe getShip:subdesc]; // retained - + if ((self->isStation)&&([subdesc rangeOfString:@"dock"].location != NSNotFound)) [(StationEntity*)self setDockingPortModel:(ShipEntity*)subent :sub_pos :sub_q]; - + if (subent) { // NSLog(@"DEBUG adding subentity %@ %@ to new %@ at %.3f,%.3f,%.3f", subent, [(ShipEntity*)subent name], name, sub_pos.x, sub_pos.y, sub_pos.z ); @@ -1097,11 +1097,11 @@ static NSMutableDictionary* smallOctreeDict = nil; [sub_entities release]; sub_entities = [[NSArray arrayWithArray:temp] retain]; } - + [subent setOwner: self]; - + // NSLog(@"DEBUG added subentity %@ to position %.3f,%.3f,%.3f", subent, subent->position.x, subent->position.y, subent->position.z ); - + [subent release]; } } @@ -1112,7 +1112,7 @@ static NSMutableDictionary* smallOctreeDict = nil; if ([shipdict objectForKey:@"frangible"]) // if an object has frangible == YES then it can have its subentities shot away! isFrangible = [(NSNumber *)[shipdict objectForKey:@"frangible"] boolValue]; subentity_taking_damage = nil; - // + // if ([shipdict objectForKey:@"laser_color"]) { NSString *laser_color_string = (NSString *)[shipdict objectForKey:@"laser_color"]; @@ -1123,7 +1123,7 @@ static NSMutableDictionary* smallOctreeDict = nil; if ([color_thing isKindOfClass:[OOColor class]]) [self setLaserColor:(OOColor *)color_thing]; } - } + } else [self setLaserColor:[OOColor redColor]]; // @@ -1131,9 +1131,9 @@ static NSMutableDictionary* smallOctreeDict = nil; if ([shipdict objectForKey:@"scanClass"]) { NSString *s_class= (NSString *)[shipdict objectForKey:@"scanClass"]; - + //NSLog(@"----- initialising ship with scan class '%@'",s_class); - + scan_class = CLASS_NEUTRAL; if ([s_class isEqual:@"CLASS_STATION"]) scan_class = CLASS_STATION; @@ -1161,7 +1161,7 @@ static NSMutableDictionary* smallOctreeDict = nil; else scan_class = CLASS_NOT_SET; // - // scripting + // scripting if ([shipdict objectForKey:KEY_LAUNCH_ACTIONS]) [launch_actions addObjectsFromArray:(NSArray *)[shipdict objectForKey:KEY_LAUNCH_ACTIONS]]; if ([shipdict objectForKey:KEY_SCRIPT_ACTIONS]) @@ -1175,12 +1175,12 @@ static NSMutableDictionary* smallOctreeDict = nil; PlayerEntity* player = (PlayerEntity*)[universe entityZero]; [player setScript_target:self]; NSArray * setup_actions = (NSArray *)[shipdict objectForKey:KEY_SETUP_ACTIONS]; - + [player scriptActions: setup_actions forTarget: self]; } } - + // escorts // if ([shipdict objectForKey:@"escorts"]) @@ -1189,7 +1189,7 @@ static NSMutableDictionary* smallOctreeDict = nil; //NSLog(@"DEBUG adding %d escorts for new %@", n_escorts, name); escortsAreSetUp = (n_escorts == 0); } - + // beacons // if ([shipdict objectForKey:@"beacon"]) @@ -1239,12 +1239,12 @@ static NSMutableDictionary* smallOctreeDict = nil; portWeaponOffset = [Entity vectorFromString: (NSString *)[shipdict objectForKey:@"weapon_position_port"]]; if ([shipdict objectForKey:@"weapon_position_starboard"]) starboardWeaponOffset = [Entity vectorFromString: (NSString *)[shipdict objectForKey:@"weapon_position_starboard"]]; - + // fuel scoop destination position (where cargo gets sucked into) tractor_position = make_vector( 0.0f, 0.0f, 0.0f); if ([shipdict objectForKey:@"scoop_position"]) tractor_position = [Entity vectorFromString: (NSString *)[shipdict objectForKey:@"scoop_position"]]; - + // ship skin insulation factor (1.0 is normal) heat_insulation = 1.0; if ([shipdict objectForKey:@"heat_insulation"]) @@ -1292,10 +1292,10 @@ BOOL ship_canCollide (ShipEntity* ship) return NO; if ([collidingEntities containsObject:other]) // we know about this already! return NO; - + if ((other->isShip)&&[self canScoop: (ShipEntity*)other]) // quick test - could this improve scooping for small ships? I think so! return YES; - + if (trackCloseContacts) { // in update we check if close contacts have gone out of touch range (origin within our collision_radius) @@ -1314,10 +1314,10 @@ BOOL ship_canCollide (ShipEntity* ship) primaryTarget = temp_id; } } - + if (zero_distance > CLOSE_COLLISION_CHECK_MAX_RANGE2) // don't work too hard on entities that are far from the player return YES; - + if (other->isShip) { // check bounding spheres versus bounding spheres @@ -1371,7 +1371,7 @@ BOOL ship_canCollide (ShipEntity* ship) if (d2 < d1 * d1) { // NSLog(@"DEBUG performing further checks for collision between %@ and %@", entity1[i], entity2[j]); - + BOOL collision = YES; if (i == 0) { @@ -1405,7 +1405,7 @@ BOOL ship_canCollide (ShipEntity* ship) // // get bounding box relative to this ship's orientation BoundingBox arbb = [other findBoundingBoxRelativeTo:self InVectors: v_right: v_up: v_forward]; - + // construct 6 rectangles based on the sides of the possibly overlapping bounding boxes NSRect other_x_rect = NSMakeRect(arbb.min.z, arbb.min.y, arbb.max.z - arbb.min.z, arbb.max.y - arbb.min.y); NSRect other_y_rect = NSMakeRect(arbb.min.x, arbb.min.z, arbb.max.x - arbb.min.x, arbb.max.z - arbb.min.z); @@ -1444,12 +1444,12 @@ BOOL ship_canCollide (ShipEntity* ship) - (BOOL) subentityCheckBoundingBoxCollisionWith:(Entity *)other { // NSLog(@"DEBUG [%@ subentityCheckBoundingBoxCollisionWith:%@]", self, other); - + BoundingBox sebb = [self findSubentityBoundingBox]; - + // NSLog(@"DEBUG bounding box for subentity: %@ [%.1fm %.1fm]x [%.1fm %.1fm]y [%.1fm %.1fm]z", self, // sebb.min.x, sebb.max.x, sebb.min.y, sebb.max.y, sebb.min.z, sebb.max.z); - + if (other->isShip) { // check bounding boxes ... @@ -1459,14 +1459,14 @@ BOOL ship_canCollide (ShipEntity* ship) Vector i = vector_right_from_quaternion(parent->q_rotation); Vector j = vector_up_from_quaternion(parent->q_rotation); Vector k = vector_forward_from_quaternion(parent->q_rotation); - + // // get bounding box relative to this ship's orientation BoundingBox arbb = [other findBoundingBoxRelativeTo:parent InVectors: i: j: k]; - + // NSLog(@"DEBUG bounding box for other: %@ [%.1fm %.1fm]x [%.1fm %.1fm]y [%.1fm %.1fm]z", other, // arbb.min.x, arbb.max.x, arbb.min.y, arbb.max.y, arbb.min.z, arbb.max.z); - + // construct 6 rectangles based on the sides of the possibly overlapping bounding boxes NSRect x_rect = NSMakeRect(sebb.min.z, sebb.min.y, sebb.max.z - sebb.min.z, sebb.max.y - sebb.min.y); NSRect y_rect = NSMakeRect(sebb.min.x, sebb.min.z, sebb.max.x - sebb.min.x, sebb.max.z - sebb.min.z); @@ -1474,7 +1474,7 @@ BOOL ship_canCollide (ShipEntity* ship) NSRect other_x_rect = NSMakeRect(arbb.min.z, arbb.min.y, arbb.max.z - arbb.min.z, arbb.max.y - arbb.min.y); NSRect other_y_rect = NSMakeRect(arbb.min.x, arbb.min.z, arbb.max.x - arbb.min.x, arbb.max.z - arbb.min.z); NSRect other_z_rect = NSMakeRect(arbb.min.x, arbb.min.y, arbb.max.x - arbb.min.x, arbb.max.y - arbb.min.y); - + // NSLog(@"DEBUG intersects in x:%@: y:%@: z:%@", // NSIntersectsRect(x_rect,other_x_rect)? @"YES": @"NO ", // NSIntersectsRect(y_rect,other_y_rect)? @"YES": @"NO ", @@ -1506,7 +1506,7 @@ BOOL ship_canCollide (ShipEntity* ship) return YES; } -- (BoundingBox) findSubentityBoundingBox +- (BoundingBox) findSubentityBoundingBox { BoundingBox result; Vector v = vertices[0]; @@ -1521,10 +1521,10 @@ BOOL ship_canCollide (ShipEntity* ship) v.x += position.x; v.y += position.y; v.z += position.z; bounding_box_add_vector(&result,v); } - + // NSLog(@"DEBUG subentity bounding box for %@ of %@ is [%.1fm %.1fm]x [%.1fm %.1fm]y [%.1fm %.1fm]z", self, [self owner], // result.min.x, result.max.x, result.min.y, result.max.y, result.min.z, result.max.z); - + return result; } @@ -1555,7 +1555,7 @@ BOOL ship_canCollide (ShipEntity* ship) w = make_vector( dot_product( v, vi), dot_product( v, vj), dot_product( v, vk)); bounding_box_add_vector(&result,w); } - + return result; } @@ -1609,7 +1609,7 @@ BOOL ship_canCollide (ShipEntity* ship) - (Vector) absolutePositionForSubentityOffset:(Vector) offset { - + Vector off = offset; mult_vector_gl_matrix(&off, rotMatrix); Vector abspos = make_vector( position.x + off.x, position.y + off.y, position.z + off.z); @@ -1683,7 +1683,7 @@ BOOL ship_canCollide (ShipEntity* ship) } } // - + if (trackCloseContacts) { // in checkCloseCollisionWith: we check if some thing has come within touch range (origin within our collision_radius) @@ -1726,11 +1726,11 @@ BOOL ship_canCollide (ShipEntity* ship) [closeContactsInfo removeObjectForKey: other_key]; } } - + // super update // [super update:delta_t]; - + // DEBUGGING // if (reportAImessages && (debug_condition != behaviour)) @@ -1738,7 +1738,7 @@ BOOL ship_canCollide (ShipEntity* ship) NSLog(@"DEBUG %@ behaviour is now %d", self, behaviour); debug_condition = behaviour; } - + // update time between shots // shot_time +=delta_t; @@ -1751,7 +1751,7 @@ BOOL ship_canCollide (ShipEntity* ship) if (message_time < 0.0) message_time = 0.0; } - + // temperature factors // double external_temp = 0.0; @@ -1766,7 +1766,7 @@ BOOL ship_canCollide (ShipEntity* ship) if ([sun goneNova]) external_temp *= 100; } - + // work on the ship temperature // if (external_temp > ship_temperature) @@ -1783,7 +1783,7 @@ BOOL ship_canCollide (ShipEntity* ship) // are we burning due to low energy if ((energy < max_energy * 0.20)&&(energy_recharge_rate > 0.0)) // prevents asteroid etc. from burning throw_sparks = YES; - + // burning effects // if (throw_sparks) @@ -1795,7 +1795,7 @@ BOOL ship_canCollide (ShipEntity* ship) throw_sparks = NO; // until triggered again } } - + // cloaking device if (has_cloaking_device) { @@ -1818,7 +1818,7 @@ BOOL ship_canCollide (ShipEntity* ship) } } } - + // military_jammer if (has_military_jammer) { @@ -1838,7 +1838,7 @@ BOOL ship_canCollide (ShipEntity* ship) // check outside factors // aegis_status = [self checkForAegis]; // is a station or something nearby?? - + //scripting if ((status == STATUS_IN_FLIGHT)&&([launch_actions count])) { @@ -1846,7 +1846,7 @@ BOOL ship_canCollide (ShipEntity* ship) [(PlayerEntity *)[universe entityZero] scriptActions: launch_actions forTarget: self]; [launch_actions removeAllObjects]; } - + // behaviours according to status and behaviour // if (status == STATUS_LAUNCHING) @@ -1901,9 +1901,9 @@ BOOL ship_canCollide (ShipEntity* ship) else { double target_speed = max_flight_speed; - + ShipEntity* target = (ShipEntity*)[universe entityForUniversalID:primaryTarget]; - + if ((target == nil)||(target->scan_class == CLASS_NO_DRAW)||(!target->isShip)) { // It's no longer a parrot, it has ceased to be, it has joined the choir invisible... @@ -1922,7 +1922,7 @@ BOOL ship_canCollide (ShipEntity* ship) } } } - + switch (behaviour) { case BEHAVIOUR_TUMBLE : @@ -1933,86 +1933,86 @@ BOOL ship_canCollide (ShipEntity* ship) case BEHAVIOUR_STATION_KEEPING : [self behaviour_stop_still: delta_t]; break; - + case BEHAVIOUR_IDLE : [self behaviour_idle: delta_t]; break; - + case BEHAVIOUR_TRACTORED : [self behaviour_tractored: delta_t]; break; - + case BEHAVIOUR_TRACK_TARGET : [self behaviour_track_target: delta_t]; break; - + case BEHAVIOUR_INTERCEPT_TARGET : case BEHAVIOUR_COLLECT_TARGET : [self behaviour_intercept_target: delta_t]; break; - + case BEHAVIOUR_ATTACK_TARGET : [self behaviour_attack_target: delta_t]; break; - + case BEHAVIOUR_ATTACK_FLY_TO_TARGET_SIX : case BEHAVIOUR_ATTACK_FLY_TO_TARGET_TWELVE : [self behaviour_fly_to_target_six: delta_t]; break; - + case BEHAVIOUR_ATTACK_MINING_TARGET : [self behaviour_attack_mining_target: delta_t]; - break; - + break; + case BEHAVIOUR_ATTACK_FLY_TO_TARGET : [self behaviour_attack_fly_to_target: delta_t]; break; - + case BEHAVIOUR_ATTACK_FLY_FROM_TARGET : [self behaviour_attack_fly_from_target: delta_t]; break; - + case BEHAVIOUR_RUNNING_DEFENSE : [self behaviour_running_defense: delta_t]; break; - + case BEHAVIOUR_FLEE_TARGET : [self behaviour_flee_target: delta_t]; break; - + case BEHAVIOUR_FLY_RANGE_FROM_DESTINATION : [self behaviour_fly_range_from_destination: delta_t]; break; - + case BEHAVIOUR_FACE_DESTINATION : [self behaviour_face_destination: delta_t]; break; - + case BEHAVIOUR_FORMATION_FORM_UP : [self behaviour_formation_form_up: delta_t]; break; - + case BEHAVIOUR_FLY_TO_DESTINATION : [self behaviour_fly_to_destination: delta_t]; break; - + case BEHAVIOUR_FLY_FROM_DESTINATION : case BEHAVIOUR_FORMATION_BREAK : [self behaviour_fly_from_destination: delta_t]; break; - + case BEHAVIOUR_AVOID_COLLISION : [self behaviour_avoid_collision: delta_t]; break; - + case BEHAVIOUR_TRACK_AS_TURRET : [self behaviour_track_as_turret: delta_t]; break; - + case BEHAVIOUR_EXPERIMENTAL : [self behaviour_experimental: delta_t]; break; - + } // // manage energy @@ -2157,7 +2157,7 @@ BOOL ship_canCollide (ShipEntity* ship) velocity.y += delta_t * dp.y * tf / d2; velocity.z += delta_t * dp.z * tf / d2; } - + thrust = 10.0; // used to damp velocity if (status == STATUS_BEING_SCOOPED) { @@ -2212,12 +2212,12 @@ BOOL ship_canCollide (ShipEntity* ship) // double slowdownTime = 96.0 / thrust; // more thrust implies better slowing double minTurnSpeedFactor = 0.005 * max_flight_pitch * max_flight_roll; // faster turning implies higher speeds - + if ((eta < slowdownTime)&&(flight_speed > max_flight_speed * minTurnSpeedFactor)) desired_speed = flight_speed * 0.75; // cut speed by 50% to a minimum minTurnSpeedFactor of speed else desired_speed = max_flight_speed; - + if (desired_speed < target_speed) { desired_speed += target_speed; @@ -2346,7 +2346,7 @@ BOOL ship_canCollide (ShipEntity* ship) int missile_chance = 0; int rhs = 3.2 / delta_t; if (rhs) missile_chance = 1 + (ranrot_rand() % rhs); - + double hurt_factor = 16 * pow(energy/max_energy, 4.0); if (missiles > missile_chance * hurt_factor) { @@ -2409,7 +2409,7 @@ BOOL ship_canCollide (ShipEntity* ship) else { //NSLog(@"DEBUG >>>>> %@ %d entering running defense mode", name, universal_id); - + jink = make_vector( 0.0f, 0.0f, 0.0f); behaviour = BEHAVIOUR_RUNNING_DEFENSE; frustration = 0.0; @@ -2470,7 +2470,7 @@ BOOL ship_canCollide (ShipEntity* ship) int missile_chance = 0; int rhs = 3.2 / delta_t; if (rhs) missile_chance = 1 + (ranrot_rand() % rhs); - + double hurt_factor = 16 * pow(energy/max_energy, 4.0); if (missiles > missile_chance * hurt_factor) { @@ -2495,11 +2495,11 @@ BOOL ship_canCollide (ShipEntity* ship) frustration = 0.0; } [self trackPrimaryTarget:delta_t:YES]; - + int missile_chance = 0; int rhs = 3.2 / delta_t; if (rhs) missile_chance = 1 + (ranrot_rand() % rhs); - + double hurt_factor = 16 * pow(energy/max_energy, 4.0); if (missiles > missile_chance * hurt_factor) { @@ -2543,7 +2543,7 @@ BOOL ship_canCollide (ShipEntity* ship) int missile_chance = 0; int rhs = 3.2 / delta_t; if (rhs) missile_chance = 1 + (ranrot_rand() % rhs); - + if ((has_energy_bomb) && (range < 10000.0)) { float qbomb_chance = 0.01 * delta_t; @@ -2552,7 +2552,7 @@ BOOL ship_canCollide (ShipEntity* ship) [self launchEnergyBomb]; } } - + double hurt_factor = 16 * pow(energy/max_energy, 4.0); if (([(ShipEntity *)[self getPrimaryTarget] getPrimaryTarget] == self)&&(missiles > missile_chance * hurt_factor)) [self fireMissile]; @@ -2625,18 +2625,18 @@ BOOL ship_canCollide (ShipEntity* ship) double last_success_factor = success_factor; double last_distance = last_success_factor; double eta = distance / flight_speed; - + success_factor = distance; - + // do the actual piloting!! [self trackDestination:delta_t:NO]; - + double slowdownTime = (thrust > 0.0)? flight_speed / thrust : 4.0; // 10% safety margin double minTurnSpeedFactor = 0.05 * max_flight_pitch * max_flight_roll; // faster turning implies higher speeds - + if ((eta < slowdownTime)&&(flight_speed > max_flight_speed * minTurnSpeedFactor)) desired_speed = flight_speed * 0.50; // cut speed by 50% to a minimum minTurnSpeedFactor of speed - + if (distance < last_distance) // improvement { frustration -= delta_t; @@ -2644,7 +2644,7 @@ BOOL ship_canCollide (ShipEntity* ship) frustration = 0.0; } else - { + { frustration += delta_t; if ((frustration > slowdownTime * 10.0)||(frustration > 15.0)) // 10x slowdownTime or 15s of frustration { @@ -2791,7 +2791,7 @@ BOOL ship_canCollide (ShipEntity* ship) resetFrame.position = position; resetFrame.q_rotation = qrot; resetFrame.k = v_forward; - Vector vel = make_vector( v_forward.x * flight_speed, v_forward.y * flight_speed, v_forward.z * flight_speed); + Vector vel = make_vector( v_forward.x * flight_speed, v_forward.y * flight_speed, v_forward.z * flight_speed); [self resetFramesFromFrame:resetFrame withVelocity:vel]; if (sub_entities) { @@ -2834,19 +2834,19 @@ BOOL ship_canCollide (ShipEntity* ship) if (!translucent) [super drawEntity:immediate:translucent]; - + // // test octree drawing // if (translucent && (octree)) // if (status == STATUS_DEMO) // [octree drawOctree]; - + // checkGLErrors([NSString stringWithFormat:@"ShipEntity after drawing Entity (main) %@", self]); // - + if (immediate) return; // don't draw sub-entities when constructing a displayList - + if (sub_entities) { int i; @@ -2857,7 +2857,7 @@ BOOL ship_canCollide (ShipEntity* ship) [se drawSubEntity:immediate:translucent]; } } - + // checkGLErrors([NSString stringWithFormat:@"ShipEntity after drawing Entity (subentities) %@", self]); // @@ -2894,11 +2894,11 @@ BOOL ship_canCollide (ShipEntity* ship) glPushMatrix(); // position and orientation is absolute glTranslated( abspos.x, abspos.y, abspos.z); - + glMultMatrixf(rotMatrix); - + [self drawEntity:immediate :translucent]; - + // NSLog(@"drawn active entity : %@", basefile); } @@ -2908,9 +2908,9 @@ BOOL ship_canCollide (ShipEntity* ship) glTranslated( position.x, position.y, position.z); glMultMatrixf(rotMatrix); - + [self drawEntity:immediate :translucent]; - + glPopMatrix(); } } @@ -2928,7 +2928,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple - (GLfloat *) scannerDisplayColorForShip:(ShipEntity*)otherShip :(BOOL)isHostile :(BOOL)flash { - + if (has_military_jammer && military_jammer_active) { if (![otherShip hasMilitaryScannerFilter]) @@ -2946,7 +2946,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple } } } - + switch (scan_class) { case CLASS_ROCK : @@ -2987,12 +2987,12 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple - (BOOL) isJammingScanning { return (has_military_jammer && military_jammer_active); -} +} - (BOOL) hasMilitaryScannerFilter { return has_military_scanner_filter; -} +} - (void) addExhaust:(ParticleEntity *)exhaust { @@ -3016,16 +3016,16 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple [self addExhaust:exhaust]; [exhaust release]; // released } - + - (void) applyThrust:(double) delta_t { double max_available_speed = (has_fuel_injection && (fuel > 1))? max_flight_speed * AFTERBURNER_FACTOR : max_flight_speed; - + position.x += delta_t*velocity.x; position.y += delta_t*velocity.y; position.z += delta_t*velocity.z; - + // if (thrust) { @@ -3043,11 +3043,11 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple if (behaviour == BEHAVIOUR_TUMBLE) return; //testing - + // check for speed if (desired_speed > max_available_speed) desired_speed = max_available_speed; - + if (flight_speed > desired_speed) { [self decrease_flight_speed:delta_t*thrust]; @@ -3059,7 +3059,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple if (flight_speed > desired_speed) flight_speed = desired_speed; } [self moveForward:delta_t*flight_speed]; - + // burn fuel at the appropriate rate if ((flight_speed > max_flight_speed) && has_fuel_injection && (fuel > 0)) { @@ -3074,24 +3074,24 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple } - (void) applyRoll:(GLfloat) roll1 andClimb:(GLfloat) climb1 -{ +{ Quaternion q1; - + if ((!roll1)&&(!climb1)&&(!has_rotated)) return; - + quaternion_set_identity(&q1); - + if (roll1) quaternion_rotate_about_z( &q1, -roll1); if (climb1) quaternion_rotate_about_x( &q1, -climb1); - + q_rotation = quaternion_multiply( q1, q_rotation); quaternion_normalise(&q_rotation); // probably not strictly necessary but good to do to keep q_rotation sane quaternion_into_gl_matrix(q_rotation, rotMatrix); - + v_forward = vector_forward_from_quaternion(q_rotation); v_up = vector_up_from_quaternion(q_rotation); v_right = vector_right_from_quaternion(q_rotation); @@ -3105,14 +3105,14 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple // NSLog(@"DEBUG ***** %@ in AVOID COLLISION!", self); - + ShipEntity* prox_ship = [self proximity_alert]; - + if (prox_ship) { // if (self == [universe entityZero]) // NSLog(@"DEBUG ***** proximity alert for %@ %d against target %d", name, universal_id, proximity_alert); - + if (previousCondition) { // @@ -3121,9 +3121,9 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple [previousCondition release]; previousCondition = nil; } - + previousCondition = [(NSMutableDictionary *)[NSMutableDictionary alloc] initWithCapacity:16]; - + [previousCondition setObject:[NSNumber numberWithInt:behaviour] forKey:@"behaviour"]; [previousCondition setObject:[NSNumber numberWithInt:primaryTarget] forKey:@"primaryTarget"]; [previousCondition setObject:[NSNumber numberWithFloat:desired_range] forKey:@"desired_range"]; @@ -3131,13 +3131,13 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple [previousCondition setObject:[NSNumber numberWithFloat:destination.x] forKey:@"destination.x"]; [previousCondition setObject:[NSNumber numberWithFloat:destination.y] forKey:@"destination.y"]; [previousCondition setObject:[NSNumber numberWithFloat:destination.z] forKey:@"destination.z"]; - + destination = prox_ship->position; destination.x += position.x; destination.y += position.y; destination.z += position.z; destination.x *= 0.5; destination.y *= 0.5; destination.z *= 0.5; // point between us and them - + desired_range = prox_ship->collision_radius * PROXIMITY_AVOID_DISTANCE; - + behaviour = BEHAVIOUR_AVOID_COLLISION; } } @@ -3146,9 +3146,9 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple { if (!previousCondition) return; - + // NSLog(@"DEBUG ***** proximity alert for %@ %d over", name, universal_id, proximity_alert); - + behaviour = [(NSNumber*)[previousCondition objectForKey:@"behaviour"] intValue]; primaryTarget = [(NSNumber*)[previousCondition objectForKey:@"primaryTarget"] intValue]; desired_range = [(NSNumber*)[previousCondition objectForKey:@"desired_range"] floatValue]; @@ -3156,13 +3156,13 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple destination.x = [(NSNumber*)[previousCondition objectForKey:@"destination.x"] floatValue]; destination.y = [(NSNumber*)[previousCondition objectForKey:@"destination.y"] floatValue]; destination.z = [(NSNumber*)[previousCondition objectForKey:@"destination.z"] floatValue]; - + [previousCondition release]; previousCondition = nil; frustration = 0.0; - + proximity_alert = NO_TARGET; - + //[shipAI message:@"RESTART_DOCKING"]; // if docking, start over, other AIs will ignore this message } @@ -3209,13 +3209,13 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple proximity_alert = NO_TARGET; return; } - + if (isStation||(other->isStation)) // don't be alarmed close to stations return; - + if ((scan_class == CLASS_CARGO)||(scan_class == CLASS_BUOY)||(scan_class == CLASS_MISSILE)||(scan_class == CLASS_ROCK)) // rocks and stuff don't get alarmed easily return; - + // check vectors Vector vdiff = vector_between( position, other->position); GLfloat d_forward = dot_product( vdiff, v_forward); @@ -3223,12 +3223,12 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple GLfloat d_right = dot_product( vdiff, v_right); if ((d_forward > 0.0)&&(flight_speed > 0.0)) // it's ahead of us and we're moving forward d_forward *= 0.25 * max_flight_speed / flight_speed; // extend the collision zone forward up to 400% - double d2 = d_forward * d_forward + d_up * d_up + d_right * d_right; + double d2 = d_forward * d_forward + d_up * d_up + d_right * d_right; double cr2 = collision_radius * 2.0 + other->collision_radius; cr2 *= cr2; // check with twice the combined radius - + if (d2 > cr2) // we're okay return; - + if (behaviour == BEHAVIOUR_AVOID_COLLISION) // already avoiding something { ShipEntity* prox = (ShipEntity*)[universe entityForUniversalID:proximity_alert]; @@ -3385,14 +3385,14 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple - (int) checkForAegis { PlanetEntity* the_planet = [universe planet]; - + if (!the_planet) - { + { if (aegis_status != AEGIS_NONE) [shipAI message:@"AEGIS_NONE"]; return AEGIS_NONE; } - + // check planet Vector p1 = the_planet->position; double cr = the_planet->collision_radius; @@ -3417,7 +3417,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple // check station StationEntity* the_station = [universe station]; if (!the_station) - { + { if (aegis_status != AEGIS_NONE) [shipAI message:@"AEGIS_NONE"]; return AEGIS_NONE; @@ -3428,7 +3428,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple if (d2 < 0.0) result = AEGIS_IN_DOCKING_RANGE; within_station_aegis = (d2 < 0.0); - + // ai messages on change in status // approaching.. if ((aegis_status == AEGIS_NONE)&&(result == AEGIS_CLOSE_TO_PLANET)) @@ -3440,9 +3440,9 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple [shipAI message:@"AEGIS_LEAVING_DOCKING_RANGE"]; if ((aegis_status != AEGIS_NONE)&&(result == AEGIS_NONE)) [shipAI message:@"AEGIS_NONE"]; - + aegis_status = result; // put this here - + return result; } @@ -3512,7 +3512,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple { flight_roll = amount * PI / 2.0; } - + - (void) setPitch:(double) amount { flight_pitch = amount * PI / 2.0; @@ -3601,8 +3601,8 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple - (void) increase_flight_speed:(double) delta { - double factor = ((desired_speed > max_flight_speed)&&(has_fuel_injection)&&(fuel > 0)) ? AFTERBURNER_FACTOR : 1.0; - + double factor = ((desired_speed > max_flight_speed)&&(has_fuel_injection)&&(fuel > 0)) ? AFTERBURNER_FACTOR : 1.0; + if (flight_speed < max_flight_speed * factor) flight_speed += delta * factor; else @@ -3700,7 +3700,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple double d2 = p2.x*p2.x + p2.y*p2.y + p2.z*p2.z - ecr*ecr; double damage = weapon_energy*desired_range/d2; [e2 takeEnergyDamage:damage from:self becauseOf:[self owner]]; - + // if ((e2)&&(e2->isShip)) // NSLog(@"DEBUG Doing %.1f damage to %@ %d",damage,[(ShipEntity *)e2 name],[(ShipEntity *)e2 universal_id]); } @@ -3754,7 +3754,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple [shipAI reactToMessage:@"ATTACKED"]; // note use the reactToMessage: method NOT the think-delayed message: method return; // Main stations are energy-bomb-proof! } - + // otherwise start a chain-reaction // if ((amount > energy)&&(energy > 10)) @@ -3782,17 +3782,17 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple // primaryAggressor = [hunter universal_id]; found_target = primaryAggressor; - + // firing on an innocent ship is an offence [self broadcastHitByLaserFrom: hunter]; - + // tell ourselves we've been attacked if (energy > 0) [shipAI reactToMessage:@"ATTACKED"]; // note use the reactToMessage: method NOT the think-delayed message: method - + // firing on an innocent ship is an offence [self broadcastHitByLaserFrom:(ShipEntity*) other]; - + // tell our group we've been attacked if (group_id != NO_TARGET) { @@ -3802,7 +3802,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple if (group_leader) { //NSLog(@"DEBUG %@ %d informs group leader %@ %d of attack by %@ %d", name, universal_id, [group_leader name], [group_leader universal_id], [hunter name], [hunter universal_id]); - + //[group_leader setReportAImessages:YES]; [group_leader setFound_target:hunter]; [group_leader setPrimaryAggressor:hunter]; @@ -3837,11 +3837,11 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple } } } - + // if I'm a copper and you're not, then mark the other as an offender! if ((iAmTheLaw)&&(!uAreTheLaw)) [hunter markAsOffender:64]; - + // avoid shooting each other if (([hunter group_id] == group_id)||(iAmTheLaw && uAreTheLaw)) { @@ -3851,7 +3851,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple [hunter setDesiredSpeed:[hunter max_flight_speed]]; } } - + if ((other)&&(other->isShip)) being_mined = [(ShipEntity *)other isMining]; } @@ -3868,7 +3868,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple [[hunter getAI] message:@"TARGET_DESTROYED"]; } } - + [self becomeExplosion]; } else @@ -3910,7 +3910,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple this_ship->position = this_pos; [this_ship release]; } - + Vector xposition = position; ParticleEntity *fragment; int i; @@ -3918,7 +3918,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple Quaternion q; int speed_low = 200; int n_alloys = floor((boundingBox.max.z - boundingBox.min.z) / 50.0); - + if (status == STATUS_DEAD) { [universe removeEntity:self]; @@ -3929,17 +3929,17 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple if ([death_actions count]) { PlayerEntity* player = (PlayerEntity *)[universe entityZero]; - + [player setScript_target:self]; [player scriptActions: death_actions forTarget: self]; - + [death_actions removeAllObjects]; } - - + + if ([roles isEqual:@"thargoid"]) [self broadcastThargoidDestroyed]; - + if (collision_radius > 49.9) // big! { // quick test of hyperring @@ -3950,7 +3950,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple [universe addEntity:ring]; [ring release]; } - + // several parts to the explosion: // 1. fast sparks fragment = [[ParticleEntity alloc] initFragburstSize: collision_radius FromPosition: xposition]; @@ -3959,12 +3959,12 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple // 2. slow clouds fragment = [[ParticleEntity alloc] initBurst2Size: collision_radius FromPosition: xposition]; [universe addEntity:fragment]; - [fragment release]; + [fragment release]; // 3. flash fragment = [[ParticleEntity alloc] initFlashSize: collision_radius FromPosition: xposition]; [universe addEntity:fragment]; - [fragment release]; - + [fragment release]; + // we need to throw out cargo at this point. NSArray *jetsam = nil; // this will contain the stuff to get thrown out int cargo_chance = 10; @@ -3977,7 +3977,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple cargo_chance = 100; // chance of any given piece of cargo surviving decompression cargo_flag = CARGO_FLAG_CANISTERS; } - + int cargo_to_go = max_cargo * cargo_chance / 100; while (cargo_to_go > 15) cargo_to_go = ranrot_rand() % cargo_to_go; @@ -3991,12 +3991,12 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple jetsam = [universe getContainersOfCommodity:commodity_name :cargo_to_go]; } break; - + case CARGO_FLAG_FULL_PLENTIFUL : // NSLog(@"DEBUG dropping plentiful cargo (CARGO_FLAG_FULL_PLENTIFUL)"); jetsam = [universe getContainersOfPlentifulGoods:cargo_to_go]; break; - + case CARGO_FLAG_PIRATE : // NSLog(@"DEBUG dropping pirated cargo (CARGO_FLAG_PIRATE)"); cargo_to_go = likely_cargo; @@ -4005,19 +4005,19 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple cargo_chance = 65; // 35% chance of spoilage jetsam = [universe getContainersOfScarceGoods:cargo_to_go]; break; - + case CARGO_FLAG_FULL_SCARCE : // NSLog(@"DEBUG dropping scarce cargo (CARGO_FLAG_FULL_SCARCE)"); jetsam = [universe getContainersOfScarceGoods:cargo_to_go]; break; - + case CARGO_FLAG_CANISTERS: // NSLog(@"DEBUG dropping ship's scooped cargo (CARGO_FLAG_CANISTERS)"); jetsam = [NSArray arrayWithArray:cargo]; // what the ship is carrying [cargo removeAllObjects]; // dispense with it! break; } - + if (jetsam) { for (i = 0; i < [jetsam count]; i++) @@ -4089,7 +4089,7 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple [universe removeEntity:self]; return; // don't do anything more } - + if ([roles isEqual:@"boulder"]) { if ((being_mined)||(ranrot_rand() % 100 < 20)) @@ -4302,22 +4302,22 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q Vector xposition = position; ParticleEntity *fragment; int n_cargo = (ranrot_rand() % (likely_cargo + 1)); - + if (status == STATUS_DEAD) return; - + status = STATUS_DEAD; //scripting if ([death_actions count]) { PlayerEntity* player = (PlayerEntity *)[universe entityZero]; - + [player setScript_target:self]; [player scriptActions: death_actions forTarget: self]; - + [death_actions removeAllObjects]; } - + // two parts to the explosion: // 1. fast sparks float how_many = factor; @@ -4335,11 +4335,11 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q { fragment = [[ParticleEntity alloc] initBurst2Size: collision_radius FromPosition:xposition]; [universe addEntity:fragment]; - [fragment release]; + [fragment release]; how_many -= 1.0f; } - - + + // we need to throw out cargo at this point. int cargo_chance = 10; if ([[name lowercaseString] rangeOfString:@"medical"].location != NSNotFound) @@ -4392,7 +4392,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q [cargo removeObjectAtIndex:0]; } // - + if (!isPlayer) [universe removeEntity:self]; } @@ -4523,11 +4523,11 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q mult_vector_gl_matrix(&my_ref, r_mat); Vector pos = father->position; my_position.x += pos.x; my_position.y += pos.y; my_position.z += pos.z; - + father = [father owner]; r_mat = [father drawRotationMatrix]; } - + if (targent) { vector_to_target = targent->position; @@ -4537,7 +4537,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q vector_to_target = unit_vector(&vector_to_target); else vector_to_target.z = 1.0; - // + // // do the tracking! aim_cos = dot_product(vector_to_target, my_aim); ref_cos = dot_product(vector_to_target, my_ref); @@ -4550,7 +4550,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q // //NSLog(@"DEBUG ball_tracking vtt (%.2f,%.2f,%.2f)", vector_to_target.x, vector_to_target.y, vector_to_target.z); //NSLog(@"DEBUG ball_tracking target %@ aim_cos = %.3f ref_cos = %.3f", [(ShipEntity *)targent name], aim_cos, ref_cos); - + if (ref_cos > TURRET_MINIMUM_COS) // target is forward of self { axis_to_track_by = cross_product(vector_to_target, my_aim); @@ -4560,14 +4560,14 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q aim_cos = 0.0; axis_to_track_by = cross_product(my_ref, my_aim); // return to center } - + quaternion_rotate_about_axis( &q_rotation, axis_to_track_by, thrust * delta_t); - + quaternion_normalise(&q_rotation); quaternion_into_gl_matrix(q_rotation, rotMatrix); - + status = STATUS_ACTIVE; - + return aim_cos; } @@ -4580,7 +4580,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q // if (!targent) return; - + vector_to_target = targent->position; vector_to_target.x -= position.x; vector_to_target.y -= position.y; vector_to_target.z -= position.z; // @@ -4595,7 +4595,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q vector_to_target = unit_vector(&vector_to_target); else vector_to_target.z = 1.0; - // + // q_minarc = quaternion_rotation_between( v_forward, vector_to_target); // q_rotation = quaternion_multiply( q_minarc, q_rotation); @@ -4630,11 +4630,11 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q mult_vector_gl_matrix(&my_ref, r_mat); Vector pos = father->position; my_position.x += pos.x; my_position.y += pos.y; my_position.z += pos.z; - + father = [father owner]; r_mat = [father drawRotationMatrix]; } - + if (targent) { vector_to_target = targent->position; @@ -4648,7 +4648,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q vector_to_target = unit_vector(&vector_to_target); else vector_to_target.z = 1.0; - // + // // do the tracking! aim_cos = dot_product(vector_to_target, my_aim); ref_cos = dot_product(vector_to_target, my_ref); @@ -4661,7 +4661,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q // //NSLog(@"DEBUG ball_tracking vtt (%.2f,%.2f,%.2f)", vector_to_target.x, vector_to_target.y, vector_to_target.z); //NSLog(@"DEBUG ball_tracking target %@ aim_cos = %.3f ref_cos = %.3f", [(ShipEntity *)targent name], aim_cos, ref_cos); - + if (ref_cos > TURRET_MINIMUM_COS) // target is forward of self { axis_to_track_by = cross_product(vector_to_target, my_aim); @@ -4671,14 +4671,14 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q aim_cos = 0.0; axis_to_track_by = cross_product(my_ref, my_aim); // return to center } - + quaternion_rotate_about_axis( &q_rotation, axis_to_track_by, thrust * delta_t); - + quaternion_normalise(&q_rotation); quaternion_into_gl_matrix(q_rotation, rotMatrix); - + status = STATUS_ACTIVE; - + return aim_cos; } @@ -4686,31 +4686,31 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q - (double) trackPrimaryTarget:(double) delta_t :(BOOL) retreat { Entity* target = [self getPrimaryTarget]; - + if (!target) // leave now! { [shipAI message:@"TARGET_LOST"]; return 0.0; } - + if (scan_class == CLASS_MISSILE) return [self missileTrackPrimaryTarget: delta_t]; - + GLfloat d_forward, d_up, d_right; - Vector relativePosition = target->position; + Vector relativePosition = target->position; relativePosition.x -= position.x; relativePosition.y -= position.y; relativePosition.z -= position.z; double range2 = magnitude2(relativePosition); - + if (range2 > SCANNER_MAX_RANGE2) { [shipAI message:@"TARGET_LOST"]; return 0.0; } - + //jink if retreating if (retreat && (range2 > 250000.0)) // don't jink if closer than 500m - just RUN { @@ -4738,37 +4738,37 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q relativePosition = unit_vector(&relativePosition); else relativePosition.z = 1.0; - + double targetRadius = 0.75 * target->actual_radius; - + double max_cos = sqrt(1 - targetRadius*targetRadius/range2); - + double damping = 0.5 * delta_t; double rate2 = 4.0 * delta_t; double rate1 = 2.0 * delta_t; - + double stick_roll = 0.0; //desired roll and pitch double stick_pitch = 0.0; - + double reverse = (retreat)? -1.0: 1.0; - + double min_d = 0.004; - + d_right = dot_product(relativePosition, v_right); d_up = dot_product(relativePosition, v_up); d_forward = dot_product(relativePosition, v_forward); // == cos of angle between v_forward and vector to target if (d_forward * reverse > max_cos) // on_target! return d_forward; - + // begin rule-of-thumb manoeuvres stick_pitch = 0.0; stick_roll = 0.0; - - + + if ((reverse * d_forward < -0.5) && !pitching_over) // we're going the wrong way! pitching_over = YES; - + if (pitching_over) { if (reverse * d_up > 0) // pitch up @@ -4784,7 +4784,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q NSLog(@"missile %@ in tracking mode", self); [self trackOntoTarget: delta_t withDForward: d_forward]; return d_forward; - } + } // check if we are flying toward the destination.. if ((d_forward < max_cos)||(retreat)) // not on course so we must adjust controls.. @@ -4793,7 +4793,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q { d_up = min_d * 2.0; } - + if (d_up > min_d) { int factor = sqrt( fabs(d_right) / fabs(min_d)); @@ -4814,7 +4814,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q if (d_right < -min_d) stick_roll = - max_flight_roll * reverse * 0.125 * factor; } - + if (stick_roll == 0.0) { int factor = sqrt( fabs(d_up) / fabs(min_d)); @@ -4826,7 +4826,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q stick_pitch = + max_flight_pitch * reverse * 0.125 * factor; } } - + // end rule-of-thumb manoeuvres // apply stick movement limits @@ -4849,7 +4849,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q flight_pitch += (flight_pitch < -damping) ? damping : -flight_pitch; if (flight_pitch > 0) flight_pitch -= (flight_pitch > damping) ? damping : flight_pitch; - + // apply stick to attitude control flight_roll = stick_roll; flight_pitch = stick_pitch; @@ -4859,54 +4859,54 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q if (d_forward < 0.0) return 0.0; - + if ((!flight_roll)&&(!flight_pitch)) // no correction return 1.0; - + return d_forward; } - (double) missileTrackPrimaryTarget:(double) delta_t { - Vector relativePosition; + Vector relativePosition; GLfloat d_forward, d_up, d_right, range2; Entity *target = [self getPrimaryTarget]; - + if (!target) // leave now! return 0.0; - + double damping = 0.5 * delta_t; double rate2 = 4.0 * delta_t; double rate1 = 2.0 * delta_t; - + double stick_roll = 0.0; //desired roll and pitch double stick_pitch = 0.0; - + double tolerance1 = pitch_tolerance; - + relativePosition = target->position; relativePosition.x -= position.x; relativePosition.y -= position.y; relativePosition.z -= position.z; - + range2 = magnitude2(relativePosition); - + if (relativePosition.x||relativePosition.y||relativePosition.z) relativePosition = unit_vector(&relativePosition); else relativePosition.z = 1.0; - + d_right = dot_product(relativePosition, v_right); // = cosine of angle between angle to target and v_right d_up = dot_product(relativePosition, v_up); // = cosine of angle between angle to target and v_up d_forward = dot_product(relativePosition, v_forward); // = cosine of angle between angle to target and v_forward // begin rule-of-thumb manoeuvres - + stick_roll = 0.0; - + if (pitching_over) pitching_over = (stick_pitch != 0.0); - + if ((d_forward < -tolerance1) && (!pitching_over)) { pitching_over = YES; @@ -4915,7 +4915,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q if (d_up < 0) stick_pitch = max_flight_pitch; } - + if (pitching_over) { pitching_over = (d_forward < 0.5); @@ -4925,7 +4925,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q stick_pitch = -max_flight_pitch * d_up; stick_roll = -max_flight_roll * d_right; } - + // end rule-of-thumb manoeuvres // apply damping @@ -4947,11 +4947,11 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q stick_pitch = flight_pitch + rate2; if (flight_pitch - rate2 > stick_pitch) stick_pitch = flight_pitch - rate2; - + // apply stick to attitude flight_roll = stick_roll; flight_pitch = stick_pitch; - + // // return target confidence 0.0 .. 1.0 // @@ -4962,43 +4962,43 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q - (double) trackDestination:(double) delta_t :(BOOL) retreat { - Vector relativePosition; + Vector relativePosition; GLfloat d_forward, d_up, d_right; - + BOOL we_are_docking = (nil != dockingInstructions); - + double damping = 0.5 * delta_t; double rate2 = 4.0 * delta_t; double rate1 = 2.0 * delta_t; - + double stick_roll = 0.0; //desired roll and pitch double stick_pitch = 0.0; - + double reverse = 1.0; - + double min_d = 0.004; double max_cos = 0.85; - + if (retreat) reverse = -reverse; if (isPlayer) reverse = -reverse; - + relativePosition = destination; relativePosition.x -= position.x; relativePosition.y -= position.y; relativePosition.z -= position.z; - + double range2 = magnitude2(relativePosition); max_cos = sqrt(1 - desired_range*desired_range/range2); - + if (relativePosition.x||relativePosition.y||relativePosition.z) relativePosition = unit_vector(&relativePosition); else relativePosition.z = 1.0; - + d_right = dot_product(relativePosition, v_right); d_up = dot_product(relativePosition, v_up); d_forward = dot_product(relativePosition, v_forward); // == cos of angle between v_forward and vector to target @@ -5006,19 +5006,19 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q // begin rule-of-thumb manoeuvres stick_pitch = 0.0; stick_roll = 0.0; - + // if (isPlayer) // NSLog(@"DEBUG trackDestination:: max_cos %.4f, d_forward %.4f, we_are_docking %@", max_cos, d_forward, (we_are_docking)? @":YES:" : @":NO:"); - + // check if we are flying toward the destination.. if ((d_forward < max_cos)||(retreat)) // not on course so we must adjust controls.. { - + if (d_forward < -max_cos) // hack to avoid just flying away from the destination { d_up = min_d * 2.0; } - + if (d_up > min_d) { int factor = sqrt( fabs(d_right) / fabs(min_d)); @@ -5039,7 +5039,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q if (d_right < -min_d) stick_roll = - max_flight_roll * reverse * 0.125 * factor; //roll_roll * reverse; } - + if (stick_roll == 0.0) { int factor = sqrt( fabs(d_up) / fabs(min_d)); @@ -5051,35 +5051,35 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q stick_pitch = + max_flight_pitch * reverse * 0.125 * factor; //pitch_pitch * reverse; } } - + if (we_are_docking && docking_match_rotation && (d_forward > max_cos)) { /* we are docking and need to consider the rotation/orientation of the docking port */ - + // NSLog(@"DEBUG DOCKING MATCH ROTATION %@ targetStation = %d %@ primaryTarget = %d %@", // self, targetStation, [universe entityForUniversalID:targetStation], primaryTarget, [universe entityForUniversalID:primaryTarget]); StationEntity* station_for_docking = (StationEntity*)[universe entityForUniversalID:targetStation]; - + if ((station_for_docking)&&(station_for_docking->isStation)) { Vector up_vec = [station_for_docking portUpVector]; double cosTheta = dot_product(up_vec, v_up); // == cos of angle between up vectors double sinTheta = dot_product(up_vec, v_right); - + double station_roll = [station_for_docking flight_roll]; - + if (!isPlayer) { station_roll = -station_roll; // make necessary corrections for a different viewpoint sinTheta = -sinTheta; } - + if (cosTheta < 0) { cosTheta = -cosTheta; sinTheta = -sinTheta; } - + if (sinTheta > 0.0) { // increase roll rate @@ -5095,7 +5095,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q // self, [self getPrimaryTarget], cosTheta, sinTheta, station_roll, stick_roll); } } - + // end rule-of-thumb manoeuvres // apply stick movement limits @@ -5121,7 +5121,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q flight_pitch += (flight_pitch < -damping) ? damping : -flight_pitch; if (flight_pitch > 0) flight_pitch -= (flight_pitch > damping) ? damping : flight_pitch; - + // apply stick to attitude control flight_roll = stick_roll; flight_pitch = stick_pitch; @@ -5131,10 +5131,10 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q if (d_forward < 0.0) return 0.0; - + if ((!flight_roll)&&(!flight_pitch)) // no correction return 1.0; - + return d_forward; } @@ -5228,7 +5228,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q [self firePlasmaShot:weapon_offset_x:1500.0:[OOColor yellowColor]]; fired = YES; break; - + case WEAPON_PULSE_LASER : case WEAPON_BEAM_LASER : case WEAPON_MINING_LASER : @@ -5236,27 +5236,27 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q [self fireLaserShotInDirection: VIEW_FORWARD]; fired = YES; break; - + case WEAPON_THARGOID_LASER : [self fireDirectLaserShot]; fired = YES; break; - + } - + //can we fire lasers from our subentities? int n_subs = [sub_entities count]; if (n_subs) { int i = 0; for (i = 0; i < n_subs; i++) - { + { ShipEntity* subent = (ShipEntity*)[sub_entities objectAtIndex:i]; if ((subent)&&(subent->isShip)) fired |= [subent fireSubentityLaserShot: range]; } } - + return fired; } @@ -5275,7 +5275,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q [self set_weapon_data_from_type:aft_weapon_type]; // // - + //NSLog(@"DEBUG %@ should fire aft weapon",name); if (shot_time < weapon_recharge_rate) @@ -5284,7 +5284,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q return NO; if (range > randf() * weapon_range) return NO; - + //NSLog(@"DEBUG %@ firing aft weapon",name); if (result) @@ -5301,7 +5301,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q [self fireDirectLaserShot]; return YES; break; - + } } // @@ -5338,19 +5338,19 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q double start = collision_radius + 0.5; double speed = TURRET_SHOT_SPEED; OOColor* color = laser_color; - + origin.x += vel.x * start; origin.y += vel.y * start; origin.z += vel.z * start; - + vel.x *= speed; vel.y *= speed; vel.z *= speed; - + // vel.x += vel_father.x; // vel.y += vel_father.y; // vel.z += vel_father.z; -// +// shot = [[ParticleEntity alloc] init]; // alloc retains! [shot setPosition:origin]; // directly ahead [shot setScanClass: CLASS_NO_DRAW]; @@ -5362,12 +5362,12 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q [shot setColor:color]; [shot setSize:NSMakeSize(12,12)]; [universe addEntity:shot]; - + [shot setOwner:[self owner]]; // has to be done AFTER adding shot to the universe // NSLog(@"DEBUG Plasma cannon shot owner is %@", [shot owner]); - + [shot release]; //release - + shot_time = 0.0; return YES; } @@ -5388,24 +5388,24 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q int direction = VIEW_FORWARD; GLfloat hit_at_range; target_laser_hit = NO_TARGET; - + if (forward_weapon_type == WEAPON_NONE) return NO; [self set_weapon_data_from_type:forward_weapon_type]; ShipEntity* parent = (ShipEntity*)[self owner]; - + if (shot_time < weapon_recharge_rate) return NO; - + if (range > weapon_range) return NO; - + hit_at_range = weapon_range; target_laser_hit = [universe getFirstEntityHitByLaserFromEntity:self inView:direction offset: make_vector(0,0,0) rangeFound: &hit_at_range]; - + // NSLog(@"DEBUG target hit by SubEntityLaserShot: %d %@", target_laser_hit, [universe entityForUniversalID:target_laser_hit]); - + shot = [[ParticleEntity alloc] initLaserFromSubentity:self view:direction]; // alloc retains! [shot setColor:laser_color]; [shot setScanClass: CLASS_NO_DRAW]; @@ -5418,7 +5418,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q Vector p1 = victim->position; if (victim->isShip) { - ShipEntity* ship_hit = ((ShipEntity*)victim); + ShipEntity* ship_hit = ((ShipEntity*)victim); ShipEntity* subent = ship_hit->subentity_taking_damage; if ((subent) && [ship_hit->sub_entities containsObject:subent]) { @@ -5437,7 +5437,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q { [(ShipEntity *)victim takeEnergyDamage:weapon_energy from:self becauseOf:parent]; // a very palpable hit // [shot setCollisionRadius:sqrt(dist2)]; // so it's drawn to the right size - + // calculate where to draw flash // double cr = shot->collision_radius - victim->collision_radius; double cr = hit_at_range; @@ -5454,16 +5454,16 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q } [universe addEntity:shot]; [shot release]; //release - + shot_time = 0.0; - + return YES; } - (BOOL) fireDirectLaserShot { // NSLog(@"DEBUG %@ %d laser fired direct shot on %@ %d", name, universal_id, [(ShipEntity*)[self getPrimaryTarget] name], primaryTarget); - + GLfloat hit_at_range; Entity* my_target = [self getPrimaryTarget]; if (!my_target) @@ -5484,7 +5484,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q q_laser.y += 0.01 * (randf() - 0.5); q_laser.z += 0.01 * (randf() - 0.5); quaternion_normalise(&q_laser); - + Quaternion q_save = q_rotation; // save rotation q_rotation = q_laser; // face in direction of laser target_laser_hit = [universe getFirstEntityHitByLaserFromEntity:self inView:VIEW_FORWARD offset: make_vector(0,0,0) rangeFound: &hit_at_range]; @@ -5519,7 +5519,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q } } } - + if (victim) { Vector p0 = shot->position; @@ -5547,13 +5547,13 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q } [universe addEntity:shot]; [shot release]; //release - + shot_time = 0.0; - + // random laser over-heating for AI ships if ((!isPlayer)&&((ranrot_rand() & 255) < weapon_energy)&&(![self isMining])) shot_time -= (randf() * weapon_energy); - + return YES; } @@ -5564,13 +5564,13 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q GLfloat hit_at_range; Vector vel; target_laser_hit = NO_TARGET; - + vel.x = v_forward.x * flight_speed; vel.y = v_forward.y * flight_speed; vel.z = v_forward.z * flight_speed; Vector laserPortOffset = forwardWeaponOffset; - + switch(direction) { case VIEW_AFT: @@ -5587,19 +5587,19 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q } target_laser_hit = [universe getFirstEntityHitByLaserFromEntity:self inView:direction offset:laserPortOffset rangeFound: &hit_at_range]; - + // if (isPlayer) // NSLog(@"DEBUG target double-check range = %.2f victim = %d --> %@\n\n", hit_at_range, target_laser_hit, [universe entityForUniversalID:target_laser_hit]); - + shot = [[ParticleEntity alloc] initLaserFromShip:self view:direction offset:laserPortOffset]; // alloc retains! - + [shot setColor:laser_color]; [shot setScanClass: CLASS_NO_DRAW]; [shot setVelocity: vel]; if (target_laser_hit != NO_TARGET) { Entity *victim = [universe entityForUniversalID:target_laser_hit]; - + if ((victim) && (victim->isShip)) { ShipEntity* parent = (ShipEntity*)[victim owner]; @@ -5609,16 +5609,16 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q victim = parent; } } - + if (victim) { Vector p0 = shot->position; Vector p1 = victim->position; p1.x -= p0.x; p1.y -= p0.y; p1.z -= p0.z; - + if (victim->isShip) { - ShipEntity* ship_hit = ((ShipEntity*)victim); + ShipEntity* ship_hit = ((ShipEntity*)victim); ShipEntity* subent = ship_hit->subentity_taking_damage; if ((subent) && [ship_hit->sub_entities containsObject:subent]) { @@ -5638,10 +5638,10 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q [(ShipEntity *)victim takeEnergyDamage:weapon_energy from:self becauseOf:self]; // a very palpable hit GLfloat cr = hit_at_range; - + // if (isPlayer) // NSLog(@"DEBUG distance double check = %.2f", cr); - + [shot setCollisionRadius: cr]; Vector vd = vector_forward_from_quaternion(shot->q_rotation); Vector p0 = shot->position; @@ -5655,13 +5655,13 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q } [universe addEntity:shot]; [shot release]; //release - + shot_time = 0.0; - + // random laser over-heating for AI ships if ((!isPlayer)&&((ranrot_rand() & 255) < weapon_energy)&&(![self isMining])) shot_time -= (randf() * weapon_energy); - + return YES; } @@ -5670,11 +5670,11 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q ParticleEntity* spark; Vector vel; Vector origin = position; - + GLfloat lr = randf() * (boundingBox.max.x - boundingBox.min.x) + boundingBox.min.x; GLfloat ud = randf() * (boundingBox.max.y - boundingBox.min.y) + boundingBox.min.y; GLfloat fb = randf() * boundingBox.max.z + boundingBox.min.z; // rear section only - + origin.x += fb * v_forward.x; origin.y += fb * v_forward.y; origin.z += fb * v_forward.z; @@ -5686,15 +5686,15 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q origin.x += lr * v_right.x; origin.y += lr * v_right.y; origin.z += lr * v_right.z; - + float w = boundingBox.max.x - boundingBox.min.x; float h = boundingBox.max.y - boundingBox.min.y; float m = (w < h) ? 0.25 * w: 0.25 * h; - + float sz = m * (1 + randf() + randf()); // half minimum dimension on average - + vel = make_vector( 2.0 * (origin.x - position.x), 2.0 * (origin.y - position.y), 2.0 * (origin.z - position.z)); - + spark = [[ParticleEntity alloc] init]; // alloc retains! [spark setPosition:origin]; // directly ahead [spark setScanClass: CLASS_NO_DRAW]; @@ -5708,7 +5708,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q [spark setOwner:self]; [universe addEntity:spark]; [spark release]; //release - + next_spark_time = randf(); } @@ -5718,15 +5718,15 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q Vector vel, rt; Vector origin = position; double start = collision_radius + 0.5; - + speed += flight_speed; if (++shot_counter % 2) offset = -offset; - + vel = v_forward; rt = v_right; - + if (isPlayer) // player can fire into multiple views! { switch ([universe viewDir]) @@ -5749,19 +5749,19 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q break; } } - + origin.x += vel.x * start; origin.y += vel.y * start; origin.z += vel.z * start; - + origin.x += rt.x * offset; origin.y += rt.y * offset; origin.z += rt.z * offset; - + vel.x *= speed; vel.y *= speed; vel.z *= speed; - + shot = [[ParticleEntity alloc] init]; // alloc retains! [shot setPosition:origin]; // directly ahead [shot setScanClass: CLASS_NO_DRAW]; @@ -5774,9 +5774,9 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q [shot setOwner:self]; [universe addEntity:shot]; [shot release]; //release - + shot_time = 0.0; - + return YES; } @@ -5786,7 +5786,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q Vector vel; Vector origin = position; Vector start, v_eject; - + // default launching position start.x = 0.0; // in the middle start.y = boundingBox.min.y - 4.0; // 4m below bounding box @@ -5796,18 +5796,18 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q { start = [Entity vectorFromString:(NSString *)[shipinfoDictionary objectForKey:@"missile_launch_position"]]; } - + double throw_speed = 250.0; Quaternion q1 = q_rotation; Entity *target = [self getPrimaryTarget]; - + if ((missiles <= 0)||(target == nil)||(target->scan_class == CLASS_NO_DRAW)|| ((target->isShip)&&(!has_military_scanner_filter)&&([(ShipEntity*)target isJammingScanning]))) // no missile lock! return NO; - + // if (scan_class == CLASS_THARGOID) // return [self fireTharglet]; - + // custom missiles if ([shipinfoDictionary objectForKey:@"missile_role"]) missile = [universe getShipWithRole:(NSString*)[shipinfoDictionary objectForKey:@"missile_role"]]; @@ -5818,18 +5818,18 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q else // otherwise choose any with the role 'missile' - which may include alternative weapons missile = [universe getShipWithRole:@"missile"]; // retained } - + if (!missile) return NO; - + missiles--; - + double mcr = missile->collision_radius; v_eject = unit_vector( &start); - + vel = make_vector( 0.0f, 0.0f, 0.0f); // starting velocity - + // check if start is within bounding box... while ( (start.x > boundingBox.min.x - mcr)&&(start.x < boundingBox.max.x + mcr)&& (start.y > boundingBox.min.y - mcr)&&(start.y < boundingBox.max.y + mcr)&& @@ -5838,18 +5838,18 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q start.x += mcr * v_eject.x; start.y += mcr * v_eject.y; start.z += mcr * v_eject.z; vel.x += 10.0f * mcr * v_eject.x; vel.y += 10.0f * mcr * v_eject.y; vel.z += 10.0f * mcr * v_eject.z; // throw it outward a bit harder } - + if (isPlayer) q1.w = -q1.w; // player view is reversed remember! - + vel.x += (flight_speed + throw_speed) * v_forward.x; vel.y += (flight_speed + throw_speed) * v_forward.y; vel.z += (flight_speed + throw_speed) * v_forward.z; - + origin.x = position.x + v_right.x * start.x + v_up.x * start.y + v_forward.x * start.z; origin.y = position.y + v_right.y * start.x + v_up.y * start.y + v_forward.y * start.z; origin.z = position.z + v_right.z * start.x + v_up.z * start.y + v_forward.z * start.z; - + [missile addTarget: target]; [missile setOwner: self]; [missile setGroup_id: group_id]; @@ -5863,13 +5863,13 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q [universe addEntity: missile]; // [missile release]; //release - + if ([missile scanClass] == CLASS_MISSILE) { [(ShipEntity *)target setPrimaryAggressor:self]; [[(ShipEntity *)target getAI] reactToMessage:@"INCOMING_MISSILE"]; } - + return YES; } @@ -5885,23 +5885,23 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q // double throw_speed = 500.0; // Quaternion q1 = q_rotation; // Entity *target = [self getPrimaryTarget]; -// +// // if ((missiles <= 0)||(target == nil)) // return NO; -// +// // missiles--; -// +// // if (isPlayer) // q1.w = -q1.w; // player view is reversed remember! -// +// // vel.x = (flight_speed + throw_speed) * v_forward.x; // vel.y = (flight_speed + throw_speed) * v_forward.y; // vel.z = (flight_speed + throw_speed) * v_forward.z; -// +// // origin.x = position.x + v_right.x * start.x + v_up.x * start.y + v_forward.x * start.z; // origin.y = position.y + v_right.y * start.x + v_up.y * start.y + v_forward.y * start.z; // origin.z = position.z + v_right.z * start.x + v_up.z * start.y + v_forward.z * start.z; -// +// // tharglet = [universe getShipWithRole:@"tharglet"]; // retain count = 1 // if (tharglet) // { @@ -5916,11 +5916,11 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q // //[tharglet setReportAImessages:YES]; // debug // [universe addEntity:tharglet]; // //NSLog(@"tharglet collision radius is %.1f",tharglet->collision_radius); -// +// // [tharglet setGroup_id:group_id]; -// +// // [tharglet release]; //release -// +// // return YES; // } // return NO; @@ -6009,7 +6009,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q - (int) launchEscapeCapsule { ShipEntity *pod; - + pod = [universe getShipWithRole:@"escape-capsule"]; // retain count = 1 if (pod) { @@ -6035,7 +6035,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q { if (status == STATUS_DEAD) return 0; - + int result = CARGO_NOT_CARGO; if (([cargo count] > 0)&&([universe getTime] - cargo_dump_time > 0.5)) // space them 0.5s or 10m apart { @@ -6072,15 +6072,15 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q start.x = 0.0; // in the middle start.y = 0.0; // start.z = boundingBox.min.z - jcr; // 1m behind of bounding box - + // custom launching position if ([shipinfoDictionary objectForKey:@"aft_eject_position"]) { start = [Entity vectorFromString:(NSString *)[shipinfoDictionary objectForKey:@"aft_eject_position"]]; - } - + } + v_eject = unit_vector( &start); - + // check if start is within bounding box... while ( (start.x > boundingBox.min.x - jcr)&&(start.x < boundingBox.max.x + jcr)&& (start.y > boundingBox.min.y - jcr)&&(start.y < boundingBox.max.y + jcr)&& @@ -6088,29 +6088,29 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q { start.x += jcr * v_eject.x; start.y += jcr * v_eject.y; start.z += jcr * v_eject.z; } - + v_eject = make_vector( v_right.x * start.x + v_up.x * start.y + v_forward.x * start.z, v_right.y * start.x + v_up.y * start.y + v_forward.y * start.z, v_right.z * start.x + v_up.z * start.y + v_forward.z * start.z); - + rpos.x += v_eject.x; rpos.y += v_eject.y; rpos.z += v_eject.z; - + v_eject = unit_vector( &v_eject); - + v_eject.x += (randf() - randf())/eject_speed; v_eject.y += (randf() - randf())/eject_speed; v_eject.z += (randf() - randf())/eject_speed; - + vel.x = v_forward.x * flight_speed + v_eject.x * eject_speed; vel.y = v_forward.y * flight_speed + v_eject.y * eject_speed; vel.z = v_forward.z * flight_speed + v_eject.z * eject_speed; - + velocity.x += v_eject.x * eject_reaction; velocity.y += v_eject.y * eject_reaction; velocity.z += v_eject.z * eject_reaction; - + [jetto setPosition:rpos]; [jetto setQRotation:random_direction]; [jetto setRoll:random_roll]; @@ -6166,21 +6166,21 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q } [ent release]; } - } + } } - (BOOL) collideWithShip:(ShipEntity *)other { Vector loc, opos, pos; double inc1, dam1, dam2; - + // NSLog(@"DEBUG %@ %d colliding with other %@ %d", name, universal_id, [other name], [other universal_id]); if (!other) return NO; - + ShipEntity* otherParent = (ShipEntity*)[other owner]; BOOL otherIsSubentity = ((otherParent)&&(otherParent != other)&&([otherParent->sub_entities containsObject:other])); - + // calculate line of centers using centres if (otherIsSubentity) opos = [other absolutePositionForSubentity]; @@ -6188,14 +6188,14 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q opos = other->position; loc = opos; loc.x -= position.x; loc.y -= position.y; loc.z -= position.z; - + if (loc.x||loc.y||loc.z) loc = unit_vector(&loc); else loc.z = 1.0; - + inc1 = (v_forward.x*loc.x)+(v_forward.y*loc.y)+(v_forward.z*loc.z); - + if ([self canScoop:other]) { [self scoopIn:other]; @@ -6210,9 +6210,9 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q return NO; if (other->universal_id == NO_TARGET) return NO; - + // find velocity along line of centers - // + // // momentum = mass x velocity // ke = mass x velocity x velocity // @@ -6220,7 +6220,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q GLfloat m2 = [other mass]; // mass of other // starting velocities: - Vector vel1b = [self getVelocity]; + Vector vel1b = [self getVelocity]; // calculate other's velocity relative to self Vector v = [other getVelocity]; if (otherIsSubentity) @@ -6235,17 +6235,17 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q else v = make_vector( 0.0f, 0.0f, 0.0f); } - + // v = make_vector( vel1b.x - v.x, vel1b.y - v.y, vel1b.z - v.z); // velocity of self relative to other - + // GLfloat v2b = dot_product( v, loc); // velocity of other along loc before collision // GLfloat v1a = sqrt(v2b * v2b * m2 / m1); // velocity of self along loc after elastic collision if (v2b < 0.0f) v1a = -v1a; // in same direction as v2b - - + + // are they moving apart at over 1m/s already? if (v2b < 0.0f) { @@ -6266,29 +6266,29 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q // NSLog(@"MOVING CLOSER %@ >%.3f %.3f< %@", self, sqrt(distance2(position, opos)), v2b, other); // } // - + // convert change in velocity into damage energy (KE) // dam1 = m2 * v2b * v2b / 50000000; dam2 = m1 * v2b * v2b / 50000000; - + // calculate adjustments to velocity after collision Vector vel1a = make_vector( -v1a * loc.x, -v1a * loc.y, -v1a * loc.z); Vector vel2a = make_vector( v2b * loc.x, v2b * loc.y, v2b * loc.z); - + if (magnitude2(v) <= 0.1) // virtually no relative velocity - we must provide at least 1m/s to avoid conjoined objects { vel1a = make_vector( -loc.x, -loc.y, -loc.z); vel2a = make_vector( loc.x, loc.y, loc.z); } - + // apply change in velocity if ((otherIsSubentity)&&(otherParent)) [otherParent adjustVelocity:vel1a]; // move the otherParent not the subentity else [self adjustVelocity:vel1a]; [other adjustVelocity:vel2a]; - + // // BOOL selfDestroyed = (dam1 > energy); @@ -6316,7 +6316,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q [other adjustVelocity:vel1a]; } } - + // NSLog(@"DEBUG back-off distance is %.3fm\n\n", back_dist); // if ((!selfDestroyed)&&(!otherDestroyed)) @@ -6326,22 +6326,22 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q pos = self->position; opos = other->position; // - Vector pos1a = make_vector(pos.x + t * v1a * loc.x, pos.y + t * v1a * loc.y, pos.z + t * v1a * loc.z); + Vector pos1a = make_vector(pos.x + t * v1a * loc.x, pos.y + t * v1a * loc.y, pos.z + t * v1a * loc.z); Vector pos2a = make_vector(opos.x - t * v2b * loc.x, opos.y - t * v2b * loc.y, opos.z - t * v2b * loc.z); // [self setPosition:pos1a]; [other setPosition:pos2a]; } - + // // remove self from other's collision list // [[other collisionArray] removeObject:self]; // //// - + [shipAI reactToMessage:@"COLLISION"]; - + return YES; } @@ -6361,8 +6361,8 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q - (void) addImpactMoment:(Vector) moment fraction:(GLfloat) howmuch { - velocity.x += howmuch * moment.x / mass; - velocity.y += howmuch * moment.y / mass; + velocity.x += howmuch * moment.x / mass; + velocity.y += howmuch * moment.y / mass; velocity.z += howmuch * moment.z / mass; } @@ -6384,7 +6384,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q return NO; Vector loc = vector_between( position, other->position); - + GLfloat inc1 = (v_forward.x*loc.x)+(v_forward.y*loc.y)+(v_forward.z*loc.z); if (inc1 < 0.0f) return NO; GLfloat inc2 = (v_up.x*loc.x)+(v_up.y*loc.y)+(v_up.z*loc.z); @@ -6446,10 +6446,10 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q if ([actions count]) { PlayerEntity* player = (PlayerEntity *)[universe entityZero]; - + [player setScript_target:self]; [player scriptActions: actions forTarget: other]; - + } // NSLog(@"DEBUG Scooped scripted item %@ %@ %d", other, [other name], [other universal_id]); if (isPlayer) @@ -6492,15 +6492,15 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q { if (status == STATUS_DEAD) // it's too late for this one! return; - + if ([universe station] == self) // main stations are indestructible return; - + if (status == STATUS_LAUNCHING) // no collisions during launches please return; if ((ent)&&(ent->status == STATUS_LAUNCHING)) // no collisions during launches please return; - + // energy -= amount; // oops we hit too hard!!! @@ -6536,9 +6536,9 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q return; energy -= amount; - + throw_sparks = YES; - + // oops we're burning up! if (energy <= 0.0) [self becomeExplosion]; @@ -6556,7 +6556,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q if (dockingInstructions) [dockingInstructions autorelease]; dockingInstructions = nil; - + [shipAI message:@"DOCKED"]; [station noteDockedShip:self]; [universe removeEntity:self]; @@ -6586,7 +6586,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q { if (![[universe sun] willGoNova]) // if the sun's not going nova [universe witchspaceShipWithRole:roles]; // then add a new ship like this one leaving! - + [w_hole suckInShip: self]; // removes ship from universe } @@ -6600,12 +6600,12 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q [ring2 setSize:NSMakeSize([ring2 size].width * -2.5 ,[ring2 size].height * -2.0 )]; // shrinking! [universe addEntity:ring2]; [ring2 release]; - + [shipAI message:@"ENTERED_WITCHSPACE"]; - + if (![[universe sun] willGoNova]) // if the sun's not going nova [universe witchspaceShipWithRole:roles]; // then add a new ship like this one leaving! - + [universe removeEntity:self]; } @@ -6631,9 +6631,9 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q status = STATUS_LAUNCHING; [shipAI message:@"EXITED_WITCHSPACE"]; [universe addEntity:self]; - + //NSLog(@"DEBUG Ship: %@ %d exiting witchspace now!", name, universal_id); - + // witchspace exit effects here ParticleEntity *ring1 = [[ParticleEntity alloc] initHyperringFromShip:self]; // retained [universe addEntity:ring1]; @@ -6690,34 +6690,34 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q inline BOOL pairOK(NSString* my_role, NSString* their_role) { BOOL pairing_okay = NO; - + pairing_okay |= (![my_role isEqual:@"escort"] && ![my_role isEqual:@"wingman"] && [their_role isEqual:@"escort"]); pairing_okay |= (([my_role isEqual:@"police"]||[my_role isEqual:@"interceptor"]) && [their_role isEqual:@"wingman"]); - + // NSLog(@"checking if pairOK for ( %@, %@) >> %@", my_role, their_role, (pairing_okay)? @"YES":@"NO"); - + return pairing_okay; } - (BOOL) acceptAsEscort:(ShipEntity *) other_ship -{ +{ // can't pair with self if (self == other_ship) return NO; - + // NSLog(@"DEBUG %@ %d asked to accept %@ %d as escort when ai_stack_depth is %d", name, universal_id, [other_ship name], [other_ship universal_id], [shipAI ai_stack_depth]); - + // if not in standard ai mode reject approach if ([shipAI ai_stack_depth] > 1) return NO; - + // NSLog(@"DEBUG pairOK( %@, %@) = %@", roles, [other_ship roles], (pairOK( roles, [other_ship roles]))? @"YES":@"NO"); - + if (pairOK( roles, [other_ship roles])) { // check total number acceptable int max_escorts = [(NSNumber *)[shipinfoDictionary objectForKey:@"escorts"] intValue]; - + // check it's not already been accepted int i; for (i = 0; i < n_escorts; i++) @@ -6729,17 +6729,17 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) return YES; } } - + if ((n_escorts < MAX_ESCORTS)&&(n_escorts < max_escorts)) { escort_ids[n_escorts] = [other_ship universal_id]; [other_ship setGroup_id:universal_id]; [self setGroup_id:universal_id]; // make self part of same group n_escorts++; - + //debug // NSLog(@"DEBUG ::YES:: %@ accepts escort %@", self, other_ship); - + return YES; } } @@ -6750,7 +6750,7 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) { int f_hi = 1 + (f_pos >> 2); int f_lo = f_pos & 3; - + int fp = f_lo * 3; int escort_positions[12] = { -2,0,-1, 2,0,-1, -3,0,-3, 3,0,-3 }; Vector pos = position; @@ -6761,7 +6761,7 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) pos.x += v_right.x * xx; pos.y += v_right.y * xx; pos.z += v_right.z * xx; pos.x += v_up.x * yy; pos.y += v_up.y * yy; pos.z += v_up.z * yy; pos.x += v_forward.x * zz; pos.y += v_forward.y * zz; pos.z += v_forward.z * zz; - + return pos; } @@ -6769,25 +6769,25 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) { if (n_escorts < 1) return; - + if (![self getPrimaryTarget]) return; - + if (primaryTarget == last_escort_target) { // already deployed escorts onto this target! // NSLog(@"DEBUG attempting to deploy more escorts onto same target - denied"); return; } - + last_escort_target = primaryTarget; - + int n_deploy = ranrot_rand() % n_escorts; if (n_deploy == 0) n_deploy = 1; - + //NSLog(@"DEBUG %@ %d deploying %d escorts", name, universal_id, n_deploy); - + int i_deploy = n_escorts - 1; while ((n_deploy > 0)&&(n_escorts > 0)) { @@ -6805,7 +6805,7 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) [escorter addTarget:[self getPrimaryTarget]]; [[escorter getAI] setStateMachine:@"interceptAI.plist"]; [[escorter getAI] setState:@"GLOBAL"]; - + escort_ids[i_deploy] = NO_TARGET; i_deploy--; n_deploy--; @@ -6819,14 +6819,14 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) escort_ids[i_deploy--] = escort_ids[--n_escorts]; // remove the escort } } - + } - (void) dockEscorts { if (n_escorts < 1) return; - + int i; for (i = 0; i < n_escorts; i++) { @@ -6863,7 +6863,7 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) targetStation = primaryTarget; return; // head for mother! } - + /*- selects the nearest station it can find -*/ if (!universe) return; @@ -7058,7 +7058,7 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) [localExpandedMessage replaceOccurrencesOfString:@"[target:name]" withString:[other_ship identFromShip: self] options:NSLiteralSearch range:NSMakeRange( 0, [localExpandedMessage length])]; - + Random_Seed very_random_seed; very_random_seed.a = rand() & 255; very_random_seed.b = rand() & 255; @@ -7165,7 +7165,7 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) [self sendExpandedMessage:@"[thanks-for-assist]" toShip:(ShipEntity*)rescuer]; thanked_ship_id = rescuer_id; [(ShipEntity*)switcher setBounty:[(ShipEntity*)switcher getBounty] + 5 + (ranrot_rand() & 15)]; // reward - } + } } } @@ -7207,7 +7207,7 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) rv.z = dot_product(_k,pv); bounding_box_add_vector(&result,rv); } - + return result; } @@ -7222,12 +7222,12 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) NSLog(@"***** CANNOT SPAWN: '%@'",roles_number); return; } - + roleString = (NSString *)[tokens objectAtIndex:0]; numberString = (NSString *)[tokens objectAtIndex:1]; - + int number = [numberString intValue]; - + if (debug) NSLog(@"DEBUG ..... Going to spawn %d x '%@' near %@ %d", number, roleString, name, universal_id); @@ -7245,16 +7245,16 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) // 10km is 10,000m, // 10km squared is 100,000,000 // therefore K is 0.10 - + int result = NO_TARGET; - + GLfloat k = 0.1; - + int ent_count = universe->n_entities; Entity** uni_entities = universe->sortedEntities; // grab the public sorted list ShipEntity* my_entities[ent_count]; int i; - + int ship_count = 0; for (i = 0; i < ent_count; i++) if ((uni_entities[i]->isShip)&&(uni_entities[i] != self)) @@ -7294,4 +7294,23 @@ inline BOOL pairOK(NSString* my_role, NSString* their_role) } } +#ifdef WIN32 +// No over-ride of Entity's version of the method is required for non-Win32 platforms. +- (void) reloadTextures +{ + //NSLog(@"ShipEntity::reloadTextures called, resetting subentities and calling super"); + int i; + for (i = 0; i < [sub_entities count]; i++) + { + Entity *e = (Entity *)[sub_entities objectAtIndex:i]; + //NSLog(@"ShipEntity::reloadTextures calling reloadTextures on: %@", [e description]); + [e reloadTextures]; + } + + // Reset the entity display list. + [super reloadTextures]; +} + +#endif + @end diff --git a/src/Core/SkyEntity.m b/src/Core/SkyEntity.m index fb9c3c52..7b51e9f1 100644 --- a/src/Core/SkyEntity.m +++ b/src/Core/SkyEntity.m @@ -51,7 +51,7 @@ Your fair use and other rights are in no way affected by the above. @implementation SkyEntity - (id) init -{ +{ self = [super init]; // quaternion_set_identity(&q_rotation); @@ -83,7 +83,7 @@ Your fair use and other rights are in no way affected by the above. // [self set_up_billboards:col1 :col2]; // - + // usingVAR = [self OGL_InitVAR]; // @@ -99,7 +99,7 @@ Your fair use and other rights are in no way affected by the above. } - (id) initWithColors:(OOColor *) col1:(OOColor *) col2 -{ +{ self = [super init]; // n_stars = SKY_N_STARS; @@ -148,10 +148,10 @@ Your fair use and other rights are in no way affected by the above. } - (id) initWithColors:(OOColor *) col1:(OOColor *) col2 andSystemInfo:(NSDictionary *) systeminfo -{ +{ OOColor* color1 = col1; OOColor* color2 = col2; - + self = [super init]; // n_stars = SKY_N_STARS; @@ -178,7 +178,7 @@ Your fair use and other rights are in no way affected by the above. blob_scale = SKY_BLOB_SCALE; blob_scale_prime = 0.005 / blob_scale; // - + //// possible systeminfo overrides // if ([systeminfo objectForKey:@"sky_rgb_colors"]) @@ -242,13 +242,13 @@ Your fair use and other rights are in no way affected by the above. } // //// - + sky_color = [[color2 blendedColorWithFraction:0.5 ofColor:color1] retain]; // // init stars // [self set_up_billboards:color1 :color2]; - + // usingVAR = [self OGL_InitVAR]; // @@ -321,7 +321,7 @@ Your fair use and other rights are in no way affected by the above. Vector star_vector[n_stars]; GLfloat star_color[n_stars][4]; Vector star_quad[4][n_stars]; - + // blobs Vector blob_vector[n_blobs]; GLfloat blob_color[n_blobs][4]; @@ -358,7 +358,7 @@ Your fair use and other rights are in no way affected by the above. star_quad[3][i].x = star_quad[0][i].x + p_size * vi.x; star_quad[3][i].y = star_quad[0][i].y + p_size * vi.y; star_quad[3][i].z = star_quad[0][i].z + p_size * vi.z; - + int j; for (j = 0; j < 4; j++) { @@ -368,7 +368,7 @@ Your fair use and other rights are in no way affected by the above. } //** SET UP VERTEX ARRAY DATA **// - + // set up texture and vertex arrays starsData.texture_uv_array[ 4*i*2 + 0] = 0; starsData.texture_uv_array[ 4*i*2 + 1] = 0; starsData.vertex_array[ 4*i*3 + 0] = star_quad[0][i].x; starsData.vertex_array[ 4*i*3 + 1] = star_quad[0][i].y; starsData.vertex_array[ 4*i*3 + 2] = star_quad[0][i].z; @@ -378,7 +378,7 @@ Your fair use and other rights are in no way affected by the above. starsData.vertex_array[ 4*i*3 + 6] = star_quad[2][i].x; starsData.vertex_array[ 4*i*3 + 7] = star_quad[2][i].y; starsData.vertex_array[ 4*i*3 + 8] = star_quad[2][i].z; starsData.texture_uv_array[ 4*i*2 + 6] = 0; starsData.texture_uv_array[ 4*i*2 + 7] = 1; starsData.vertex_array[ 4*i*3 + 9] = star_quad[3][i].x; starsData.vertex_array[ 4*i*3 + 10] = star_quad[3][i].y; starsData.vertex_array[ 4*i*3 + 11] = star_quad[3][i].z; - + // set up color array for (j = 0; j < 4; j++) { @@ -421,14 +421,14 @@ Your fair use and other rights are in no way affected by the above. double p_size = blob_scale * r1 * BILLBOARD_DEPTH / 500.0; blob_color[i][3] *= 0.5 + (float)r1 / 32.0; // make smaller blobs dimmer blob_quad[0][i] = blob_vector[i]; - + // rotate vi and vj a random amount double r = randf() * PI * 2.0; quaternion_rotate_about_axis(&q, vk, r); vi = vector_right_from_quaternion(q); vj = vector_up_from_quaternion(q); // - + blob_quad[1][i].x = blob_quad[0][i].x + p_size * vj.x; blob_quad[1][i].y = blob_quad[0][i].y + p_size * vj.y; blob_quad[1][i].z = blob_quad[0][i].z + p_size * vj.z; @@ -438,7 +438,7 @@ Your fair use and other rights are in no way affected by the above. blob_quad[3][i].x = blob_quad[0][i].x + p_size * vi.x; blob_quad[3][i].y = blob_quad[0][i].y + p_size * vi.y; blob_quad[3][i].z = blob_quad[0][i].z + p_size * vi.z; - + int j; for (j = 0; j < 4; j++) { @@ -446,9 +446,9 @@ Your fair use and other rights are in no way affected by the above. blob_quad[j][i].y -= 0.5 * p_size * (vi.y + vj.y); blob_quad[j][i].z -= 0.5 * p_size * (vi.z + vj.z); } - + //** SET UP VERTEX ARRAY DATA **// - + // set up texture and vertex arrays blobsData.texture_uv_array[ 4*i*2 + 0] = 0; blobsData.texture_uv_array[ 4*i*2 + 1] = 0; blobsData.vertex_array[ 4*i*3 + 0] = blob_quad[0][i].x; blobsData.vertex_array[ 4*i*3 + 1] = blob_quad[0][i].y; blobsData.vertex_array[ 4*i*3 + 2] = blob_quad[0][i].z; @@ -458,7 +458,7 @@ Your fair use and other rights are in no way affected by the above. blobsData.vertex_array[ 4*i*3 + 6] = blob_quad[2][i].x; blobsData.vertex_array[ 4*i*3 + 7] = blob_quad[2][i].y; blobsData.vertex_array[ 4*i*3 + 8] = blob_quad[2][i].z; blobsData.texture_uv_array[ 4*i*2 + 6] = 0; blobsData.texture_uv_array[ 4*i*2 + 7] = 1; blobsData.vertex_array[ 4*i*3 + 9] = blob_quad[3][i].x; blobsData.vertex_array[ 4*i*3 + 10] = blob_quad[3][i].y; blobsData.vertex_array[ 4*i*3 + 11] = blob_quad[3][i].z; - + // set up color array for (j = 0; j < 4; j++) { @@ -469,7 +469,7 @@ Your fair use and other rights are in no way affected by the above. } p_size *= 500/BILLBOARD_DEPTH; // back to normal scale - + // shuffle it around a bit in a random walk q.x += p_size * blob_scale_prime * (randf() - 0.5); q.y += p_size * blob_scale_prime * (randf() - 0.5); @@ -511,7 +511,7 @@ Your fair use and other rights are in no way affected by the above. } - (void) drawEntity:(BOOL) immediate :(BOOL) translucent -{ +{ if ([universe breakPatternHide]) return; // DON'T DRAW // @@ -524,7 +524,7 @@ Your fair use and other rights are in no way affected by the above. glDisable(GL_CULL_FACE); // face culling // glShadeModel(GL_SMOOTH); // smoothing for color values... - + if (immediate) { switch (sky_type) @@ -532,9 +532,9 @@ Your fair use and other rights are in no way affected by the above. case SKY_POINTS : NSLog(@"ERROR: SkyEntity SKY_POINTS deprecated"); break; - + case SKY_BILLBOARDS : - + if ((star_textureName == 0)&&(universe)) star_textureName = [[universe textureStore] getTextureNameFor:@"star64.png"]; if ((blob_textureName == 0)&&(universe)) @@ -546,43 +546,43 @@ Your fair use and other rights are in no way affected by the above. // stars #ifdef GNUSTEP // TODO: find replacement for APPLE function -#else +#else if (usingVAR) glBindVertexArrayAPPLE(gVertexArrayRangeObjects[0]); -#endif - +#endif + // if (usingVAR) // NSLog(@"DEBUG using accelerated memory technique to draw %@ (%@)", self, basefile); -// +// glBindTexture(GL_TEXTURE_2D, star_textureName); - + glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer( 3, GL_FLOAT, 0, starsData.vertex_array); // 3 coords per vertex // of type GL_FLOAT // 0 stride (tightly packed) // pointer to first vertex - + glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer( 2, GL_INT, 0, starsData.texture_uv_array); // 2 coords per vertex // of type GL_INT // 0 stride (tightly packed) // pointer to first coordinate pair - + glEnableClientState(GL_COLOR_ARRAY); glColorPointer( 4, GL_FLOAT, 0, starsData.color_array); // 4 values per vertex color // of type GL_FLOAT // 0 stride (tightly packed) // pointer to quadruplet - + glDisableClientState(GL_INDEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_EDGE_FLAG_ARRAY); - + glDrawArrays( GL_QUADS, 0, 4 * n_stars); - + // // blobs if (![universe reducedDetail]) @@ -593,33 +593,33 @@ Your fair use and other rights are in no way affected by the above. #else if (usingVAR) glBindVertexArrayAPPLE(gVertexArrayRangeObjects[1]); -#endif - +#endif + glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer( 3, GL_FLOAT, 0, blobsData.vertex_array); // 3 coords per vertex // of type GL_FLOAT // 0 stride (tightly packed) // pointer to first vertex - + glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer( 2, GL_INT, 0, blobsData.texture_uv_array); // 2 coords per vertex // of type GL_INT // 0 stride (tightly packed) // pointer to first coordinate pair - + glEnableClientState(GL_COLOR_ARRAY); glColorPointer( 4, GL_FLOAT, 0, blobsData.color_array); // 4 values per vertex color // of type GL_FLOAT // 0 stride (tightly packed) // pointer to quadruplet - + glDisableClientState(GL_INDEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_EDGE_FLAG_ARRAY); - + glDrawArrays( GL_QUADS, 0, 4 * n_blobs); } @@ -638,7 +638,7 @@ Your fair use and other rights are in no way affected by the above. // } } - + // reapply lighting &c glEnable(GL_CULL_FACE); // face culling glEnable(GL_LIGHTING); @@ -648,8 +648,20 @@ Your fair use and other rights are in no way affected by the above. checkGLErrors([NSString stringWithFormat:@"SkyEntity after drawing %@", self]); } +#ifdef WIN32 +// No over-ride of Entity's version of the method is required for non-Win32 platforms. +- (void) reloadTextures +{ + //NSLog(@"SkyEntity::reloadTextures called, calling super and resetTextureNames"); + // Force the sky textures to be reloaded next time a frame is drawn. + star_textureName = 0; + blob_textureName = 0; + // Reset the entity display list. + [super reloadTextures]; +} +#endif @end diff --git a/src/Core/TextureStore.m b/src/Core/TextureStore.m index c6ffee8b..bb2654be 100644 --- a/src/Core/TextureStore.m +++ b/src/Core/TextureStore.m @@ -74,23 +74,23 @@ Your fair use and other rights are in no way affected by the above. #endif NSSize imageSize; GLuint texName; - + unsigned char *texBytes; BOOL freeTexBytes; - + int texture_h = 4; int texture_w = 4; int image_h, image_w; int n_planes, im_bytes, tex_bytes; - + int im_bytesPerRow; - - int texi = 0; - + + int texi = 0; + if (![textureDictionary objectForKey:filename]) { NSMutableDictionary* texProps = [NSMutableDictionary dictionaryWithCapacity:3]; // autoreleased -#ifndef GNUSTEP +#ifndef GNUSTEP texImage = [ResourceManager imageNamed:filename inFolder:@"Textures"]; #else texImage = [ResourceManager surfaceNamed:filename inFolder:@"Textures"]; @@ -105,12 +105,12 @@ Your fair use and other rights are in no way affected by the above. [myException raise]; return 0; } - + #ifndef GNUSTEP NSArray* reps = [texImage representations]; - + // NSLog(@"DEBUG texture %@ representations:\n%@", filename, reps); - + int i; for (i = 0; ((i < [reps count]) && !bitmapImageRep); i++) { @@ -128,17 +128,17 @@ Your fair use and other rights are in no way affected by the above. [myException raise]; return 0; } - + // imageSize = [texImage size]; // Gives size in points, which is bad. imageSize = NSMakeSize( [bitmapImageRep pixelsWide], [bitmapImageRep pixelsHigh]); // Gives size in pixels, which is good. image_w = imageSize.width; image_h = imageSize.height; - + while (texture_w < image_w) texture_w *= 2; while (texture_h < image_h) texture_h *= 2; - + n_planes = [bitmapImageRep samplesPerPixel]; im_bytes = image_w * image_h * n_planes; tex_bytes = texture_w * texture_h * n_planes; @@ -149,12 +149,12 @@ Your fair use and other rights are in no way affected by the above. imageSize = NSMakeSize([texImage surface]->w, [texImage surface]->h); image_w = imageSize.width; image_h = imageSize.height; - + while (texture_w < image_w) texture_w *= 2; while (texture_h < image_h) texture_h *= 2; - + n_planes = [texImage surface]->format->BytesPerPixel; im_bytesPerRow = [texImage surface]->pitch; unsigned char* imageBuffer = [texImage surface]->pixels; @@ -169,12 +169,12 @@ Your fair use and other rights are in no way affected by the above. // NSLog(@"DEBUG filling image data for %@ (%d x %d) with special sauce!", filename, texture_w, texture_h); fillSquareImageDataWithBlur(imageBuffer, texture_w, n_planes); } - + if ((texture_w > image_w)||(texture_h > image_h)) // we need to scale the image to the texture dimensions { texBytes = malloc(tex_bytes); freeTexBytes = YES; - + // do bilinear scaling int x, y, n; float texel_w = (float)image_w / (float)texture_w; @@ -195,7 +195,7 @@ Your fair use and other rights are in no way affected by the above. py0 = (y1 - y_lo) / texel_h; py1 = 1.0 - py0; } - + for ( x = 0; x < texture_w; x++) { float x_lo = texel_w * x; @@ -203,7 +203,7 @@ Your fair use and other rights are in no way affected by the above. int x0 = floor(x_lo); int x1 = floor(x_hi); float acc = 0; - + float px0 = 1.0; float px1 = 0.0; if (x1 > x0) @@ -211,19 +211,19 @@ Your fair use and other rights are in no way affected by the above. px0 = (x1 - x_lo) / texel_w; px1 = 1.0 - px0; } - + int xy00 = y0 * im_bytesPerRow + n_planes * x0; int xy01 = y0 * im_bytesPerRow + n_planes * x1; int xy10 = y1 * im_bytesPerRow + n_planes * x0; int xy11 = y1 * im_bytesPerRow + n_planes * x1; - + for (n = 0; n < n_planes; n++) { acc = py0 * (px0 * imageBuffer[ xy00 + n] + px1 * imageBuffer[ xy10 + n]) + py1 * (px0 * imageBuffer[ xy01 + n] + px1 * imageBuffer[ xy11 + n]); texBytes[ texi++] = (char)acc; // float -> char } - } + } } } else @@ -232,16 +232,16 @@ Your fair use and other rights are in no way affected by the above. texBytes = imageBuffer; freeTexBytes = NO; } - + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(1, &texName); // get a new unique texture name glBindTexture(GL_TEXTURE_2D, texName); - + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // adjust this glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // adjust this - + switch (n_planes) // fromt he number of planes work out how to treat the image as a texture { case 4: @@ -263,14 +263,14 @@ Your fair use and other rights are in no way affected by the above. [myException raise]; return 0; } -// +// // if (n_planes == 4) // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_w, texture_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, texBytes); // else // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_w, texture_h, 0, GL_RGB, GL_UNSIGNED_BYTE, texBytes); - + if (freeTexBytes) free(texBytes); - + // add to dictionary // [texProps setObject:[NSNumber numberWithInt:texName] forKey:@"texName"]; @@ -299,6 +299,20 @@ Your fair use and other rights are in no way affected by the above. - (void) reloadTextures { +#ifdef WIN32 + int i; + + // Free up the texture image data from video memory. I assume this is a reasonable thing + // to do for any platform, but just in case... stick it in a WIN32 only condition. + NSArray *keys = [textureDictionary allKeys]; + for (i = 0; i < [keys count]; i++) + { + GLuint texName = (GLuint)[(NSNumber *)[[textureDictionary objectForKey:[keys objectAtIndex:i]] objectForKey:@"texName"] intValue]; + NSLog(@"deleting texture #%d (%@)", texName, (NSString *)[keys objectAtIndex:i]); + glDeleteTextures(1, &texName); + } +#endif + [textureDictionary removeAllObjects]; return; } @@ -320,16 +334,16 @@ void fillSquareImageDataWithBlur(unsigned char * imageBuffer, int width, int npl d = r; float fi = 255.0 - 255.0 * d * r1; unsigned char i = (unsigned char)fi; - + i_error += fi - i; // accumulate the error between i and fi - + if ((i_error > 1.0)&&(i < 255)) { // NSLog(@"DEBUG err correct"); i_error -= 1.0; i++; } - + int p; for (p = 0; p < nplanes - 1; p++) { diff --git a/src/SDL/MyOpenGLView.m b/src/SDL/MyOpenGLView.m index 8611ea90..b2db7228 100644 --- a/src/SDL/MyOpenGLView.m +++ b/src/SDL/MyOpenGLView.m @@ -443,13 +443,16 @@ Your fair use and other rights are in no way affected by the above. Universe *universe = [gameController universe]; if (universe) { + NSLog(@"WIN32: clearing texture store cache"); [[universe textureStore] reloadTextures]; // clears the cached references PlayerEntity *player = (PlayerEntity *)[universe entityZero]; if (player) { + NSLog(@"WIN32: resetting text texture"); [[player hud] setPlayer:player]; // resets the reference to the asciitext texture } + NSLog(@"WIN32: resetting entity textures"); int i; Entity **elist = universe->sortedEntities; for (i = 0; i < universe->n_entities; i++)