/** * @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 Have pilot stop shooting his weapon. * * Only really deals with beam weapons. * * @param p Pilot that was shooting. * @param level Level of the shot. */ void pilot_shootStop( Pilot* p, int level ) { int i; PilotWeaponSet *ws; /* Get active set. */ ws = pilot_weapSet( p, p->active_set ); /* Case no outfits. */ if (ws->slots == NULL) return; /* Stop all beams. */ for (i=0; i<array_size(ws->slots); i++) { /* Must have assosciated outfit. */ if (ws->slots[i].slot->outfit == NULL) continue; /* Must match level. */ if ((level != -1) && (ws->slots[i].level != level)) continue; /* Only handle beams. */ if (!outfit_isBeam(ws->slots[i].slot->outfit)) continue; /* Stop beam. */ if (ws->slots[i].slot->u.beamid > 0) { beam_end( p->id, ws->slots[i].slot->u.beamid ); ws->slots[i].slot->u.beamid = 0; } } }
/** * @brief Changes the weapon sets mode. * * @param p Pilot to manipulate. * @param id ID of the weapon set. * @param fire Whether or not to enable fire mode. */ void pilot_weapSetMode( Pilot* p, int id, int fire ) { PilotWeaponSet *ws; ws = pilot_weapSet(p,id); ws->fire = fire; }
/** * @brief Checks the current weapon set mode. * * @param p Pilot to manipulate. * @param id ID of the weapon set to check. * @return The fire mode of the weapon set. */ int pilot_weapSetModeCheck( Pilot* p, int id ) { PilotWeaponSet *ws; ws = pilot_weapSet(p,id); return ws->fire; }
/** * @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 Have pilot stop shooting their weapon. * * Only really deals with beam weapons. * * @param p Pilot that was shooting. * @param level Level of the shot. */ void pilot_shootStop( Pilot* p, int level ) { int i, recalc; PilotWeaponSet *ws; PilotOutfitSlot *slot; /* Get active set. */ ws = pilot_weapSet( p, p->active_set ); /* Case no outfits. */ if (ws->slots == NULL) return; /* Stop all beams. */ recalc = 0; for (i=0; i<array_size(ws->slots); i++) { slot = ws->slots[i].slot; /* Must have associated outfit. */ if (ws->slots[i].slot->outfit == NULL) continue; /* Must match level. */ if ((level != -1) && (ws->slots[i].level != level)) continue; /* Only handle beams. */ if (!outfit_isBeam(slot->outfit)) { /* Turn off the state. */ if (outfit_isMod( slot->outfit )) { slot->state = PILOT_OUTFIT_OFF; recalc = 1; } continue; } /* Stop beam. */ if (ws->slots[i].slot->u.beamid > 0) { /* Enforce minimum duration if set. */ if (slot->outfit->u.bem.min_duration > 0.) { slot->stimer = slot->outfit->u.bem.min_duration - (slot->outfit->u.bem.duration - slot->timer); if (slot->stimer > 0.) continue; } beam_end( p->id, slot->u.beamid ); pilot_stopBeam(p, slot); } } /* Must recalculate. */ if (recalc) pilot_calcStats( p ); }
/** * @brief Makes the pilot shoot. * * @param p The pilot which is shooting. * @param level Level of the shot. * @return The number of shots fired. */ int pilot_shoot( Pilot* p, int level ) { PilotWeaponSet *ws; /* Get active set. */ ws = pilot_weapSet( p, p->active_set ); /* Fire weapons. */ return pilot_weapSetFire( p, ws, level ); }
/** * @brief Clears the pilots weapon settings. * * @param p Pilot whose weapons we're clearing. */ void pilot_weaponClear( Pilot *p ) { int i; PilotWeaponSet *ws; for (i=0; i<PILOT_WEAPON_SETS; i++) { ws = pilot_weapSet( p, i ); if (ws->slots != NULL) array_erase( &ws->slots, &ws->slots[0], &ws->slots[ array_size(ws->slots) ] ); } }
/** * @brief Makes the pilot shoot. * * @param p The pilot which is shooting. * @param level Level of the shot. * @return The number of shots fired. */ int pilot_shoot( Pilot* p, int level ) { PilotWeaponSet *ws; /* Get active set. */ ws = pilot_weapSet( p, p->active_set ); /* Fire weapons. */ if (ws->type == WEAPSET_TYPE_CHANGE) /* Must be a change set or a weaponset. */ return pilot_weapSetFire( p, ws, level ); return 0; }
/** * @brief Sets the weapon set name. * * @param p Pilot to manipulate. * @param id ID of the weapon set. * @param name Name to set for the weapon set. */ void pilot_weapSetNameSet( Pilot* p, int id, const char *name ) { PilotWeaponSet *ws; ws = pilot_weapSet(p,id); if (ws->name != NULL) { if (strcmp(ws->name,name)==0) return; free( ws->name ); } ws->name = strdup(name); }
/** * @brief Gets the name of a weapon set. */ const char *pilot_weapSetName( Pilot* p, int id ) { PilotWeaponSet *ws; ws = pilot_weapSet(p,id); if ((ws->slots == NULL) || (array_size(ws->slots)==0)) return _("Unused"); switch (ws->type) { case WEAPSET_TYPE_CHANGE: return _("Weapons - Switched"); break; case WEAPSET_TYPE_WEAPON: return _("Weapons - Instant"); break; case WEAPSET_TYPE_ACTIVE: return _("Abilities - Toggled"); break; } return NULL; }
/** * @brief Cleans up a weapon set. * * @param p Pilot who owns the weapon set. * @param id ID of the weapon set to clean up. */ void pilot_weapSetCleanup( Pilot* p, int id ) { PilotWeaponSet *ws; ws = pilot_weapSet(p,id); if (ws->slots != NULL) array_free( ws->slots ); ws->slots = NULL; /* Update range. */ pilot_weapSetUpdateRange( ws ); }
/** * @brief Lists the items in a pilot weapon set. * * @param p Pilot who owns the weapon set. * @param id ID of the weapon set. * @param[out] n Number of elements in the list. * @return The array of pilot weaponset outfits. */ PilotWeaponSetOutfit* pilot_weapSetList( Pilot* p, int id, int *n ) { PilotWeaponSet *ws; ws = pilot_weapSet(p,id); if (ws->slots == NULL) { *n = 0; return NULL; } *n = array_size(ws->slots); return ws->slots; }
/** * @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 Handles a weapon set press. */ void pilot_weapSetPress( Pilot* p, int id, int type ) { PilotWeaponSet *ws; ws = pilot_weapSet(p,id); /* Handle fire groups. */ if (ws->fire) { if (type > 0) ws->active = 1; else if (type < 0) ws->active = 0; } else if (type > 0) pilot_weapSetExec( p, id ); }
/** * @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 Gets the speed of the current pilot weapon set. * * @param p Pilot to get the speed of. * @param id ID of weapon set to get the speed of. * @param Level of the weapons to get the speed of (-1 for all). */ double pilot_weapSetSpeed( Pilot* p, int id, int level ) { PilotWeaponSet *ws; int i; double speed; ws = pilot_weapSet(p,id); if (level < 0) { speed = 0; for (i=0; i<PILOT_WEAPSET_MAX_LEVELS; i++) speed += ws->speed[i]; } else speed = ws->speed[ level ]; return speed; }
/** * @brief Gets the range of the current pilot weapon set. * * @param p Pilot to get the range of. * @param id ID of weapon set to get the range of. * @param Level of the weapons to get the range of (-1 for all). */ double pilot_weapSetRange( Pilot* p, int id, int level ) { PilotWeaponSet *ws; int i; double range; ws = pilot_weapSet(p,id); if (level < 0) { range = 0; for (i=0; i<PILOT_WEAPSET_MAX_LEVELS; i++) range += ws->range[i]; } else range = ws->range[ level ]; return range; }
/** * @brief Changes the weapon sets mode. * * @param p Pilot to manipulate. * @param id ID of the weapon set. * @param fire Whether or not to enable fire mode. */ void pilot_weapSetType( Pilot* p, int id, int type ) { int i; PilotWeaponSet *ws; ws = pilot_weapSet(p,id); ws->type = type; /* Set levels just in case. */ if (ws->slots == NULL) return; /* See if we must overwrite levels. */ if ((ws->type == WEAPSET_TYPE_WEAPON) || (ws->type == WEAPSET_TYPE_ACTIVE)) for (i=0; i<array_size(ws->slots); i++) ws->slots[i].level = 0; }
/** * @brief Checks to see if a slot is in a weapon set. * * @param p Pilot to check. * @param id ID of the weapon set. * @param o Outfit slot to check. * @return The level to which it belongs (or -1 if it isn't set). */ int pilot_weapSetCheck( 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 -1; /* Find the slot. */ for (i=0; i<array_size(ws->slots); i++) if (ws->slots[i].slot == o) return ws->slots[i].level; /* Not found. */ return -1; }
/** * @brief Makes the pilot shoot. * * @param p The pilot which is shooting. * @param level Level of the shot. * @return The number of shots fired. */ int pilot_shoot( Pilot* p, int level ) { PilotWeaponSet *ws; int ret; /* Get active set. */ ws = pilot_weapSet( p, p->active_set ); /* Fire weapons. */ if (ws->type == WEAPSET_TYPE_CHANGE) { /* Must be a change set or a weaponset. */ ret = pilot_weapSetFire( p, ws, level ); /* Firing weapons aborts active cooldown. */ if (pilot_isFlag(p, PILOT_COOLDOWN) && ret) pilot_cooldownEnd(p, NULL); return ret; } return 0; }
/** * @brief Removes slots by type from the weapon set. */ void pilot_weapSetRmSlot( Pilot *p, int id, OutfitSlotType type ) { int i, n, l; PilotWeaponSet *ws; /* We must clean up the slots. */ n = 0; /* Number to remove. */ ws = pilot_weapSet(p,id); if (ws->slots == NULL) return; l = array_size(ws->slots); for (i=0; i<l; i++) { if (ws->slots->slot->sslot->slot.type != type) continue; /* Move down. */ memmove( &ws->slots[i], &ws->slots[i+1], sizeof(PilotWeaponSetOutfit) * (l-i-1) ); n++; } /* Remove surplus. */ array_erase( &ws->slots, &ws->slots[l-n], &ws->slots[l] ); }
/** * @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 Gets the name of a weapon set. */ const char *pilot_weapSetName( Pilot* p, int id ) { PilotWeaponSet *ws; ws = pilot_weapSet(p,id); return ws->name; }
/** * @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 Changes the weapon set inrange property. * * @param p Pilot to manipulate. * @param id ID of the weapon set. * @param inrange Whether or not to only fire at stuff in range. */ void pilot_weapSetInrange( Pilot* p, int id, int inrange ) { PilotWeaponSet *ws; ws = pilot_weapSet(p,id); ws->inrange = inrange; }
/** * @brief Checks the current weapon set inrange property. * * @param p Pilot to manipulate. * @param id ID of the weapon set to check. * @return The inrange mode of the weapon set. */ int pilot_weapSetInrangeCheck( Pilot* p, int id ) { PilotWeaponSet *ws; ws = pilot_weapSet(p,id); return ws->inrange; }
/** * @brief Checks the current weapon set type. * * @param p Pilot to manipulate. * @param id ID of the weapon set to check. * @return The type of the weapon set. */ int pilot_weapSetTypeCheck( Pilot* p, int id ) { PilotWeaponSet *ws; ws = pilot_weapSet(p,id); return ws->type; }