diff --git a/dat/outfit.xml b/dat/outfit.xml index 5d87879..5a225e2 100644 --- a/dat/outfit.xml +++ b/dat/outfit.xml @@ -163,6 +163,7 @@ <turn>50</turn> <energy>130</energy> <damage type="energy">100</damage> + <gfx>beam_ragnarok</gfx> </specific> </outfit> <outfit name="Seeker Launcher"> diff --git a/dat/ship.xml b/dat/ship.xml index e4b8dc8..4dcbdaf 100644 --- a/dat/ship.xml +++ b/dat/ship.xml @@ -238,7 +238,8 @@ <cap_cargo>10</cap_cargo> </characteristics> <outfits> - <outfit quantity="2">Ripper MK2</outfit> + <outfit quantity="2">Ripper MK2</outfit> + <outfit quantity="1">Ragnarok Beam</outfit> <outfit quantity="1">Headhunter Launcher</outfit> <outfit quantity="20">Headhunter</outfit> </outfits> diff --git a/gfx/outfit/space/beam_ragnarok.png b/gfx/outfit/space/beam_ragnarok.png new file mode 100644 index 0000000..50d6245 Binary files /dev/null and b/gfx/outfit/space/beam_ragnarok.png differ diff --git a/src/opengl.c b/src/opengl.c index 45f2256..30ce204 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -313,6 +313,10 @@ static GLuint gl_loadSurface(SDL_Surface* surface, int *rw, int* rh) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + /* Always wrap just in case. */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + /* Now lead the texture data up. */ SDL_LockSurface(surface); glTexImage2D(GL_TEXTURE_2D, 0, surface->format->BytesPerPixel, diff --git a/src/outfit.c b/src/outfit.c index 12cb330..9efc09f 100644 --- a/src/outfit.c +++ b/src/outfit.c @@ -280,6 +280,7 @@ int outfit_isMap(const Outfit* o) { */ glTexture* outfit_gfx(const Outfit* o) { if(outfit_isBolt(o)) return o->u.blt.gfx_space; + else if(outfit_isBeam(o)) return o->u.bem.gfx; else if(outfit_isAmmo(o)) return o->u.amm.gfx_space; else if(outfit_isTurret(o)) return o->u.blt.gfx_space; return NULL; @@ -561,22 +562,32 @@ static void outfit_parseSBolt(Outfit* tmp, const xmlNodePtr parent) { */ static void outfit_parseSBeam(Outfit* tmp, const xmlNodePtr parent) { xmlNodePtr node; - + char str[PATH_MAX] = "\0"; + node = parent->xmlChildrenNode; do { /* Load all the data. */ xmlr_float(node, "range", tmp->u.bem.range); 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_float(node, "warmup", tmp->u.bem.warmup); xmlr_float(node, "duration", tmp->u.bem.duration); - if(xml_isNode(node, "damage")) + if(xml_isNode(node, "damage")) { outfit_parseDamage(&tmp->u.bem.dtype, &tmp->u.bem.damage, node); + continue; + } + + if(xml_isNode(node, "gfx")) { + snprintf(str, strlen(xml_get(node))+sizeof(OUTFIT_GFX)+10, + OUTFIT_GFX"space/%s.png", xml_get(node)); + tmp->u.bem.gfx = gl_newSprite(str, 1, 1); + continue; + } } while(xml_nextNode(node)); - tmp->u.bem.colour = &cWhite; /** @todo Make it loadable. */ - #define MELEMENT(o,s) if(0) WARN("Outfit '%s' missing/invalid '"s"' element", tmp->name) + MELEMENT(tmp->u.bem.gfx==NULL, "gfx"); MELEMENT(tmp->u.bem.delay==0, "range"); MELEMENT(tmp->u.bem.duration==0, "duration"); MELEMENT(tmp->u.bem.range==0, "range"); @@ -590,8 +601,8 @@ static void outfit_parseSBeam(Outfit* tmp, const xmlNodePtr parent) { /* Parse the specific area for a launcher and loads it into Outfit. */ static void outfit_parseSLauncher(Outfit* tmp, const xmlNodePtr parent) { xmlNodePtr node; + node = parent->xmlChildrenNode; - do { /* Load the dataz. */ if(xml_isNode(node, "delay")) tmp->u.lau.delay = xml_getInt(node); diff --git a/src/outfit.h b/src/outfit.h index 5a96911..e4ba241 100644 --- a/src/outfit.h +++ b/src/outfit.h @@ -52,6 +52,7 @@ typedef struct OutfitBoltData_ { DamageType dtype; /**< Damage type. */ double damage; /**< damage. */ + /* Sound and graphics. */ glTexture* gfx_space; /**< Graphic. */ int sound; /**< Sound to play. */ int spfx; /**< Special effect on hit. */ @@ -63,14 +64,21 @@ typedef struct OutfitBoltData_ { * @brief Represents the particular properties of a beam weapon. */ typedef struct OutfitBeamData_ { + /* Time stuff. */ unsigned int delay; /**< Delay between usage. */ - unsigned int duration; /**< How long the beam lasts active. */ + double warmup; /**< How long it takes to warm up. */ + double duration; /**< How long the beam lasts active. */ + + /* Beam properties. */ double range; /**< How far it goes. */ double turn; /**< How fast it can turn. Only for turrets. */ glColour* colour; /**< Beam colour. */ double energy; /**< Amount of energy it drains (per second). */ DamageType dtype; /**< Damage type. */ double damage; /**< Damage amount. */ + + /* Graphics */ + glTexture* gfx; /**< Base texture. */ } OutfitBeamData; /** diff --git a/src/weapon.c b/src/weapon.c index 78d7635..5d9a5b3 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -373,16 +373,51 @@ static void weapon_render(const Weapon* w) { /* Beam weapons. */ case OUTFIT_TYPE_BEAM: case OUTFIT_TYPE_TURRET_BEAM: + gfx = outfit_gfx(w->outfit); x = w->solid->pos.x - VX(*gl_camera) + gui_xoff; y = w->solid->pos.y - VY(*gl_camera) + gui_yoff; - 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)); + + /* Set up the matrix. */ + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glTranslated(x, y, 0.); + glRotated(270. + w->solid->dir / M_PI * 180., 0., 0., 1.); + + /* Preparatives. */ + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, gfx->texture); + glShadeModel(GL_SMOOTH); + + /* Actual rendering. */ + glBegin(GL_QUAD_STRIP); + COLOUR(cWhite); + + /* Full strength. */ + glTexCoord2d(0., 0.); + glVertex2d(-gfx->sh/2., 0.); + + glTexCoord2d(0., 1.); + glVertex2d(+gfx->sh/2., 0.); + + glTexCoord2d(0.8*w->outfit->u.bem.range / gfx->sw, 0.); + glVertex2d(+gfx->sh/2., 0.8*w->outfit->u.bem.range); + + /* Fades out. */ + ACOLOUR(cWhite, 0.); + + glTexCoord2d(w->outfit->u.bem.range / gfx->sw, 0.); + glVertex2d(-gfx->sh/2., w->outfit->u.bem.range); + + glTexCoord2d(w->outfit->u.bem.range / gfx->sw, 1.); + glVertex2d(+gfx->sh/2., w->outfit->u.bem.range); glEnd(); - glLineWidth(1.); + + /* Clean up. */ + glDisable(GL_TEXTURE_2D); + glShadeModel(GL_FLAT); + glPopMatrix(); + gl_checkErr(); + break; default: