diff --git a/dat/outfit.xml b/dat/outfit.xml index 702ffa6..5d87879 100644 --- a/dat/outfit.xml +++ b/dat/outfit.xml @@ -146,6 +146,24 @@ <energy>35</energy> <damage type="kinetic">40</damage> </specific> +</outfit> + <outfit name="Ragnarok Beam"> + <general> + <max>1</max> + <tech>13</tech> + <mass>60</mass> + <price>745000</price> + <description>Ragnorak beam is one of the most powerful beam class weapons on the market. It's designed for capital ship combat, although it's exremely high payload makes it also somewhat useful for clearing enemy fighters.</description> + <gfx_store>turret3</gfx_store> + </general> + <specific type="turret beam" secondary="1"> + <delay>7000</delay> + <duration>3</duration> + <range>400</range> + <turn>50</turn> + <energy>130</energy> + <damage type="energy">100</damage> + </specific> </outfit> <outfit name="Seeker Launcher"> <general> diff --git a/src/outfit.c b/src/outfit.c index 3b58960..12cb330 100644 --- a/src/outfit.c +++ b/src/outfit.c @@ -568,7 +568,7 @@ static void outfit_parseSBeam(Outfit* tmp, const xmlNodePtr parent) { xmlr_float(node, "turn", tmp->u.bem.turn); xmlr_float(node, "energy", tmp->u.bem.energy); xmlr_long(node, "delay", tmp->u.bem.delay); - xmlr_long(node, "duration", tmp->u.bem.duration); + xmlr_float(node, "duration", tmp->u.bem.duration); if(xml_isNode(node, "damage")) outfit_parseDamage(&tmp->u.bem.dtype, &tmp->u.bem.damage, node); diff --git a/src/pilot.c b/src/pilot.c index 7a8c765..f838c76 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -705,6 +705,10 @@ int pilot_addOutfit(Pilot* pilot, Outfit* outfit, int quantity) { /* Used to speed up AI. */ pilot_setFlag(pilot, PILOT_HASTURRET); + if(outfit_isBeam(outfit)) + /* Used to speed up some calculation. */ + pilot_setFlag(pilot, PILOT_HASBEAMS); + /* Hack due to realloc possibility. */ pilot_setSecondary(pilot, osec); pilot_setAfterburner(pilot); diff --git a/src/pilot.h b/src/pilot.h index 7cc6ff2..a6f7344 100644 --- a/src/pilot.h +++ b/src/pilot.h @@ -33,6 +33,7 @@ /* Creation. */ #define PILOT_PLAYER (1<<0) /**< Pilot is a player. */ #define PILOT_HASTURRET (1<<20) /**< Pilot has turrets. */ +#define PILOT_HASBEAMS (1<<23) /**< Pilot has beam weapons. */ #define PILOT_NO_OUTFITS (1<<21) /**< Do not create the pilot with outfits. */ #define PILOT_EMPTY (1<<22) /**< Do not add pilot to stack. */ /* Dynamic. */ diff --git a/src/weapon.c b/src/weapon.c index d081e74..4f40c43 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -206,7 +206,8 @@ static void think_seeker(Weapon* w, const double dt) { */ static void think_beam(Weapon* w, const double dt) { (void) dt; - Pilot* p; + Pilot* p, *t; + double diff; /* Get pilot, if pilot is dead beam is destroyed too. */ p = pilot_get(w->parent); @@ -215,18 +216,41 @@ static void think_beam(Weapon* w, const double dt) { return; } + /* Check if pilot has enough energy left to keep beam active. */ + p->energy -= dt*w->outfit->u.bem.energy; + if(p->energy < 0.) { + p->energy = 0.; + w->timer = -1; + return; + } + /* Update beam position to match pilot. */ w->solid->pos.x = p->solid->pos.x; w->solid->pos.y = p->solid->pos.y; + t = pilot_get(w->target); + if(t == NULL) { + w->solid->dir_vel = 0.; + return; + } + /* Handle aiming. */ switch(w->outfit->type) { case OUTFIT_TYPE_BEAM: w->solid->dir = p->solid->dir; break; case OUTFIT_TYPE_TURRET_BEAM: - /** @todo Have beam turret aim independently. */ - w->solid->dir = p->solid->dir; + if(w->target == w->parent) /* Invalid target, try to follow shooter. */ + diff = angle_diff(w->solid->dir, p->solid->dir); + else + diff = angle_diff(w->solid->dir, /* Get angle to target pos. */ + vect_angle(&w->solid->pos, &t->solid->pos)); + w->solid->dir_vel = 10 * diff * w->outfit->u.bem.turn; /* Face pos. */ + /* Check for under/overflows. */ + if(w->solid->dir_vel > w->outfit->u.bem.turn) + w->solid->dir_vel = w->outfit->u.bem.turn; + else if(w->solid->dir_vel < -w->outfit->u.bem.turn) + w->solid->dir_vel = -w->outfit->u.bem.turn; break; default: return; @@ -337,12 +361,14 @@ static void weapon_render(const Weapon* w) { case OUTFIT_TYPE_TURRET_BEAM: x = w->solid->pos.x - VX(*gl_camera) + gui_xoff; y = w->solid->pos.y - VY(*gl_camera) + gui_yoff; - COLOUR(*w->outfit->u.bem.colour); + ACOLOUR(*w->outfit->u.bem.colour, 0.8); + glLineWidth(3.); glBegin(GL_LINES); glVertex2d(x, y); glVertex2d(x + w->outfit->u.bem.range * cos(w->solid->dir), y + w->outfit->u.bem.range * sin(w->solid->dir)); glEnd(); + glLineWidth(1.); break; default: @@ -553,8 +579,15 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2* /* Beam weapons are treated together. */ case OUTFIT_TYPE_BEAM: case OUTFIT_TYPE_TURRET_BEAM: + if((outfit->type == OUTFIT_TYPE_TURRET_BOLT) && (w->parent != w->target) && + (w->target != 0)) { /* Must have valid target. */ + pilot_target = pilot_get(target); + rdir = (pilot_target == NULL) ? dir : + vect_angle(pos, &pilot_target->solid->pos); + } else + rdir = dir; mass = 1.; - w->solid = solid_create(mass, dir, pos, NULL); + w->solid = solid_create(mass, rdir, pos, NULL); w->think = think_beam; w->timer = outfit->u.bem.duration; break;