コード例 #1
0
ファイル: g_reaction.cpp プロジェクト: MyWifeRules/ufoai-1
/**
 * @brief Perform the reaction fire shot
 * @param[in] player The player this action belongs to (the human player or the ai)
 * @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
 */
static bool G_ReactionFireShoot (const player_t *player, edict_t *shooter, const pos3_t at, shoot_types_t type, fireDefIndex_t firemode)
{
	const int minhit = 30;
	shot_mock_t mock;
	int ff, i;
	/* this is the max amount of friendly units that were hit during the mock calculation */
	int maxff;

	if (G_IsInsane(shooter))
		maxff = 100;
	else if (G_IsRaged(shooter))
		maxff = 60;
	else if (G_IsPaniced(shooter))
		maxff = 30;
	else if (G_IsShaken(shooter))
		maxff = 15;
	else
		maxff = 5;

	/* calculate the mock values - e.g. how many friendly units we would hit
	 * when opening the reaction fire */
	OBJZERO(mock);
	for (i = 0; i < 100; i++)
		if (!G_ClientShoot(player, shooter, at, type, firemode, &mock, false, 0))
			break;

	ff = mock.friendCount + (G_IsAlien(shooter) ? 0 : mock.civilian);
	if (ff <= maxff && mock.enemyCount >= minhit)
		return G_ClientShoot(player, shooter, at, type, firemode, NULL, false, 0);

	return false;
}
コード例 #2
0
ファイル: g_reaction.cpp プロジェクト: ArkyRomania/ufoai
/**
 * @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)
{
	/* this is the max amount of friendly units that were hit during the mock calculation */
	int maxff;

	if (shooter->isInsane())
		maxff = 100;
	else if (shooter->isRaged())
		maxff = 60;
	else if (shooter->isPanicked())
		maxff = 30;
	else if (shooter->isShaken())
		maxff = 15;
	else
		maxff = 5;

	/* calculate the mock values - e.g. how many friendly units we would hit
	 * when opening the reaction fire */
	const int minhit = 30;
	shot_mock_t mock;
	const Player& player = shooter->getPlayer();
	for (int i = 0; i < 100; i++)
		if (!G_ClientShoot(player, shooter, at, type, firemode, &mock, false, 0))
			break;

	const int ff = mock.friendCount + (G_IsAlien(shooter) ? 0 : mock.civilian);
	if (ff <= maxff && mock.enemyCount >= minhit)
		return G_ClientShoot(player, shooter, at, type, firemode, nullptr, false, 0);

	return false;
}
コード例 #3
0
ファイル: g_reaction.cpp プロジェクト: ufoai/ufoai
/**
 * @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
ファイル: g_ai_lua.cpp プロジェクト: Qazzian/ufoai_suspend
/**
 * @brief Shoots the actor.
 */
static int actorL_shoot (lua_State *L)
{
	int tu, shots;
	shoot_types_t shootType;
	const item_t *item;
	const fireDef_t *fdArray;

	assert(lua_isactor(L, 1));

	/* Target */
	aiActor_t *target = lua_toactor(L, 1);

	/* Number of TU to spend shooting, fire mode will adjust to that. */
	if (lua_gettop(L) > 1) {
		assert(lua_isnumber(L, 2)); /* Must be a number. */

		tu = (int) lua_tonumber(L, 2);
	} else {
		tu = G_ActorUsableTUs(AIL_ent);
	}

	shootType = ST_RIGHT;
	item = AI_GetItemForShootType(shootType, AIL_ent);
	if (item == NULL) {
		shootType = ST_LEFT;
		item = AI_GetItemForShootType(shootType, AIL_ent);
	}

	/* Failure - no weapon. */
	if (item == NULL) {
		lua_pushboolean(L, 0);
		return 1;
	}

	/** @todo Choose fire mode based on TU available - currently the first one is used. */
	fdArray = FIRESH_FiredefForWeapon(item);
	if (fdArray == NULL) {
		/* Failure - no weapon. */
		lua_pushboolean(L, 0);
		return 1;
	}

	shots = tu / G_GetActorTimeForFiredef(AIL_ent, fdArray, false);

	while (shots > 0) {
		shots--;
		/** @todo actually handle fire modes */
		G_ClientShoot(AIL_player, AIL_ent, target->ent->pos,
				shootType, 0, NULL, true, 0);
	}

	/* Success. */
	lua_pushboolean(L, 1);
	return 1;
}
コード例 #5
0
/**
 * @brief The client sent us a message that he did something. We now execute the related function(s) and notify him if necessary.
 * @param[in] player The player to execute the action for (the actor belongs to this player)
 * @note a client action will also send the server side edict number to determine the actor
 */
