diff --git a/src/pilot.c b/src/pilot.c index 706c36e..9e4a6b4 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -714,16 +714,19 @@ void pilot_calcStats(Pilot* pilot) { pilot->armour_regen = pilot->ship->armour_regen; pilot->shield_regen = pilot->ship->shield_regen; pilot->energy_regen = pilot->ship->energy_regen; + /* Jamming. */ + pilot->jam_range = 0.; + pilot->jam_chance = 0.; /* Cargo has to be reset. */ pilot_calcCargo(pilot); /* Now add outfit changes. */ for(i = 0; i < pilot->noutfits; i++) { - if(outfit_isMod(pilot->outfits[i].outfit)) { - q = (double) pilot->outfits[i].quantity; - o = pilot->outfits[i].outfit; + o = pilot->outfits[i].outfit; + q = (double) pilot->outfits[i].quantity; + if(outfit_isMod(o)) { /* Modification. */ /* Movement. */ pilot->thrust += o->u.mod.thrust * q; pilot->turn += o->u.mod.turn * q; @@ -740,9 +743,15 @@ void pilot_calcStats(Pilot* pilot) { /* Misc. */ pilot->cargo_free += o->u.mod.cargo * q; } - else if(outfit_isAfterburner(pilot->outfits[i].outfit)) /* Set afterburner. */ - /* Set the afterburner. */ - pilot->afterburner = &pilot->outfits[i]; + else if(outfit_isAfterburner(o)) /* Afterburner. */ + pilot->afterburner = &pilot->outfits[i]; /* Set afterburner. */ + else if(outfit_isJammer(o)) { /* Jammer. */ + if(pilot->jam_chance < o->u.jam.chance) { /* Substitude. */ + pilot->jam_range = o->u.jam.range; + pilot->jam_chance = o->u.jam.chance; + } + pilot->energy_regen -= o->u.jam.energy; + } } /* Give the pilot her health proportion back. */ @@ -946,6 +955,10 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, int faction, } } + /* Jamming - must be set before calcStats. */ + pilot->jam_range = 0.; + pilot->jam_chance = 0.; + /* Cargo must be set before calcStats. */ pilot->credits = 0; pilot->commodities = NULL; diff --git a/src/pilot.h b/src/pilot.h index 50556ba..dc26866 100644 --- a/src/pilot.h +++ b/src/pilot.h @@ -96,6 +96,10 @@ typedef struct Pilot_ { PilotOutfit* ammo; /* Secondary ammo (if needed). */ PilotOutfit* afterburner; /* Ze afterburner. */ + /* Jamming. */ + double jam_range; + double jam_chance; + /* Cargo. */ int credits; /* Moniez the pilot has. */ PilotCommodity* commodities; /* Commodity and quantity. */ diff --git a/src/weapon.c b/src/weapon.c index 677bb5a..ca08a0f 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -19,7 +19,12 @@ #define VOICE_PRIORITY_AMMO 8 /* Higher. */ #define VOICE_PRIORITY_BEAM 6 /* Even higher. */ -#define WEAPON_CHUNK 32 +#define WEAPON_CHUNK 128 /* Size to increment array with. */ + +/* Weapon status. */ +#define WEAPON_STATUS_OK 0 /* Weapon is fine. */ +#define WEAPON_STATUS_JAMMED 1 /* Got jammed. */ +#define WEAPON_STATUS_UNJAMMED 2 /* Surviving jaming. */ /* Some stuff from pilot. */ extern Pilot** pilot_stack; @@ -47,6 +52,8 @@ typedef struct Weapon_ { /* Update position and render. */ void(*update)(struct Weapon_*, const double, WeaponLayer); /* Position update and render. */ void(*think)(struct Weapon_*, const double); /* Some missiles need to be inteligent.a */ + + char status; /* Weapon status - to check for jamming. */ } Weapon; /* Behind Pilot layer. */ @@ -105,27 +112,68 @@ void weapon_minimap(const double res, const double w, static void think_seeker(Weapon* w, const double dt) { double diff; double vel; + Pilot* p; + int effect; + if(w->target == w->parent) return; /* HEY! Self harm is not allowed. */ - Pilot* p = pilot_get(w->target); + p = pilot_get(w->target); /* No null pilot_nstack. */ if(p == NULL) { - limit_speed(&w->solid->vel, w->outfit->u.amm.speed, dt); + w->solid->dir_vel = 0.; /* Go straight. */ + vectnull(&w->solid->force); /* No force. */ return; } /* Ammo isn't locked on yet.. */ if(SDL_GetTicks() > (w->outfit->u.amm.lockon)) { - diff = angle_diff(w->solid->dir, vect_angle(&w->solid->pos, &p->solid->pos)); + switch(w->status) { + case WEAPON_STATUS_OK: /* Check to see if can get jammed. */ + if((p->jam_range != 0.) && /* Target has jammer and weapon is in range. */ + (vect_dist(&w->solid->pos, &p->solid->pos) < p->jam_range)) { + + if(RNGF() < p->jam_chance) { /* Is jammed? */ + w->status = WEAPON_STATUS_JAMMED; + /* Give it a nice random effect. */ + effect = RNG(0, 4); + switch(effect) { + case 0: /* Blow up. */ + w->timer = -1.; + break; + case 1: /* Stuck in left loop. */ + w->solid->dir_vel = w->outfit->u.amm.turn; + break; + case 2: /* Stuck in right loop. */ + w->solid->dir_vel = -w->outfit->u.amm.turn; + break; + default: /* Go straight. */ + w->solid->dir_vel = 0.; + return; + } + } + else /* Can't get jammed anymore. */ + w->status = WEAPON_STATUS_UNJAMMED; + } - /*diff = angle_diff(w->solid->dir, CollidePath(*&w->solid->pos, &w->solid->vel, - &p->solid->pos, &p->solid->vel, 0.01));*/ + /* Purpose fallthrough. */ + case WEAPON_STATUS_UNJAMMED: /* Work as expected. */ + diff = angle_diff(w->solid->dir, /* Get angle to target pos. */ + vect_angle(&w->solid->pos, &p->solid->pos)); + w->solid->dir_vel = 10 * diff * w->outfit->u.amm.turn; /* Face pos. */ + /* Check for under/overflows. */ + if(w->solid->dir_vel > w->outfit->u.amm.turn) + w->solid->dir_vel = w->outfit->u.amm.turn; + else if(w->solid->dir_vel < -w->outfit->u.amm.turn) + w->solid->dir_vel = -w->outfit->u.amm.turn; + break; - w->solid->dir_vel = 10 * diff * w->outfit->u.amm.turn; - /* Face the target. */ - if(w->solid->dir_vel > w->outfit->u.amm.turn) - w->solid->dir_vel = w->outfit->u.amm.turn; - else if(w->solid->dir_vel < -w->outfit->u.amm.turn) - w->solid->dir_vel = -w->outfit->u.amm.turn; + case WEAPON_STATUS_JAMMED: /* Continue doinng whatever. */ + /* Do nothing. */ + break; + + default: + WARN("Unknown weapon status for '%s'", w->outfit->name); + break; + } } /* Limit speed here. */ @@ -345,11 +393,12 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2* /* Create basic features. */ w = MALLOC_L(Weapon); w->faction = pilot_get(parent)->faction; /*Non-Changeable. */ - w->parent = parent; /* Non-Changeable. */ - w->target = target; /* Non-Changeable. */ - w->outfit = outfit; /* Non-Changeable. */ - w->update = weapon_update; - w->think = NULL; + w->parent = parent; /* Non-Changeable. */ + w->target = target; /* Non-Changeable. */ + w->outfit = outfit; /* Non-Changeable. */ + w->update = weapon_update; + w->think = NULL; + w->status = WEAPON_STATUS_OK; switch(outfit->type) { /* Bolts treated together. */