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/ilwrath/ilwrath.c | 409 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 409 insertions(+) create mode 100644 src/uqm/ships/ilwrath/ilwrath.c (limited to 'src/uqm/ships/ilwrath/ilwrath.c') diff --git a/src/uqm/ships/ilwrath/ilwrath.c b/src/uqm/ships/ilwrath/ilwrath.c new file mode 100644 index 0000000..3947081 --- /dev/null +++ b/src/uqm/ships/ilwrath/ilwrath.c @@ -0,0 +1,409 @@ +//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 "ilwrath.h" +#include "resinst.h" + +#include "uqm/colors.h" +#include "uqm/globdata.h" + + +// Core characteristics +#define MAX_CREW 22 +#define MAX_ENERGY 16 +#define ENERGY_REGENERATION 4 +#define ENERGY_WAIT 4 +#define MAX_THRUST 25 +#define THRUST_INCREMENT 5 +#define THRUST_WAIT 0 +#define TURN_WAIT 2 +#define SHIP_MASS 7 +#define LOOK_AHEAD 4 + /* Controls how much the auto-turn will attempt to "lead" + * its target. */ + +// Hellfire Spout +#define WEAPON_ENERGY_COST 1 +#define WEAPON_WAIT 0 +#define MISSILE_LIFE 8 +#define ILWRATH_OFFSET 29 +#define MISSILE_SPEED MAX_THRUST +#define MISSILE_HITS 1 +#define MISSILE_DAMAGE 1 +#define MISSILE_OFFSET 0 + +// Cloaking Device +#define SPECIAL_ENERGY_COST 3 +#define SPECIAL_WAIT 13 + +static RACE_DESC ilwrath_desc = +{ + { /* SHIP_INFO */ + FIRES_FORE, + 10, /* Super Melee cost */ + MAX_CREW, MAX_CREW, + MAX_ENERGY, MAX_ENERGY, + ILWRATH_RACE_STRINGS, + ILWRATH_ICON_MASK_PMAP_ANIM, + ILWRATH_MICON_MASK_PMAP_ANIM, + NULL, NULL, NULL + }, + { /* FLEET_STUFF */ + 1410 / SPHERE_RADIUS_INCREMENT * 2, /* Initial SoI radius */ + { /* Known location (center of SoI) */ + 48, 1700, + }, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + ILWRATH_BIG_MASK_PMAP_ANIM, + ILWRATH_MED_MASK_PMAP_ANIM, + ILWRATH_SML_MASK_PMAP_ANIM, + }, + { + FIRE_BIG_MASK_PMAP_ANIM, + FIRE_MED_MASK_PMAP_ANIM, + FIRE_SML_MASK_PMAP_ANIM, + }, + { + NULL_RESOURCE, + NULL_RESOURCE, + NULL_RESOURCE, + }, + { + ILWRATH_CAPTAIN_MASK_PMAP_ANIM, + NULL, NULL, NULL, NULL, NULL + }, + ILWRATH_VICTORY_SONG, + ILWRATH_SHIP_SOUNDS, + { NULL, NULL, NULL }, + { NULL, NULL, NULL }, + { NULL, NULL, NULL }, + NULL, NULL + }, + { + 0, + CLOSE_RANGE_WEAPON, + NULL, + }, + (UNINIT_FUNC *) NULL, + (PREPROCESS_FUNC *) NULL, + (POSTPROCESS_FUNC *) NULL, + (INIT_WEAPON_FUNC *) NULL, + 0, + 0, /* CodeRef */ +}; + +static void +flame_preprocess (ELEMENT *ElementPtr) +{ + if (ElementPtr->turn_wait > 0) + --ElementPtr->turn_wait; + else + { + ElementPtr->next.image.frame = + IncFrameIndex (ElementPtr->current.image.frame); + ElementPtr->state_flags |= CHANGING; + + ElementPtr->turn_wait = ElementPtr->next_turn; + } +} + +static void +flame_collision (ELEMENT *ElementPtr0, POINT *pPt0, + ELEMENT *ElementPtr1, POINT *pPt1) +{ + weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); + ElementPtr0->state_flags &= ~DISAPPEARING; + ElementPtr0->state_flags |= NONSOLID; +} + +static void +ilwrath_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, + COUNT ConcernCounter) +{ + EVALUATE_DESC *lpEvalDesc; + STARSHIP *StarShipPtr; + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + lpEvalDesc->MoveState = PURSUE; + if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 10) + /* don't want to dodge when you could be flaming */ + ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr = 0; + + ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); + + GetElementStarShip (ShipPtr, &StarShipPtr); + if (lpEvalDesc->ObjectPtr + && (lpEvalDesc->which_turn <= 6 + || (lpEvalDesc->which_turn <= 10 + && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn <= 10))) + { + StarShipPtr->ship_input_state &= ~SPECIAL; + if (OBJECT_CLOAKED (ShipPtr)) + { + StarShipPtr->ship_input_state &= ~LEFT | RIGHT; + StarShipPtr->ship_input_state |= THRUST; + } + StarShipPtr->ship_input_state |= WEAPON; + } + else if (StarShipPtr->special_counter == 0 + && (LOBYTE (GLOBAL (CurrentActivity)) != IN_ENCOUNTER + || !GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER))) + { + StarShipPtr->ship_input_state &= ~SPECIAL; + if (!OBJECT_CLOAKED (ShipPtr) + && !(StarShipPtr->ship_input_state & WEAPON)) + StarShipPtr->ship_input_state |= SPECIAL; + } +} + +static COUNT +initialize_flame (ELEMENT *ShipPtr, HELEMENT FlameArray[]) +{ + 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 = 0; + MissileBlock.sender = ShipPtr->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; + FlameArray[0] = initialize_missile (&MissileBlock); + + if (FlameArray[0]) + { + SIZE dx, dy; + ELEMENT *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 void +ilwrath_preprocess (ELEMENT *ElementPtr) +{ + STATUS_FLAGS status_flags; + STARSHIP *StarShipPtr; + PRIMITIVE *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) || + !sameColor (color, BLACK_COLOR)))) + { + if (sameColor (color, + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F))) + SetPrimType (lpPrim, STAMP_PRIM); + else if (sameColor (color, + BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B))) + SetPrimColor (lpPrim, + BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); + else if (sameColor (color, + BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03))) + SetPrimColor (lpPrim, + BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)); + else if (sameColor (color, + BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09))) + SetPrimColor (lpPrim, + BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); + else if (sameColor (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) + { + ELEMENT *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 (!sameColor (color, BLACK_COLOR)) + { + if (sameColor (color, + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01))) + { + SetPrimColor (lpPrim, BLACK_COLOR); + Untarget (ElementPtr); + } + else if (sameColor (color, + BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09))) + SetPrimColor (lpPrim, + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); + else if (sameColor (color, + BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03))) + SetPrimColor (lpPrim, + BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); + else if (sameColor (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; + } +} + +RACE_DESC* +init_ilwrath (void) +{ + RACE_DESC *RaceDescPtr; + + ilwrath_desc.preprocess_func = ilwrath_preprocess; + ilwrath_desc.init_weapon_func = initialize_flame; + ilwrath_desc.cyborg_control.intelligence_func = ilwrath_intelligence; + + RaceDescPtr = &ilwrath_desc; + + return (RaceDescPtr); +} + -- cgit v1.2.3