static void druuge_postprocess (ELEMENT *ElementPtr) { STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); /* if just fired cannon */ if ((StarShipPtr->cur_status_flags & WEAPON) && StarShipPtr->weapon_counter == StarShipPtr->RaceDescPtr->characteristics.weapon_wait) { COUNT angle; SIZE cur_delta_x, cur_delta_y; StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE; DeltaVelocityComponents (&ElementPtr->velocity, COSINE (angle, RECOIL_VELOCITY), SINE (angle, RECOIL_VELOCITY)); GetCurrentVelocityComponents (&ElementPtr->velocity, &cur_delta_x, &cur_delta_y); if ((long)cur_delta_x * (long)cur_delta_x + (long)cur_delta_y * (long)cur_delta_y > (long)MAX_RECOIL_VELOCITY * (long)MAX_RECOIL_VELOCITY) { angle = ARCTAN (cur_delta_x, cur_delta_y); SetVelocityComponents (&ElementPtr->velocity, COSINE (angle, MAX_RECOIL_VELOCITY), SINE (angle, MAX_RECOIL_VELOCITY)); } } }
static 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 decelerate_preprocess (ELEMENT *ElementPtr) { SIZE dx, dy; GetCurrentVelocityComponents (&ElementPtr->velocity, &dx, &dy); dx /= 2; dy /= 2; SetVelocityComponents (&ElementPtr->velocity, dx, dy); if (dx == 0 && dy == 0) { ElementPtr->preprocess_func = buzztrack_preprocess; } spin_preprocess (ElementPtr); }
static COUNT initialize_flame (PELEMENT ShipPtr, HELEMENT FlameArray[]) { #define ILWRATH_OFFSET 29 #define MISSILE_SPEED MAX_THRUST #define MISSILE_HITS 1 #define MISSILE_DAMAGE 1 #define MISSILE_OFFSET 0 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; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.index = 0; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | 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; FlameArray[0] = initialize_missile (&MissileBlock); if (FlameArray[0]) { SIZE dx, dy; ELEMENTPTR FlamePtr; LockElement (FlameArray[0], &FlamePtr); GetCurrentVelocityComponents (&ShipPtr->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 (FlameArray[0]); } return (1); }
static COUNT initialize_cannon (ELEMENT *ShipPtr, HELEMENT CannonArray[]) { 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.face = StarShipPtr->ShipFacing; MissileBlock.index = MissileBlock.face; MissileBlock.sender = ShipPtr->playerNr; MissileBlock.flags = IGNORE_SIMILAR; MissileBlock.pixoffs = DRUUGE_OFFSET; MissileBlock.speed = (MISSILE_SPEED << RESOLUTION_FACTOR); MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL; MissileBlock.blast_offs = MISSILE_OFFSET; CannonArray[0] = initialize_missile (&MissileBlock); if (CannonArray[0]) { SIZE dx, dy; ELEMENT *CannonPtr; LockElement (CannonArray[0], &CannonPtr); CannonPtr->collision_func = cannon_collision; GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); dx = dx * 1/2; dy = dy * 1/2; // Add some of the Mauler's velocity to its projectiles. DeltaVelocityComponents (&CannonPtr->velocity, dx, dy); CannonPtr->current.location.x -= VELOCITY_TO_WORLD (dx); CannonPtr->current.location.y -= VELOCITY_TO_WORLD (dy); UnlockElement (CannonArray[0]); } return (1); }
static COUNT initialize_test_pump_up (ELEMENT *ShipPtr, HELEMENT PumpUpArray[]) { STARSHIP *StarShipPtr; MISSILE_BLOCK MissileBlock; //ELEMENT *PumpUpPtr; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.index = 0; MissileBlock.sender = ShipPtr->playerNr; MissileBlock.flags = IGNORE_SIMILAR; MissileBlock.pixoffs = MELNORME_OFFSET; MissileBlock.speed = PUMPUP_SPEED; MissileBlock.hit_points = PUMPUP_DAMAGE; MissileBlock.damage = PUMPUP_DAMAGE; MissileBlock.life = PUMPUP_LIFE; MissileBlock.preprocess_func = 0; MissileBlock.blast_offs = 0; PumpUpArray[0] = initialize_missile (&MissileBlock); if (PumpUpArray[0]) { SIZE dx, dy; ELEMENT *MissilePtr; LockElement (PumpUpArray[0], &MissilePtr); GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); dx = dx * 1/2; dy = dy * 1/2; // Add some of the Trader's velocity to its projectiles. DeltaVelocityComponents (&MissilePtr->velocity, dx, dy); MissilePtr->current.location.x -= VELOCITY_TO_WORLD (dx); MissilePtr->current.location.y -= VELOCITY_TO_WORLD (dy); UnlockElement (PumpUpArray[0]); } return (1); }
static COUNT initialize_confusion (ELEMENT *ShipPtr, HELEMENT ConfusionArray[]) { STARSHIP *StarShipPtr; MISSILE_BLOCK ConfusionBlock; GetElementStarShip (ShipPtr, &StarShipPtr); ConfusionBlock.cx = ShipPtr->next.location.x; ConfusionBlock.cy = ShipPtr->next.location.y; ConfusionBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; ConfusionBlock.index = 0; ConfusionBlock.face = StarShipPtr->ShipFacing; ConfusionBlock.sender = ShipPtr->playerNr; ConfusionBlock.flags = IGNORE_SIMILAR; ConfusionBlock.pixoffs = MELNORME_OFFSET; ConfusionBlock.speed = CMISSILE_SPEED; ConfusionBlock.hit_points = CMISSILE_HITS; ConfusionBlock.damage = CMISSILE_DAMAGE; ConfusionBlock.life = CMISSILE_LIFE; ConfusionBlock.preprocess_func = confuse_preprocess; ConfusionBlock.blast_offs = CMISSILE_OFFSET; ConfusionArray[0] = initialize_missile (&ConfusionBlock); if (ConfusionArray[0]) { ELEMENT *CMissilePtr; SIZE dx,dy; LockElement (ConfusionArray[0], &CMissilePtr); CMissilePtr->collision_func = confusion_collision; SetElementStarShip (CMissilePtr, StarShipPtr); GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); dx = dx * 3/4; dy = dy * 3/4; // Add some of the Trader's velocity to its projectiles. DeltaVelocityComponents (&CMissilePtr->velocity, dx, dy); CMissilePtr->current.location.x -= VELOCITY_TO_WORLD (dx); CMissilePtr->current.location.y -= VELOCITY_TO_WORLD (dy); UnlockElement (ConfusionArray[0]); } return (1); }
static void cannon_collision (ELEMENT *ElementPtr0, POINT *pPt0, ELEMENT *ElementPtr1, POINT *pPt1) { weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); if ((ElementPtr1->state_flags & PLAYER_SHIP) && ElementPtr1->crew_level && !GRAVITY_MASS (ElementPtr1->mass_points + 1)) { COUNT angle; SIZE cur_delta_x, cur_delta_y; STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr1, &StarShipPtr); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); angle = FACING_TO_ANGLE ( GetFrameIndex (ElementPtr0->next.image.frame) ); DeltaVelocityComponents (&ElementPtr1->velocity, COSINE (angle, RECOIL_VELOCITY), SINE (angle, RECOIL_VELOCITY)); GetCurrentVelocityComponents (&ElementPtr1->velocity, &cur_delta_x, &cur_delta_y); if ((long)cur_delta_x * (long)cur_delta_x + (long)cur_delta_y * (long)cur_delta_y > (long)MAX_RECOIL_VELOCITY * (long)MAX_RECOIL_VELOCITY) { angle = ARCTAN (cur_delta_x, cur_delta_y); SetVelocityComponents (&ElementPtr1->velocity, COSINE (angle, MAX_RECOIL_VELOCITY), SINE (angle, MAX_RECOIL_VELOCITY)); } } }
static void androsynth_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter) { EVALUATE_DESC *lpEvalDesc; STARSHIP *StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; /* in blazer form */ if (ShipPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) { ObjectsOfConcern[CREW_OBJECT_INDEX].ObjectPtr = 0; if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE) { if ((lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE) && !(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) lpEvalDesc->MoveState = AVOID; else lpEvalDesc->ObjectPtr = 0; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); } else { STARSHIP *pEnemyStarShip = NULL; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr) { GetElementStarShip (lpEvalDesc->ObjectPtr, &pEnemyStarShip); // JMS_GFX if (lpEvalDesc->which_turn <= 16 && (StarShipPtr->special_counter > 0 || StarShipPtr->RaceDescPtr->ship_info.energy_level < MAX_ENERGY / 3 || ((WEAPON_RANGE (&pEnemyStarShip->RaceDescPtr->cyborg_control) <= (CLOSE_RANGE_WEAPON << RESOLUTION_FACTOR) && lpEvalDesc->ObjectPtr->crew_level > BLAZER_DAMAGE) || (lpEvalDesc->ObjectPtr->crew_level > (BLAZER_DAMAGE * 3) && MANEUVERABILITY (&pEnemyStarShip->RaceDescPtr->cyborg_control) > SLOW_SHIP)))) lpEvalDesc->MoveState = ENTICE; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (StarShipPtr->special_counter == 0) { StarShipPtr->ship_input_state &= ~SPECIAL; // JMS_GFX if ((ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn <= 4) || (lpEvalDesc->ObjectPtr && StarShipPtr->RaceDescPtr->ship_info.energy_level >= MAX_ENERGY / 3 && (WEAPON_RANGE (&pEnemyStarShip->RaceDescPtr->cyborg_control) >= WEAPON_RANGE (&StarShipPtr->RaceDescPtr->cyborg_control) << 1 || (lpEvalDesc->which_turn < 16 && (WEAPON_RANGE (&pEnemyStarShip->RaceDescPtr->cyborg_control) > (CLOSE_RANGE_WEAPON << RESOLUTION_FACTOR) || lpEvalDesc->ObjectPtr->crew_level <= BLAZER_DAMAGE) && (lpEvalDesc->ObjectPtr->crew_level <= (BLAZER_DAMAGE * 3) || MANEUVERABILITY (&pEnemyStarShip->RaceDescPtr->cyborg_control) <= SLOW_SHIP))))) StarShipPtr->ship_input_state |= SPECIAL; } if (!(StarShipPtr->ship_input_state & SPECIAL) && StarShipPtr->weapon_counter == 0 && lpEvalDesc->ObjectPtr) { if (lpEvalDesc->which_turn <= 4) StarShipPtr->ship_input_state |= WEAPON; else if (lpEvalDesc->MoveState != PURSUE && lpEvalDesc->which_turn <= 12) { COUNT travel_facing, direction_facing; SIZE delta_x, delta_y, ship_delta_x, ship_delta_y, other_delta_x, other_delta_y; GetCurrentVelocityComponents (&ShipPtr->velocity, &ship_delta_x, &ship_delta_y); GetCurrentVelocityComponents (&lpEvalDesc->ObjectPtr->velocity, &other_delta_x, &other_delta_y); delta_x = ship_delta_x - other_delta_x; delta_y = ship_delta_y - other_delta_y; travel_facing = ARCTAN (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_facing = ARCTAN (delta_x, delta_y); if (NORMALIZE_ANGLE (travel_facing - direction_facing + OCTANT) <= QUADRANT) StarShipPtr->ship_input_state |= WEAPON; } } } }
static COUNT initialize_flak (ELEMENT *ShipPtr, HELEMENT MissileArray[]) { 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.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = ShipPtr->playerNr; MissileBlock.flags = IGNORE_SIMILAR; MissileBlock.pixoffs = SPATHI_FORWARD_OFFSET; MissileBlock.speed = (MISSILE_SPEED << RESOLUTION_FACTOR); MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = flak_preprocess; MissileBlock.blast_offs = MISSILE_OFFSET; for(i = 0; i < 3; ++i) { if (i == 0) { MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; } else if (i == 1) { MissileBlock.cx = ShipPtr->next.location.x + COSINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), 12); MissileBlock.cy = ShipPtr->next.location.y + SINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), 12); } else if (i == 2) { MissileBlock.cx = ShipPtr->next.location.x + COSINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), -12); MissileBlock.cy = ShipPtr->next.location.y + SINE(FACING_TO_ANGLE(StarShipPtr->ShipFacing + 4), -12); } if ((MissileArray[i] = initialize_missile (&MissileBlock))) { SIZE dx, dy, angle, speed; ELEMENT *MissilePtr; LockElement (MissileArray[i], &MissilePtr); if (i > 0) { angle = GetVelocityTravelAngle (&MissilePtr->velocity); GetCurrentVelocityComponents(&MissilePtr->velocity, &dx, &dy); speed = square_root (dx*dx + dy*dy); if (i == 1) angle += 1; else if (i == 2) angle -= 1; SetVelocityComponents(&MissilePtr->velocity, COSINE(angle, speed), SINE(angle, speed)); } GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); // Add the Eluder's velocity to its projectiles. DeltaVelocityComponents (&MissilePtr->velocity, dx, dy); MissilePtr->current.location.x -= VELOCITY_TO_WORLD (dx); MissilePtr->current.location.y -= VELOCITY_TO_WORLD (dy); MissilePtr->turn_wait = 1; UnlockElement (MissileArray[i]); } } return (3); }
static void pump_up_postprocess (ELEMENT *ElementPtr) { if (ElementPtr->state_flags & APPEARING) { ZeroVelocityComponents (&ElementPtr->velocity); } else { HELEMENT hPumpUp; ELEMENT *EPtr; ELEMENT *ShipPtr; STARSHIP *StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); LockElement (StarShipPtr->hShip, &ShipPtr); initialize_pump_up (ShipPtr, &hPumpUp); DeltaEnergy (ShipPtr, 0); UnlockElement (StarShipPtr->hShip); LockElement (hPumpUp, &EPtr); EPtr->current.image.frame = ElementPtr->current.image.frame; EPtr->turn_wait = ElementPtr->turn_wait; EPtr->thrust_wait = ElementPtr->thrust_wait; if (--EPtr->thrust_wait == 0) { if ((EPtr->turn_wait & ~REVERSE_DIR) < MAX_PUMP - 1) { ++EPtr->turn_wait; EPtr->current.image.frame = SetRelFrameIndex ( EPtr->current.image.frame, NUM_PUMP_ANIMS); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2), EPtr); } EPtr->thrust_wait = LEVEL_COUNTER; } EPtr->mass_points = EPtr->hit_points = (PUMPUP_DAMAGE << (ElementPtr->turn_wait & ~REVERSE_DIR)); SetElementStarShip (EPtr, StarShipPtr); if (EPtr->thrust_wait & 1) { COUNT frame_index; frame_index = GetFrameIndex (EPtr->current.image.frame); if (((EPtr->turn_wait & REVERSE_DIR) && (frame_index % NUM_PUMP_ANIMS) != 0) || (!(EPtr->turn_wait & REVERSE_DIR) && ((frame_index + 1) % NUM_PUMP_ANIMS) == 0)) { --frame_index; EPtr->turn_wait |= REVERSE_DIR; } else { ++frame_index; EPtr->turn_wait &= ~REVERSE_DIR; } EPtr->current.image.frame = SetAbsFrameIndex ( EPtr->current.image.frame, frame_index); } if (StarShipPtr->cur_status_flags & StarShipPtr->old_status_flags & WEAPON) { StarShipPtr->weapon_counter = WEAPON_WAIT; } else { SIZE dx, dy; COUNT angle; EPtr->life_span = PUMPUP_LIFE; EPtr->preprocess_func = pump_up_preprocess; EPtr->postprocess_func = 0; angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); SetVelocityComponents (&EPtr->velocity, COSINE (angle, WORLD_TO_VELOCITY (PUMPUP_SPEED)), SINE (angle, WORLD_TO_VELOCITY (PUMPUP_SPEED))); GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); dx = dx * 1/2; dy = dy * 1/2; // Add some of the Trader's velocity to its projectiles. DeltaVelocityComponents (&EPtr->velocity, dx, dy); EPtr->current.location.x -= VELOCITY_TO_WORLD (dx); EPtr->current.location.y -= VELOCITY_TO_WORLD (dy); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 3), EPtr); } UnlockElement (hPumpUp); PutElement (hPumpUp); SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], NO_PRIM); ElementPtr->state_flags |= NONSOLID; } }
static void mmrnmhrm_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter) { BOOLEAN CanTransform; EVALUATE_DESC *lpEvalDesc; STARSHIP *StarShipPtr; STARSHIP *EnemyStarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); CanTransform = (BOOLEAN)(StarShipPtr->special_counter == 0 && StarShipPtr->RaceDescPtr->ship_info.energy_level >= StarShipPtr->RaceDescPtr->characteristics.special_energy_cost); lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr) { GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); StarShipPtr->ship_input_state &= ~SPECIAL; if (CanTransform && lpEvalDesc->ObjectPtr && !(StarShipPtr->ship_input_state & WEAPON)) { SIZE delta_x, delta_y; COUNT travel_angle, direction_angle; GetCurrentVelocityComponents (&lpEvalDesc->ObjectPtr->velocity, &delta_x, &delta_y); if (delta_x == 0 && delta_y == 0) direction_angle = travel_angle = 0; else { delta_x = lpEvalDesc->ObjectPtr->current.location.x - ShipPtr->current.location.x; delta_y = lpEvalDesc->ObjectPtr->current.location.y - ShipPtr->current.location.y; direction_angle = ARCTAN (-delta_x, -delta_y); travel_angle = GetVelocityTravelAngle ( &lpEvalDesc->ObjectPtr->velocity ); } if (ShipPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.ship) { if (lpEvalDesc->which_turn > 8) { if (MANEUVERABILITY (&EnemyStarShipPtr->RaceDescPtr->cyborg_control) <= SLOW_SHIP || NORMALIZE_ANGLE ( direction_angle - travel_angle + QUADRANT ) > HALF_CIRCLE) StarShipPtr->ship_input_state |= SPECIAL; } } else { SIZE ship_delta_x, ship_delta_y; GetCurrentVelocityComponents (&ShipPtr->velocity, &ship_delta_x, &ship_delta_y); delta_x -= ship_delta_x; delta_y -= ship_delta_y; travel_angle = ARCTAN (delta_x, delta_y); if (lpEvalDesc->which_turn < 16) { if (lpEvalDesc->which_turn <= 8 || NORMALIZE_ANGLE ( direction_angle - travel_angle + OCTANT ) <= QUADRANT) StarShipPtr->ship_input_state |= SPECIAL; } else if (lpEvalDesc->which_turn > 32 && NORMALIZE_ANGLE ( direction_angle - travel_angle + QUADRANT ) > HALF_CIRCLE) StarShipPtr->ship_input_state |= SPECIAL; } } if (ShipPtr->current.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) { if (!(StarShipPtr->ship_input_state & SPECIAL) && lpEvalDesc->ObjectPtr) StarShipPtr->ship_input_state |= WEAPON; else StarShipPtr->ship_input_state &= ~WEAPON; } }
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 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 COUNT initialize_weapon (ELEMENT *ShipPtr, HELEMENT WeaponArray[]) { COUNT i; STARSHIP *StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; // MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = ShipPtr->playerNr; MissileBlock.flags = IGNORE_SIMILAR; MissileBlock.speed = (MISSILE_SPEED << RESOLUTION_FACTOR); MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.blast_offs = MISSILE_OFFSET; MissileBlock.preprocess_func = 0; for (i = 0; i < 2; ++i) { if (i == 0) { MissileBlock.pixoffs = THRADDASH_OFFSET_2; MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; } else if (StarShipPtr->static_counter == 0) { MissileBlock.pixoffs = THRADDASH_OFFSET_1; MissileBlock.cx = ShipPtr->next.location.x + COSINE(FACING_TO_ANGLE (MissileBlock.face + 4), -25); MissileBlock.cy = ShipPtr->next.location.y + SINE(FACING_TO_ANGLE (MissileBlock.face + 4), -25); } else { MissileBlock.pixoffs = THRADDASH_OFFSET_1; MissileBlock.cx = ShipPtr->next.location.x + COSINE(FACING_TO_ANGLE (MissileBlock.face + 4), 25); MissileBlock.cy = ShipPtr->next.location.y + SINE(FACING_TO_ANGLE (MissileBlock.face + 4), 25); } if ((WeaponArray[i] = initialize_missile (&MissileBlock))) { SIZE dx, dy; ELEMENT *WeaponPtr; LockElement (WeaponArray[i], &WeaponPtr); GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); DeltaVelocityComponents (&WeaponPtr->velocity, dx, dy); WeaponPtr->current.location.x -= VELOCITY_TO_WORLD (dx); WeaponPtr->current.location.y -= VELOCITY_TO_WORLD (dy); // WeaponPtr->collision_func = repulsor_collision; UnlockElement (WeaponArray[i]); } } return (2); }
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 void baul_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter) { BYTE old_count; STARSHIP *StarShipPtr; EVALUATE_DESC *lpEvalDesc; BYTE in_gas_cloud = 0; GetElementStarShip (ShipPtr, &StarShipPtr); old_count = StarShipPtr->weapon_counter; // Don't spawn gas unless specifically told to. StarShipPtr->ship_input_state &= ~SPECIAL; // See if there is gas sticking to OUR ship. lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (lpEvalDesc->ObjectPtr) { if (lpEvalDesc->ObjectPtr->state_flags & GASSY_SUBSTANCE && lpEvalDesc->ObjectPtr->mass_points == 0 && lpEvalDesc->which_turn <= 1) in_gas_cloud = 1; } // Now that we're done with the gas examinations, examine enemy ship. lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; // Actions towards enemy ship: if (lpEvalDesc->ObjectPtr) { #define STATIONARY_SPEED WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (4 << RESOLUTION_FACTOR)) // JMS_GFX SIZE dx, dy; GetCurrentVelocityComponents (&lpEvalDesc->ObjectPtr->velocity, &dx, &dy); // Chase the ship if it's within a reasonable distance and there's no gas sticking to OUR ship. if ((lpEvalDesc->which_turn < 20 || (long)dx * dx + (long)dy * dy <= (long)STATIONARY_SPEED * STATIONARY_SPEED) && !in_gas_cloud) lpEvalDesc->MoveState = PURSUE; // Otherwise, entice. else lpEvalDesc->MoveState = ENTICE; } // Normal ship intelligence. ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); // We don't want the Baul shooting all the time so it doesn't kill itself so easily. if (lpEvalDesc->ObjectPtr) { STARSHIP *EnemyStarShipPtr; GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); // If the enemy is very close, don't shoot him with the primary to avoid damage to self. // We shoot however, if the enemy ship has lazer or tries to shoot us. // The philosophy: Better to kill both than do nothing and die. if (StarShipPtr->ship_input_state & WEAPON && lpEvalDesc->which_turn < 8 && !(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & IMMEDIATE_WEAPON) && !(EnemyStarShipPtr->ship_input_state & WEAPON) && !(EnemyStarShipPtr->ship_input_state & SPECIAL) ) StarShipPtr->ship_input_state &= ~WEAPON; } // Drop gas whenever the battery tops off and when we are far away from the enemy. if ((StarShipPtr->RaceDescPtr->ship_info.energy_level == StarShipPtr->RaceDescPtr->ship_info.max_energy) && lpEvalDesc->which_turn > 12 && !in_gas_cloud) StarShipPtr->ship_input_state |= SPECIAL; // Consider dropping gas also when the enemy is in our sights. if (StarShipPtr->special_counter == 0) { BYTE old_input_state; old_input_state = StarShipPtr->ship_input_state; // The final decision of "to gas or not to gas" is made by evaluating a test weapon function. StarShipPtr->RaceDescPtr->init_weapon_func = initialize_test_gas; ship_intelligence (ShipPtr, ObjectsOfConcern, ENEMY_SHIP_INDEX + 1); // Since we faked using primary weapon even though we really are gonna use special, // change the WEAPON button press to SPECIAL. if (StarShipPtr->ship_input_state & WEAPON) { StarShipPtr->ship_input_state &= ~WEAPON; StarShipPtr->ship_input_state |= SPECIAL; } StarShipPtr->ship_input_state = (unsigned char)(old_input_state | (StarShipPtr->ship_input_state & SPECIAL)); } // Return the original stats. StarShipPtr->weapon_counter = old_count; StarShipPtr->RaceDescPtr->init_weapon_func = initialize_spray; }
// Secondary weapon: Gas cloud. // The IGNORE_VELOCITY flag is very important: It doesn't only stop the gas from reacting to gravity, // (see collide.h) but it also makes it possible for the gas to stick to enemy ship (see this file's other gas functions). static void spawn_gas (ELEMENT *ShipPtr) { STARSHIP *StarShipPtr; MISSILE_BLOCK MissileBlock; HELEMENT Missile; SIZE offs_x, offs_y; COUNT angle; static COUNT gas_side[NUM_SIDES] = {0, 0}; static COUNT gas_number[NUM_SIDES] = {0, 0}; GetElementStarShip (ShipPtr, &StarShipPtr); gas_number[ShipPtr->playerNr] = (gas_number[ShipPtr->playerNr] + 1) % 32; gas_side[ShipPtr->playerNr] = (gas_side[ShipPtr->playerNr] + 1) % 2; angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); // This mechanism can be used to alter the "pipe" from which the gas clouds come. if(gas_side[ShipPtr->playerNr]) { offs_x = -SINE (angle, GAS_HORZ_OFFSET); offs_y = COSINE (angle, GAS_HORZ_OFFSET); } else { offs_x = -SINE (angle, GAS_HORZ_OFFSET); offs_y = COSINE (angle, GAS_HORZ_OFFSET); } MissileBlock.cx = ShipPtr->next.location.x + offs_x; MissileBlock.cy = ShipPtr->next.location.y + offs_y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; MissileBlock.face = StarShipPtr->ShipFacing;// Baul's gas now flies forward. (this was: (StarShipPtr->ShipFacing - 8) % 16;) MissileBlock.index = LAST_DISSOLVE_INDEX; // Start with the gas emerge animation which is the last .pngs in gasXX.ani MissileBlock.sender = ShipPtr->playerNr; MissileBlock.flags = GASSY_SUBSTANCE | IGNORE_VELOCITY; // Don't erase the IGNORE_VELOCITY. It's very important. MissileBlock.pixoffs = GAS_OFFSET; MissileBlock.speed = GAS_INIT_SPEED; MissileBlock.hit_points = GAS_HITS; MissileBlock.damage = GAS_DAMAGE; MissileBlock.life = GAS_LIFE; MissileBlock.preprocess_func = gas_preprocess; MissileBlock.blast_offs = 0; Missile = initialize_missile (&MissileBlock); if (Missile) { ELEMENT *GasPtr; SIZE dx, dy; // Baul's gas now flies forward. LockElement (Missile, &GasPtr); // Baul's gas now flies forward. GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); DeltaVelocityComponents (&GasPtr->velocity, dx, dy); GasPtr->current.location.x -= VELOCITY_TO_WORLD (dx); GasPtr->current.location.y -= VELOCITY_TO_WORLD (dy); GasPtr->collision_func = gas_collision; GasPtr->death_func = gas_death; GasPtr->thrust_wait = 1; GasPtr->weapon_element_index = gas_number[ShipPtr->playerNr]; SetElementStarShip (GasPtr, StarShipPtr); ProcessSound (SetAbsSoundIndex (StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), GasPtr); UnlockElement (Missile); PutElement (Missile); } }