Пример #1
0
/**
 * @brief Change the amount of available ammo for the given entity
 * @param ent The entity to change the amount of ammo for
 * @param ammo The ammo to change
 * @param amount The new amount of the left ammo
 * @param shootType The shooting type to determine which container to use
 */
void G_EventInventoryAmmo (const Edict& ent, const objDef_t* ammo, int amount, shoot_types_t shootType)
{
	G_EventAdd(G_VisToPM(ent.visflags), EV_INV_AMMO, ent.number);
	gi.WriteByte(amount);
	gi.WriteByte(ammo->idx);
	if (IS_SHOT_RIGHT(shootType))
		gi.WriteByte(CID_RIGHT);
	else
		gi.WriteByte(CID_LEFT);
	/* x and y value */
	gi.WriteByte(0);
	gi.WriteByte(0);
	G_EventEnd();
}
Пример #2
0
/**
 * @brief Change the amount of available ammo for the given entity
 * @param ent The entity to change the amount of ammo for
 * @param ammo The ammo to change
 * @param amount The new amount of the left ammo
 * @param shootType The shooting type to determine which container to use
 */
void G_EventInventoryAmmo (const edict_t* ent, const objDef_t* ammo, int amount, shoot_types_t shootType)
{
	G_EventAdd(G_VisToPM(ent->visflags), EV_INV_AMMO, ent->number);
	gi.WriteByte(amount);
	gi.WriteByte(ammo->idx);
	if (IS_SHOT_RIGHT(shootType))
		gi.WriteByte(gi.csi->idRight);
	else
		gi.WriteByte(gi.csi->idLeft);
	/* x and y value */
	gi.WriteByte(0);
	gi.WriteByte(0);
	G_EventEnd();
}
Пример #3
0
/**
 * @brief Perform the reaction fire shot
 * @param[in] shooter The actor that is trying to shoot
 * @param[in] at Position to fire on.
 * @param[in] type What type of shot this is (left, right reaction-left etc...).
 * @param[in] firemode The firemode index of the ammo for the used weapon (objDef.fd[][x])  .
 * @return true if everything went ok (i.e. the shot(s) where fired ok), otherwise false.
 * @sa G_ClientShoot
 */
bool ReactionFire::shoot (Actor* shooter, const pos3_t at, shoot_types_t type, fireDefIndex_t firemode)
{
	const Item* weapon = nullptr;
	if (IS_SHOT_RIGHT(type)) {
		weapon = shooter->getRightHandItem();
		if (!weapon)
			return false;
	} else {
		weapon = shooter->getLeftHandItem();
		if (!weapon)
			return false;
	}

	const fireDef_t* fdArray = weapon->getFiredefs();
	if (!fdArray)
		return false;

	/* Adjust the number of samples we take so that we don't end firing thousands of shots
	 * in case the fire mode is multi-shot */
	const int shotsPerFD = fdArray[firemode].shots;
	const int samples = std::max(1, 100 / shotsPerFD);
	const Player& player = shooter->getPlayer();
	shot_mock_t mock;
	for (int i = 0; i < samples; ++i)
		if (!G_ClientShoot(player, shooter, at, type, firemode, &mock, false, 0))
			break;

	/* this is the max amount of friendly units that were hit during the mock calculation */
	const int maxShots = samples * shotsPerFD;
	int maxff;
	if (shooter->isInsane())
		maxff = maxShots;
	else if (shooter->isRaged())
		maxff = maxShots * 2 / 3;
	else if (shooter->isPanicked())
		maxff = maxShots / 3;
	else if (shooter->isShaken())
		maxff = maxShots / 6;
	else
		maxff = maxShots / 20;

	/* calculate the mock values - e.g. how many friendly units we would hit
	 * when opening the reaction fire */
	const int ff = mock.friendCount + (G_IsAlien(shooter) ? 0 : mock.civilian);
	const int hits = shooter->isInsane() ? ff + mock.enemyCount : mock.enemyCount;
	if (ff <= maxff && hits > 0)
		return G_ClientShoot(player, shooter, at, type, firemode, nullptr, false, 0);

	return false;
}
Пример #4
0
/**
 * @brief Calculates the muzzle for the current weapon the actor is shooting with
 * @param[in] actor The actor that is shooting. Might not be @c nullptr
 * @param[out] muzzle The muzzle vector to spawn the particle at. Might not be @c nullptr. This is not
 * modified if there is no tag for the muzzle found for the weapon or item the actor has
 * in the hand (also see the given shoot type)
 * @param[in] shootType The shoot type to determine which tag of the actor should be used
 * to resolve the world coordinates. Also used to determine which item (or better which hand)
 * should be used to resolve the actor's item.
 */
