static void druuge_postprocess (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); /* if just fired cannon */ if ((StarShipPtr->cur_status_flags & WEAPON) && StarShipPtr->weapon_counter == StarShipPtr->RaceDescPtr->characteristics.weapon_wait) { COUNT angle; SIZE cur_delta_x, cur_delta_y; StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE; DeltaVelocityComponents (&ElementPtr->velocity, COSINE (angle, RECOIL_VELOCITY), SINE (angle, RECOIL_VELOCITY)); GetCurrentVelocityComponents (&ElementPtr->velocity, &cur_delta_x, &cur_delta_y); if ((long)cur_delta_x * (long)cur_delta_x + (long)cur_delta_y * (long)cur_delta_y > (long)MAX_RECOIL_VELOCITY * (long)MAX_RECOIL_VELOCITY) { angle = ARCTAN (cur_delta_x, cur_delta_y); SetVelocityComponents (&ElementPtr->velocity, COSINE (angle, MAX_RECOIL_VELOCITY), SINE (angle, MAX_RECOIL_VELOCITY)); } } }
static bool GenerateVux_generatePlanets (SOLARSYS_STATE *solarSys) { COUNT angle; GenerateDefault_generatePlanets (solarSys); if (CurStarDescPtr->Index == MAIDENS_DEFINED) { GenerateDefault_generatePlanets (solarSys); // XXX: this is the second time that this function is // called. Is it safe to remove one, or does this change // the RNG so that the outcome is different? solarSys->PlanetDesc[0].data_index = REDUX_WORLD; solarSys->PlanetDesc[0].radius = EARTH_RADIUS * 212L / 100; angle = ARCTAN (solarSys->PlanetDesc[0].location.x, solarSys->PlanetDesc[0].location.y); solarSys->PlanetDesc[0].location.x = COSINE (angle, solarSys->PlanetDesc[0].radius); solarSys->PlanetDesc[0].location.y = SINE (angle, solarSys->PlanetDesc[0].radius); ComputeSpeed(&solarSys->PlanetDesc[0], FALSE, 1); } else { if (CurStarDescPtr->Index == VUX_DEFINED) { solarSys->PlanetDesc[0].data_index = REDUX_WORLD; solarSys->PlanetDesc[0].NumPlanets = 1; solarSys->PlanetDesc[0].radius = EARTH_RADIUS * 42L / 100; angle = HALF_CIRCLE + OCTANT; ComputeSpeed(&solarSys->PlanetDesc[0], FALSE, 1); } else /* if (CurStarDescPtr->Index == VUX_BEAST_DEFINED) */ { memmove (&solarSys->PlanetDesc[1], &solarSys->PlanetDesc[0], sizeof (solarSys->PlanetDesc[0]) * solarSys->SunDesc[0].NumPlanets); ++solarSys->SunDesc[0].NumPlanets; angle = HALF_CIRCLE - OCTANT; solarSys->PlanetDesc[0].data_index = WATER_WORLD; solarSys->PlanetDesc[0].radius = EARTH_RADIUS * 110L / 100; solarSys->PlanetDesc[0].NumPlanets = 0; ComputeSpeed(&solarSys->PlanetDesc[0], FALSE, 1); } solarSys->PlanetDesc[0].location.x = COSINE (angle, solarSys->PlanetDesc[0].radius); solarSys->PlanetDesc[0].location.y = SINE (angle, solarSys->PlanetDesc[0].radius); solarSys->PlanetDesc[0].rand_seed = MAKE_DWORD ( solarSys->PlanetDesc[0].location.x, solarSys->PlanetDesc[0].location.y); } return true; }
static bool GenerateSpathi_generateMoons (SOLARSYS_STATE *solarSys, PLANET_DESC *planet) { COUNT angle; GenerateDefault_generateMoons (solarSys, planet); if (matchWorld (solarSys, planet, 0, MATCH_PLANET)) { #ifdef NOTYET utf8StringCopy (GLOBAL_SIS (PlanetName), sizeof (GLOBAL_SIS (PlanetName)), "Spathiwa"); #endif /* NOTYET */ solarSys->MoonDesc[0].data_index = PELLUCID_WORLD; solarSys->MoonDesc[0].alternate_colormap = NULL; solarSys->MoonDesc[0].radius = MIN_MOON_RADIUS + MOON_DELTA; angle = NORMALIZE_ANGLE (LOWORD (RandomContext_Random (SysGenRNG))); solarSys->MoonDesc[0].location.x = COSINE (angle, solarSys->MoonDesc[0].radius); solarSys->MoonDesc[0].location.y = SINE (angle, solarSys->MoonDesc[0].radius); ComputeSpeed(&solarSys->MoonDesc[0], TRUE, 1); } return true; }
static COUNT initialize_autoaim_laser (ELEMENT *ShipPtr, HELEMENT LaserArray[]) { COUNT orig_facing; SIZE delta_facing; STARSHIP *StarShipPtr; LASER_BLOCK LaserBlock; GetElementStarShip (ShipPtr, &StarShipPtr); LaserBlock.face = orig_facing = StarShipPtr->ShipFacing; if ((delta_facing = TrackShip (ShipPtr, &LaserBlock.face)) > 0) LaserBlock.face = NORMALIZE_FACING (orig_facing + delta_facing); ShipPtr->hTarget = 0; LaserBlock.cx = ShipPtr->next.location.x; LaserBlock.cy = ShipPtr->next.location.y; LaserBlock.ex = COSINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); LaserBlock.ey = SINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); LaserBlock.sender = ShipPtr->playerNr; LaserBlock.flags = IGNORE_SIMILAR; LaserBlock.pixoffs = ARILOU_OFFSET; LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E); LaserArray[0] = initialize_laser (&LaserBlock); return (1); }
static bool GenerateDruuge_generatePlanets (SOLARSYS_STATE *solarSys) { COUNT angle; GenerateDefault_generatePlanets (solarSys); memmove (&solarSys->PlanetDesc[1], &solarSys->PlanetDesc[0], sizeof (solarSys->PlanetDesc[0]) * solarSys->SunDesc[0].NumPlanets); ++solarSys->SunDesc[0].NumPlanets; solarSys->PlanetDesc[0].data_index = DUST_WORLD; solarSys->PlanetDesc[0].radius = EARTH_RADIUS * 50L / 100; solarSys->PlanetDesc[0].NumPlanets = 0; angle = HALF_CIRCLE - OCTANT; solarSys->PlanetDesc[0].location.x = COSINE (angle, solarSys->PlanetDesc[0].radius); solarSys->PlanetDesc[0].location.y = SINE (angle, solarSys->PlanetDesc[0].radius); solarSys->PlanetDesc[0].rand_seed = MAKE_DWORD ( solarSys->PlanetDesc[0].location.x, solarSys->PlanetDesc[0].location.y); ComputeSpeed(&solarSys->PlanetDesc[0], FALSE, 1); return true; }
static bool GenerateTrap_generatePlanets (SOLARSYS_STATE *solarSys) { COUNT angle; int planetArray[] = { PRIMORDIAL_WORLD, WATER_WORLD, TELLURIC_WORLD }; solarSys->SunDesc[0].NumPlanets = (BYTE)~0; solarSys->SunDesc[0].PlanetByte = 0; if(!PrimeSeed){ solarSys->SunDesc[0].NumPlanets = (RandomContext_Random (SysGenRNG) % (9 - 1) + 1); } FillOrbits (solarSys, solarSys->SunDesc[0].NumPlanets, solarSys->PlanetDesc, FALSE); GeneratePlanets (solarSys); solarSys->PlanetDesc[solarSys->SunDesc[0].PlanetByte].data_index = TELLURIC_WORLD; solarSys->PlanetDesc[solarSys->SunDesc[0].PlanetByte].alternate_colormap = NULL; solarSys->PlanetDesc[solarSys->SunDesc[0].PlanetByte].NumPlanets = 1; if(!PrimeSeed){ solarSys->PlanetDesc[solarSys->SunDesc[0].PlanetByte].data_index = planetArray[RandomContext_Random (SysGenRNG) % 2]; } else { solarSys->PlanetDesc[solarSys->SunDesc[0].PlanetByte].radius = EARTH_RADIUS * 203L / 100; angle = ARCTAN (solarSys->PlanetDesc[solarSys->SunDesc[0].PlanetByte].location.x, solarSys->PlanetDesc[solarSys->SunDesc[0].PlanetByte].location.y); solarSys->PlanetDesc[solarSys->SunDesc[0].PlanetByte].location.x = COSINE (angle, solarSys->PlanetDesc[solarSys->SunDesc[0].PlanetByte].radius); solarSys->PlanetDesc[solarSys->SunDesc[0].PlanetByte].location.y = SINE (angle, solarSys->PlanetDesc[solarSys->SunDesc[0].PlanetByte].radius); ComputeSpeed(&solarSys->PlanetDesc[solarSys->SunDesc[0].PlanetByte], FALSE, 1); } return true; }
static bool GenerateSaMatra_reinitNpcs (SOLARSYS_STATE *solarSys) { BOOLEAN GuardEngaged; HIPGROUP hGroup; HIPGROUP hNextGroup; GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); EncounterGroup = 0; EncounterRace = -1; // Do not want guards to chase the player GuardEngaged = FALSE; for (hGroup = GetHeadLink (&GLOBAL (ip_group_q)); hGroup; hGroup = hNextGroup) { IP_GROUP *GroupPtr; GroupPtr = LockIpGroup (&GLOBAL (ip_group_q), hGroup); hNextGroup = _GetSuccLink (GroupPtr); if (GET_GAME_STATE (URQUAN_MESSED_UP)) { GroupPtr->task &= REFORM_GROUP; GroupPtr->task |= FLEE | IGNORE_FLAGSHIP; GroupPtr->dest_loc = 0; } else if (GroupPtr->task & REFORM_GROUP) { // REFORM_GROUP was set in ipdisp.c:ip_group_collision // during a collision with the flagship. GroupPtr->task &= ~REFORM_GROUP; GroupPtr->group_counter = 0; GuardEngaged = TRUE; } UnlockIpGroup (&GLOBAL (ip_group_q), hGroup); } if (GuardEngaged) { COUNT angle; POINT org; org = planetOuterLocation (4); angle = ARCTAN (GLOBAL (ip_location.x) - org.x, GLOBAL (ip_location.y) - org.y); GLOBAL (ip_location.x) = org.x + COSINE (angle, 3000); GLOBAL (ip_location.y) = org.y + SINE (angle, 3000); XFormIPLoc (&GLOBAL (ip_location), &GLOBAL (ShipStamp.origin), TRUE); } (void) solarSys; return true; }
static void spawn_doggy (ELEMENT *ElementPtr) { HELEMENT hDoggyElement; if ((hDoggyElement = AllocElement ()) != 0) { COUNT angle; ELEMENT *DoggyElementPtr; STARSHIP *StarShipPtr; ElementPtr->state_flags |= DEFY_PHYSICS; PutElement (hDoggyElement); LockElement (hDoggyElement, &DoggyElementPtr); DoggyElementPtr->hit_points = DOGGY_HITS; DoggyElementPtr->mass_points = DOGGY_MASS; DoggyElementPtr->thrust_wait = 0; DoggyElementPtr->playerNr = ElementPtr->playerNr; DoggyElementPtr->state_flags = APPEARING; DoggyElementPtr->life_span = NORMAL_LIFE; SetPrimType (&(GLOBAL (DisplayArray))[DoggyElementPtr->PrimIndex], STAMP_PRIM); { DoggyElementPtr->preprocess_func = doggy_preprocess; DoggyElementPtr->postprocess_func = NULL; DoggyElementPtr->collision_func = doggy_collision; DoggyElementPtr->death_func = doggy_death; } GetElementStarShip (ElementPtr, &StarShipPtr); angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE; DoggyElementPtr->current.location.x = ElementPtr->next.location.x + COSINE (angle, DISPLAY_TO_WORLD (CHENJESU_OFFSET + DOGGY_OFFSET)); DoggyElementPtr->current.location.y = ElementPtr->next.location.y + SINE (angle, DISPLAY_TO_WORLD (CHENJESU_OFFSET + DOGGY_OFFSET)); DoggyElementPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; DoggyElementPtr->current.image.frame = StarShipPtr->RaceDescPtr->ship_data.special[0]; SetVelocityVector (&DoggyElementPtr->velocity, DOGGY_SPEED, NORMALIZE_FACING (ANGLE_TO_FACING (angle))); SetElementStarShip (DoggyElementPtr, StarShipPtr); ProcessSound (SetAbsSoundIndex ( /* RELEASE_DOGGY */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 4), DoggyElementPtr); UnlockElement (hDoggyElement); } }
static void cannon_collision (ELEMENT *ElementPtr0, POINT *pPt0, ELEMENT *ElementPtr1, POINT *pPt1) { weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); if ((ElementPtr1->state_flags & PLAYER_SHIP) && ElementPtr1->crew_level && !GRAVITY_MASS (ElementPtr1->mass_points + 1)) { COUNT angle; SIZE cur_delta_x, cur_delta_y; STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr1, &StarShipPtr); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); angle = FACING_TO_ANGLE ( GetFrameIndex (ElementPtr0->next.image.frame) ); DeltaVelocityComponents (&ElementPtr1->velocity, COSINE (angle, RECOIL_VELOCITY), SINE (angle, RECOIL_VELOCITY)); GetCurrentVelocityComponents (&ElementPtr1->velocity, &cur_delta_x, &cur_delta_y); if ((long)cur_delta_x * (long)cur_delta_x + (long)cur_delta_y * (long)cur_delta_y > (long)MAX_RECOIL_VELOCITY * (long)MAX_RECOIL_VELOCITY) { angle = ARCTAN (cur_delta_x, cur_delta_y); SetVelocityComponents (&ElementPtr1->velocity, COSINE (angle, MAX_RECOIL_VELOCITY), SINE (angle, MAX_RECOIL_VELOCITY)); } } }
static bool GenerateColony_generatePlanets (SOLARSYS_STATE *solarSys) { COUNT angle; PLANET_DESC *pMinPlanet; pMinPlanet = &solarSys->PlanetDesc[0]; FillOrbits (solarSys, (BYTE)~0, pMinPlanet, FALSE); pMinPlanet->radius = EARTH_RADIUS * 115L / 100; angle = ARCTAN (pMinPlanet->location.x, pMinPlanet->location.y); pMinPlanet->location.x = COSINE (angle, pMinPlanet->radius); pMinPlanet->location.y = SINE (angle, pMinPlanet->radius); pMinPlanet->data_index = WATER_WORLD | PLANET_SHIELDED; return true; }
static bool GenerateBurvixese_generatePlanets (SOLARSYS_STATE *solarSys) { COUNT angle; GenerateDefault_generatePlanets (solarSys); solarSys->PlanetDesc[0].data_index = REDUX_WORLD; solarSys->PlanetDesc[0].NumPlanets = 1; solarSys->PlanetDesc[0].radius = EARTH_RADIUS * 39L / 100; angle = ARCTAN (solarSys->PlanetDesc[0].location.x, solarSys->PlanetDesc[0].location.y); solarSys->PlanetDesc[0].location.x = COSINE (angle, solarSys->PlanetDesc[0].radius); solarSys->PlanetDesc[0].location.y = SINE (angle, solarSys->PlanetDesc[0].radius); return true; }
static bool GenerateAndrosynth_generatePlanets (SOLARSYS_STATE *solarSys) { COUNT angle; GenerateDefault_generatePlanets (solarSys); solarSys->PlanetDesc[1].data_index = TELLURIC_WORLD; solarSys->PlanetDesc[1].radius = EARTH_RADIUS * 204L / 100; angle = ARCTAN (solarSys->PlanetDesc[1].location.x, solarSys->PlanetDesc[1].location.y); solarSys->PlanetDesc[1].location.x = COSINE (angle, solarSys->PlanetDesc[1].radius); solarSys->PlanetDesc[1].location.y = SINE (angle, solarSys->PlanetDesc[1].radius); ComputeSpeed(&solarSys->PlanetDesc[1], FALSE, 1); return true; }
static void flak_preprocess (ELEMENT *ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { SIZE angle, delta_speed; angle = GetVelocityTravelAngle (&ElementPtr->velocity); delta_speed = WORLD_TO_VELOCITY (MISSILE_DECELERATION); DeltaVelocityComponents (&ElementPtr->velocity, (SIZE)COSINE (angle, -delta_speed), (SIZE)SINE (angle, -delta_speed)); ElementPtr->turn_wait = MISSILE_DECEL_WAIT; ElementPtr->state_flags |= CHANGING; } }
static bool GenerateSupox_generatePlanets (SOLARSYS_STATE *solarSys) { COUNT angle; GenerateDefault_generatePlanets (solarSys); solarSys->PlanetDesc[0].data_index = WATER_WORLD; solarSys->PlanetDesc[0].NumPlanets = 2; solarSys->PlanetDesc[0].radius = EARTH_RADIUS * 152L / 100; angle = ARCTAN (solarSys->PlanetDesc[0].location.x, solarSys->PlanetDesc[0].location.y); solarSys->PlanetDesc[0].location.x = COSINE (angle, solarSys->PlanetDesc[0].radius); solarSys->PlanetDesc[0].location.y = SINE (angle, solarSys->PlanetDesc[0].radius); ComputeSpeed(&solarSys->PlanetDesc[0], FALSE, 1); return true; }
static bool GenerateSaMatra_generateMoons (SOLARSYS_STATE *solarSys, PLANET_DESC *planet) { GenerateDefault_generateMoons (solarSys, planet); if (matchWorld (solarSys, planet, 4, MATCH_PLANET)) { COUNT angle; DWORD rand_val; solarSys->MoonDesc[0].data_index = SA_MATRA; solarSys->MoonDesc[0].radius = MIN_MOON_RADIUS + (2 * MOON_DELTA); rand_val = TFB_Random (); angle = NORMALIZE_ANGLE (LOWORD (rand_val)); solarSys->MoonDesc[0].location.x = COSINE (angle, solarSys->MoonDesc[0].radius); solarSys->MoonDesc[0].location.y = SINE (angle, solarSys->MoonDesc[0].radius); } return true; }
static bool GenerateBurvixese_generateMoons (SOLARSYS_STATE *solarSys, PLANET_DESC *planet) { GenerateDefault_generateMoons (solarSys, planet); if (matchWorld (solarSys, planet, 0, MATCH_PLANET)) { COUNT angle; DWORD rand_val; solarSys->MoonDesc[0].data_index = SELENIC_WORLD; solarSys->MoonDesc[0].radius = MIN_MOON_RADIUS + (MAX_MOONS - 1) * MOON_DELTA; rand_val = TFB_Random (); angle = NORMALIZE_ANGLE (LOWORD (rand_val)); solarSys->MoonDesc[0].location.x = COSINE (angle, solarSys->MoonDesc[0].radius); solarSys->MoonDesc[0].location.y = SINE (angle, solarSys->MoonDesc[0].radius); ComputeSpeed(&solarSys->MoonDesc[0], TRUE, 1); } return true; }
static bool GenerateChmmr_generateMoons (SOLARSYS_STATE *solarSys, PLANET_DESC *planet) { GenerateDefault_generateMoons (solarSys, planet); if (matchWorld (solarSys, planet, 1, MATCH_PLANET)) { COUNT angle; DWORD rand_val; solarSys->MoonDesc[0].data_index = HIERARCHY_STARBASE; solarSys->MoonDesc[0].radius = MIN_MOON_RADIUS; rand_val = TFB_Random (); angle = NORMALIZE_ANGLE (LOWORD (rand_val)); solarSys->MoonDesc[0].location.x = COSINE (angle, solarSys->MoonDesc[0].radius); solarSys->MoonDesc[0].location.y = SINE (angle, solarSys->MoonDesc[0].radius); ComputeSpeed(&solarSys->MoonDesc[0], TRUE, 1); } return true; }
static bool GenerateUtwig_generatePlanets (SOLARSYS_STATE *solarSys) { COUNT angle; GenerateDefault_generatePlanets (solarSys); if (CurStarDescPtr->Index == UTWIG_DEFINED) { solarSys->PlanetDesc[0].data_index = WATER_WORLD; solarSys->PlanetDesc[0].NumPlanets = 1; solarSys->PlanetDesc[0].radius = EARTH_RADIUS * 174L / 100; angle = ARCTAN (solarSys->PlanetDesc[0].location.x, solarSys->PlanetDesc[0].location.y); solarSys->PlanetDesc[0].location.x = COSINE (angle, solarSys->PlanetDesc[0].radius); solarSys->PlanetDesc[0].location.y = SINE (angle, solarSys->PlanetDesc[0].radius); ComputeSpeed(&solarSys->PlanetDesc[0], FALSE, 1); } return true; }
static bool GenerateRainbowWorld_generatePlanets (SOLARSYS_STATE *solarSys) { COUNT angle; GenerateDefault_generatePlanets (solarSys); solarSys->PlanetDesc[0].data_index = RAINBOW_WORLD; solarSys->PlanetDesc[0].NumPlanets = 0; solarSys->PlanetDesc[0].radius = EARTH_RADIUS * 50L / 100; angle = ARCTAN (solarSys->PlanetDesc[0].location.x, solarSys->PlanetDesc[0].location.y); if (angle <= QUADRANT) angle += QUADRANT; else if (angle >= FULL_CIRCLE - QUADRANT) angle -= QUADRANT; solarSys->PlanetDesc[0].location.x = COSINE (angle, solarSys->PlanetDesc[0].radius); solarSys->PlanetDesc[0].location.y = SINE (angle, solarSys->PlanetDesc[0].radius); return true; }
static bool GenerateSpathi_generatePlanets (SOLARSYS_STATE *solarSys) { PLANET_DESC *pMinPlanet; COUNT angle; pMinPlanet = &solarSys->PlanetDesc[0]; solarSys->SunDesc[0].NumPlanets = 1; FillOrbits (solarSys, solarSys->SunDesc[0].NumPlanets, pMinPlanet, FALSE); pMinPlanet->radius = EARTH_RADIUS * 1150L / 100; angle = ARCTAN (pMinPlanet->location.x, pMinPlanet->location.y); pMinPlanet->location.x = COSINE (angle, pMinPlanet->radius); pMinPlanet->location.y = SINE (angle, pMinPlanet->radius); pMinPlanet->data_index = WATER_WORLD; pMinPlanet->alternate_colormap = NULL; if (GET_GAME_STATE (SPATHI_SHIELDED_SELVES)) pMinPlanet->data_index |= PLANET_SHIELDED; pMinPlanet->NumPlanets = 1; ComputeSpeed(pMinPlanet, FALSE, 1); return true; }
void GeneratePkunk (BYTE control) { switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT i, which_node; DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; if (!GET_GAME_STATE (CLEAR_SPINDLE)) pSolarSysState->SysInfo.PlanetInfo.CurType = 0; else pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i)) { pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] &= ~(1L << i); if (!GET_GAME_STATE (CLEAR_SPINDLE)) { ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; SET_GAME_STATE (CLEAR_SPINDLE, 1); SET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP, 1); } } if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; pSolarSysState->PlanetDesc[0].NumPlanets = 1; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 104L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { if (ActivateStarShip (PKUNK_SHIP, SPHERE_TRACKING)) { NotifyOthers (PKUNK_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (PKUNK_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); InitCommunication (PKUNK_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); } break; } else { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (PKUNK_RUINS_STRTAB) ); if (GET_GAME_STATE (CLEAR_SPINDLE)) pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = SetAbsStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, 1 ); } } default: GenerateRandomIP (control); break; } }
static void pump_up_postprocess (ELEMENT *ElementPtr) { if (ElementPtr->state_flags & APPEARING) { ZeroVelocityComponents (&ElementPtr->velocity); } else { HELEMENT hPumpUp; ELEMENT *EPtr; ELEMENT *ShipPtr; STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); LockElement (StarShipPtr->hShip, &ShipPtr); initialize_pump_up (ShipPtr, &hPumpUp); DeltaEnergy (ShipPtr, 0); UnlockElement (StarShipPtr->hShip); LockElement (hPumpUp, &EPtr); EPtr->current.image.frame = ElementPtr->current.image.frame; EPtr->turn_wait = ElementPtr->turn_wait; EPtr->thrust_wait = ElementPtr->thrust_wait; if (--EPtr->thrust_wait == 0) { if ((EPtr->turn_wait & ~REVERSE_DIR) < MAX_PUMP - 1) { ++EPtr->turn_wait; EPtr->current.image.frame = SetRelFrameIndex ( EPtr->current.image.frame, NUM_PUMP_ANIMS); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2), EPtr); } EPtr->thrust_wait = LEVEL_COUNTER; } EPtr->mass_points = EPtr->hit_points = (PUMPUP_DAMAGE << (ElementPtr->turn_wait & ~REVERSE_DIR)); SetElementStarShip (EPtr, StarShipPtr); if (EPtr->thrust_wait & 1) { COUNT frame_index; frame_index = GetFrameIndex (EPtr->current.image.frame); if (((EPtr->turn_wait & REVERSE_DIR) && (frame_index % NUM_PUMP_ANIMS) != 0) || (!(EPtr->turn_wait & REVERSE_DIR) && ((frame_index + 1) % NUM_PUMP_ANIMS) == 0)) { --frame_index; EPtr->turn_wait |= REVERSE_DIR; } else { ++frame_index; EPtr->turn_wait &= ~REVERSE_DIR; } EPtr->current.image.frame = SetAbsFrameIndex ( EPtr->current.image.frame, frame_index); } if (StarShipPtr->cur_status_flags & StarShipPtr->old_status_flags & WEAPON) { StarShipPtr->weapon_counter = WEAPON_WAIT; } else { SIZE dx, dy; COUNT angle; EPtr->life_span = PUMPUP_LIFE; EPtr->preprocess_func = pump_up_preprocess; EPtr->postprocess_func = 0; angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); SetVelocityComponents (&EPtr->velocity, COSINE (angle, WORLD_TO_VELOCITY (PUMPUP_SPEED)), SINE (angle, WORLD_TO_VELOCITY (PUMPUP_SPEED))); GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); dx = dx * 1/2; dy = dy * 1/2; // Add some of the Trader's velocity to its projectiles. DeltaVelocityComponents (&EPtr->velocity, dx, dy); EPtr->current.location.x -= VELOCITY_TO_WORLD (dx); EPtr->current.location.y -= VELOCITY_TO_WORLD (dy); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 3), EPtr); } UnlockElement (hPumpUp); PutElement (hPumpUp); SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], NO_PRIM); ElementPtr->state_flags |= NONSOLID; } }
static void initialize_diagonal_flame (ELEMENT *ElementPtr) { COUNT i; STARSHIP *StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ElementPtr, &StarShipPtr); MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.index = 0; MissileBlock.sender = ElementPtr->playerNr; MissileBlock.flags = IGNORE_SIMILAR; MissileBlock.pixoffs = ILWRATH_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = flame_preprocess; MissileBlock.blast_offs = MISSILE_OFFSET; for(i = 0; i < 2; ++i) { HELEMENT hFlame; if (i == 0) { MissileBlock.cx = ElementPtr->next.location.x + COSINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), -32); MissileBlock.cy = ElementPtr->next.location.y + SINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), -32); MissileBlock.face = NORMALIZE_FACING (StarShipPtr->ShipFacing + 2); } else { MissileBlock.cx = ElementPtr->next.location.x + COSINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), 32); MissileBlock.cy = ElementPtr->next.location.y + SINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), 32); MissileBlock.face = NORMALIZE_FACING (StarShipPtr->ShipFacing - 2); } hFlame = initialize_missile (&MissileBlock); if (hFlame) { SIZE dx, dy; ELEMENT *FlamePtr; LockElement (hFlame, &FlamePtr); SetElementStarShip (FlamePtr, StarShipPtr); FlamePtr->hTarget = 0; GetCurrentVelocityComponents (&ElementPtr->velocity, &dx, &dy); DeltaVelocityComponents (&FlamePtr->velocity, dx, dy); FlamePtr->current.location.x -= VELOCITY_TO_WORLD (dx); FlamePtr->current.location.y -= VELOCITY_TO_WORLD (dy); FlamePtr->collision_func = flame_collision; FlamePtr->turn_wait = 0; UnlockElement (hFlame); PutElement (hFlame); } } }
// Preprocess function for spawning a ship into or out of battle. // Used when a new ship warps in, or a ship escapes by warping out, but not // when a Pkunk ship is reborn. void ship_transition (ELEMENT *ElementPtr) { if (ElementPtr->state_flags & PLAYER_SHIP) { if (ElementPtr->state_flags & APPEARING) { ElementPtr->life_span = HYPERJUMP_LIFE; ElementPtr->preprocess_func = ship_transition; ElementPtr->postprocess_func = NULL; SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; } else if (ElementPtr->life_span < HYPERJUMP_LIFE) { if (ElementPtr->life_span == NORMAL_LIFE && ElementPtr->crew_level) { ElementPtr->current.image.frame = ElementPtr->next.image.frame = SetEquFrameIndex ( ElementPtr->current.image.farray[0], ElementPtr->current.image.frame); SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMP_PRIM); InitIntersectStartPoint (ElementPtr); InitIntersectEndPoint (ElementPtr); InitIntersectFrame (ElementPtr); ZeroVelocityComponents (&ElementPtr->velocity); ElementPtr->state_flags &= ~(NONSOLID | FINITE_LIFE); ElementPtr->state_flags |= CHANGING; ElementPtr->preprocess_func = ship_preprocess; ElementPtr->postprocess_func = ship_postprocess; } return; } } { HELEMENT hShipImage; ELEMENT *ShipImagePtr; STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); LockElement (StarShipPtr->hShip, &ShipImagePtr); if (!(ShipImagePtr->state_flags & NONSOLID)) { ElementPtr->preprocess_func = NULL; } else if ((hShipImage = AllocElement ())) { #define TRANSITION_SPEED DISPLAY_TO_WORLD (40 << RESOLUTION_FACTOR) // JMS_GFX #define TRANSITION_LIFE 1 COUNT angle; PutElement (hShipImage); angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); LockElement (hShipImage, &ShipImagePtr); ShipImagePtr->playerNr = NEUTRAL_PLAYER_NUM; ShipImagePtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; ShipImagePtr->thrust_wait = TRANSITION_LIFE; ShipImagePtr->life_span = ShipImagePtr->thrust_wait; // When the element "dies", in the death_func // 'cycle_ion_trail', it is given new life a number of // times, by setting life_span to thrust_wait. SetPrimType (&DisplayArray[ShipImagePtr->PrimIndex], STAMPFILL_PRIM); SetPrimColor (&DisplayArray[ShipImagePtr->PrimIndex], START_ION_COLOR); ShipImagePtr->colorCycleIndex = 0; ShipImagePtr->current.image = ElementPtr->current.image; ShipImagePtr->current.location = ElementPtr->current.location; if (!(ElementPtr->state_flags & PLAYER_SHIP)) { ShipImagePtr->current.location.x += COSINE (angle, TRANSITION_SPEED); ShipImagePtr->current.location.y += SINE (angle, TRANSITION_SPEED); ElementPtr->preprocess_func = NULL; } else if (ElementPtr->crew_level) { ShipImagePtr->current.location.x -= COSINE (angle, TRANSITION_SPEED) * (ElementPtr->life_span - 1); ShipImagePtr->current.location.y -= SINE (angle, TRANSITION_SPEED) * (ElementPtr->life_span - 1); ShipImagePtr->current.location.x = WRAP_X (ShipImagePtr->current.location.x); ShipImagePtr->current.location.y = WRAP_Y (ShipImagePtr->current.location.y); } ShipImagePtr->preprocess_func = ship_transition; ShipImagePtr->death_func = cycle_ion_trail; SetElementStarShip (ShipImagePtr, StarShipPtr); UnlockElement (hShipImage); } UnlockElement (StarShipPtr->hShip); } }
static COUNT initialize_weapon (ELEMENT *ShipPtr, HELEMENT WeaponArray[]) { COUNT i; STARSHIP *StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; // MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = ShipPtr->playerNr; MissileBlock.flags = IGNORE_SIMILAR; MissileBlock.speed = (MISSILE_SPEED << RESOLUTION_FACTOR); MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.blast_offs = MISSILE_OFFSET; MissileBlock.preprocess_func = 0; for (i = 0; i < 2; ++i) { if (i == 0) { MissileBlock.pixoffs = THRADDASH_OFFSET_2; MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; } else if (StarShipPtr->static_counter == 0) { MissileBlock.pixoffs = THRADDASH_OFFSET_1; MissileBlock.cx = ShipPtr->next.location.x + COSINE(FACING_TO_ANGLE (MissileBlock.face + 4), -25); MissileBlock.cy = ShipPtr->next.location.y + SINE(FACING_TO_ANGLE (MissileBlock.face + 4), -25); } else { MissileBlock.pixoffs = THRADDASH_OFFSET_1; MissileBlock.cx = ShipPtr->next.location.x + COSINE(FACING_TO_ANGLE (MissileBlock.face + 4), 25); MissileBlock.cy = ShipPtr->next.location.y + SINE(FACING_TO_ANGLE (MissileBlock.face + 4), 25); } if ((WeaponArray[i] = initialize_missile (&MissileBlock))) { SIZE dx, dy; ELEMENT *WeaponPtr; LockElement (WeaponArray[i], &WeaponPtr); GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); DeltaVelocityComponents (&WeaponPtr->velocity, dx, dy); WeaponPtr->current.location.x -= VELOCITY_TO_WORLD (dx); WeaponPtr->current.location.y -= VELOCITY_TO_WORLD (dy); // WeaponPtr->collision_func = repulsor_collision; UnlockElement (WeaponArray[i]); } } return (2); }
// Secondary weapon: Gas cloud. // The IGNORE_VELOCITY flag is very important: It doesn't only stop the gas from reacting to gravity, // (see collide.h) but it also makes it possible for the gas to stick to enemy ship (see this file's other gas functions). static void spawn_gas (ELEMENT *ShipPtr) { STARSHIP *StarShipPtr; MISSILE_BLOCK MissileBlock; HELEMENT Missile; SIZE offs_x, offs_y; COUNT angle; static COUNT gas_side[NUM_SIDES] = {0, 0}; static COUNT gas_number[NUM_SIDES] = {0, 0}; GetElementStarShip (ShipPtr, &StarShipPtr); gas_number[ShipPtr->playerNr] = (gas_number[ShipPtr->playerNr] + 1) % 32; gas_side[ShipPtr->playerNr] = (gas_side[ShipPtr->playerNr] + 1) % 2; angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); // This mechanism can be used to alter the "pipe" from which the gas clouds come. if(gas_side[ShipPtr->playerNr]) { offs_x = -SINE (angle, GAS_HORZ_OFFSET); offs_y = COSINE (angle, GAS_HORZ_OFFSET); } else { offs_x = -SINE (angle, GAS_HORZ_OFFSET); offs_y = COSINE (angle, GAS_HORZ_OFFSET); } MissileBlock.cx = ShipPtr->next.location.x + offs_x; MissileBlock.cy = ShipPtr->next.location.y + offs_y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; MissileBlock.face = StarShipPtr->ShipFacing;// Baul's gas now flies forward. (this was: (StarShipPtr->ShipFacing - 8) % 16;) MissileBlock.index = LAST_DISSOLVE_INDEX; // Start with the gas emerge animation which is the last .pngs in gasXX.ani MissileBlock.sender = ShipPtr->playerNr; MissileBlock.flags = GASSY_SUBSTANCE | IGNORE_VELOCITY; // Don't erase the IGNORE_VELOCITY. It's very important. MissileBlock.pixoffs = GAS_OFFSET; MissileBlock.speed = GAS_INIT_SPEED; MissileBlock.hit_points = GAS_HITS; MissileBlock.damage = GAS_DAMAGE; MissileBlock.life = GAS_LIFE; MissileBlock.preprocess_func = gas_preprocess; MissileBlock.blast_offs = 0; Missile = initialize_missile (&MissileBlock); if (Missile) { ELEMENT *GasPtr; SIZE dx, dy; // Baul's gas now flies forward. LockElement (Missile, &GasPtr); // Baul's gas now flies forward. GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); DeltaVelocityComponents (&GasPtr->velocity, dx, dy); GasPtr->current.location.x -= VELOCITY_TO_WORLD (dx); GasPtr->current.location.y -= VELOCITY_TO_WORLD (dy); GasPtr->collision_func = gas_collision; GasPtr->death_func = gas_death; GasPtr->thrust_wait = 1; GasPtr->weapon_element_index = gas_number[ShipPtr->playerNr]; SetElementStarShip (GasPtr, StarShipPtr); ProcessSound (SetAbsSoundIndex (StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), GasPtr); UnlockElement (Missile); PutElement (Missile); } }
// Primary weapon. It must deal at least 1 damage, otherwise it won't interact with other // elements, not even gas. However, we can prevent this damage with a separate collision function. static COUNT initialize_spray (ELEMENT *ShipPtr, HELEMENT SprayArray[]) { STARSHIP *StarShipPtr; MISSILE_BLOCK MissileBlock; SIZE offs_x, offs_y; COUNT i, angle; static COUNT spray_side[NUM_SIDES]={0,0}; GetElementStarShip (ShipPtr, &StarShipPtr); angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); for (i = 0; i < NUM_SPRAYS; i++) { BYTE damage; // Only the foremost one deals damage if (i == NUM_SPRAYS-1) damage = 1; else damage = 0; // This mechanism can be used to alter the "pipe" from which the spray particles come. spray_side[ShipPtr->playerNr] = (spray_side[ShipPtr->playerNr] + 1) % 2; if(spray_side[ShipPtr->playerNr]) { offs_x = -SINE (angle, SPRAY_HORZ_OFFSET + (i << RESOLUTION_FACTOR)); offs_y = COSINE (angle, SPRAY_HORZ_OFFSET + (i << RESOLUTION_FACTOR)); } else { offs_x = -SINE (angle, SPRAY_HORZ_OFFSET + (i << RESOLUTION_FACTOR)); offs_y = COSINE (angle, SPRAY_HORZ_OFFSET + (i << RESOLUTION_FACTOR)); } MissileBlock.cx = ShipPtr->next.location.x + offs_x; MissileBlock.cy = ShipPtr->next.location.y + offs_y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.index = 0; MissileBlock.sender = ShipPtr->playerNr; MissileBlock.flags = IGNORE_SIMILAR | GASSY_SUBSTANCE; MissileBlock.pixoffs = 4 + ((i * SPRAY_DIST) << RESOLUTION_FACTOR); MissileBlock.speed = MISSILE_SPEED << RESOLUTION_FACTOR; // JMS_GFX MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = damage; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = spray_preprocess; MissileBlock.blast_offs = MISSILE_OFFSET; SprayArray[i] = initialize_missile (&MissileBlock); if (SprayArray[i]) { ELEMENT *SprayPtr; LockElement (SprayArray[i], &SprayPtr); SprayPtr->collision_func = spray_collision; SprayPtr->thrust_wait = 1; // This makes the spray shoot in a slight angle towards the centerline. // If you want a "curved" shot, put this mechanism into spray_preprocess // where it accelerates the whot towards the centerline on every frame. offs_x = -SINE (angle, (100 << RESOLUTION_FACTOR)); offs_y = COSINE (angle, (100 << RESOLUTION_FACTOR)); DeltaVelocityComponents (&SprayPtr->velocity, offs_x, offs_y); UnlockElement (SprayArray[i]); } } return (NUM_SPRAYS); }
static COUNT initialize_dual_weapons (ELEMENT *ShipPtr, HELEMENT WeaponArray[]) { #define CENTER_OFFS DISPLAY_TO_WORLD (4) COORD cx, cy; COUNT facing, angle; SIZE offs_x, offs_y; STARSHIP *StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); facing = StarShipPtr->ShipFacing; angle = FACING_TO_ANGLE (facing); cx = ShipPtr->next.location.x + COSINE (angle, CENTER_OFFS); cy = ShipPtr->next.location.y + SINE (angle, CENTER_OFFS); if (ShipPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.ship) { #define WING_OFFS DISPLAY_TO_WORLD (10) COORD ex, ey; LASER_BLOCK LaserBlock; ELEMENT *LaserPtr; LaserBlock.sender = ShipPtr->state_flags & (GOOD_GUY | BAD_GUY); LaserBlock.pixoffs = 0; LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C); LaserBlock.face = facing; ex = cx + COSINE (angle, LASER_RANGE); ey = cy + SINE (angle, LASER_RANGE); offs_x = -SINE (angle, WING_OFFS); offs_y = COSINE (angle, WING_OFFS); LaserBlock.cx = cx + offs_x; LaserBlock.cy = cy + offs_y; LaserBlock.ex = ex - LaserBlock.cx; LaserBlock.ey = ey - LaserBlock.cy; if ((WeaponArray[0] = initialize_laser (&LaserBlock))) { LockElement (WeaponArray[0], &LaserPtr); LaserPtr->collision_func = twin_laser_collision; UnlockElement (WeaponArray[0]); } LaserBlock.cx = cx - offs_x; LaserBlock.cy = cy - offs_y; LaserBlock.ex = ex - LaserBlock.cx; LaserBlock.ey = ey - LaserBlock.cy; if ((WeaponArray[1] = initialize_laser (&LaserBlock))) { LockElement (WeaponArray[1], &LaserPtr); LaserPtr->collision_func = twin_laser_collision; UnlockElement (WeaponArray[1]); } } else { #define MISSILE_HITS 1 #define MISSILE_DAMAGE 1 #define MISSILE_OFFSET 0 #define MISSILE_LIFE 40 #define LAUNCH_OFFS DISPLAY_TO_WORLD (4) MISSILE_BLOCK TorpBlock; ELEMENT *TorpPtr; TorpBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; TorpBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; TorpBlock.pixoffs = 0; TorpBlock.speed = MISSILE_SPEED; TorpBlock.hit_points = MISSILE_HITS; TorpBlock.damage = MISSILE_DAMAGE; TorpBlock.life = MISSILE_LIFE; TorpBlock.preprocess_func = missile_preprocess; TorpBlock.blast_offs = MISSILE_OFFSET; TorpBlock.face = TorpBlock.index = NORMALIZE_FACING (facing - 1); offs_x = -SINE (FACING_TO_ANGLE (TorpBlock.face), LAUNCH_OFFS); offs_y = COSINE (FACING_TO_ANGLE (TorpBlock.face), LAUNCH_OFFS); TorpBlock.cx = cx + offs_x; TorpBlock.cy = cy + offs_y; if ((WeaponArray[0] = initialize_missile (&TorpBlock))) { LockElement (WeaponArray[0], &TorpPtr); TorpPtr->turn_wait = TRACK_WAIT; UnlockElement (WeaponArray[0]); } TorpBlock.face = TorpBlock.index = NORMALIZE_FACING (facing + 1); TorpBlock.cx = cx - offs_x; TorpBlock.cy = cy - offs_y; if ((WeaponArray[1] = initialize_missile (&TorpBlock))) { LockElement (WeaponArray[1], &TorpPtr); TorpPtr->turn_wait = TRACK_WAIT; UnlockElement (WeaponArray[1]); } } return (2); }
void GenerateBurvixes (BYTE control) { COUNT i; DWORD rand_val; switch (control) { case GENERATE_ENERGY: { DWORD rand_val, old_rand; if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT which_node; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } else if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0] && !GET_GAME_STATE (BURVIXESE_BROADCASTERS)) { old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; pSolarSysState->SysInfo.PlanetInfo.CurType = 0; if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) && pSolarSysState->CurNode == (COUNT)~0) pSolarSysState->CurNode = 1; else { pSolarSysState->CurNode = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { SET_GAME_STATE (BURVIXESE_BROADCASTERS, 1); SET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP, 1); } } TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; } case GENERATE_MOONS: GenerateRandomIP (GENERATE_MOONS); if (pSolarSysState->pBaseDesc == &pSolarSysState->PlanetDesc[0]) { COUNT angle; pSolarSysState->MoonDesc[0].data_index = SELENIC_WORLD; pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS + (MAX_MOONS - 1) * MOON_DELTA; rand_val = TFB_Random (); angle = NORMALIZE_ANGLE (LOWORD (rand_val)); pSolarSysState->MoonDesc[0].location.x = COSINE (angle, pSolarSysState->MoonDesc[0].radius); pSolarSysState->MoonDesc[0].location.y = SINE (angle, pSolarSysState->MoonDesc[0].radius); } break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = REDUX_WORLD; pSolarSysState->PlanetDesc[0].NumPlanets = 1; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 39L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); break; } case GENERATE_ORBITAL: { rand_val = DoPlanetaryAnalysis ( &pSolarSysState->SysInfo, pSolarSysState->pOrbitalDesc ); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] = rand_val; i = (COUNT)~0; rand_val = GenerateLifeForms (&pSolarSysState->SysInfo, &i); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val; i = (COUNT)~0; GenerateMineralDeposits (&pSolarSysState->SysInfo, &i); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] = rand_val; if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM)); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (BURV_RUINS_STRTAB)); pSolarSysState->SysInfo.PlanetInfo.Weather = 0; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; } else if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0] && !GET_GAME_STATE (BURVIXESE_BROADCASTERS)) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (BURV_BCS_MASK_PMAP_ANIM)); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (BURV_BCS_STRTAB)); } LoadPlanet (NULL); break; } default: GenerateRandomIP (control); break; } }
static void gas_preprocess (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; SDWORD dx, dy; // Baul's gas now flies forward. Slow down the gas smoothly. GetCurrentVelocityComponentsSdword (&ElementPtr->velocity, &dx, &dy); if (dx != 0 || dy != 0) { dx = (SDWORD)(dx * 9 / 10); dy = (SDWORD)(dy * 9 / 10); SetVelocityComponents (&ElementPtr->velocity, dx, dy); } GetElementStarShip (ElementPtr, &StarShipPtr); // Move to next image frame. (Abusing thrust_wait to slow down the anim.) if (ElementPtr->thrust_wait > 0) --ElementPtr->thrust_wait; else { // Abusing thrust_wait to slow down the anim. (Should help performance a bit.) ElementPtr->thrust_wait = 1; // This makes the gas animate even if the ships are not moving and the screen is stationary. ElementPtr->state_flags |= CHANGING; if (GetFrameIndex (ElementPtr->current.image.frame) >= LAST_DISSOLVE_INDEX && GetFrameIndex (ElementPtr->current.image.frame) < LAST_DISSOLVE_INDEX + NUM_EMERGE_FRAMES) ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); else if (GetFrameIndex (ElementPtr->current.image.frame) < LAST_GAS_INDEX - 1) ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); else ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, 0); } // If enemy ship dies, remove the gas (this prevents game crashing upon enemy ship dying with gas on it). if ((!(ElementPtr->state_flags & IGNORE_VELOCITY) && ElementPtr->hTarget == 0) || StarShipPtr->RaceDescPtr->ship_info.crew_level == 0) { ElementPtr->life_span = 0; ElementPtr->state_flags |= DISAPPEARING; } // When the gas has collided with enemy ship, it sticks to the ship until expires. // (When the gas is sticking to enemy ship, the gas's IGNORE_VELOCITY flag is disabled.) else if (!(ElementPtr->state_flags & IGNORE_VELOCITY) && !(ElementPtr->state_flags & DISAPPEARING)) { ELEMENT *eptr; SIZE offs_x, offs_y; SBYTE leftOrRight, upOrDown; COUNT angle, angleCorrect; static BYTE alignment[NUM_SIDES]={0,0}; // eptr points to enemy ship now. LockElement (ElementPtr->hTarget, &eptr); // Make gas's location the same as the enemy ship's. ElementPtr->next.location = eptr->next.location; // Randomize the gas's location so every gas cloud doesn't stick to the same place on the enemy ship. GetElementStarShip (eptr, &StarShipPtr); angle = (ElementPtr->weapon_element_index) % 16; alignment[ElementPtr->playerNr] = ElementPtr->weapon_element_index % 4; if (alignment[ElementPtr->playerNr] == 0) { leftOrRight = -1; upOrDown = 1; angleCorrect = 0; } else if (alignment[ElementPtr->playerNr] == 1) { leftOrRight = 1; upOrDown = -1; angleCorrect = 0; } else if (alignment[ElementPtr->playerNr] == 2) { leftOrRight = -1; upOrDown = 1; angleCorrect = HALF_CIRCLE / 2; } else { leftOrRight = 1; upOrDown = -1; angleCorrect = HALF_CIRCLE / 2; } offs_x = SINE (angle - angleCorrect, (ElementPtr->weapon_element_index % 16) * (5 << RESOLUTION_FACTOR)); offs_y = COSINE (angle - angleCorrect, (ElementPtr->weapon_element_index % 16) * (5 << RESOLUTION_FACTOR)); ElementPtr->next.location.x = ElementPtr->next.location.x + leftOrRight * offs_x; ElementPtr->next.location.y = ElementPtr->next.location.y + upOrDown * offs_y; if (ElementPtr->turn_wait) { HELEMENT hEffect; hEffect = AllocElement (); if (hEffect) { // eptr points to the new gas element now. LockElement (hEffect, &eptr); eptr->playerNr = ElementPtr->playerNr; eptr->state_flags = FINITE_LIFE | GASSY_SUBSTANCE | CHANGING; eptr->life_span = 1; eptr->thrust_wait = 1; eptr->weapon_element_index = ElementPtr->weapon_element_index; eptr->current = eptr->next = ElementPtr->next; eptr->preprocess_func = gas_preprocess; eptr->collision_func = gas_collision; // No need to have death_func here: It carries on from the declaration in gas_collision. // In fact, if gas_death is put here as death_func, it just messes up the graphics. SetPrimType (&(GLOBAL (DisplayArray))[eptr->PrimIndex], STAMP_PRIM); GetElementStarShip (ElementPtr, &StarShipPtr); SetElementStarShip (eptr, StarShipPtr); eptr->hTarget = ElementPtr->hTarget; UnlockElement (hEffect); PutElement (hEffect); } } UnlockElement (ElementPtr->hTarget); } }