/** * @brief Gives the pilot a default weapon set. */ void pilot_weaponSetDefault( Pilot *p ) { int i; /* If current set isn't a fire group no need to worry. */ if (p->weapon_sets[ p->active_set ].type != WEAPSET_TYPE_CHANGE) { /* Update active weapon set. */ pilot_weapSetUpdateOutfits( p, &p->weapon_sets[ p->active_set ] ); return; } /* Find first fire group. */ for (i=0; i<PILOT_WEAPON_SETS; i++) if (p->weapon_sets[i].type == WEAPSET_TYPE_CHANGE) break; /* Set active set to first if all fire groups or first non-fire group. */ if (i >= PILOT_WEAPON_SETS) p->active_set = 0; else p->active_set = i; /* Update active weapon set. */ pilot_weapSetUpdateOutfits( p, &p->weapon_sets[ p->active_set ] ); }
/** * @brief Adds an outfit to a weapon set. * * @param p Pilot to manipulate. * @param id ID of the weapon set. * @param o Outfit to add. * @param level Level of the trigger. */ void pilot_weapSetAdd( Pilot* p, int id, PilotOutfitSlot *o, int level ) { PilotWeaponSet *ws; PilotWeaponSetOutfit *slot; Outfit *oo; int i, j; double r; ws = pilot_weapSet(p,id); /* Make sure outfit is valid. */ oo = o->outfit; if (oo == NULL) return; /* Make sure outfit type is weapon (or usable). */ if (!outfit_isActive(oo)) return; /* Create if needed. */ if (ws->slots == NULL) ws->slots = array_create( PilotWeaponSetOutfit ); /* Check if already there. */ for (i=0; i<array_size(ws->slots); i++) { if (ws->slots[i].slot == o) { ws->slots[i].level = level; /* Update if needed. */ if (id == p->active_set) pilot_weapSetUpdateOutfits( p, ws ); return; } } /* Add it. */ slot = &array_grow( &ws->slots ); slot->level = level; slot->slot = o; r = outfit_range(oo); if (r > 0) slot->range2 = pow2(r); /* Updated cached weapset. */ o->weapset = -1; for (j=0; j<PILOT_WEAPON_SETS; j++) { if (pilot_weapSetCheck(p, j, o) != -1) { o->weapset = j; break; } } /* Update range. */ pilot_weapSetUpdateRange( ws ); /* Update if needed. */ if (id == p->active_set) pilot_weapSetUpdateOutfits( p, ws ); }
/** * @brief Removes a slot from a weapon set. * * @param p Pilot who owns the weapon set. * @param id ID of the weapon set. * @param o Outfit to remove. */ void pilot_weapSetRm( Pilot* p, int id, PilotOutfitSlot *o ) { PilotWeaponSet *ws; int i; /* Make sure it has slots. */ ws = pilot_weapSet(p,id); if (ws->slots == NULL) return; /* Find the slot. */ for (i=0; i<array_size(ws->slots); i++) { if (ws->slots[i].slot != o) continue; array_erase( &ws->slots, &ws->slots[i], &ws->slots[i+1] ); /* Update range. */ pilot_weapSetUpdateRange( ws ); /* Update if needed. */ if (id == p->active_set) pilot_weapSetUpdateOutfits( p, ws ); return; } }
/** * @brief Adds an outfit to a weapon set. * * @param p Pilot to manipulate. * @param id ID of the weapon set. * @param o Outfit to add. * @param level Level of the trigger. */ void pilot_weapSetAdd( Pilot* p, int id, PilotOutfitSlot *o, int level ) { PilotWeaponSet *ws; PilotWeaponSetOutfit *slot; Outfit *oo; int i; ws = pilot_weapSet(p,id); /* Make sure outfit is valid. */ oo = o->outfit; if (oo == NULL) return; /* Make sure outfit type is weapon (or usable). */ if (!(outfit_isBeam(oo) || outfit_isBolt(oo) || outfit_isLauncher(oo) || outfit_isFighterBay(oo))) return; /* Create if needed. */ if (ws->slots == NULL) ws->slots = array_create( PilotWeaponSetOutfit ); /* Check if already there. */ for (i=0; i<array_size(ws->slots); i++) { if (ws->slots[i].slot == o) { ws->slots[i].level = level; /* Update if needed. */ if (id == p->active_set) pilot_weapSetUpdateOutfits( p, ws ); return; } } /* Add it. */ slot = &array_grow( &ws->slots ); slot->level = level; slot->slot = o; /* Update range. */ pilot_weapSetUpdateRange( ws ); /* Update if needed. */ if (id == p->active_set) pilot_weapSetUpdateOutfits( p, ws ); }
/** * @brief Executes a weapon set. * * @param p Pilot to manipulate. * @param id ID of the weapon set. * @param 1 if is keydown, -1 if is keyup, 0 if should be dry. */ void pilot_weapSetExec( Pilot* p, int id ) { PilotWeaponSet *ws; ws = pilot_weapSet(p,id); if (ws->fire) { pilot_weapSetFire( p, ws, -1 ); } else { if (id != p->active_set) pilot_weapSetUpdateOutfits( p, ws ); p->active_set = id; } }
/** * @brief Removes a slot from a weapon set. * * @param p Pilot who owns the weapon set. * @param id ID of the weapon set. * @param o Outfit to remove. */ void pilot_weapSetRm( Pilot* p, int id, PilotOutfitSlot *o ) { PilotWeaponSet *ws; int i, j; /* Make sure it has slots. */ ws = pilot_weapSet(p,id); if (ws->slots == NULL) return; /* Find the slot. */ for (i=0; i<array_size(ws->slots); i++) { if (ws->slots[i].slot != o) continue; array_erase( &ws->slots, &ws->slots[i], &ws->slots[i+1] ); /* Update range. */ pilot_weapSetUpdateRange( ws ); /* Update if needed. */ if (id == p->active_set) pilot_weapSetUpdateOutfits( p, ws ); /* Updated cached weapset. */ o->weapset = -1; for (j=0; j<PILOT_WEAPON_SETS; j++) { if (pilot_weapSetCheck(p, j, o) != -1) { o->weapset = j; break; } } return; } }
/** * @brief Handles a weapon set press. * * @param p Pilot the weapon set belongs to. * @param id ID of the weapon set. * @param type Is +1 if it's a press or -1 if it's a release. */ void pilot_weapSetPress( Pilot* p, int id, int type ) { int i, l, on, n; PilotWeaponSet *ws; ws = pilot_weapSet(p,id); /* Case no outfits. */ if (ws->slots == NULL) return; /* Handle fire groups. */ switch (ws->type) { case WEAPSET_TYPE_CHANGE: /* On press just change active weapon set to whatever is available. */ if (type > 0) { if (id != p->active_set) pilot_weapSetUpdateOutfits( p, ws ); p->active_set = id; } break; case WEAPSET_TYPE_WEAPON: /* Activation philosophy here is to turn on while pressed and off * when it's not held anymore. */ if (type > 0) ws->active = 1; else if (type < 0) ws->active = 0; break; case WEAPSET_TYPE_ACTIVE: /* The behaviour here is more complex. What we do is consider a group * to be entirely off if not all outfits are either on or cooling down. * In the case it's deemed to be off, all outfits that are off get turned * on, otherwise all outfits that are on are turrned to cooling down. */ /* Only care about presses. */ if (type < 0) break; /* Must not be disabled or cooling down. */ if ((pilot_isDisabled(p)) || (pilot_isFlag(p, PILOT_COOLDOWN))) return; /* Decide what to do. */ on = 1; l = array_size(ws->slots); for (i=0; i<l; i++) { if (ws->slots[i].slot->state == PILOT_OUTFIT_OFF) { on = 0; break; } } /* Turn them off. */ n = 0; if (on) { for (i=0; i<l; i++) { if (ws->slots[i].slot->state != PILOT_OUTFIT_ON) continue; n += pilot_outfitOff( p, ws->slots[i].slot ); } } /* Turn them on. */ else { for (i=0; i<l; i++) { if (ws->slots[i].slot->state != PILOT_OUTFIT_OFF) continue; if (outfit_isAfterburner(ws->slots[i].slot->outfit)) pilot_afterburn( p ); else { ws->slots[i].slot->state = PILOT_OUTFIT_ON; ws->slots[i].slot->stimer = outfit_duration( ws->slots[i].slot->outfit ); } n++; } } /* Must recalculate stats. */ if (n > 0) pilot_calcStats( p ); break; } }
/** * @brief Tries to automatically set and create the pilot's weapon set. * * Weapon set 0 is for all weapons. <br /> * Weapon set 1 is for forward weapons. Ammo using weapons are secondaries. <br /> * Weapon set 2 is for turret weapons. Ammo using weapons are secondaries. <br /> * Weapon set 3 is for all weapons. Forwards are primaries and turrets are secondaries. <br /> * Weapon set 4 is for seeking weapons. High payload variants are secondaries. <br /> * Weapon set 5 is for fighter bays. <br /> * * @param p Pilot to automagically generate weapon lists. */ void pilot_weaponAuto( Pilot *p ) { PilotOutfitSlot *slot; Outfit *o; int i, level, id; /* Clear weapons. */ pilot_weaponClear( p ); /* Set modes. */ pilot_weapSetType( p, 0, WEAPSET_TYPE_CHANGE ); pilot_weapSetType( p, 1, WEAPSET_TYPE_CHANGE ); pilot_weapSetType( p, 2, WEAPSET_TYPE_CHANGE ); pilot_weapSetType( p, 3, WEAPSET_TYPE_CHANGE ); pilot_weapSetType( p, 4, WEAPSET_TYPE_WEAPON ); pilot_weapSetType( p, 5, WEAPSET_TYPE_WEAPON ); pilot_weapSetType( p, 6, WEAPSET_TYPE_ACTIVE ); pilot_weapSetType( p, 7, WEAPSET_TYPE_ACTIVE ); pilot_weapSetType( p, 8, WEAPSET_TYPE_ACTIVE ); pilot_weapSetType( p, 9, WEAPSET_TYPE_ACTIVE ); /* All should be inrange. */ if (!pilot_isPlayer(p)) for (i=0; i<PILOT_WEAPON_SETS; i++){ pilot_weapSetInrange( p, i, 1 ); /* Update range and speed (at 0)*/ pilot_weapSetUpdateRange( &p->weapon_sets[i] ); } /* Iterate through all the outfits. */ for (i=0; i<p->noutfits; i++) { slot = p->outfits[i]; o = slot->outfit; /* Must be non-empty, and a weapon or active outfit. */ if ((o == NULL) || !outfit_isActive(o)) { slot->level = -1; /* Clear level. */ slot->weapset = -1; continue; } /* Manually defined group preempts others. */ if (o->group) { id = o->group; } /* Bolts and beams. */ else if (outfit_isBolt(o) || outfit_isBeam(o) || (outfit_isLauncher(o) && !outfit_isSeeker(o->u.lau.ammo))) { id = outfit_isTurret(o) ? 2 : 1; } /* Seekers. */ else if (outfit_isLauncher(o) && outfit_isSeeker(o->u.lau.ammo)) { id = 4; } /* Fighter bays. */ else if (outfit_isFighterBay(o)) { id = 5; } /* Ignore rest. */ else { slot->level = -1; continue; } /* Set level based on secondary flag. */ level = outfit_isSecondary(o); /* Add to its base group. */ pilot_weapSetAdd( p, id, slot, level ); /* Also add another copy to another group. */ if (id == 1) { /* Forward. */ pilot_weapSetAdd( p, 0, slot, level ); /* Also get added to 'All'. */ pilot_weapSetAdd( p, 3, slot, 0 ); /* Also get added to 'Fwd/Tur'. */ } else if (id == 2) { /* Turrets. */ pilot_weapSetAdd( p, 0, slot, level ); /* Also get added to 'All'. */ pilot_weapSetAdd( p, 3, slot, 1 ); /* Also get added to 'Fwd/Tur'. */ } else if (id == 4) /* Seekers */ pilot_weapSetAdd( p, 0, slot, level ); /* Also get added to 'All'. */ } /* Update active weapon set. */ pilot_weapSetUpdateOutfits( p, &p->weapon_sets[ p->active_set ] ); }