static void CL_ActorGetMuzzle (const le_t* actor, vec3_t muzzle, shoot_types_t shootType)
{
	if (actor == nullptr)
		return;

	const Item* weapon;
	const char* tag;
	if (IS_SHOT_RIGHT(shootType)) {
		tag = "tag_rweapon";
		weapon = actor->getRightHandItem();
	} else {
		tag = "tag_lweapon";
		weapon = actor->getLeftHandItem();
	}

	if (!weapon || !weapon->def())
		return;

	const objDef_t* od = weapon->def();
	const model_t* model = cls.modelPool[od->idx];
	if (!model)
		Com_Error(ERR_DROP, "Model for item %s is not precached", od->id);

	/* not every weapon has a muzzle tag assigned */
	if (R_GetTagIndexByName(model, "tag_muzzle") == -1)
		return;

	float modifiedMatrix[16];
	if (!R_GetTagMatrix(actor->model1, tag, actor->as.frame, modifiedMatrix))
		Com_Error(ERR_DROP, "Could not find tag %s for actor model %s", tag, actor->model1->name);

	float mc[16];
	GLMatrixAssemble(actor->origin, actor->angles, mc);

	float matrix[16];
	GLMatrixMultiply(mc, modifiedMatrix, matrix);

	R_GetTagMatrix(model, "tag_muzzle", 0, modifiedMatrix);
	GLMatrixMultiply(matrix, modifiedMatrix, mc);

	muzzle[0] = mc[12];
	muzzle[1] = mc[13];
	muzzle[2] = mc[14];
}
/**
 * @brief Starts shooting with actor.
 * @param[in] self Pointer to the event structure that is currently executed
 * @param[in] msg The netchannel message
 * @sa CL_ActorShootHidden
 * @sa CL_ActorShoot
 * @sa CL_ActorDoShoot
 * @todo Improve detection of left- or right animation.
 * @sa EV_ACTOR_START_SHOOT
 */
void CL_ActorStartShoot (const eventRegister_t *self, dbuffer *msg)
{
	le_t *le;
	pos3_t from, target;
	int entnum;
	shoot_types_t shootType;

	NET_ReadFormat(msg, self->formatString, &entnum, &shootType, &from, &target);

	/* shooting actor */
	le = LE_Get(entnum);

	/* center view (if wanted) */
	if (cl.actTeam != cls.team)
		CL_CameraRoute(from, target);

	/* actor dependent stuff following */
	if (!le)
		/* it's OK, the actor is not visible */
		return;

	if (!LE_IsLivingActor(le) || LE_IsStunned(le)) {
		Com_Printf("CL_ActorStartShoot: LE (%i) not a living actor (type: %i)\n", entnum, le->type);
		return;
	}

	/* ET_ACTORHIDDEN actors don't have a model yet */
	if (le->type == ET_ACTORHIDDEN)
		return;

	/* Animate - we have to check if it is right or left weapon usage. */
	if (IS_SHOT_RIGHT(shootType)) {
		R_AnimChange(&le->as, le->model1, LE_GetAnim("move", le->right, le->left, le->state));
	} else if (IS_SHOT_LEFT(shootType)) {
		R_AnimChange(&le->as, le->model1, LE_GetAnim("move", le->left, le->right, le->state));
	} else if (!IS_SHOT_HEADGEAR(shootType)) {
		/* no animation for headgear (yet) */
		Com_Error(ERR_DROP, "CL_ActorStartShoot: Invalid shootType given (entnum: %i, shootType: %i).\n", shootType, entnum);
	}
}
Пример #6
0
/**
 * @brief Shoot with weapon.
 * @sa CL_ActorShoot
 * @sa CL_ActorShootHidden
 * @todo Improve detection of left- or right animation.
 * @sa EV_ACTOR_SHOOT
 */