int G_ClientAction (player_t * player)
{
	player_action_t action;
	int num;
	pos3_t pos;
	int i;
	fireDefIndex_t firemode;
	int from, fx, fy, to, tx, ty;
	actorHands_t hand;
	int fmIdx, objIdx;
	int resCrouch, resShot;
	edict_t *ent;
	const char *format;

	/* read the header */
	action = (player_action_t)gi.ReadByte();
	num = gi.ReadShort();

	ent = G_EdictsGetByNum(num);
	if (ent == NULL)
		return action;

	format = pa_format[action];

	switch (action) {
	case PA_NULL:
		/* do nothing on a null action */
		break;

	case PA_TURN:
		gi.ReadFormat(format, &i);
		G_ClientTurn(player, ent, (dvec_t) i);
		break;

	case PA_MOVE:
		gi.ReadFormat(format, &pos);
		G_ClientMove(player, player->pers.team, ent, pos);
		break;

	case PA_STATE:
		gi.ReadFormat(format, &i);
		G_ClientStateChange(player, ent, i, true);
		break;

	case PA_SHOOT:
		gi.ReadFormat(format, &pos, &i, &firemode, &from);
		G_ClientShoot(player, ent, pos, i, firemode, NULL, true, from);
		break;

	case PA_INVMOVE:
		gi.ReadFormat(format, &from, &fx, &fy, &to, &tx, &ty);

		if (from < 0 || from >= gi.csi->numIDs || to < 0 || to >= gi.csi->numIDs) {
			gi.DPrintf("G_ClientAction: PA_INVMOVE Container index out of range. (from: %i, to: %i)\n", from, to);
		} else {
			const invDef_t *fromPtr = INVDEF(from);
			const invDef_t *toPtr = INVDEF(to);
			invList_t *fromItem = INVSH_SearchInInventory(&ent->chr.i, fromPtr, fx, fy);
			if (fromItem)
				G_ActorInvMove(ent, fromPtr, fromItem, toPtr, tx, ty, true);
		}
		break;

	case PA_USE:
		if (ent->clientAction) {
			edict_t *actionEnt;

			/* read the door the client wants to open */
			gi.ReadFormat(format, &i);

			/* get the door edict */
			actionEnt = G_EdictsGetByNum(i);

			/* maybe the door is no longer 'alive' because it was destroyed */
			if (actionEnt && ent->clientAction == actionEnt) {
				if (G_IsDoor(actionEnt)) {
					G_ActorUseDoor(ent, actionEnt);
				}
			}
		}
		break;

	case PA_REACT_SELECT:
		gi.ReadFormat(format, &hand, &fmIdx, &objIdx);
		G_ReactionFireSettingsUpdate(ent, fmIdx, hand, INVSH_GetItemByIDX(objIdx));
		break;

	case PA_RESERVE_STATE:
		gi.ReadFormat(format, &resShot, &resCrouch);

		G_ActorReserveTUs(ent, ent->chr.reservedTus.reaction, resShot, resCrouch);
		break;

	default:
		gi.Error("G_ClientAction: Unknown action!\n");
	}
	return action;
}