static void spathi_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter) { STARSHIP *StarShipPtr; EVALUATE_DESC *lpEvalDesc; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); StarShipPtr->ship_input_state &= ~SPECIAL; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (StarShipPtr->special_counter == 0 && lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 24) { COUNT travel_facing, direction_facing; SIZE delta_x, delta_y; travel_facing = NORMALIZE_FACING ( ANGLE_TO_FACING (GetVelocityTravelAngle (&ShipPtr->velocity) + HALF_CIRCLE) ); delta_x = lpEvalDesc->ObjectPtr->current.location.x - ShipPtr->current.location.x; delta_y = lpEvalDesc->ObjectPtr->current.location.y - ShipPtr->current.location.y; direction_facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) ); if (NORMALIZE_FACING (direction_facing - (StarShipPtr->ShipFacing + ANGLE_TO_FACING (HALF_CIRCLE)) + ANGLE_TO_FACING (QUADRANT)) <= ANGLE_TO_FACING (HALF_CIRCLE) && (lpEvalDesc->which_turn <= 8 || NORMALIZE_FACING (direction_facing + ANGLE_TO_FACING (HALF_CIRCLE) - ANGLE_TO_FACING (GetVelocityTravelAngle ( &lpEvalDesc->ObjectPtr->velocity )) + ANGLE_TO_FACING (QUADRANT)) <= ANGLE_TO_FACING (HALF_CIRCLE)) && (!(StarShipPtr->cur_status_flags & (SHIP_BEYOND_MAX_SPEED | SHIP_IN_GRAVITY_WELL)) || NORMALIZE_FACING (direction_facing - travel_facing + ANGLE_TO_FACING (QUADRANT)) <= ANGLE_TO_FACING (HALF_CIRCLE))) StarShipPtr->ship_input_state |= SPECIAL; } }
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 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 void buzztrack_preprocess (PELEMENT ElementPtr) { if (ElementPtr->thrust_wait) --ElementPtr->thrust_wait; else { COUNT facing = 0; if (ElementPtr->hTarget == 0 && TrackShip (ElementPtr, &facing) < 0) { ZeroVelocityComponents (&ElementPtr->velocity); } else { #define ACTIVATE_RANGE 224 /* Originally SPACE_WIDTH */ SIZE delta_x, delta_y; ELEMENTPTR eptr; LockElement (ElementPtr->hTarget, &eptr); delta_x = eptr->current.location.x - ElementPtr->current.location.x; delta_y = eptr->current.location.y - ElementPtr->current.location.y; UnlockElement (ElementPtr->hTarget); delta_x = WRAP_DELTA_X (delta_x); delta_y = WRAP_DELTA_Y (delta_y); facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) ); if (delta_x < 0) delta_x = -delta_x; if (delta_y < 0) delta_y = -delta_y; delta_x = WORLD_TO_DISPLAY (delta_x); delta_y = WORLD_TO_DISPLAY (delta_y); if (delta_x >= ACTIVATE_RANGE || delta_y >= ACTIVATE_RANGE || (DWORD)((UWORD)delta_x * delta_x) + (DWORD)((UWORD)delta_y * delta_y) >= (DWORD)ACTIVATE_RANGE * ACTIVATE_RANGE) { ZeroVelocityComponents (&ElementPtr->velocity); } else { ElementPtr->thrust_wait = TRACK_WAIT; SetVelocityVector (&ElementPtr->velocity, DISPLAY_TO_WORLD (2), facing); } } } spin_preprocess (ElementPtr); }
static COUNT initialize_turret_missile (PELEMENT ShipPtr, HELEMENT MissileArray[]) { #define MISSILE_HITS 2 #define MISSILE_DAMAGE 3 #define MISSILE_OFFSET 1 ELEMENTPTR TurretPtr; STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; LockElement (GetSuccElement (ShipPtr), &TurretPtr); if (TurretPtr->turn_wait == 0 && (StarShipPtr->cur_status_flags & SPECIAL) && (StarShipPtr->cur_status_flags & (LEFT | RIGHT))) { if (StarShipPtr->cur_status_flags & RIGHT) ++TurretPtr->thrust_wait; else --TurretPtr->thrust_wait; TurretPtr->turn_wait = TURRET_WAIT + 1; } MissileBlock.face = MissileBlock.index = NORMALIZE_FACING (StarShipPtr->ShipFacing + TurretPtr->thrust_wait); UnlockElement (GetSuccElement (ShipPtr)); MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = TURRET_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = MISSILE_OFFSET; MissileArray[0] = initialize_missile (&MissileBlock); if (MissileArray[0]) { ELEMENTPTR HowitzerPtr; LockElement (MissileArray[0], &HowitzerPtr); HowitzerPtr->collision_func = howitzer_collision; UnlockElement (MissileArray[0]); } return (1); }
static COUNT initialize_bug_missile (ELEMENT *ShipPtr, HELEMENT MissileArray[]) { #define PKUNK_OFFSET 15 #define MISSILE_HITS 1 #define MISSILE_DAMAGE 1 #define MISSILE_OFFSET 1 COUNT i; STARSHIP *StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.index = 0; MissileBlock.sender = ShipPtr->playerNr; MissileBlock.flags = IGNORE_SIMILAR; MissileBlock.pixoffs = PKUNK_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL; MissileBlock.blast_offs = MISSILE_OFFSET; for (i = 0; i < 3; ++i) { MissileBlock.face = StarShipPtr->ShipFacing + (ANGLE_TO_FACING (QUADRANT) * i); if (i == 2) MissileBlock.face += ANGLE_TO_FACING (QUADRANT); MissileBlock.face = NORMALIZE_FACING (MissileBlock.face); if ((MissileArray[i] = initialize_missile (&MissileBlock))) { SIZE dx, dy; ELEMENT *MissilePtr; LockElement (MissileArray[i], &MissilePtr); GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); DeltaVelocityComponents (&MissilePtr->velocity, dx, dy); MissilePtr->current.location.x -= VELOCITY_TO_WORLD (dx); MissilePtr->current.location.y -= VELOCITY_TO_WORLD (dy); MissilePtr->preprocess_func = animate; UnlockElement (MissileArray[i]); } } return (3); }
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 spawn_butt_missile (ELEMENT *ShipPtr) { #define SPATHI_REAR_OFFSET 20 #define DISCRIMINATOR_LIFE 30 #define DISCRIMINATOR_HITS 1 #define DISCRIMINATOR_DAMAGE 2 #define DISCRIMINATOR_OFFSET 4 HELEMENT ButtMissile; STARSHIP *StarShipPtr; MISSILE_BLOCK ButtMissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); ButtMissileBlock.cx = ShipPtr->next.location.x; ButtMissileBlock.cy = ShipPtr->next.location.y; ButtMissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; ButtMissileBlock.face = ButtMissileBlock.index = NORMALIZE_FACING (StarShipPtr->ShipFacing + ANGLE_TO_FACING (HALF_CIRCLE)); ButtMissileBlock.sender = ShipPtr->playerNr; ButtMissileBlock.flags = 0; ButtMissileBlock.pixoffs = SPATHI_REAR_OFFSET; ButtMissileBlock.speed = DISCRIMINATOR_SPEED; ButtMissileBlock.hit_points = DISCRIMINATOR_HITS; ButtMissileBlock.damage = DISCRIMINATOR_DAMAGE; ButtMissileBlock.life = DISCRIMINATOR_LIFE; ButtMissileBlock.preprocess_func = butt_missile_preprocess; ButtMissileBlock.blast_offs = DISCRIMINATOR_OFFSET; ButtMissile = initialize_missile (&ButtMissileBlock); if (ButtMissile) { ELEMENT *ButtPtr; LockElement (ButtMissile, &ButtPtr); ButtPtr->turn_wait = TRACK_WAIT; SetElementStarShip (ButtPtr, StarShipPtr); ProcessSound (SetAbsSoundIndex ( /* LAUNCH_BUTT_MISSILE */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ButtPtr); UnlockElement (ButtMissile); PutElement (ButtMissile); } }
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); }
static void blaster_preprocess (ELEMENT *ElementPtr) { BYTE wait; switch (ElementPtr->mass_points) { case BLASTER_DAMAGE * 1: if (GetFrameIndex (ElementPtr->current.image.frame) < 8) { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; } break; case BLASTER_DAMAGE * 3: if (GetFrameIndex (ElementPtr->current.image.frame) < 19) ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); else ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, 16); ElementPtr->state_flags |= CHANGING; break; } if (LONIBBLE (ElementPtr->turn_wait)) --ElementPtr->turn_wait; else if ((wait = HINIBBLE (ElementPtr->turn_wait))) { COUNT facing; facing = NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity))); if (TrackShip (ElementPtr, &facing) > 0) SetVelocityVector (&ElementPtr->velocity, BLASTER_SPEED, facing); ElementPtr->turn_wait = MAKE_BYTE (wait, wait); } }
static void asteroid_preprocess (ELEMENT *ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { COUNT frame_index; frame_index = GetFrameIndex (ElementPtr->current.image.frame); if (ElementPtr->thrust_wait & (1 << 7)) --frame_index; else ++frame_index; ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, NORMALIZE_FACING (frame_index)); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = (unsigned char)(ElementPtr->thrust_wait & ((1 << 7) - 1)); } }
static void pkunk_preprocess (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (ElementPtr->state_flags & APPEARING) { HELEMENT hPhoenix = 0; if ((BYTE)TFB_Random () & 1) hPhoenix = AllocElement (); if (hPhoenix) { ELEMENT *PhoenixPtr; LockElement (hPhoenix, &PhoenixPtr); PhoenixPtr->playerNr = ElementPtr->playerNr; PhoenixPtr->state_flags = FINITE_LIFE | NONSOLID | IGNORE_SIMILAR; PhoenixPtr->life_span = 1; PhoenixPtr->death_func = intercept_pkunk_death; SetElementStarShip (PhoenixPtr, StarShipPtr); UnlockElement (hPhoenix); InsertElement (hPhoenix, GetHeadElement ()); } StarShipPtr->RaceDescPtr->data = (intptr_t) hPhoenix; if (ElementPtr->hTarget == 0) StarShipPtr->RaceDescPtr->preprocess_func = 0; else { COUNT angle, facing; ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1 ), ElementPtr); ElementPtr->life_span = PHOENIX_LIFE; SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], NO_PRIM); ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; facing = StarShipPtr->ShipFacing; for (angle = OCTANT; angle < FULL_CIRCLE; angle += QUADRANT) { StarShipPtr->ShipFacing = NORMALIZE_FACING ( facing + ANGLE_TO_FACING (angle) ); phoenix_transition (ElementPtr); } StarShipPtr->ShipFacing = facing; } } if (StarShipPtr->RaceDescPtr->preprocess_func) { StarShipPtr->cur_status_flags &= ~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL); if (ElementPtr->life_span == NORMAL_LIFE) { ElementPtr->current.image.frame = ElementPtr->next.image.frame = SetEquFrameIndex ( ElementPtr->current.image.farray[0], ElementPtr->current.image.frame); SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], STAMP_PRIM); InitIntersectStartPoint (ElementPtr); InitIntersectEndPoint (ElementPtr); InitIntersectFrame (ElementPtr); ZeroVelocityComponents (&ElementPtr->velocity); ElementPtr->state_flags &= ~(NONSOLID | FINITE_LIFE); ElementPtr->state_flags |= CHANGING; StarShipPtr->RaceDescPtr->preprocess_func = 0; } } }
static void new_pkunk (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (!(ElementPtr->state_flags & PLAYER_SHIP)) { ELEMENT *ShipPtr; LockElement (StarShipPtr->hShip, &ShipPtr); ShipPtr->death_func = new_pkunk; UnlockElement (StarShipPtr->hShip); } else { ElementPtr->state_flags = APPEARING | PLAYER_SHIP | IGNORE_SIMILAR; ElementPtr->mass_points = SHIP_MASS; ElementPtr->preprocess_func = StarShipPtr->RaceDescPtr->preprocess_func; ElementPtr->postprocess_func = StarShipPtr->RaceDescPtr->postprocess_func; ElementPtr->death_func = (void (*) (ELEMENT *ElementPtr)) StarShipPtr->RaceDescPtr->init_weapon_func; StarShipPtr->RaceDescPtr->preprocess_func = pkunk_preprocess; StarShipPtr->RaceDescPtr->postprocess_func = pkunk_postprocess; StarShipPtr->RaceDescPtr->init_weapon_func = initialize_bug_missile; StarShipPtr->RaceDescPtr->ship_info.crew_level = MAX_CREW; StarShipPtr->RaceDescPtr->ship_info.energy_level = MAX_ENERGY; /* fix vux impairment */ StarShipPtr->RaceDescPtr->characteristics.max_thrust = MAX_THRUST; StarShipPtr->RaceDescPtr->characteristics.thrust_increment = THRUST_INCREMENT; StarShipPtr->RaceDescPtr->characteristics.turn_wait = TURN_WAIT; StarShipPtr->RaceDescPtr->characteristics.thrust_wait = THRUST_WAIT; StarShipPtr->RaceDescPtr->characteristics.special_wait = 0; StarShipPtr->ship_input_state = 0; StarShipPtr->cur_status_flags = 0; StarShipPtr->old_status_flags = 0; StarShipPtr->energy_counter = 0; StarShipPtr->weapon_counter = 0; StarShipPtr->special_counter = 0; ElementPtr->crew_level = 0; ElementPtr->turn_wait = 0; ElementPtr->thrust_wait = 0; ElementPtr->life_span = NORMAL_LIFE; StarShipPtr->ShipFacing = NORMALIZE_FACING (TFB_Random ()); ElementPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; ElementPtr->current.image.frame = SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], StarShipPtr->ShipFacing); SetPrimType (&(GLOBAL (DisplayArray))[ ElementPtr->PrimIndex ], STAMP_PRIM); do { ElementPtr->current.location.x = WRAP_X (DISPLAY_ALIGN_X (TFB_Random ())); ElementPtr->current.location.y = WRAP_Y (DISPLAY_ALIGN_Y (TFB_Random ())); } while (CalculateGravity (ElementPtr) || TimeSpaceMatterConflict (ElementPtr)); ElementPtr->hTarget = StarShipPtr->hShip; } }
static void supox_preprocess (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) /* && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST) */ ) { SIZE add_facing; add_facing = 0; if (StarShipPtr->cur_status_flags & THRUST) { if (ElementPtr->thrust_wait == 0) ++ElementPtr->thrust_wait; add_facing = ANGLE_TO_FACING (HALF_CIRCLE); } if (StarShipPtr->cur_status_flags & LEFT) { if (ElementPtr->turn_wait == 0) ++ElementPtr->turn_wait; if (add_facing) add_facing += ANGLE_TO_FACING (OCTANT); else add_facing = -ANGLE_TO_FACING (QUADRANT); } else if (StarShipPtr->cur_status_flags & RIGHT) { if (ElementPtr->turn_wait == 0) ++ElementPtr->turn_wait; if (add_facing) add_facing -= ANGLE_TO_FACING (OCTANT); else add_facing = ANGLE_TO_FACING (QUADRANT); } if (add_facing) { COUNT facing; STATUS_FLAGS thrust_status; facing = StarShipPtr->ShipFacing; StarShipPtr->ShipFacing = NORMALIZE_FACING ( facing + add_facing ); thrust_status = inertial_thrust (ElementPtr); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED | SHIP_IN_GRAVITY_WELL); StarShipPtr->cur_status_flags |= thrust_status; StarShipPtr->ShipFacing = facing; } } }
static void BuildUrquanGuard (SOLARSYS_STATE *solarSys) { BYTE ship1, ship2; BYTE b0, b1; POINT org; HIPGROUP hGroup, hNextGroup; GLOBAL (BattleGroupRef) = GET_GAME_STATE_32 (SAMATRA_GRPOFFS0); if (!GET_GAME_STATE (KOHR_AH_FRENZY)) { ship1 = URQUAN_SHIP; ship2 = BLACK_URQUAN_SHIP; } else { ship1 = BLACK_URQUAN_SHIP; ship2 = URQUAN_SHIP; } assert (CountLinks (&GLOBAL (npc_built_ship_q)) == 0); for (b0 = 0; b0 < MAX_SHIPS_PER_SIDE; ++b0) CloneShipFragment (ship1, &GLOBAL (npc_built_ship_q), 0); if (GLOBAL (BattleGroupRef) == 0) { GLOBAL (BattleGroupRef) = PutGroupInfo (GROUPS_ADD_NEW, 1); SET_GAME_STATE_32 (SAMATRA_GRPOFFS0, GLOBAL (BattleGroupRef)); } #define NUM_URQUAN_GUARDS0 12 for (b0 = 1; b0 <= NUM_URQUAN_GUARDS0; ++b0) PutGroupInfo (GLOBAL (BattleGroupRef), b0); ReinitQueue (&GLOBAL (npc_built_ship_q)); for (b0 = 0; b0 < MAX_SHIPS_PER_SIDE; ++b0) CloneShipFragment (ship2, &GLOBAL (npc_built_ship_q), 0); #define NUM_URQUAN_GUARDS1 4 for (b0 = 1; b0 <= NUM_URQUAN_GUARDS1; ++b0) PutGroupInfo (GLOBAL (BattleGroupRef), (BYTE)(NUM_URQUAN_GUARDS0 + b0)); ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GLOBAL (BattleGroupRef), GROUP_INIT_IP); org = planetOuterLocation (4); hGroup = GetHeadLink (&GLOBAL (ip_group_q)); for (b0 = 0, b1 = 0; b0 < NUM_URQUAN_GUARDS0; ++b0, b1 += FULL_CIRCLE / (NUM_URQUAN_GUARDS0 + NUM_URQUAN_GUARDS1)) { IP_GROUP *GroupPtr; if (b1 % (FULL_CIRCLE / NUM_URQUAN_GUARDS1) == 0) b1 += FULL_CIRCLE / (NUM_URQUAN_GUARDS0 + NUM_URQUAN_GUARDS1); GroupPtr = LockIpGroup (&GLOBAL (ip_group_q), hGroup); hNextGroup = _GetSuccLink (GroupPtr); GroupPtr->task = ON_STATION | IGNORE_FLAGSHIP; GroupPtr->sys_loc = 0; GroupPtr->dest_loc = 4 + 1; GroupPtr->orbit_pos = NORMALIZE_FACING (ANGLE_TO_FACING (b1)); GroupPtr->group_counter = 0; GroupPtr->loc.x = org.x + COSINE (b1, STATION_RADIUS); GroupPtr->loc.y = org.y + SINE (b1, STATION_RADIUS); UnlockIpGroup (&GLOBAL (ip_group_q), hGroup); hGroup = hNextGroup; } for (b0 = 0, b1 = 0; b0 < NUM_URQUAN_GUARDS1; ++b0, b1 += FULL_CIRCLE / NUM_URQUAN_GUARDS1) { IP_GROUP *GroupPtr; GroupPtr = LockIpGroup (&GLOBAL (ip_group_q), hGroup); hNextGroup = _GetSuccLink (GroupPtr); GroupPtr->task = ON_STATION | IGNORE_FLAGSHIP; GroupPtr->sys_loc = 0; GroupPtr->dest_loc = 4 + 1; GroupPtr->orbit_pos = NORMALIZE_FACING (ANGLE_TO_FACING (b1)); GroupPtr->group_counter = 0; GroupPtr->loc.x = org.x + COSINE (b1, STATION_RADIUS); GroupPtr->loc.y = org.y + SINE (b1, STATION_RADIUS); UnlockIpGroup (&GLOBAL (ip_group_q), hGroup); hGroup = hNextGroup; } (void) solarSys; }
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 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); } } }
static void thraddash_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter) { STARSHIP *StarShipPtr; EVALUATE_DESC *lpEvalDesc; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr) { #define STATIONARY_SPEED WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (4)) SIZE dx, dy; GetCurrentVelocityComponents ( &lpEvalDesc->ObjectPtr->velocity, &dx, &dy ); if (lpEvalDesc->which_turn > 8 || (long)dx * dx + (long)dy * dy <= (long)STATIONARY_SPEED * STATIONARY_SPEED) lpEvalDesc->MoveState = PURSUE; else lpEvalDesc->MoveState = ENTICE; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->special_counter == 0) { StarShipPtr->ship_input_state &= ~SPECIAL; if (ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr && ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState == ENTICE) { if ((StarShipPtr->ship_input_state & THRUST) || (ShipPtr->turn_wait == 0 && !(StarShipPtr->ship_input_state & (LEFT | RIGHT))) || NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle ( &ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr->velocity ) + HALF_CIRCLE + OCTANT) - StarShipPtr->ShipFacing) > ANGLE_TO_FACING (QUADRANT)) StarShipPtr->ship_input_state |= SPECIAL; } else if (lpEvalDesc->ObjectPtr) { if (lpEvalDesc->MoveState == PURSUE) { if (StarShipPtr->RaceDescPtr->ship_info.energy_level >= WEAPON_ENERGY_COST + SPECIAL_ENERGY_COST && ShipPtr->turn_wait == 0 && !(StarShipPtr->ship_input_state & (LEFT | RIGHT)) && (!(StarShipPtr->cur_status_flags & SPECIAL) || !(StarShipPtr->cur_status_flags & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)))) StarShipPtr->ship_input_state |= SPECIAL; } else if (lpEvalDesc->MoveState == ENTICE) { 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); if ((lpEvalDesc->which_turn > 24 && !(StarShipPtr->ship_input_state & (LEFT | RIGHT))) || (lpEvalDesc->which_turn <= 16 && NORMALIZE_ANGLE (direction_angle - (FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE) + QUADRANT) <= HALF_CIRCLE && (lpEvalDesc->which_turn < 12 || NORMALIZE_ANGLE (direction_angle - (GetVelocityTravelAngle ( &lpEvalDesc->ObjectPtr->velocity ) + HALF_CIRCLE) + (OCTANT + 2)) <= ((OCTANT + 2) << 1)))) StarShipPtr->ship_input_state |= SPECIAL; } } if ((StarShipPtr->ship_input_state & SPECIAL) && StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST) StarShipPtr->ship_input_state &= ~THRUST; } }
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 spawn_asteroid (ELEMENT *ElementPtr) { HELEMENT hAsteroidElement; if ((hAsteroidElement = AllocElement ()) == 0) { if (ElementPtr != 0) { ElementPtr->state_flags &= ~DISAPPEARING; SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); ElementPtr->life_span = 1; } } else { ELEMENT *AsteroidElementPtr; COUNT val; LockElement (hAsteroidElement, &AsteroidElementPtr); AsteroidElementPtr->playerNr = NEUTRAL_PLAYER_NUM; AsteroidElementPtr->hit_points = 1; AsteroidElementPtr->mass_points = 3; AsteroidElementPtr->state_flags = APPEARING; AsteroidElementPtr->life_span = NORMAL_LIFE; SetPrimType (&DisplayArray[AsteroidElementPtr->PrimIndex], STAMP_PRIM); if ((val = (COUNT)TFB_Random ()) & (1 << 0)) { if (!(val & (1 << 1))) AsteroidElementPtr->current.location.x = 0; else AsteroidElementPtr->current.location.x = LOG_SPACE_WIDTH; AsteroidElementPtr->current.location.y = WRAP_Y (DISPLAY_ALIGN_Y (TFB_Random ())); } else { AsteroidElementPtr->current.location.x = WRAP_X (DISPLAY_ALIGN_X (TFB_Random ())); if (!(val & (1 << 1))) AsteroidElementPtr->current.location.y = 0; else AsteroidElementPtr->current.location.y = LOG_SPACE_HEIGHT; } { // Using these temporary variables because the execution order // of function arguments may vary per system, which may break // synchronisation on network games. SIZE magnitude = DISPLAY_TO_WORLD (((SIZE)TFB_Random () & 7) + 4); COUNT facing = (COUNT)TFB_Random (); SetVelocityVector (&AsteroidElementPtr->velocity, magnitude, facing); } AsteroidElementPtr->current.image.farray = asteroid; AsteroidElementPtr->current.image.frame = SetAbsFrameIndex (asteroid[0], NORMALIZE_FACING (TFB_Random ())); AsteroidElementPtr->turn_wait = AsteroidElementPtr->thrust_wait = (BYTE)TFB_Random () & (BYTE)((1 << 2) - 1); AsteroidElementPtr->thrust_wait |= (BYTE)TFB_Random () & (BYTE)(1 << 7); AsteroidElementPtr->preprocess_func = asteroid_preprocess; AsteroidElementPtr->death_func = spawn_rubble; AsteroidElementPtr->collision_func = collision; AsteroidElementPtr->triggers_teleport_safety = TRUE; UnlockElement (hAsteroidElement); PutElement (hAsteroidElement); } }
static void androsynth_preprocess (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; STATUS_FLAGS cur_status_flags; GetElementStarShip (ElementPtr, &StarShipPtr); cur_status_flags = StarShipPtr->cur_status_flags; if (ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.ship) { if (cur_status_flags & SPECIAL) { if (StarShipPtr->RaceDescPtr->ship_info.energy_level < SPECIAL_ENERGY_COST) DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST); /* so text will flash */ else { cur_status_flags &= ~WEAPON; ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; ElementPtr->next.image.frame = SetEquFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0], ElementPtr->next.image.frame); ElementPtr->state_flags |= CHANGING; } } } else { cur_status_flags &= ~(THRUST | WEAPON | SPECIAL); /* protection against vux */ if (StarShipPtr->RaceDescPtr->characteristics.turn_wait > BLAZER_TURN_WAIT) { StarShipPtr->RaceDescPtr->characteristics.special_wait += StarShipPtr->RaceDescPtr->characteristics.turn_wait - BLAZER_TURN_WAIT; StarShipPtr->RaceDescPtr->characteristics.turn_wait = BLAZER_TURN_WAIT; } if (StarShipPtr->RaceDescPtr->ship_info.energy_level == 0) { ZeroVelocityComponents (&ElementPtr->velocity); cur_status_flags &= ~(LEFT | RIGHT | SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); StarShipPtr->RaceDescPtr->characteristics.turn_wait = StarShipPtr->RaceDescPtr->characteristics.special_wait; StarShipPtr->RaceDescPtr->characteristics.energy_regeneration = ENERGY_REGENERATION; ElementPtr->mass_points = SHIP_MASS; ElementPtr->collision_func = (CollisionFunc *) StarShipPtr->RaceDescPtr->data; ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; ElementPtr->next.image.frame = SetEquFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], ElementPtr->next.image.frame); ElementPtr->state_flags |= CHANGING; } else { if (ElementPtr->thrust_wait) --ElementPtr->thrust_wait; else { #define BLAZER_THRUST (60 << RESOLUTION_FACTOR) // JMS_GFX COUNT facing; facing = StarShipPtr->ShipFacing; if (ElementPtr->turn_wait == 0 && (cur_status_flags & (LEFT | RIGHT))) { if (cur_status_flags & LEFT) --facing; else ++facing; } SetVelocityVector (&ElementPtr->velocity, BLAZER_THRUST, NORMALIZE_FACING (facing)); cur_status_flags |= SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED; } } } StarShipPtr->cur_status_flags = cur_status_flags; }
static void sis_hyper_preprocess (ELEMENT *ElementPtr) { SIZE udx, udy, dx, dy; SIZE AccelerateDirection; STARSHIP *StarShipPtr; if (ElementPtr->state_flags & APPEARING) ElementPtr->velocity = GLOBAL (velocity); AccelerateDirection = 0; GetElementStarShip (ElementPtr, &StarShipPtr); ++StarShipPtr->weapon_counter; /* no shooting in hyperspace! */ if ((GLOBAL (autopilot)).x == ~0 || (GLOBAL (autopilot)).y == ~0 || (StarShipPtr->cur_status_flags & (LEFT | RIGHT | THRUST))) { LeaveAutoPilot: (GLOBAL (autopilot)).x = (GLOBAL (autopilot)).y = ~0; if (!(StarShipPtr->cur_status_flags & THRUST) || (GLOBAL_SIS (FuelOnBoard) == 0 && GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1)) { AccelerateDirection = -1; GetCurrentVelocityComponents (&ElementPtr->velocity, &dx, &dy); udx = dx << 4; udy = dy << 4; StarShipPtr->cur_status_flags &= ~THRUST; } } else { SIZE facing; POINT universe; universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); udx = (GLOBAL (autopilot)).x - universe.x; udy = -((GLOBAL (autopilot)).y - universe.y); if ((dx = udx) < 0) dx = -dx; if ((dy = udy) < 0) dy = -dy; if (dx <= 1 && dy <= 1) goto LeaveAutoPilot; facing = NORMALIZE_FACING (ANGLE_TO_FACING (ARCTAN (udx, udy))); /* This prevents ship from flying backwards on auto-pilot. * It could also theoretically abort autopilot in a bad savegame */ if ((StarShipPtr->cur_status_flags & SHIP_AT_MAX_SPEED) /*|| (ElementPtr->state_flags & APPEARING)*/ ) { if (NORMALIZE_FACING (StarShipPtr->ShipFacing + ANGLE_TO_FACING (QUADRANT) - facing) > ANGLE_TO_FACING (HALF_CIRCLE)) goto LeaveAutoPilot; facing = StarShipPtr->ShipFacing; } else if ((int)facing != (int)StarShipPtr->ShipFacing && ElementPtr->turn_wait == 0) { if (NORMALIZE_FACING ( StarShipPtr->ShipFacing - facing ) >= ANGLE_TO_FACING (HALF_CIRCLE)) { facing = NORMALIZE_FACING (facing - 1); StarShipPtr->cur_status_flags |= RIGHT; } else if ((int)StarShipPtr->ShipFacing != (int)facing) { facing = NORMALIZE_FACING (facing + 1); StarShipPtr->cur_status_flags |= LEFT; } if ((int)facing == (int)StarShipPtr->ShipFacing) { ZeroVelocityComponents (&ElementPtr->velocity); } } GetCurrentVelocityComponents (&ElementPtr->velocity, &dx, &dy); if ((GLOBAL_SIS (FuelOnBoard) || GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1) && (int)facing == (int)StarShipPtr->ShipFacing) { StarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED; AccelerateDirection = 1; } else { AccelerateDirection = -1; udx = dx << 4; udy = dy << 4; } } if (ElementPtr->thrust_wait == 0 && AccelerateDirection) { COUNT dist; SIZE speed, velocity_increment; velocity_increment = WORLD_TO_VELOCITY ( StarShipPtr->RaceDescPtr->characteristics.thrust_increment); if ((dist = square_root ((long)udx * udx + (long)udy * udy)) == 0) dist = 1; /* prevent divide by zero */ speed = square_root ((long)dx * dx + (long)dy * dy); if (AccelerateDirection < 0) { dy = (speed / velocity_increment - 1) * velocity_increment; if (dy < speed - velocity_increment) dy = speed - velocity_increment; if ((speed = dy) < 0) speed = 0; StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; } else { SIZE max_velocity; AccelerateDirection = 0; max_velocity = WORLD_TO_VELOCITY ( StarShipPtr->RaceDescPtr->characteristics.max_thrust); dy = (speed / velocity_increment + 1) * velocity_increment; if (dy < speed + velocity_increment) dy = speed + velocity_increment; if ((speed = dy) > max_velocity) { speed = max_velocity; StarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED; } } dx = (SIZE)((long)udx * speed / (long)dist); dy = (SIZE)((long)udy * speed / (long)dist); SetVelocityComponents (&ElementPtr->velocity, dx, dy); ElementPtr->thrust_wait = StarShipPtr->RaceDescPtr->characteristics.thrust_wait; } }
static void ilwrath_preprocess (PELEMENT ElementPtr) { ELEMENT_FLAGS status_flags; STARSHIPPTR StarShipPtr; PPRIMITIVE lpPrim; GetElementStarShip (ElementPtr, &StarShipPtr); status_flags = StarShipPtr->cur_status_flags; lpPrim = &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex]; if (GetPrimType (lpPrim) == STAMPFILL_PRIM) { COLOR Color; BOOLEAN weapon_discharge; Color = GetPrimColor (lpPrim); weapon_discharge = ((status_flags & WEAPON) && StarShipPtr->RaceDescPtr->ship_info.energy_level >= WEAPON_ENERGY_COST); if (weapon_discharge || (StarShipPtr->special_counter == 0 && ((status_flags & SPECIAL) || Color != BLACK_COLOR))) { if (Color == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)) SetPrimType (lpPrim, STAMP_PRIM); else if (Color == BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); else if (Color == BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)); else if (Color == BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); else if (Color == BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); else { ProcessSound (SetAbsSoundIndex ( /* CLOAKING_OFF */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2), ElementPtr); SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); if (weapon_discharge) { COUNT facing; facing = StarShipPtr->ShipFacing; if (TrackShip (ElementPtr, &facing) >= 0) { #define LOOK_AHEAD 4 ELEMENTPTR eptr; SIZE dx0, dy0, dx1, dy1; VELOCITY_DESC v; LockElement (ElementPtr->hTarget, &eptr); v = eptr->velocity; GetNextVelocityComponents (&v, &dx0, &dy0, LOOK_AHEAD); v = ElementPtr->velocity; GetNextVelocityComponents (&v, &dx1, &dy1, LOOK_AHEAD); dx0 = (eptr->current.location.x + dx0) - (ElementPtr->current.location.x + dx1); dy0 = (eptr->current.location.y + dy0) - (ElementPtr->current.location.y + dy1); UnlockElement (ElementPtr->hTarget); StarShipPtr->ShipFacing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (dx0, dy0)) ); #ifdef NOTYET if (ElementPtr->thrust_wait == 0 && (StarShipPtr->cur_status_flags & THRUST)) { COUNT last_facing; do { VELOCITY_DESC temp_v; last_facing = StarShipPtr->ShipFacing; inertial_thrust (ElementPtr); temp_v = ElementPtr->velocity; ElementPtr->velocity = v; dx0 += dx1; dy0 += dy1; GetNextVelocityComponents (&temp_v, &dx1, &dy1, LOOK_AHEAD); dx0 -= dx1; dy0 -= dy1; StarShipPtr->ShipFacing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (dx0, dy0)) ); } while (StarShipPtr->ShipFacing != last_facing); } #endif /* NOTYET */ if (ElementPtr->turn_wait == 0) ++ElementPtr->turn_wait; ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->next.image.frame, StarShipPtr->ShipFacing); } ElementPtr->hTarget = 0; } } ElementPtr->state_flags |= CHANGING; status_flags &= ~SPECIAL; StarShipPtr->special_counter = 0; } else if (Color != BLACK_COLOR) { if (Color == BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)) { SetPrimColor (lpPrim, BLACK_COLOR); Untarget (ElementPtr); } else if (Color == BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); else if (Color == BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); else if (Color == BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); else SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)); ElementPtr->state_flags |= CHANGING; } } if ((status_flags & SPECIAL) && StarShipPtr->special_counter == 0 && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); SetPrimType (lpPrim, STAMPFILL_PRIM); ProcessSound (SetAbsSoundIndex ( /* CLOAKING_ON */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; ElementPtr->state_flags |= CHANGING; } }
static COUNT initialize_blasters (ELEMENT *ShipPtr, HELEMENT BlasterArray[]) { #define SIS_VERT_OFFSET 28 #define SIS_HORZ_OFFSET 20 #define BLASTER_HITS 2 #define BLASTER_OFFSET 8 COUNT num_blasters; BYTE nt; COUNT i; STARSHIP *StarShipPtr; MISSILE_BLOCK MissileBlock[6]; MISSILE_BLOCK *lpMB; GetElementStarShip (ShipPtr, &StarShipPtr); num_blasters = 0; for (i = 0, lpMB = &MissileBlock[0]; i < NUM_MODULE_SLOTS; ++i) { BYTE which_gun; if (i == 3) i = NUM_MODULE_SLOTS - 1; which_gun = GLOBAL_SIS (ModuleSlots[(NUM_MODULE_SLOTS - 1) - i]); if (which_gun >= GUN_WEAPON && which_gun <= CANNON_WEAPON) { which_gun -= GUN_WEAPON - 1; lpMB->cx = ShipPtr->next.location.x; lpMB->cy = ShipPtr->next.location.y; lpMB->farray = StarShipPtr->RaceDescPtr->ship_data.weapon; lpMB->sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; lpMB->blast_offs = BLASTER_OFFSET; lpMB->speed = BLASTER_SPEED; lpMB->preprocess_func = blaster_preprocess; lpMB->hit_points = BLASTER_HITS * which_gun; lpMB->damage = BLASTER_DAMAGE * which_gun; lpMB->life = BLASTER_LIFE + ((BLASTER_LIFE >> 2) * (which_gun - 1)); if (which_gun == 1) lpMB->index = 0; else if (which_gun == 2) lpMB->index = 9; else lpMB->index = 16; switch (i) { case 0: /* NOSE WEAPON */ lpMB->pixoffs = SIS_VERT_OFFSET; lpMB->face = StarShipPtr->ShipFacing; break; case 1: /* SPREAD WEAPON */ lpMB->pixoffs = SIS_VERT_OFFSET; lpMB->face = NORMALIZE_FACING ( StarShipPtr->ShipFacing + 1); lpMB[1] = lpMB[0]; ++lpMB; lpMB->face = NORMALIZE_FACING ( StarShipPtr->ShipFacing - 1); break; case 2: /* SIDE WEAPON */ lpMB->pixoffs = SIS_HORZ_OFFSET; lpMB->face = NORMALIZE_FACING ( StarShipPtr->ShipFacing + ANGLE_TO_FACING (QUADRANT)); lpMB[1] = lpMB[0]; ++lpMB; lpMB->face = NORMALIZE_FACING ( StarShipPtr->ShipFacing - ANGLE_TO_FACING (QUADRANT)); break; case NUM_MODULE_SLOTS - 1: /* TAIL WEAPON */ lpMB->pixoffs = SIS_VERT_OFFSET; lpMB->face = NORMALIZE_FACING ( StarShipPtr->ShipFacing + ANGLE_TO_FACING (HALF_CIRCLE)); break; } ++lpMB; } }