diff options
Diffstat (limited to 'src/uqm/ships/syreen/syreen.c')
-rw-r--r-- | src/uqm/ships/syreen/syreen.c | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/src/uqm/ships/syreen/syreen.c b/src/uqm/ships/syreen/syreen.c new file mode 100644 index 0000000..c65ecd2 --- /dev/null +++ b/src/uqm/ships/syreen/syreen.c @@ -0,0 +1,284 @@ +//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 "syreen.h" +#include "resinst.h" + +#include "libs/mathlib.h" + +// Core characteristics +#define SYREEN_MAX_CREW_SIZE MAX_CREW_SIZE +#define MAX_CREW 12 +#define MAX_ENERGY 16 +#define ENERGY_REGENERATION 1 +#define ENERGY_WAIT 6 +#define MAX_THRUST /* DISPLAY_TO_WORLD (8) */ 36 +#define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 9 +#define THRUST_WAIT 1 +#define TURN_WAIT 1 +#define SHIP_MASS 2 + +// Particle Beam Stiletto +#define WEAPON_ENERGY_COST 1 +#define WEAPON_WAIT 8 +#define SYREEN_OFFSET 30 +#define MISSILE_SPEED DISPLAY_TO_WORLD (30) +#define MISSILE_LIFE 10 +#define MISSILE_HITS 1 +#define MISSILE_DAMAGE 2 +#define MISSILE_OFFSET 3 + +// Syreen song +#define SPECIAL_ENERGY_COST 5 +#define SPECIAL_WAIT 20 +#define ABANDONER_RANGE 208 /* originally SPACE_HEIGHT */ +#define MAX_ABANDONERS 8 + +static RACE_DESC syreen_desc = +{ + { /* SHIP_INFO */ + FIRES_FORE, + 13, /* Super Melee cost */ + MAX_CREW, SYREEN_MAX_CREW_SIZE, + MAX_ENERGY, MAX_ENERGY, + SYREEN_RACE_STRINGS, + SYREEN_ICON_MASK_PMAP_ANIM, + SYREEN_MICON_MASK_PMAP_ANIM, + NULL, NULL, NULL + }, + { /* FLEET_STUFF */ + 0, /* Initial sphere of influence radius */ + { /* Known location (center of SoI) */ + 0, 0, + }, + }, + { + MAX_THRUST, + THRUST_INCREMENT, + ENERGY_REGENERATION, + WEAPON_ENERGY_COST, + SPECIAL_ENERGY_COST, + ENERGY_WAIT, + TURN_WAIT, + THRUST_WAIT, + WEAPON_WAIT, + SPECIAL_WAIT, + SHIP_MASS, + }, + { + { + SYREEN_BIG_MASK_PMAP_ANIM, + SYREEN_MED_MASK_PMAP_ANIM, + SYREEN_SML_MASK_PMAP_ANIM, + }, + { + DAGGER_BIG_MASK_PMAP_ANIM, + DAGGER_MED_MASK_PMAP_ANIM, + DAGGER_SML_MASK_PMAP_ANIM, + }, + { + NULL_RESOURCE, + NULL_RESOURCE, + NULL_RESOURCE, + }, + { + SYREEN_CAPTAIN_MASK_PMAP_ANIM, + NULL, NULL, NULL, NULL, NULL + }, + SYREEN_VICTORY_SONG, + SYREEN_SHIP_SOUNDS, + { NULL, NULL, NULL }, + { NULL, NULL, NULL }, + { NULL, NULL, NULL }, + NULL, NULL + }, + { + 0, + (MISSILE_SPEED * MISSILE_LIFE * 2 / 3), + NULL, + }, + (UNINIT_FUNC *) NULL, + (PREPROCESS_FUNC *) NULL, + (POSTPROCESS_FUNC *) NULL, + (INIT_WEAPON_FUNC *) NULL, + 0, + 0, /* CodeRef */ +}; + +static COUNT +initialize_dagger (ELEMENT *ShipPtr, HELEMENT DaggerArray[]) +{ + 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 = SYREEN_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; + DaggerArray[0] = initialize_missile (&MissileBlock); + + return (1); +} + +static void +spawn_crew (ELEMENT *ElementPtr) +{ + if (ElementPtr->state_flags & PLAYER_SHIP) + { + HELEMENT hCrew; + + hCrew = AllocElement (); + if (hCrew != 0) + { + ELEMENT *CrewPtr; + + LockElement (hCrew, &CrewPtr); + CrewPtr->next.location = ElementPtr->next.location; + CrewPtr->playerNr = ElementPtr->playerNr; + CrewPtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE; + CrewPtr->life_span = 0; + CrewPtr->death_func = spawn_crew; + CrewPtr->pParent = ElementPtr->pParent; + CrewPtr->hTarget = 0; + UnlockElement (hCrew); + + PutElement (hCrew); + } + } + else + { + HELEMENT hElement, hNextElement; + + for (hElement = GetHeadElement (); + hElement != 0; hElement = hNextElement) + { + ELEMENT *ObjPtr; + + LockElement (hElement, &ObjPtr); + hNextElement = GetSuccElement (ObjPtr); + + if ((ObjPtr->state_flags & PLAYER_SHIP) + && !elementsOfSamePlayer (ObjPtr, ElementPtr) + && ObjPtr->crew_level > 1) + { + SIZE dx, dy; + DWORD d_squared; + + dx = ObjPtr->next.location.x - ElementPtr->next.location.x; + if (dx < 0) + dx = -dx; + dy = ObjPtr->next.location.y - ElementPtr->next.location.y; + if (dy < 0) + dy = -dy; + + dx = WORLD_TO_DISPLAY (dx); + dy = WORLD_TO_DISPLAY (dy); + if (dx <= ABANDONER_RANGE && dy <= ABANDONER_RANGE + && (d_squared = (DWORD)((UWORD)dx * (UWORD)dx) + + (DWORD)((UWORD)dy * (UWORD)dy)) <= + (DWORD)((UWORD)ABANDONER_RANGE * (UWORD)ABANDONER_RANGE)) + { + COUNT crew_loss; + + crew_loss = ((MAX_ABANDONERS + * (ABANDONER_RANGE - square_root (d_squared))) + / ABANDONER_RANGE) + 1; + if (crew_loss >= ObjPtr->crew_level) + crew_loss = ObjPtr->crew_level - 1; + + AbandonShip (ObjPtr, ElementPtr, crew_loss); + } + } + + UnlockElement (hElement); + } + } +} + +static void +syreen_intelligence (ELEMENT *ShipPtr, EVALUATE_DESC *ObjectsOfConcern, + COUNT ConcernCounter) +{ + EVALUATE_DESC *lpEvalDesc; + + ship_intelligence (ShipPtr, + ObjectsOfConcern, ConcernCounter); + + lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; + if (lpEvalDesc->ObjectPtr != NULL) + { + STARSHIP *StarShipPtr; + STARSHIP *EnemyStarShipPtr; + + GetElementStarShip (ShipPtr, &StarShipPtr); + GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); + if (!(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & CREW_IMMUNE) + && StarShipPtr->special_counter == 0 + && lpEvalDesc->ObjectPtr->crew_level > 1 + && lpEvalDesc->which_turn <= 14) + StarShipPtr->ship_input_state |= SPECIAL; + else + StarShipPtr->ship_input_state &= ~SPECIAL; + } +} + +static void +syreen_postprocess (ELEMENT *ElementPtr) +{ + STARSHIP *StarShipPtr; + + GetElementStarShip (ElementPtr, &StarShipPtr); + if ((StarShipPtr->cur_status_flags & SPECIAL) + && StarShipPtr->special_counter == 0 + && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) + { + ProcessSound (SetAbsSoundIndex ( + /* SYREEN_SONG */ + StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); + spawn_crew (ElementPtr); + + StarShipPtr->special_counter = + StarShipPtr->RaceDescPtr->characteristics.special_wait; + } +} + +RACE_DESC* +init_syreen (void) +{ + RACE_DESC *RaceDescPtr; + + syreen_desc.postprocess_func = syreen_postprocess; + syreen_desc.init_weapon_func = initialize_dagger; + syreen_desc.cyborg_control.intelligence_func = syreen_intelligence; + + RaceDescPtr = &syreen_desc; + + return (RaceDescPtr); +} + |