From 7f6002caba3f0a6749820c2772161caf55b8d267 Mon Sep 17 00:00:00 2001 From: neonloop Date: Fri, 7 May 2021 20:00:12 +0000 Subject: Initial commit (uqm-0.8.0) --- src/uqm/ships/slylandr/slylandr.c | 438 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 438 insertions(+) create mode 100644 src/uqm/ships/slylandr/slylandr.c (limited to 'src/uqm/ships/slylandr/slylandr.c') diff --git a/src/uqm/ships/slylandr/slylandr.c b/src/uqm/ships/slylandr/slylandr.c new file mode 100644 index 0000000..8c4ca95 --- /dev/null +++ b/src/uqm/ships/slylandr/slylandr.c @@ -0,0 +1,438 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "../ship.h" +#include "slylandr.h" +#include "resinst.h" + +#include "uqm/globdata.h" +#include "libs/mathlib.h" + +// Core characteristics +#define MAX_CREW 12 +#define MAX_ENERGY 20 +#define ENERGY_REGENERATION 0 +#define ENERGY_WAIT 10 +#define MAX_THRUST 60 +#define THRUST_INCREMENT MAX_THRUST +#define THRUST_WAIT 0 +#define TURN_WAIT 0 +#define SHIP_MASS 1 + +// Lightning weapon +#define WEAPON_ENERGY_COST 2 +#define WEAPON_WAIT 17 +#define SLYLANDRO_OFFSET 9 +#define LASER_LENGTH 32 + /* Total length of lighting bolts. Actual range is usually less than + * this, since the lightning rarely is straight. */ + +// Harvester +#define SPECIAL_ENERGY_COST 0 +#define SPECIAL_WAIT 20 +#define HARVEST_RANGE (208 * 3 / 8) + /* Was originally (SPACE_HEIGHT * 3 / 8) */ + +static RACE_DESC slylandro_desc = +{ + { /* SHIP_INFO */ + SEEKING_WEAPON | CREW_IMMUNE, + 17, /* Super Melee cost */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + SLYLANDRO_RACE_STRINGS, + SLYLANDRO_ICON_MASK_PMAP_ANIM, + SLYLANDRO_MICON_MASK_PMAP_ANIM, + NULL, NULL, NULL + }, + { /* FLEET_STUFF */ + INFINITE_RADIUS, /* Initial sphere of influence radius */ + { /* Known location (center of SoI) */ + 333, 9812, + }, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + SLYLANDRO_BIG_MASK_PMAP_ANIM, + SLYLANDRO_MED_MASK_PMAP_ANIM, + SLYLANDRO_SML_MASK_PMAP_ANIM, + }, + { + NULL_RESOURCE, + NULL_RESOURCE, + NULL_RESOURCE, + }, + { + NULL_RESOURCE, + NULL_RESOURCE, + NULL_RESOURCE, + }, + { + SLYLANDRO_CAPTAIN_MASK_PMAP_ANIM, + NULL, NULL, NULL, NULL, NULL + }, + SLYLANDRO_VICTORY_SONG, + SLYLANDRO_SHIP_SOUNDS, + { NULL, NULL, NULL }, + { NULL, NULL, NULL }, + { NULL, NULL, NULL }, + NULL, NULL + }, + { + 0, + CLOSE_RANGE_WEAPON << 1, + NULL, + }, + (UNINIT_FUNC *) NULL, + (PREPROCESS_FUNC *) NULL, + (POSTPROCESS_FUNC *) NULL, + (INIT_WEAPON_FUNC *) NULL, + 0, + 0, /* CodeRef */ +}; + +static COUNT initialize_lightning (ELEMENT *ElementPtr, + HELEMENT LaserArray[]); + +static void +lightning_postprocess (ELEMENT *ElementPtr) +{ + if (ElementPtr->turn_wait + && !(ElementPtr->state_flags & COLLISION)) + { + HELEMENT Lightning; + + initialize_lightning (ElementPtr, &Lightning); + if (Lightning) + PutElement (Lightning); + } +} + +static void +lightning_collision (ELEMENT *ElementPtr0, POINT *pPt0, + ELEMENT *ElementPtr1, POINT *pPt1) +{ + STARSHIP *StarShipPtr; + + GetElementStarShip (ElementPtr0, &StarShipPtr); + if (StarShipPtr->weapon_counter > WEAPON_WAIT >> 1) + StarShipPtr->weapon_counter = + WEAPON_WAIT - StarShipPtr->weapon_counter; + StarShipPtr->weapon_counter -= ElementPtr0->turn_wait; + ElementPtr0->turn_wait = 0; + + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); +} + +static COUNT +initialize_lightning (ELEMENT *ElementPtr, HELEMENT LaserArray[]) +{ + LASER_BLOCK LaserBlock; + + LaserBlock.cx = ElementPtr->next.location.x; + LaserBlock.cy = ElementPtr->next.location.y; + LaserBlock.ex = 0; + LaserBlock.ey = 0; + + LaserBlock.sender = ElementPtr->playerNr; + LaserBlock.flags = IGNORE_SIMILAR; + LaserBlock.face = 0; + LaserBlock.pixoffs = 0; + LaserArray[0] = initialize_laser (&LaserBlock); + + if (LaserArray[0]) + { + SIZE delta; + COUNT angle, facing; + DWORD rand_val; + ELEMENT *LaserPtr; + STARSHIP *StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + + LockElement (LaserArray[0], &LaserPtr); + LaserPtr->postprocess_func = lightning_postprocess; + LaserPtr->collision_func = lightning_collision; + + rand_val = TFB_Random (); + + if (!(ElementPtr->state_flags & PLAYER_SHIP)) + { + angle = GetVelocityTravelAngle (&ElementPtr->velocity); + facing = NORMALIZE_FACING (ANGLE_TO_FACING (angle)); + delta = TrackShip (ElementPtr, &facing); + + LaserPtr->turn_wait = ElementPtr->turn_wait - 1; + + SetPrimColor (&(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], + GetPrimColor (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex])); + } + else + { + facing = StarShipPtr->ShipFacing; + ElementPtr->hTarget = 0; + delta = TrackShip (ElementPtr, &facing); + ElementPtr->hTarget = 0; + angle = FACING_TO_ANGLE (facing); + + if ((LaserPtr->turn_wait = StarShipPtr->weapon_counter) == 0) + LaserPtr->turn_wait = WEAPON_WAIT; + + if (LaserPtr->turn_wait > WEAPON_WAIT >> 1) + LaserPtr->turn_wait = WEAPON_WAIT - LaserPtr->turn_wait; + + switch (HIBYTE (LOWORD (rand_val)) & 3) + { + case 0: + SetPrimColor ( + &(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) + ); + break; + case 1: + SetPrimColor ( + &(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], + BUILD_COLOR (MAKE_RGB15 (0x16, 0x17, 0x1F), 0x42) + ); + break; + case 2: + SetPrimColor ( + &(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], + BUILD_COLOR (MAKE_RGB15 (0x06, 0x07, 0x1F), 0x4A) + ); + break; + case 3: + SetPrimColor ( + &(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x18), 0x50) + ); + break; + } + } + + if (delta == -1 || delta == ANGLE_TO_FACING (HALF_CIRCLE)) + angle += LOWORD (rand_val); + else if (delta == 0) + angle += LOWORD (rand_val) & 1 ? -1 : 1; + else if (delta < ANGLE_TO_FACING (HALF_CIRCLE)) + angle += LOWORD (rand_val) & (QUADRANT - 1); + else + angle -= LOWORD (rand_val) & (QUADRANT - 1); + delta = WORLD_TO_VELOCITY ( + DISPLAY_TO_WORLD ((HIWORD (rand_val) & (LASER_LENGTH - 1)) + 4) + ); + SetVelocityComponents (&LaserPtr->velocity, + COSINE (angle, delta), SINE (angle, delta)); + + SetElementStarShip (LaserPtr, StarShipPtr); + UnlockElement (LaserArray[0]); + } + + return (1); +} + +static void +slylandro_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, + COUNT ConcernCounter) +{ + EVALUATE_DESC *lpEvalDesc; + STARSHIP *StarShipPtr; + + if (LOBYTE (GLOBAL (CurrentActivity)) == IN_ENCOUNTER) + /* no dodging in role playing game */ + ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr = 0; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (StarShipPtr->special_counter == 0 + && StarShipPtr->RaceDescPtr->ship_info.energy_level == 0 + && ObjectsOfConcern[GRAVITY_MASS_INDEX].ObjectPtr == 0) + ConcernCounter = FIRST_EMPTY_INDEX + 1; + if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == PURSUE + && lpEvalDesc->which_turn <= 6) + lpEvalDesc->MoveState = ENTICE; + + ++ShipPtr->thrust_wait; + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + --ShipPtr->thrust_wait; + + if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 14) + StarShipPtr->ship_input_state |= WEAPON; + else + StarShipPtr->ship_input_state &= ~WEAPON; + + StarShipPtr->ship_input_state &= ~SPECIAL; + if (StarShipPtr->RaceDescPtr->ship_info.energy_level < + StarShipPtr->RaceDescPtr->ship_info.max_energy) + { + lpEvalDesc = &ObjectsOfConcern[FIRST_EMPTY_INDEX]; + if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 14) + StarShipPtr->ship_input_state |= SPECIAL; + } +} + +static BOOLEAN +harvest_space_junk (ELEMENT *ElementPtr) +{ + BOOLEAN retval; + HELEMENT hElement, hNextElement; + + retval = FALSE; + for (hElement = GetHeadElement (); + hElement; hElement = hNextElement) + { + ELEMENT *ObjPtr; + + LockElement (hElement, &ObjPtr); + hNextElement = GetSuccElement (ObjPtr); + + if (!(ObjPtr->state_flags & (APPEARING | PLAYER_SHIP | FINITE_LIFE)) + && ObjPtr->playerNr == NEUTRAL_PLAYER_NUM + && !GRAVITY_MASS (ObjPtr->mass_points) + && CollisionPossible (ObjPtr, ElementPtr)) + { + SIZE dx, dy; + + if ((dx = ObjPtr->next.location.x + - ElementPtr->next.location.x) < 0) + dx = -dx; + if ((dy = ObjPtr->next.location.y + - ElementPtr->next.location.y) < 0) + dy = -dy; + dx = WORLD_TO_DISPLAY (dx); + dy = WORLD_TO_DISPLAY (dy); + if (dx <= HARVEST_RANGE && dy <= HARVEST_RANGE + && dx * dx + dy * dy <= HARVEST_RANGE * HARVEST_RANGE) + { + ObjPtr->life_span = 0; + ObjPtr->state_flags |= NONSOLID; + + if (!retval) + { + STARSHIP *StarShipPtr; + + retval = TRUE; + + GetElementStarShip (ElementPtr, &StarShipPtr); + ProcessSound (SetAbsSoundIndex ( + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); + DeltaEnergy (ElementPtr, MAX_ENERGY); + } + } + } + + UnlockElement (hElement); + } + + return (retval); +} + +static void +slylandro_postprocess (ELEMENT *ElementPtr) +{ + STARSHIP *StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if (StarShipPtr->weapon_counter + && StarShipPtr->weapon_counter < WEAPON_WAIT) + { + HELEMENT Lightning; + + initialize_lightning (ElementPtr, &Lightning); + if (Lightning) + PutElement (Lightning); + } + + if (StarShipPtr->special_counter == 0 + && (StarShipPtr->cur_status_flags & SPECIAL) + && harvest_space_junk (ElementPtr)) + { + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } +} + +static void +slylandro_preprocess (ELEMENT *ElementPtr) +{ + if (!(ElementPtr->state_flags & (APPEARING | NONSOLID))) + { + STARSHIP *StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & THRUST) + && !(StarShipPtr->old_status_flags & THRUST)) + StarShipPtr->ShipFacing += ANGLE_TO_FACING (HALF_CIRCLE); + + if (ElementPtr->turn_wait == 0) + { + ElementPtr->turn_wait += + StarShipPtr->RaceDescPtr->characteristics.turn_wait + 1; + if (StarShipPtr->cur_status_flags & LEFT) + --StarShipPtr->ShipFacing; + else if (StarShipPtr->cur_status_flags & RIGHT) + ++StarShipPtr->ShipFacing; + } + + StarShipPtr->ShipFacing = NORMALIZE_FACING (StarShipPtr->ShipFacing); + + if (ElementPtr->thrust_wait == 0) + { + ElementPtr->thrust_wait += + StarShipPtr->RaceDescPtr->characteristics.thrust_wait + 1; + + SetVelocityVector (&ElementPtr->velocity, + StarShipPtr->RaceDescPtr->characteristics.max_thrust, + StarShipPtr->ShipFacing); + StarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED; + StarShipPtr->cur_status_flags &= ~SHIP_IN_GRAVITY_WELL; + } + + ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->next.image.frame); + ElementPtr->state_flags |= CHANGING; + } +} + +RACE_DESC* +init_slylandro (void) +{ + RACE_DESC *RaceDescPtr; + + slylandro_desc.preprocess_func = slylandro_preprocess; + slylandro_desc.postprocess_func = slylandro_postprocess; + slylandro_desc.init_weapon_func = initialize_lightning; + slylandro_desc.cyborg_control.intelligence_func = slylandro_intelligence; + + RaceDescPtr = &slylandro_desc; + + return (RaceDescPtr); +} -- cgit v1.2.3