/** * @brief Renders the entire spfx layer. * * @param layer Layer to render. */ void spfx_render( const int layer ) { SPFX *spfx_stack; int i, spfx_nstack; SPFX_Base *effect; int sx, sy; double time; /* get the appropriate layer */ switch (layer) { case SPFX_LAYER_FRONT: spfx_stack = spfx_stack_front; spfx_nstack = spfx_nstack_front; break; case SPFX_LAYER_BACK: spfx_stack = spfx_stack_back; spfx_nstack = spfx_nstack_back; break; } /* Now render the layer */ for (i=spfx_nstack-1; i>=0; i--) { effect = &spfx_effects[ spfx_stack[i].effect ]; /* Simplifies */ sx = (int)effect->gfx->sx; sy = (int)effect->gfx->sy; if (!paused) { /* don't calculate frame if paused */ time = fmod(spfx_stack[i].timer,effect->anim) / effect->anim; spfx_stack[i].lastframe = sx * sy * MIN(time, 1.); } /* Renders */ gl_blitSprite( effect->gfx, VX(spfx_stack[i].pos), VY(spfx_stack[i].pos), spfx_stack[i].lastframe % sx, spfx_stack[i].lastframe / sx, NULL ); } }
/** * @brief Renders an individual weapon. * * @param w Weapon to render. * @param dt Current delta tick. */ static void weapon_render( Weapon* w, const double dt ) { double x,y, cx,cy, gx,gy; glTexture *gfx; double z; glColour c = { .r=1., .g=1., .b=1. }; switch (w->outfit->type) { /* Weapons that use sprites. */ case OUTFIT_TYPE_AMMO: case OUTFIT_TYPE_TURRET_AMMO: case OUTFIT_TYPE_BOLT: case OUTFIT_TYPE_TURRET_BOLT: gfx = outfit_gfx(w->outfit); /* Alpha based on strength. */ c.a = w->strength; /* Outfit spins around. */ if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_SPIN)) { /* Check timer. */ w->anim -= dt; if (w->anim < 0.) { w->anim = outfit_spin(w->outfit); /* Increment sprite. */ w->sprite++; if (w->sprite >= gfx->sx*gfx->sy) w->sprite = 0; } /* Render. */ if (outfit_isBolt(w->outfit) && w->outfit->u.blt.gfx_end) gl_blitSpriteInterpolate( gfx, w->outfit->u.blt.gfx_end, w->timer / w->life, w->solid->pos.x, w->solid->pos.y, w->sprite % (int)gfx->sx, w->sprite / (int)gfx->sx, &c ); else gl_blitSprite( gfx, w->solid->pos.x, w->solid->pos.y, w->sprite % (int)gfx->sx, w->sprite / (int)gfx->sx, &c ); } /* Outfit faces direction. */ else { if (outfit_isBolt(w->outfit) && w->outfit->u.blt.gfx_end) gl_blitSpriteInterpolate( gfx, w->outfit->u.blt.gfx_end, w->timer / w->life, w->solid->pos.x, w->solid->pos.y, w->sx, w->sy, &c ); else gl_blitSprite( gfx, w->solid->pos.x, w->solid->pos.y, w->sx, w->sy, &c ); } break; /* Beam weapons. */ case OUTFIT_TYPE_BEAM: case OUTFIT_TYPE_TURRET_BEAM: gfx = outfit_gfx(w->outfit); /* Zoom. */ gl_cameraZoomGet( &z ); /* Position. */ gl_cameraGet( &cx, &cy ); gui_getOffset( &gx, &gy ); x = (w->solid->pos.x - cx)*z + gx; y = (w->solid->pos.y - cy)*z + gy; /* 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); /* Start faded. */ ACOLOUR(cWhite, 0.); glTexCoord2d( w->anim, 0. ); glVertex2d( -gfx->sh/2.*z, 0. ); glTexCoord2d( w->anim, 1. ); glVertex2d( +gfx->sh/2.*z, 0. ); /* Full strength. */ COLOUR(cWhite); glTexCoord2d( w->anim + 10. / gfx->sw, 0. ); glVertex2d( -gfx->sh/2.*z, 10.*z ); glTexCoord2d( w->anim + 10. / gfx->sw, 1. ); glVertex2d( +gfx->sh/2.*z, 10.*z ); glTexCoord2d( w->anim + 0.8*w->outfit->u.bem.range / gfx->sw, 0. ); glVertex2d( -gfx->sh/2.*z, 0.8*w->outfit->u.bem.range*z ); glTexCoord2d( w->anim + 0.8*w->outfit->u.bem.range / gfx->sw, 1. ); glVertex2d( +gfx->sh/2.*z, 0.8*w->outfit->u.bem.range*z ); /* Fades out. */ ACOLOUR(cWhite, 0.); glTexCoord2d( w->anim + w->outfit->u.bem.range / gfx->sw, 0. ); glVertex2d( -gfx->sh/2.*z, w->outfit->u.bem.range*z ); glTexCoord2d( w->anim + w->outfit->u.bem.range / gfx->sw, 1. ); glVertex2d( +gfx->sh/2.*z, w->outfit->u.bem.range*z ); glEnd(); /* GL_QUAD_STRIP */ /* Do the beam movement. */ w->anim -= 5. * dt; if (w->anim <= -gfx->sw) w->anim += gfx->sw; /* Clean up. */ glDisable(GL_TEXTURE_2D); glShadeModel(GL_FLAT); glPopMatrix(); /* GL_PROJECTION */ gl_checkErr(); break; default: WARN("Weapon of type '%s' has no render implemented yet!", w->outfit->name); break; } } /** * @brief Checks to see if the weapon can hit the pilot. * * @param w Weapon to check if hits pilot. * @param p Pilot to check if is hit by weapon. * @return 1 if can be hit, 0 if can't. */ static int weapon_checkCanHit( Weapon* w, Pilot *p ) { Pilot *parent; /* Can't hit invincible stuff. */ if (pilot_isFlag(p, PILOT_INVINCIBLE)) return 0; /* Can never hit same faction. */ if (p->faction == w->faction) return 0; /* Go "through" dead pilots. */ if (pilot_isFlag(p, PILOT_DEAD)) return 0; /* Player behaves differently. */ if (w->faction == FACTION_PLAYER) { /* Always hit without safety. */ if (!weapon_safety) return 1; /* Always hit target. */ else if (w->target == p->id) return 1; /* Always hit hostiles. */ else if (pilot_isFlag(p, PILOT_HOSTILE)) return 1; /* Always hit unbribed enemies. */ else if (!pilot_isFlag(p, PILOT_BRIBED) && areEnemies(w->faction, p->faction)) return 1; /* Miss rest - can be neutral/ally. */ else return 0; } /* Let hostiles hit player. */ if (p->faction == FACTION_PLAYER) { parent = pilot_get(w->parent); if (parent != NULL) { if (pilot_isFlag(parent, PILOT_BRIBED)) return 0; if (pilot_isFlag(parent, PILOT_HOSTILE)) return 1; } } /* Hit non-allies. */ if (areEnemies(w->faction, p->faction)) return 1; return 0; }