void CL_ActorDoShoot (const eventRegister_t* self, dbuffer* msg)
{
	vec3_t muzzle, impact;
	int flags, normal, shooterEntnum, victimEntnum;
	int objIdx;
	int first;
	weaponFireDefIndex_t weapFdsIdx;
	fireDefIndex_t fdIdx;
	int surfaceFlags;
	shoot_types_t shootType;

	/* read data */
	NET_ReadFormat(msg, self->formatString, &shooterEntnum, &victimEntnum, &first, &objIdx, &weapFdsIdx, &fdIdx, &shootType, &flags, &surfaceFlags, &muzzle, &impact, &normal);

	le_t* leVictim;
	if (victimEntnum != SKIP_LOCAL_ENTITY) {
		leVictim = LE_Get(victimEntnum);
		if (!leVictim)
			LE_NotFoundError(victimEntnum);
	} else {
		leVictim = nullptr;
	}

	/* get shooter le */
	le_t* leShooter = LE_Get(shooterEntnum);

	/* get the fire def */
	const objDef_t* obj = INVSH_GetItemByIDX(objIdx);
	const fireDef_t* fd = FIRESH_GetFiredef(obj, weapFdsIdx, fdIdx);

	CL_ActorGetMuzzle(leShooter, muzzle, shootType);

	/* add effect le */
	LE_AddProjectile(fd, flags, muzzle, impact, normal, leVictim);

	/* start the sound */
	if ((first || !fd->soundOnce) && fd->fireSound != nullptr && !(flags & SF_BOUNCED))
		S_LoadAndPlaySample(fd->fireSound, muzzle, fd->fireAttenuation, SND_VOLUME_WEAPONS);

	/* do actor related stuff */
	if (!leShooter)
		return; /* maybe hidden or inuse is false? */

	if (!LE_IsActor(leShooter))
		Com_Error(ERR_DROP, "Can't shoot, LE not an actor (type: %i)", leShooter->type);

	/* no animations for hidden actors */
	if (leShooter->type == ET_ACTORHIDDEN)
		return;

	if (LE_IsDead(leShooter)) {
		Com_DPrintf(DEBUG_CLIENT, "Can't shoot, actor dead or stunned.\n");
		return;
	}

	/* Animate - we have to check if it is right or left weapon usage. */
	if (IS_SHOT_RIGHT(shootType)) {
		R_AnimChange(&leShooter->as, leShooter->model1, LE_GetAnim("shoot", leShooter->right, leShooter->left, leShooter->state));
		R_AnimAppend(&leShooter->as, leShooter->model1, LE_GetAnim("stand", leShooter->right, leShooter->left, leShooter->state));
	} else if (IS_SHOT_LEFT(shootType)) {
		R_AnimChange(&leShooter->as, leShooter->model1, LE_GetAnim("shoot", leShooter->left, leShooter->right, leShooter->state));
		R_AnimAppend(&leShooter->as, leShooter->model1, LE_GetAnim("stand", leShooter->left, leShooter->right, leShooter->state));
	} else if (IS_SHOT_HEADGEAR(shootType)) {
		if (fd->irgoggles) {
			leShooter->state |= RF_IRGOGGLESSHOT;
			if (LE_IsSelected(leShooter))
				refdef.rendererFlags |= RDF_IRGOGGLES;
		}
	} else {
		/* no animation for headgear (yet) */
		Com_Error(ERR_DROP, "CL_ActorDoShoot: Invalid shootType given (entnum: %i, shootType: %i).\n", shootType, shooterEntnum);
	}
}