static inline COUNT randomFrameIndex (SEQUENCE *pSeq, COUNT from) { ANIMATION_DESC *ADPtr = pSeq->ADPtr; return from + TFB_Random () % (ADPtr->NumFrames - from); }
static void shofixti_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { STARSHIPPTR StarShipPtr; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->special_counter == 0) { if (StarShipPtr->ship_input_state & SPECIAL) StarShipPtr->ship_input_state &= ~SPECIAL; else { PEVALUATE_DESC lpWeaponEvalDesc, lpShipEvalDesc; lpWeaponEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; lpShipEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (StarShipPtr->RaceDescPtr->ship_data.special[0] && (GetFrameCount (StarShipPtr->RaceDescPtr->ship_data.captain_control.special) - GetFrameIndex (StarShipPtr->RaceDescPtr->ship_data.captain_control.special) > 5 || (lpShipEvalDesc->ObjectPtr != NULL_PTR && lpShipEvalDesc->which_turn <= 4) || (lpWeaponEvalDesc->ObjectPtr != NULL_PTR /* means IMMEDIATE WEAPON */ && (((lpWeaponEvalDesc->ObjectPtr->state_flags & PLAYER_SHIP) && ShipPtr->crew_level == 1) || (PlotIntercept (lpWeaponEvalDesc->ObjectPtr, ShipPtr, 2, 0) && lpWeaponEvalDesc->ObjectPtr->mass_points >= ShipPtr->crew_level && (TFB_Random () & 1)))))) StarShipPtr->ship_input_state |= SPECIAL; } } }
static void pkunk_postprocess (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->RaceDescPtr->characteristics.special_wait) --StarShipPtr->RaceDescPtr->characteristics.special_wait; else if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->RaceDescPtr->ship_info.energy_level < StarShipPtr->RaceDescPtr->ship_info.max_energy) { COUNT CurSound; do { CurSound = 2 + ((COUNT)TFB_Random () % (GetSoundCount (StarShipPtr->RaceDescPtr->ship_data.ship_sounds) - 2)); } while (CurSound == LastSound); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, CurSound ), ElementPtr); LastSound = CurSound; DeltaEnergy (ElementPtr, SPECIAL_ENERGY_COST); StarShipPtr->RaceDescPtr->characteristics.special_wait = SPECIAL_WAIT; } }
static void pkunk_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter) { STARSHIP *StarShipPtr; HELEMENT hPhoenix; GetElementStarShip (ShipPtr, &StarShipPtr); hPhoenix = (HELEMENT) StarShipPtr->RaceDescPtr->data; if (hPhoenix && (StarShipPtr->control & STANDARD_RATING)) { RemoveElement (hPhoenix); FreeElement (hPhoenix); StarShipPtr->RaceDescPtr->data = 0; } if (StarShipPtr->RaceDescPtr->ship_info.energy_level < StarShipPtr->RaceDescPtr->ship_info.max_energy && (StarShipPtr->special_counter == 0 || (BYTE)TFB_Random () < 20)) StarShipPtr->ship_input_state |= SPECIAL; else StarShipPtr->ship_input_state &= ~SPECIAL; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); }
static bool GeneratePkunk_generateEnergy (SOLARSYS_STATE *solarSys, PLANET_DESC *world, COUNT *whichNode) { if (matchWorld (solarSys, world, 0, MATCH_PLANET)) { COUNT i; COUNT nodeI; DWORD rand_val; DWORD old_rand; old_rand = TFB_SeedRandom ( solarSys->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN]); nodeI = 0; i = 0; do { rand_val = TFB_Random (); solarSys->SysInfo.PlanetInfo.CurPt.x = ((LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; solarSys->SysInfo.PlanetInfo.CurPt.y = ((LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; // JMS: No more clear spindles! /*if (!GET_GAME_STATE (CLEAR_SPINDLE)) solarSys->SysInfo.PlanetInfo.CurType = 0; else*/ solarSys->SysInfo.PlanetInfo.CurType = 1; solarSys->SysInfo.PlanetInfo.CurDensity = 0; if (solarSys->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i)) { solarSys->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] &= ~(1L << i); // JMS: No more clear spindles! /*if (!GET_GAME_STATE (CLEAR_SPINDLE)) { SetLanderTakeoff (); SET_GAME_STATE (CLEAR_SPINDLE, 1); SET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP, 1); }*/ } if (nodeI >= *whichNode && !(solarSys->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++nodeI; } while (++i < 16); *whichNode = nodeI; TFB_SeedRandom (old_rand); return true; } *whichNode = 0; return true; }
static inline DWORD randomRestartRate (SEQUENCE *pSeq) { ANIMATION_DESC *ADPtr = pSeq->ADPtr; return ADPtr->BaseRestartRate + TFB_Random () % (ADPtr->RandomRestartRate + 1); }
static void arilou_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter) { STARSHIP *StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); StarShipPtr->ship_input_state |= THRUST; ObjectsOfConcern[ENEMY_SHIP_INDEX].MoveState = ENTICE; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (StarShipPtr->special_counter == 0) { EVALUATE_DESC *lpEvalDesc; StarShipPtr->ship_input_state &= ~SPECIAL; lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 6) { BOOLEAN IsTrackingWeapon; STARSHIP *EnemyStarShipPtr; GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); if (((EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & SEEKING_WEAPON) && lpEvalDesc->ObjectPtr->next.image.farray == EnemyStarShipPtr->RaceDescPtr->ship_data.weapon) || ((EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & SEEKING_SPECIAL) && lpEvalDesc->ObjectPtr->next.image.farray == EnemyStarShipPtr->RaceDescPtr->ship_data.special)) IsTrackingWeapon = TRUE; else IsTrackingWeapon = FALSE; // JMS: Added the GASSY_SUBSTANCE clauses to prevent 'long teleport' if Baul gas is sticking to the Arilou ship. if (((lpEvalDesc->ObjectPtr->state_flags & PLAYER_SHIP) /* means IMMEDIATE WEAPON */ || (IsTrackingWeapon && (lpEvalDesc->which_turn == 1 || (lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT))) /* FIGHTERS!!! */ || (PlotIntercept (lpEvalDesc->ObjectPtr, ShipPtr, 3, 0) && (!(lpEvalDesc->ObjectPtr->state_flags & GASSY_SUBSTANCE) // Ignore stuck gas || (lpEvalDesc->ObjectPtr->state_flags & GASSY_SUBSTANCE && EnemyStarShipPtr->ship_input_state & WEAPON && ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn <= 20) // If sticking to gas, teleport when Baul is near&firing primary || (lpEvalDesc->ObjectPtr->state_flags & GASSY_SUBSTANCE && lpEvalDesc->ObjectPtr->state_flags & IGNORE_VELOCITY))) // non-stuck gas ) && !(TFB_Random () & 3)) { StarShipPtr->ship_input_state &= ~(LEFT | RIGHT | THRUST | WEAPON); StarShipPtr->ship_input_state |= SPECIAL; } } } if (StarShipPtr->RaceDescPtr->ship_info.energy_level <= SPECIAL_ENERGY_COST << 1) StarShipPtr->ship_input_state &= ~WEAPON; }
static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 1); if (PLAYER_SAID (R, bye_homeworld)) NPCPhrase (GOODBYE_AND_DIE_HOMEWORLD); else if (PLAYER_SAID (R, bye_royalist)) NPCPhrase (GOODBYE_AND_DIE_ROYALIST); else if (PLAYER_SAID (R, i_demand_you_ally_homeworld0)) { NPCPhrase (ENEMY_MUST_DIE); SET_GAME_STATE (NO_YEHAT_ALLY_HOME, 1); } else if (PLAYER_SAID (R, bye_space)) { if ((BYTE)TFB_Random () & 1) NPCPhrase (GOODBYE_AND_DIE_SPACE); else { NPCPhrase (GO_IN_PEACE); SET_GAME_STATE (BATTLE_SEGUE, 0); } } else if (PLAYER_SAID (R, not_here) || PLAYER_SAID (R, not_send)) { switch (GET_GAME_STATE (YEHAT_REBEL_VISITS)) { case 0: NPCPhrase (JUST_A_TRICK_1); break; case 1: NPCPhrase (JUST_A_TRICK_2); break; } SET_GAME_STATE (YEHAT_REBEL_VISITS, 1); } else if (PLAYER_SAID (R, ok_send)) { NPCPhrase (WE_REVOLT); SET_GAME_STATE (BATTLE_SEGUE, 0); SET_GAME_STATE (YEHAT_CIVIL_WAR, 1); SET_GAME_STATE (YEHAT_VISITS, 0); SET_GAME_STATE (YEHAT_HOME_VISITS, 0); SET_GAME_STATE (YEHAT_REBEL_VISITS, 0); SET_GAME_STATE (YEHAT_REBEL_INFO, 0); SET_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK, 0); SET_GAME_STATE (NO_YEHAT_INFO, 0); AddEvent (RELATIVE_EVENT, 0, 0, 0, YEHAT_REBEL_EVENT); } }
static bool GenerateSupox_generateEnergy (SOLARSYS_STATE *solarSys, PLANET_DESC *world, COUNT *whichNode) { if (matchWorld (solarSys, world, 0, MATCH_PLANET)) { COUNT i; COUNT nodeI; DWORD rand_val; DWORD old_rand; old_rand = TFB_SeedRandom ( solarSys->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN]); nodeI = 0; i = 0; do { rand_val = TFB_Random (); solarSys->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; solarSys->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; if (!GET_GAME_STATE (ULTRON_CONDITION)) solarSys->SysInfo.PlanetInfo.CurType = 0; else solarSys->SysInfo.PlanetInfo.CurType = 1; solarSys->SysInfo.PlanetInfo.CurDensity = 0; if (solarSys->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i)) { solarSys->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] &= ~(1L << i); if (!GET_GAME_STATE (ULTRON_CONDITION)) { SetLanderTakeoff (); SET_GAME_STATE (ULTRON_CONDITION, 1); } } if (nodeI >= *whichNode && !(solarSys->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++nodeI; } while (++i < 16); *whichNode = nodeI; TFB_SeedRandom (old_rand); return true; } *whichNode = 0; return true; }
static void bubble_preprocess (ELEMENT *ElementPtr) { BYTE thrust_wait, turn_wait; thrust_wait = HINIBBLE (ElementPtr->turn_wait); turn_wait = LONIBBLE (ElementPtr->turn_wait); if (thrust_wait > 0) --thrust_wait; else { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; thrust_wait = (BYTE)((COUNT)TFB_Random () & 3); } if (turn_wait > 0) --turn_wait; else { COUNT facing; SIZE delta_facing; facing = NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity))); if ((delta_facing = TrackShip (ElementPtr, &facing)) == -1) facing = (COUNT)TFB_Random (); else if (delta_facing <= ANGLE_TO_FACING (HALF_CIRCLE)) facing += (COUNT)TFB_Random () & (ANGLE_TO_FACING (HALF_CIRCLE) - 1); else facing -= (COUNT)TFB_Random () & (ANGLE_TO_FACING (HALF_CIRCLE) - 1); SetVelocityVector (&ElementPtr->velocity, MISSILE_SPEED, facing); #define TRACK_WAIT 2 turn_wait = TRACK_WAIT; } ElementPtr->turn_wait = MAKE_BYTE (turn_wait, thrust_wait); }
void spawn_planet (void) { HELEMENT hPlanetElement; hPlanetElement = AllocElement (); if (hPlanetElement) { ELEMENT *PlanetElementPtr; extern FRAME planet[]; LockElement (hPlanetElement, &PlanetElementPtr); PlanetElementPtr->playerNr = NEUTRAL_PLAYER_NUM; PlanetElementPtr->hit_points = 200; PlanetElementPtr->state_flags = APPEARING; PlanetElementPtr->life_span = NORMAL_LIFE + 1; SetPrimType (&DisplayArray[PlanetElementPtr->PrimIndex], STAMP_PRIM); PlanetElementPtr->current.image.farray = planet; PlanetElementPtr->current.image.frame = PlanetElementPtr->current.image.farray[0]; PlanetElementPtr->collision_func = collision; PlanetElementPtr->postprocess_func = (void (*) (struct element *ElementPtr))CalculateGravity; ZeroVelocityComponents (&PlanetElementPtr->velocity); do { PlanetElementPtr->current.location.x = WRAP_X (DISPLAY_ALIGN_X (TFB_Random ())); PlanetElementPtr->current.location.y = WRAP_Y (DISPLAY_ALIGN_Y (TFB_Random ())); } while (CalculateGravity (PlanetElementPtr) || Overlap (PlanetElementPtr)); PlanetElementPtr->mass_points = PlanetElementPtr->hit_points; PlanetElementPtr->triggers_teleport_safety = TRUE; UnlockElement (hPlanetElement); PutElement (hPlanetElement); } }
static void doggy_preprocess (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); ++StarShipPtr->special_counter; if (ElementPtr->thrust_wait > 0) /* could be non-zero after a collision */ --ElementPtr->thrust_wait; else { COUNT facing, orig_facing; SIZE delta_facing; facing = orig_facing = NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity) )); if ((delta_facing = TrackShip (ElementPtr, &facing)) < 0) facing = NORMALIZE_FACING (TFB_Random ()); else { ELEMENT *ShipPtr; LockElement (ElementPtr->hTarget, &ShipPtr); facing = NORMALIZE_FACING (ANGLE_TO_FACING ( ARCTAN (ShipPtr->current.location.x - ElementPtr->current.location.x, ShipPtr->current.location.y - ElementPtr->current.location.y) )); delta_facing = NORMALIZE_FACING (facing - GetFrameIndex (ShipPtr->current.image.frame)); UnlockElement (ElementPtr->hTarget); if (delta_facing > ANGLE_TO_FACING (HALF_CIRCLE - OCTANT) && delta_facing < ANGLE_TO_FACING (HALF_CIRCLE + OCTANT)) { if (delta_facing >= ANGLE_TO_FACING (HALF_CIRCLE)) facing -= ANGLE_TO_FACING (QUADRANT); else facing += ANGLE_TO_FACING (QUADRANT); } facing = NORMALIZE_FACING (facing); } if (facing != orig_facing) SetVelocityVector (&ElementPtr->velocity, DOGGY_SPEED, facing); } }
static void arilou_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter) { STARSHIP *StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); StarShipPtr->ship_input_state |= THRUST; ObjectsOfConcern[ENEMY_SHIP_INDEX].MoveState = ENTICE; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (StarShipPtr->special_counter == 0) { EVALUATE_DESC *lpEvalDesc; StarShipPtr->ship_input_state &= ~SPECIAL; lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 6) { BOOLEAN IsTrackingWeapon; STARSHIP *EnemyStarShipPtr; GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); if (((EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & SEEKING_WEAPON) && lpEvalDesc->ObjectPtr->next.image.farray == EnemyStarShipPtr->RaceDescPtr->ship_data.weapon) || ((EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & SEEKING_SPECIAL) && lpEvalDesc->ObjectPtr->next.image.farray == EnemyStarShipPtr->RaceDescPtr->ship_data.special)) IsTrackingWeapon = TRUE; else IsTrackingWeapon = FALSE; if (((lpEvalDesc->ObjectPtr->state_flags & PLAYER_SHIP) /* means IMMEDIATE WEAPON */ || (IsTrackingWeapon && (lpEvalDesc->which_turn == 1 || (lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT))) /* FIGHTERS!!! */ || PlotIntercept (lpEvalDesc->ObjectPtr, ShipPtr, 3, 0)) && !(TFB_Random () & 3)) { StarShipPtr->ship_input_state &= ~(LEFT | RIGHT | THRUST | WEAPON); StarShipPtr->ship_input_state |= SPECIAL; } } } if (StarShipPtr->RaceDescPtr->ship_info.energy_level <= SPECIAL_ENERGY_COST << 1) StarShipPtr->ship_input_state &= ~WEAPON; }
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 void SetupAmbientSequences (SEQUENCE *pSeq, COUNT Num) { COUNT i; for (i = 0; i < Num; ++i, ++pSeq) { ANIMATION_DESC *ADPtr = &CommData.AlienAmbientArray[i]; memset (pSeq, 0, sizeof (*pSeq)); pSeq->ADPtr = ADPtr; if (ADPtr->AnimFlags & COLORXFORM_ANIM) pSeq->AnimType = COLOR_ANIM; else pSeq->AnimType = PICTURE_ANIM; pSeq->Direction = UP_DIR; pSeq->FramesLeft = ADPtr->NumFrames; // Default: first frame is neutral if (ADPtr->AnimFlags & RANDOM_ANIM) { // Set a random frame/colormap pSeq->NextIndex = TFB_Random () % ADPtr->NumFrames; } else if (ADPtr->AnimFlags & YOYO_ANIM) { // Skip the first frame/colormap (it's neutral) pSeq->NextIndex = 1; --pSeq->FramesLeft; } else if (ADPtr->AnimFlags & CIRCULAR_ANIM) { // Exception that makes everything more painful: // *Last* frame is neutral pSeq->CurIndex = ADPtr->NumFrames - 1; pSeq->NextIndex = 0; } pSeq->Alarm = randomRestartRate (pSeq) + 1; } }
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; }
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 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 confusion_collision (ELEMENT *ElementPtr0, POINT *pPt0, ELEMENT *ElementPtr1, POINT *pPt1) { if (ElementPtr1->state_flags & PLAYER_SHIP) { HELEMENT hConfusionElement, hNextElement; ELEMENT *ConfusionPtr; STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr0, &StarShipPtr); for (hConfusionElement = GetHeadElement (); hConfusionElement; hConfusionElement = hNextElement) { LockElement (hConfusionElement, &ConfusionPtr); if (elementsOfSamePlayer (ConfusionPtr, ElementPtr0) && ConfusionPtr->current.image.farray == StarShipPtr->RaceDescPtr->ship_data.special && (ConfusionPtr->state_flags & NONSOLID)) { UnlockElement (hConfusionElement); break; } hNextElement = GetSuccElement (ConfusionPtr); UnlockElement (hConfusionElement); } if (hConfusionElement || (hConfusionElement = AllocElement ())) { LockElement (hConfusionElement, &ConfusionPtr); if (ConfusionPtr->state_flags == 0) /* not allocated before */ { InsertElement (hConfusionElement, GetHeadElement ()); ConfusionPtr->current = ElementPtr0->next; ConfusionPtr->current.image.frame = SetAbsFrameIndex ( ConfusionPtr->current.image.frame, 8 ); ConfusionPtr->next = ConfusionPtr->current; ConfusionPtr->playerNr = ElementPtr0->playerNr; ConfusionPtr->state_flags = FINITE_LIFE | NONSOLID | CHANGING; ConfusionPtr->preprocess_func = confuse_preprocess; SetPrimType ( &(GLOBAL (DisplayArray))[ConfusionPtr->PrimIndex], NO_PRIM ); SetElementStarShip (ConfusionPtr, StarShipPtr); GetElementStarShip (ElementPtr1, &StarShipPtr); ConfusionPtr->hTarget = StarShipPtr->hShip; } ConfusionPtr->life_span = 400; ConfusionPtr->turn_wait = (BYTE)(1 << ((BYTE)TFB_Random () & 1)); /* LEFT or RIGHT */ UnlockElement (hConfusionElement); } ElementPtr0->hit_points = 0; ElementPtr0->life_span = 0; ElementPtr0->state_flags |= DISAPPEARING | COLLISION | NONSOLID; } (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ }
static COUNT CalcMineralDeposits (SYSTEM_INFO *SysInfoPtr, COUNT which_deposit) { BYTE j; COUNT num_deposits; const ELEMENT_ENTRY *eptr; eptr = &SysInfoPtr->PlanetInfo.PlanDataPtr->UsefulElements[0]; num_deposits = 0; j = NUM_USEFUL_ELEMENTS; do { BYTE num_possible; num_possible = (BYTE)((BYTE)TFB_Random () % (DEPOSIT_QUANTITY (eptr->Density) + 1)); while (num_possible--) { #define MEDIUM_DEPOSIT_THRESHOLD 150 #define LARGE_DEPOSIT_THRESHOLD 225 DWORD rand_val; UWORD loword, hiword; COUNT deposit_quality_fine, deposit_quality_gross; // JMS: For making the mineral blip smaller in case it is partially scavenged. SDWORD temp_deposit_quality; deposit_quality_fine = ((COUNT)TFB_Random () % 100) + ( DEPOSIT_QUALITY (eptr->Density) + SysInfoPtr->StarSize ) * 50; // BW: Check whether we're in the NE quadrant if ((GLOBAL_SIS (log_x) > UNIVERSE_TO_LOGX(5000)) && (GLOBAL_SIS (log_y) < UNIVERSE_TO_LOGY(6000))) { deposit_quality_fine = (COUNT)(deposit_quality_fine * DEPLETION_RATE); } // JMS: This makes the mineral blip smaller in case it is partially scavenged. temp_deposit_quality = deposit_quality_fine - (SysInfoPtr->PlanetInfo.PartiallyScavengedList[MINERAL_SCAN][which_deposit] * 10); if (temp_deposit_quality < 0) temp_deposit_quality = 0; if (deposit_quality_fine < MEDIUM_DEPOSIT_THRESHOLD) deposit_quality_gross = 0; else if (deposit_quality_fine < LARGE_DEPOSIT_THRESHOLD) deposit_quality_gross = 1; else deposit_quality_gross = 2; rand_val = TFB_Random (); loword = LOWORD (rand_val); hiword = HIWORD (rand_val); if (RESOLUTION_FACTOR == 0) SysInfoPtr->PlanetInfo.CurPt.x = (LOBYTE (loword) % (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 (loword) % (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.CurDensity = MAKE_WORD (deposit_quality_gross, deposit_quality_fine / 10 + 1); SysInfoPtr->PlanetInfo.CurType = eptr->ElementType; #ifdef DEBUG_SURFACE log_add (log_Debug, "\t\t%d units of %Fs", SysInfoPtr->PlanetInfo.CurDensity, Elements[eptr->ElementType].name); #endif /* DEBUG_SURFACE */ if ((num_deposits >= which_deposit && !(SysInfoPtr->PlanetInfo.ScanRetrieveMask[MINERAL_SCAN] & (1L << num_deposits))) || ++num_deposits == sizeof (DWORD) * 8) goto ExitCalcMinerals; } ++eptr; } while (--j); ExitCalcMinerals: return (num_deposits); }
void GenerateShipVault (BYTE control) { switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) { DWORD rand_val, old_rand; 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; if (!GET_GAME_STATE (SHIP_VAULT_UNLOCKED)) pSolarSysState->SysInfo.PlanetInfo.CurType = 0; else pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->CurNode = 1; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] &= ~(1L << 0); if (GET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP)) { ((PLANETSIDE_DESC*)pMenuState->ModuleFrame)->InTransit = TRUE; SET_GAME_STATE (SHIP_VAULT_UNLOCKED, 1); SET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP, 0); SET_GAME_STATE (SYREEN_HOME_VISITS, 0); } else if (!GET_GAME_STATE (KNOW_SYREEN_VAULT)) { SET_GAME_STATE (KNOW_SYREEN_VAULT, 1); SET_GAME_STATE (SYREEN_HOME_VISITS, 0); } } TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (VAULT_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (VAULT_STRTAB) ); if (GET_GAME_STATE (SHIP_VAULT_UNLOCKED)) pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = SetAbsStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, 2 ); else if (GET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP)) pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = SetAbsStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, 1 ); } default: GenerateRandomIP (control); break; } }
static void butt_missile_preprocess (ELEMENT *ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { COUNT facing; // COUNT num_frames; SIZE delta_x, delta_y, delta_facing; ELEMENT *EnemyPtr; facing = GetFrameIndex (ElementPtr->next.image.frame); if (ElementPtr->hTarget) { LockElement (ElementPtr->hTarget, &EnemyPtr); delta_x = EnemyPtr->current.location.x - ElementPtr->current.location.x; delta_x = WRAP_DELTA_X (delta_x); delta_y = EnemyPtr->current.location.y - ElementPtr->current.location.y; delta_y = WRAP_DELTA_Y (delta_y); /* num_frames = (square_root ((long)delta_x * delta_x + (long)delta_y * delta_y)) / DISCRIMINATOR_SPEED; if (num_frames == 0) num_frames = 1; GetNextVelocityComponents (&EnemyPtr->velocity, &delta_x, &delta_y, num_frames); // Lead the target by its apparent trajectory. delta_x = (EnemyPtr->current.location.x + (delta_x / 2)) - ElementPtr->current.location.x; delta_y = (EnemyPtr->current.location.y + (delta_y / 2)) - ElementPtr->current.location.y; */ delta_facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) - facing); if (delta_facing > 0 && !OBJECT_CLOAKED(EnemyPtr)) { if (delta_facing == ANGLE_TO_FACING (HALF_CIRCLE)) facing += (((BYTE)TFB_Random () & 1) << 1) - 1; else if (delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) ++facing; else --facing; } ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->next.image.frame, facing); ElementPtr->state_flags |= CHANGING; SetVelocityVector (&ElementPtr->velocity, DISCRIMINATOR_SPEED, facing); UnlockElement (ElementPtr->hTarget); } else if (TrackShip (ElementPtr, &facing) > 0) { ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->next.image.frame, facing); ElementPtr->state_flags |= CHANGING; SetVelocityVector (&ElementPtr->velocity, DISCRIMINATOR_SPEED, facing); } ElementPtr->turn_wait = TRACK_WAIT; } }
static void supox_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter) { STARSHIP *StarShipPtr; EVALUATE_DESC *lpEvalDesc; GetElementStarShip (ShipPtr, &StarShipPtr); lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (StarShipPtr->special_counter || lpEvalDesc->ObjectPtr == 0) StarShipPtr->ship_input_state &= ~SPECIAL; else { BOOLEAN LinedUp; COUNT direction_angle; SIZE delta_x, delta_y; delta_x = lpEvalDesc->ObjectPtr->next.location.x - ShipPtr->next.location.x; delta_y = lpEvalDesc->ObjectPtr->next.location.y - ShipPtr->next.location.y; direction_angle = ARCTAN (delta_x, delta_y); LinedUp = (BOOLEAN)(NORMALIZE_ANGLE (NORMALIZE_ANGLE (direction_angle - FACING_TO_ANGLE (StarShipPtr->ShipFacing)) + QUADRANT) <= HALF_CIRCLE); if (!LinedUp || lpEvalDesc->which_turn > 20 || NORMALIZE_ANGLE ( lpEvalDesc->facing - (FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE) + OCTANT ) > QUADRANT) StarShipPtr->ship_input_state &= ~SPECIAL; else if (LinedUp && lpEvalDesc->which_turn <= 12) StarShipPtr->ship_input_state |= SPECIAL; if (StarShipPtr->ship_input_state & SPECIAL) lpEvalDesc->MoveState = PURSUE; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (StarShipPtr->ship_input_state & SPECIAL) StarShipPtr->ship_input_state |= THRUST | WEAPON; lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (StarShipPtr->special_counter == 0 && lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == AVOID && ShipPtr->turn_wait == 0) { StarShipPtr->ship_input_state &= ~THRUST; StarShipPtr->ship_input_state |= SPECIAL; if (!(StarShipPtr->cur_status_flags & (LEFT | RIGHT))) StarShipPtr->ship_input_state |= 1 << ((BYTE)TFB_Random () & 1); else StarShipPtr->ship_input_state |= StarShipPtr->cur_status_flags & (LEFT | RIGHT); } }
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 bool GenerateBurvixese_generateEnergy (SOLARSYS_STATE *solarSys, PLANET_DESC *world, COUNT *whichNode) { DWORD rand_val; DWORD old_rand; if (matchWorld (solarSys, world, 0, MATCH_PLANET)) { COUNT nodeI; COUNT i; old_rand = TFB_SeedRandom ( solarSys->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN]); nodeI = 0; i = 0; do { rand_val = TFB_Random (); solarSys->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; solarSys->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; solarSys->SysInfo.PlanetInfo.CurType = 1; solarSys->SysInfo.PlanetInfo.CurDensity = 0; if (nodeI >= *whichNode && !(solarSys->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++nodeI; } while (++i < 16); *whichNode = nodeI; TFB_SeedRandom (old_rand); return true; } if (matchWorld (solarSys, world, 0, 0) && !GET_GAME_STATE (BURVIXESE_BROADCASTERS)) { old_rand = TFB_SeedRandom ( solarSys->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN]); rand_val = TFB_Random (); solarSys->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; solarSys->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; solarSys->SysInfo.PlanetInfo.CurDensity = 0; solarSys->SysInfo.PlanetInfo.CurType = 0; if (!(solarSys->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) && *whichNode == (COUNT)~0) *whichNode = 1; else { *whichNode = 0; if (solarSys->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); return true; } *whichNode = 0; return true; }
static void arilou_preprocess (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (!(ElementPtr->state_flags & NONSOLID)) { if (ElementPtr->thrust_wait == 0) { ZeroVelocityComponents (&ElementPtr->velocity); StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; } if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0 && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { /* Special key is pressed; start teleport */ #define HYPER_LIFE 5 ZeroVelocityComponents (&ElementPtr->velocity); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | LEFT | RIGHT | THRUST | WEAPON); ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; ElementPtr->life_span = HYPER_LIFE; ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; ElementPtr->next.image.frame = StarShipPtr->RaceDescPtr->ship_data.special[0]; ProcessSound (SetAbsSoundIndex ( /* HYPERJUMP */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } } else if (ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) { COUNT life_span; StarShipPtr->cur_status_flags = (StarShipPtr->cur_status_flags & ~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL)) | (StarShipPtr->old_status_flags & (LEFT | RIGHT | THRUST | WEAPON | SPECIAL)); ++StarShipPtr->weapon_counter; ++StarShipPtr->special_counter; ++StarShipPtr->energy_counter; ++ElementPtr->turn_wait; ++ElementPtr->thrust_wait; if ((life_span = ElementPtr->life_span) == NORMAL_LIFE) { /* Ending teleport */ ElementPtr->state_flags &= ~(NONSOLID | FINITE_LIFE); ElementPtr->state_flags |= APPEARING; ElementPtr->current.image.farray = ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; ElementPtr->current.image.frame = ElementPtr->next.image.frame = SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], StarShipPtr->ShipFacing); InitIntersectStartPoint (ElementPtr); } else { /* Teleporting in progress */ --life_span; if (life_span != 2) { if (life_span < 2) ElementPtr->next.image.frame = DecFrameIndex (ElementPtr->next.image.frame); else ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->next.image.frame); } else { ElementPtr->next.location.x = WRAP_X (DISPLAY_ALIGN_X (TFB_Random ())); ElementPtr->next.location.y = WRAP_Y (DISPLAY_ALIGN_Y (TFB_Random ())); } } ElementPtr->state_flags |= CHANGING; } }
BOOLEAN Battle (BattleFrameCallback *callback) { SIZE num_ships; LockMutex (GraphicsLock); #if !(DEMO_MODE || CREATE_JOURNAL) if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE) { // In Supermelee, the RNG is already initialised. TFB_SeedRandom (GetTimeCounter ()); } #else /* DEMO_MODE */ if (BattleSeed == 0) BattleSeed = TFB_Random (); TFB_SeedRandom (BattleSeed); BattleSeed = TFB_Random (); /* get next battle seed */ #endif /* DEMO_MODE */ BattleSong (FALSE); num_ships = InitShips (); if (instantVictory) { num_ships = 0; battle_counter[0] = 1; battle_counter[1] = 0; instantVictory = FALSE; } if (num_ships) { BATTLE_STATE bs; GLOBAL (CurrentActivity) |= IN_BATTLE; battle_counter[0] = CountLinks (&race_q[0]); battle_counter[1] = CountLinks (&race_q[1]); if (optMeleeScale != TFB_SCALE_STEP) SetGraphicScaleMode (optMeleeScale); setupBattleInputOrder (); #ifdef NETPLAY initBattleInputBuffers (); #ifdef NETPLAY_CHECKSUM initChecksumBuffers (); #endif /* NETPLAY_CHECKSUM */ battleFrameCount = 0; ResetWinnerStarShip (); setBattleStateConnections (&bs); #endif /* NETPLAY */ if (!selectAllShips (num_ships)) { GLOBAL (CurrentActivity) |= CHECK_ABORT; goto AbortBattle; } BattleSong (TRUE); bs.NextTime = 0; #ifdef NETPLAY initBattleStateDataConnections (); { bool allOk = negotiateReadyConnections (true, NetState_inBattle); if (!allOk) { GLOBAL (CurrentActivity) |= CHECK_ABORT; goto AbortBattle; } } #endif /* NETPLAY */ bs.InputFunc = DoBattle; bs.frame_cb = callback; bs.first_time = (BOOLEAN)(LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE); UnlockMutex (GraphicsLock); DoInput (&bs, FALSE); LockMutex (GraphicsLock); AbortBattle: if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE) { if (GLOBAL (CurrentActivity) & CHECK_ABORT) { // Do not return to the main menu when a game is aborted, // (just to the supermelee menu). #ifdef NETPLAY UnlockMutex (GraphicsLock); waitResetConnections(NetState_inSetup); // A connection may already be in inSetup (set from // GetMeleeStarship). This is not a problem, although // it will generate a warning in debug mode. LockMutex (GraphicsLock); #endif GLOBAL (CurrentActivity) &= ~CHECK_ABORT; } else { // Show the result of the battle. MeleeGameOver (); } } #ifdef NETPLAY uninitBattleInputBuffers(); #ifdef NETPLAY_CHECKSUM uninitChecksumBuffers (); #endif /* NETPLAY_CHECKSUM */ setBattleStateConnections (NULL); #endif /* NETPLAY */ StopDitty (); StopMusic (); StopSound (); } UninitShips (); FreeBattleSong (); UnlockMutex (GraphicsLock); return (BOOLEAN) (num_ships < 0); }
static void gas_collision (ELEMENT *ElementPtr0, POINT *pPt0, ELEMENT *ElementPtr1, POINT *pPt1) { STARSHIP *StarShipPtr; STARSHIP *EnemyStarShipPtr; BYTE enemyShipIsBaul = 0; BYTE enemyShipIsChmmr = 0; // This is the ship this gas cloud belongs to. GetElementStarShip (ElementPtr0, &StarShipPtr); // Check if the colliding element is a ship. If it is not, check if it's a projectile from Baul or Chmmr ship. if (!elementsOfSamePlayer(ElementPtr0, ElementPtr1) && !(ElementPtr1->state_flags & PLAYER_SHIP) && ElementPtr1->playerNr > -1) { GetElementStarShip (ElementPtr1, &EnemyStarShipPtr); if (EnemyStarShipPtr->SpeciesID == BAUL_ID) enemyShipIsBaul = 1; else if (EnemyStarShipPtr->SpeciesID == CHMMR_ID) enemyShipIsChmmr = 1; // This is important because the gas can stick to zapsats. } // If colliding with Baul's spray weapon or shockwave, EXPLODE!!! if (ElementPtr1->current.image.farray == StarShipPtr->RaceDescPtr->ship_data.weapon || (enemyShipIsBaul && ElementPtr1->current.image.farray == EnemyStarShipPtr->RaceDescPtr->ship_data.weapon)) { // Move to shockwave graphics. ElementPtr0->current.image.frame = SetAbsFrameIndex (ElementPtr0->current.image.frame, LAST_GAS_INDEX); ElementPtr0->next.image.frame = SetAbsFrameIndex (ElementPtr0->current.image.frame, LAST_GAS_INDEX); // Remove the lock on enemy ship and make the gas die on next turn. ElementPtr0->hTarget = 0; ElementPtr0->life_span = 1; // Don't do the gas dissolve anim now that the shockwave appears. ElementPtr0->death_func = NULL; // Generate the actual shockwave. generate_shockwave (ElementPtr0, -1); // XXX ElementPtr1->playerNr); } // If colliding with enemy ship, stick to the ship. // Also stick to Chmmr's zapsats. else if (ElementPtr0->state_flags & IGNORE_VELOCITY && ElementPtr1->playerNr != ElementPtr0->playerNr && (ElementPtr1->state_flags & PLAYER_SHIP || (enemyShipIsChmmr && ElementPtr1->mass_points == 10) )) { HELEMENT hGasElement; HELEMENT hTargetElement; ELEMENT *GasPtr; // Create a new gas element which is sticking to the enemy ship. if ((hGasElement = AllocElement ())) { LockElement (hGasElement, &GasPtr); if (GasPtr->state_flags == 0) /* not allocated before */ { InsertElement (hGasElement, GetHeadElement ()); GasPtr->current = ElementPtr0->next; GasPtr->next = GasPtr->current; GasPtr->playerNr = ElementPtr0->playerNr; GasPtr->state_flags = FINITE_LIFE | GASSY_SUBSTANCE | CHANGING; GasPtr->preprocess_func = gas_preprocess; GasPtr->collision_func = gas_collision; SetPrimType (&(GLOBAL (DisplayArray))[GasPtr->PrimIndex], NO_PRIM); SetElementStarShip (GasPtr, StarShipPtr); GetElementStarShip (ElementPtr1, &StarShipPtr); // Ships and Chmmr Zapsats require different ways of making them the target of the gas cloud. if (ElementPtr1->state_flags & PLAYER_SHIP) GasPtr->hTarget = StarShipPtr->hShip; else { GasPtr->life_span = 0; LockElement (ElementPtr1, &hTargetElement); GasPtr->hTarget = hTargetElement; } } GasPtr->hit_points = ElementPtr0->hit_points; GasPtr->life_span = ElementPtr0->life_span; GasPtr->thrust_wait = 1; GasPtr->weapon_element_index = ElementPtr0->weapon_element_index; GasPtr->turn_wait = (BYTE)(1 << ((BYTE)TFB_Random () & 1)); /* LEFT or RIGHT */ GasPtr->death_func = gas_death; UnlockElement (hGasElement); } // Erase the original gas element. ElementPtr0->hit_points = 0; ElementPtr0->life_span = 0; ElementPtr0->state_flags |= DISAPPEARING | COLLISION | NONSOLID; } (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ }
static void explosion_preprocess (ELEMENT *ShipPtr) { BYTE i; i = (NUM_EXPLOSION_FRAMES * 3) - ShipPtr->life_span; switch (i) { case 25: ShipPtr->preprocess_func = NULL; case 0: case 1: case 2: case 20: case 21: case 22: case 23: case 24: i = 1; break; case 3: case 4: case 5: case 18: case 19: i = 2; break; case 15: SetPrimType (&DisplayArray[ShipPtr->PrimIndex], NO_PRIM); ShipPtr->state_flags |= CHANGING; default: i = 3; break; } do { HELEMENT hElement; hElement = AllocElement (); if (hElement) { COUNT angle, dist; DWORD rand_val; ELEMENT *ElementPtr; extern FRAME explosion[]; PutElement (hElement); LockElement (hElement, &ElementPtr); ElementPtr->playerNr = NEUTRAL_PLAYER_NUM; ElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; ElementPtr->life_span = 9; SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMP_PRIM); ElementPtr->current.image.farray = explosion; ElementPtr->current.image.frame = explosion[0]; rand_val = TFB_Random (); angle = LOBYTE (HIWORD (rand_val)); dist = DISPLAY_TO_WORLD (LOBYTE (LOWORD (rand_val)) % 8); if (HIBYTE (LOWORD (rand_val)) < 256 * 1 / 3) dist += DISPLAY_TO_WORLD (8); ElementPtr->current.location.x = ShipPtr->current.location.x + COSINE (angle, dist); ElementPtr->current.location.y = ShipPtr->current.location.y + SINE (angle, dist); ElementPtr->preprocess_func = animation_preprocess; rand_val = TFB_Random (); angle = LOBYTE (LOWORD (rand_val)); dist = WORLD_TO_VELOCITY ( DISPLAY_TO_WORLD (HIBYTE (LOWORD (rand_val)) % 5)); SetVelocityComponents (&ElementPtr->velocity, COSINE (angle, dist), SINE (angle, dist)); UnlockElement (hElement); } } while (--i); }