static DWORD getStripRandomSeed (void) { DWORD x, y; // We truncate the location because encounters move the ship slightly in // HSpace, and throw some other relatively immutable values in the mix to // vary the deal when stuck at the same general location again. // It is still possible but unlikely for encounters to move the ship into // another truncation sector so the player could choose from 2 deals. x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)) / 100; y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)) / 100; // prime numbers help randomness return y * 1013 + x + GLOBAL_SIS (NumLanders) + GLOBAL_SIS (ModuleSlots[1]) + GLOBAL_SIS (ModuleSlots[4]) + GLOBAL_SIS (ModuleSlots[7]) + GLOBAL_SIS (ModuleSlots[10]); }
// Move the Flagship to the destination of the autopilot. // Should only be called from HyperSpace/QuasiSpace. // It can be called from debugHook directly after entering HS/QS though. void doInstantMove (void) { // Move to the new location: if ((GLOBAL (autopilot)).x == ~0 || (GLOBAL (autopilot)).y == ~0) { // If no destination has been selected, use the current location // as the destination. (GLOBAL (autopilot)).x = LOGX_TO_UNIVERSE(GLOBAL_SIS (log_x)); (GLOBAL (autopilot)).y = LOGY_TO_UNIVERSE(GLOBAL_SIS (log_y)); } else { // A new destination has been selected. GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX((GLOBAL (autopilot)).x); GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY((GLOBAL (autopilot)).y); } // Check for a solar systems at the destination. if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { // If there's a solar system at the destination, enter it. CurStarDescPtr = FindStar (0, &(GLOBAL (autopilot)), 0, 0); if (CurStarDescPtr) { // Leave HyperSpace/QuasiSpace if we're there: SET_GAME_STATE (USED_BROADCASTER, 0); GLOBAL (CurrentActivity) &= ~IN_BATTLE; // Enter IP: GLOBAL (ShipFacing) = 0; GLOBAL (ip_planet) = 0; GLOBAL (in_orbit) = 0; // This causes the ship position in IP to be reset. GLOBAL (CurrentActivity) |= START_INTERPLANETARY; } } // Turn off the autopilot: (GLOBAL (autopilot)).x = ~0; (GLOBAL (autopilot)).y = ~0; }
static void DoRescue (RESPONSE_REF R) { SIZE dx, dy; COUNT fuel_required; (void) R; // ignored dx = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)) - SOL_X; dy = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)) - SOL_Y; fuel_required = square_root ( (DWORD)((long)dx * dx + (long)dy * dy) ) + (2 * FUEL_TANK_SCALE); if (StripShip (fuel_required)) { Response (take_it, ExitConversation); Response (leave_it, ExitConversation); } }
static COUNT CalcLifeForms (SYSTEM_INFO *SysInfoPtr, COUNT which_life) { COUNT num_life_forms; num_life_forms = 0; if (PLANSIZE (SysInfoPtr->PlanetInfo.PlanDataPtr->Type) == GAS_GIANT) SysInfoPtr->PlanetInfo.LifeChance = -1; else { #define MIN_LIFE_CHANCE 10 SIZE life_var; life_var = 0; if (SysInfoPtr->PlanetInfo.SurfaceTemperature < -151) life_var -= 300; else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < -51) life_var -= 100; else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 0) life_var += 100; else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 50) life_var += 300; else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 150) life_var += 50; else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 250) life_var -= 100; else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 500) life_var -= 400; else life_var -= 800; if (SysInfoPtr->PlanetInfo.AtmoDensity == 0) life_var -= 1000; else if (SysInfoPtr->PlanetInfo.AtmoDensity < 15) life_var += 100; else if (SysInfoPtr->PlanetInfo.AtmoDensity < 30) life_var += 200; else if (SysInfoPtr->PlanetInfo.AtmoDensity < 100) life_var += 300; else if (SysInfoPtr->PlanetInfo.AtmoDensity < 1000) life_var += 150; else if (SysInfoPtr->PlanetInfo.AtmoDensity < 2500) ; else life_var -= 100; #ifndef NOTYET life_var += 200 + 80 + 80; #else /* NOTYET */ if (SysInfoPtr->PlanetInfo.SurfaceGravity < 10) ; else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 35) life_var += 50; else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 75) life_var += 100; else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 150) life_var += 200; else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 400) life_var += 50; else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 800) ; else life_var -= 100; if (SysInfoPtr->PlanetInfo.Tectonics < 1) life_var += 80; else if (SysInfoPtr->PlanetInfo.Tectonics < 2) life_var += 70; else if (SysInfoPtr->PlanetInfo.Tectonics < 3) life_var += 60; else if (SysInfoPtr->PlanetInfo.Tectonics < 4) life_var += 50; else if (SysInfoPtr->PlanetInfo.Tectonics < 5) life_var += 25; else if (SysInfoPtr->PlanetInfo.Tectonics < 6) ; else life_var -= 100; if (SysInfoPtr->PlanetInfo.Weather < 1) life_var += 80; else if (SysInfoPtr->PlanetInfo.Weather < 2) life_var += 70; else if (SysInfoPtr->PlanetInfo.Weather < 3) life_var += 60; else if (SysInfoPtr->PlanetInfo.Weather < 4) life_var += 50; else if (SysInfoPtr->PlanetInfo.Weather < 5) life_var += 25; else if (SysInfoPtr->PlanetInfo.Weather < 6) ; else life_var -= 100; #endif /* NOTYET */ SysInfoPtr->PlanetInfo.LifeChance = life_var; life_var = (COUNT)TFB_Random () & 1023; if (life_var < SysInfoPtr->PlanetInfo.LifeChance || (SysInfoPtr->PlanetInfo.LifeChance < MIN_LIFE_CHANCE && life_var < MIN_LIFE_CHANCE)) { BYTE num_types; num_types = (BYTE)(((BYTE)TFB_Random () % MAX_LIFE_VARIATION) + 1); do { BYTE index, num_creatures, range_types; DWORD rand_val; // JMS_GFX: Was UWORD UWORD loword, hiword; BOOLEAN zoneA, zoneB, zoneC; rand_val = (UWORD)TFB_Random (); // BW: Compute which life forms should appear zoneA = (LOGX_TO_UNIVERSE(GLOBAL_SIS (log_x)) + LOGY_TO_UNIVERSE(GLOBAL_SIS (log_y)) > 9000); zoneB = (LOGX_TO_UNIVERSE(GLOBAL_SIS (log_x)) + 3 * LOGY_TO_UNIVERSE(GLOBAL_SIS (log_y)) < 21000); zoneC = (3 * LOGX_TO_UNIVERSE(GLOBAL_SIS (log_x)) + LOGY_TO_UNIVERSE(GLOBAL_SIS (log_y)) < 19000); range_types = 0; if (zoneA) range_types += NUM_CREATURE_TYPES; if (zoneB) range_types += NUM_B_CREATURE_TYPES; if (zoneC) range_types += NUM_C_CREATURE_TYPES; //index = LOBYTE (rand_val) % range_types; index = LOBYTE ((UWORD)rand_val) % range_types; // JMS_GFX // BW: adjust index so that it takes creatures from the correct set. if (!zoneA) { index += NUM_CREATURE_TYPES + NUM_SPECIAL_CREATURE_TYPES; if (!zoneB) index += NUM_B_CREATURE_TYPES; } if (zoneA && index >= NUM_CREATURE_TYPES) { index += NUM_SPECIAL_CREATURE_TYPES; if (!zoneB) index += NUM_B_CREATURE_TYPES; } // BW: Reduce amounts in the NE quadrant if ((GLOBAL_SIS (log_x) > UNIVERSE_TO_LOGX(5000)) && (GLOBAL_SIS (log_y) < UNIVERSE_TO_LOGY(6000))) num_creatures = (BYTE)((HIBYTE ((UWORD)rand_val) % 3) + 1); else num_creatures = (BYTE)((HIBYTE ((UWORD)rand_val) % 10) + 1); do { rand_val = (DWORD)TFB_Random (); loword = LOWORD (rand_val); hiword = HIWORD (rand_val); /* if (RESOLUTION_FACTOR == 0) SysInfoPtr->PlanetInfo.CurPt.x = (LOBYTE (rand_val) % (MAP_WIDTH - (8 << 1))) + 8; else SysInfoPtr->PlanetInfo.CurPt.x = rand_val % (MAP_WIDTH - (8 << 1)) + 8; // JMS_GFX: Replaced previous line with this line (BYTE was too small for 640x480 maps.) SysInfoPtr->PlanetInfo.CurPt.y = (HIBYTE (rand_val) % (MAP_HEIGHT - (8 << 1))) + 8; // JMS_GFX */ if (RESOLUTION_FACTOR == 0) SysInfoPtr->PlanetInfo.CurPt.x = (LOBYTE ((UWORD)rand_val) % (MAP_WIDTH - (8 << 1))) + 8; else SysInfoPtr->PlanetInfo.CurPt.x = loword % (MAP_WIDTH - (8 << 1)) + 8; // JMS_GFX: Replaced previous line with this line (BYTE was too small for 640x480 maps.) if (RESOLUTION_FACTOR == 0) SysInfoPtr->PlanetInfo.CurPt.y = (HIBYTE ((UWORD)rand_val) % (MAP_HEIGHT - (8 << 1))) + 8; else SysInfoPtr->PlanetInfo.CurPt.y = hiword % (MAP_HEIGHT - (8 << 1)) + 8; // JMS_GFX: Replaced previous line with this line (BYTE was too small for 1280x960 maps.) SysInfoPtr->PlanetInfo.CurType = index; if ((num_life_forms >= which_life && !(SysInfoPtr->PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] & (1L << num_life_forms))) || ++num_life_forms == sizeof (DWORD) * 8) { num_types = 1; break; } } while (--num_creatures); } while (--num_types); } #ifdef DEBUG_SURFACE else log_add (log_Debug, "It's dead, Jim! (%d >= %d)", life_var, SysInfoPtr->PlanetInfo.LifeChance); #endif /* DEBUG_SURFACE */ } return (num_life_forms); }
static void sis_hyper_preprocess (ELEMENT *ElementPtr) { SIZE udx, udy, dx, dy; SIZE AccelerateDirection; STARSHIP *StarShipPtr; if (ElementPtr->state_flags & APPEARING) ElementPtr->velocity = GLOBAL (velocity); AccelerateDirection = 0; GetElementStarShip (ElementPtr, &StarShipPtr); ++StarShipPtr->weapon_counter; /* no shooting in hyperspace! */ if ((GLOBAL (autopilot)).x == ~0 || (GLOBAL (autopilot)).y == ~0 || (StarShipPtr->cur_status_flags & (LEFT | RIGHT | THRUST))) { LeaveAutoPilot: (GLOBAL (autopilot)).x = (GLOBAL (autopilot)).y = ~0; if (!(StarShipPtr->cur_status_flags & THRUST) || (GLOBAL_SIS (FuelOnBoard) == 0 && GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1)) { AccelerateDirection = -1; GetCurrentVelocityComponents (&ElementPtr->velocity, &dx, &dy); udx = dx << 4; udy = dy << 4; StarShipPtr->cur_status_flags &= ~THRUST; } } else { SIZE facing; POINT universe; universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); udx = (GLOBAL (autopilot)).x - universe.x; udy = -((GLOBAL (autopilot)).y - universe.y); if ((dx = udx) < 0) dx = -dx; if ((dy = udy) < 0) dy = -dy; if (dx <= 1 && dy <= 1) goto LeaveAutoPilot; facing = NORMALIZE_FACING (ANGLE_TO_FACING (ARCTAN (udx, udy))); /* This prevents ship from flying backwards on auto-pilot. * It could also theoretically abort autopilot in a bad savegame */ if ((StarShipPtr->cur_status_flags & SHIP_AT_MAX_SPEED) /*|| (ElementPtr->state_flags & APPEARING)*/ ) { if (NORMALIZE_FACING (StarShipPtr->ShipFacing + ANGLE_TO_FACING (QUADRANT) - facing) > ANGLE_TO_FACING (HALF_CIRCLE)) goto LeaveAutoPilot; facing = StarShipPtr->ShipFacing; } else if ((int)facing != (int)StarShipPtr->ShipFacing && ElementPtr->turn_wait == 0) { if (NORMALIZE_FACING ( StarShipPtr->ShipFacing - facing ) >= ANGLE_TO_FACING (HALF_CIRCLE)) { facing = NORMALIZE_FACING (facing - 1); StarShipPtr->cur_status_flags |= RIGHT; } else if ((int)StarShipPtr->ShipFacing != (int)facing) { facing = NORMALIZE_FACING (facing + 1); StarShipPtr->cur_status_flags |= LEFT; } if ((int)facing == (int)StarShipPtr->ShipFacing) { ZeroVelocityComponents (&ElementPtr->velocity); } } GetCurrentVelocityComponents (&ElementPtr->velocity, &dx, &dy); if ((GLOBAL_SIS (FuelOnBoard) || GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1) && (int)facing == (int)StarShipPtr->ShipFacing) { StarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED; AccelerateDirection = 1; } else { AccelerateDirection = -1; udx = dx << 4; udy = dy << 4; } } if (ElementPtr->thrust_wait == 0 && AccelerateDirection) { COUNT dist; SIZE speed, velocity_increment; velocity_increment = WORLD_TO_VELOCITY ( StarShipPtr->RaceDescPtr->characteristics.thrust_increment); if ((dist = square_root ((long)udx * udx + (long)udy * udy)) == 0) dist = 1; /* prevent divide by zero */ speed = square_root ((long)dx * dx + (long)dy * dy); if (AccelerateDirection < 0) { dy = (speed / velocity_increment - 1) * velocity_increment; if (dy < speed - velocity_increment) dy = speed - velocity_increment; if ((speed = dy) < 0) speed = 0; StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; } else { SIZE max_velocity; AccelerateDirection = 0; max_velocity = WORLD_TO_VELOCITY ( StarShipPtr->RaceDescPtr->characteristics.max_thrust); dy = (speed / velocity_increment + 1) * velocity_increment; if (dy < speed + velocity_increment) dy = speed + velocity_increment; if ((speed = dy) > max_velocity) { speed = max_velocity; StarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED; } } dx = (SIZE)((long)udx * speed / (long)dist); dy = (SIZE)((long)udy * speed / (long)dist); SetVelocityComponents (&ElementPtr->velocity, dx, dy); ElementPtr->thrust_wait = StarShipPtr->RaceDescPtr->characteristics.thrust_wait; } }
/** * Gets the content for index and loads it into the current conversation, * using the voice track cb if provided, or making one itself if not. * * The indices are: * - 1 000 000 : captain's name * - 999 999 : ship's name * - 999 998 : ship's location * numbers from -999 997 to 998 997 : display the name of your alliance * (not sure why this one option needs 1001 indices) * numbers from -998 996 to -1 : alien number speech (sign is flipped) * 0 : say and do nothing * positive numbers : entries from the current alien conversation's string table */ void NPCPhrase_cb (int index, TFB_TrackCB cb) { UNICODE *pStr, numbuf[400]; void *pClip, *pTimeStamp; switch (index) { case GLOBAL_PLAYER_NAME: pStr = GLOBAL_SIS (CommanderName); pClip = 0; pTimeStamp = 0; break; case GLOBAL_SHIP_NAME: pStr = GLOBAL_SIS (ShipName); pClip = 0; pTimeStamp = 0; break; case GLOBAL_PLAYER_LOCATION: { SIZE dx, dy; COUNT adx, ady; dx = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)) - 333; adx = dx >= 0 ? dx : -dx; dy = 9812 - LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); ady = dy >= 0 ? dy : -dy; sprintf (numbuf, "%+04d.%01u,%+04d.%01u", (SIZE)(dy / 10), (COUNT)(ady % 10), (SIZE)(dx / 10), (COUNT)(adx % 10)); pStr = numbuf; pClip = 0; pTimeStamp = 0; break; } case 0: { return; } default: if (index < 0) { if (index > UNREASONABLE_NUMBER) { if (CommData.AlienNumberSpeech) { NPCNumberPhrase (-index, NULL); return; } sprintf (numbuf, "%d", -index); } else { COUNT i; STRING S; index -= GLOBAL_ALLIANCE_NAME; i = GET_GAME_STATE (NEW_ALLIANCE_NAME); S = SetAbsStringTableIndex (CommData.ConversationPhrases, (index - 1) + i); strcpy (numbuf, (UNICODE *)GetStringAddress (S)); if (i == 3) strcat (numbuf, GLOBAL_SIS (CommanderName)); } pStr = numbuf; pClip = 0; pTimeStamp = 0; } else { pStr = (UNICODE *)GetStringAddress ( SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1) ); pClip = GetStringSoundClip ( SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1) ); pTimeStamp = GetStringTimeStamp ( SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1) ); } break; } if (GLOBAL (glob_flags) & VOICE_DISABLED || pClip == NULL) pClip = "noname.ogg"; SpliceTrack (pClip, pStr, pTimeStamp, cb); }