/** * @param ent The actor to set the reaction fire for * @return @c true if the needed settings could have been made or settings are * already valid, @c false otherwise. */ static bool G_ReactionFireSetDefault (edict_t *ent) { const objDef_t *weapon; const invList_t *invList; actorHands_t hand = ACTOR_HAND_RIGHT; if (G_ActorHasWorkingFireModeSet(ent)) return true; invList = ACTOR_GET_INV(ent, hand); if (!invList) { hand = ACTOR_HAND_LEFT; invList = ACTOR_GET_INV(ent, hand); } weapon = INVSH_HasReactionFireEnabledWeapon(invList); if (!weapon) return false; ent->chr.RFmode.fmIdx = 0; ent->chr.RFmode.hand = hand; ent->chr.RFmode.weapon = weapon; if (!G_IsAI(ent)) G_EventReactionFireChange(ent); return true; }
/** * @param ent The actor to set the reaction fire for * @return @c true if the needed settings could have been made or settings are * already valid, @c false otherwise. */ static bool G_ReactionFireSetDefault (edict_t *ent) { if (G_ActorHasWorkingFireModeSet(ent)) return true; actorHands_t hand = ACTOR_HAND_RIGHT; const invList_t *invList = ACTOR_GET_INV(ent, hand); if (!invList) { hand = ACTOR_HAND_LEFT; invList = ACTOR_GET_INV(ent, hand); } const objDef_t *weapon = INVSH_HasReactionFireEnabledWeapon(invList); if (!weapon) return false; ent->chr.RFmode.set(hand, 0, weapon); /* no special firemode */ if (!G_ActorHasWorkingFireModeSet(ent)) return false; if (!G_IsAI(ent)) G_EventReactionFireChange(ent); return true; }
/** * @brief Check whether ent can reaction fire at target, i.e. that it can see it and neither is dead etc. * @param[in] ent The entity that might be firing * @param[in] target The entity that might be fired at * @return @c true if 'ent' can actually fire at 'target', @c false otherwise */ static bool G_ReactionFireIsPossible (const edict_t *ent, const edict_t *target) { float actorVis; bool frustum; /* an entity can't reaction fire at itself */ if (ent == target) return false; /* Don't react in your own turn */ if (ent->team == level.activeTeam) return false; /* ent can't use RF if is in STATE_DAZED (flashbang impact) */ if (G_IsDazed(ent)) return false; if (G_IsDead(target)) return false; /* check ent has reaction fire enabled */ if (!G_IsShaken(ent) && !G_IsReaction(ent)) return false; /* check ent has weapon in RF hand */ /* @todo Should this situation even happen when G_IsReaction(ent) is true? */ if (!ACTOR_GET_INV(ent, ent->chr.RFmode.hand)) { /* print character info if this happens, for now */ gi.DPrintf("Reaction fire enabled but no weapon for hand (name=%s,hand=%i,fmIdx=%i)\n", ent->chr.name, ent->chr.RFmode.hand, ent->chr.RFmode.fmIdx); return false; } if (!G_IsVisibleForTeam(target, ent->team)) return false; /* If reaction fire is triggered by a friendly unit * and the shooter is still sane, don't shoot; * well, if the shooter isn't sane anymore... */ if (G_IsCivilian(target) || target->team == ent->team) if (!G_IsShaken(ent) || (float) ent->morale / mor_shaken->value > frand()) return false; /* check in range and visible */ if (VectorDistSqr(ent->origin, target->origin) > MAX_SPOT_DIST * MAX_SPOT_DIST) return false; frustum = G_FrustumVis(ent, target->origin); if (!frustum) return false; actorVis = G_ActorVis(ent->origin, ent, target, true); if (actorVis <= 0.2) return false; /* okay do it then */ return true; }
/** * @brief Returns the fire definition of the item the actor has in the given hand. * @param[in] actor The pointer to the actor we want to get the data from. * @param[in] hand Which hand to use * @return the used @c fireDef_t */ const fireDef_t *HUD_GetFireDefinitionForHand (const le_t * actor, const actorHands_t hand) { const invList_t *invlistWeapon; if (!actor) return NULL; invlistWeapon = ACTOR_GET_INV(actor, hand); if (!invlistWeapon || !invlistWeapon->item.t) return NULL; return FIRESH_FiredefForWeapon(&invlistWeapon->item); }
/** * @brief Starts aiming/target mode for selected left/right firemode. * @note Previously know as a combination of CL_FireRightPrimary, CL_FireRightSecondary, * @note CL_FireLeftPrimary and CL_FireLeftSecondary. */ static void HUD_FireWeapon_f (void) { actorHands_t hand; fireDefIndex_t firemode; const objDef_t *ammo; const fireDef_t *fd; if (Cmd_Argc() < 3) { /* no argument given */ Com_Printf("Usage: %s <l|r> <firemode number>\n", Cmd_Argv(0)); return; } if (!selActor) return; hand = ACTOR_GET_HAND_INDEX(Cmd_Argv(1)[0]); firemode = atoi(Cmd_Argv(2)); if (firemode >= MAX_FIREDEFS_PER_WEAPON || firemode < 0) return; fd = HUD_GetFireDefinitionForHand(selActor, hand); if (fd == NULL) return; ammo = fd->obj; /* Let's check if shooting is possible. */ if (!HUD_CheckShooting(selActor, ACTOR_GET_INV(selActor, hand))) return; if (ammo->fd[fd->weapFdsIdx][firemode].time <= CL_ActorUsableTUs(selActor)) { /* Actually start aiming. This is done by changing the current mode of display. */ if (hand == ACTOR_HAND_RIGHT) CL_ActorSetMode(selActor, M_FIRE_R); else CL_ActorSetMode(selActor, M_FIRE_L); /* Store firemode. */ selActor->currentSelectedFiremode = firemode; } else { /* Cannot shoot because of not enough TUs - every other * case should be checked previously in this function. */ HUD_DisplayMessage(_("Can't perform action:\nnot enough TUs.\n")); } }
/** * @brief Checks if the currently selected firemode is usable with the defined weapon. * @param[in] actor The actor to check the firemode for. */ static bool G_ActorHasWorkingFireModeSet (const edict_t *actor) { const FiremodeSettings *fmSettings = &actor->chr.RFmode; if (!fmSettings->isSaneFiremode()) /* just checks for valid values */ return false; const invList_t* invList = ACTOR_GET_INV(actor, fmSettings->getHand()); if (!invList) return false; const fireDef_t *fd = FIRESH_FiredefForWeapon(&invList->item); if (fd == NULL) return false; if (fd->obj->weapons[fd->weapFdsIdx] == fmSettings->weapon && fmSettings->fmIdx < fd->obj->numFiredefs[fd->weapFdsIdx]) { return true; } return false; }
/** * @brief Checks if the currently selected firemode is usable with the defined weapon. * @param[in] actor The actor to check the firemode for. */ static bool G_ActorHasWorkingFireModeSet (const edict_t *actor) { const fireDef_t *fd; const chrFiremodeSettings_t *fmSettings = &actor->chr.RFmode; const invList_t* invList; if (!SANE_FIREMODE(fmSettings)) return false; invList = ACTOR_GET_INV(actor, fmSettings->hand); if (!invList) return false; fd = FIRESH_FiredefForWeapon(&invList->item); if (fd == NULL) return false; if (fd->obj->weapons[fd->weapFdsIdx] == fmSettings->weapon && fmSettings->fmIdx < fd->obj->numFiredefs[fd->weapFdsIdx]) { return true; } return false; }