2023-08-09 19:45:39 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
Copyright (C) 2023 the OpenMoHAA team
|
|
|
|
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
|
|
or (at your option) any later version.
|
|
|
|
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "sentient.h"
|
|
|
|
#include "weapon.h"
|
|
|
|
#include "game.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "../script/scriptexception.h"
|
|
|
|
|
|
|
|
ActiveWeapon::ActiveWeapon()
|
|
|
|
{
|
|
|
|
hand = WEAPON_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ActiveWeapon::Archive(Archiver& arc)
|
|
|
|
{
|
|
|
|
arc.ArchiveObjectPointer((Class **)&weapon);
|
|
|
|
ArchiveEnum(hand, weaponhand_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sentient::IsNewActiveWeapon(void)
|
|
|
|
{
|
|
|
|
return (newActiveWeapon.weapon != NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
weaponhand_t Sentient::GetNewActiveWeaponHand(void)
|
|
|
|
{
|
|
|
|
return newActiveWeapon.hand;
|
|
|
|
}
|
|
|
|
|
|
|
|
Weapon *Sentient::GetNewActiveWeapon(void)
|
|
|
|
{
|
|
|
|
return newActiveWeapon.weapon;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::ClearNewActiveWeapon(void)
|
|
|
|
{
|
|
|
|
newActiveWeapon.weapon.Clear();
|
|
|
|
newActiveWeapon.hand = WEAPON_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::EventGiveAmmo(Event *ev)
|
|
|
|
{
|
|
|
|
int amount, maxamount = -1;
|
|
|
|
const char *type;
|
|
|
|
|
|
|
|
type = ev->GetString(1);
|
|
|
|
amount = ev->GetInteger(2);
|
|
|
|
|
|
|
|
if (ev->NumArgs() == 3) {
|
|
|
|
maxamount = ev->GetInteger(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
GiveAmmo(type, amount, maxamount);
|
|
|
|
}
|
|
|
|
|
|
|
|
int Sentient::AmmoIndex(str type)
|
|
|
|
|
|
|
|
{
|
|
|
|
Ammo *ammo;
|
|
|
|
|
|
|
|
ammo = FindAmmoByName(type);
|
|
|
|
|
|
|
|
if (ammo) {
|
|
|
|
return ammo->getIndex();
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int Sentient::AmmoCount(str type)
|
|
|
|
{
|
|
|
|
Ammo *ammo;
|
|
|
|
|
|
|
|
if (!type.length()) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ammo = FindAmmoByName(type);
|
|
|
|
|
|
|
|
if (ammo) {
|
|
|
|
return ammo->getAmount();
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int Sentient::MaxAmmoCount(str type)
|
|
|
|
{
|
|
|
|
Ammo *ammo;
|
|
|
|
|
|
|
|
ammo = FindAmmoByName(type);
|
|
|
|
|
|
|
|
if (ammo) {
|
|
|
|
return ammo->getMaxAmount();
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::GiveAmmo(str type, int amount, int maxamount)
|
|
|
|
{
|
|
|
|
Ammo *ammo;
|
|
|
|
|
|
|
|
ammo = FindAmmoByName(type);
|
|
|
|
|
|
|
|
if (ammo) {
|
|
|
|
if (maxamount >= 0) {
|
|
|
|
ammo->setMaxAmount(maxamount);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add amount to current amount
|
|
|
|
ammo->setAmount(ammo->getAmount() + amount);
|
|
|
|
} else {
|
|
|
|
// Create a new inventory entry with this name
|
|
|
|
ammo = new Ammo;
|
|
|
|
|
|
|
|
if (maxamount >= 0) {
|
|
|
|
ammo->setMaxAmount(maxamount);
|
|
|
|
}
|
|
|
|
|
|
|
|
ammo->setAmount(amount);
|
|
|
|
|
|
|
|
ammo->setName(type);
|
|
|
|
ammo_inventory.AddObject(ammo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int Sentient::UseAmmo(str type, int amount)
|
|
|
|
|
|
|
|
{
|
|
|
|
int count, i;
|
|
|
|
|
|
|
|
count = ammo_inventory.NumObjects();
|
|
|
|
|
|
|
|
for (i = 1; i <= count; i++) {
|
|
|
|
Ammo *ammo = ammo_inventory.ObjectAt(i);
|
|
|
|
if (type == ammo->getName()) {
|
|
|
|
int ammo_amount = ammo->getAmount();
|
|
|
|
|
|
|
|
// Less ammo than what we specified to use
|
|
|
|
if (ammo_amount < amount) {
|
|
|
|
ammo->setAmount(0);
|
|
|
|
AmmoAmountChanged(ammo);
|
|
|
|
return ammo_amount;
|
|
|
|
} else {
|
|
|
|
ammo->setAmount(ammo->getAmount() - amount);
|
|
|
|
AmmoAmountChanged(ammo);
|
|
|
|
return amount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::AmmoAmountInClipChanged(str type, int amount_in_clip)
|
|
|
|
{
|
|
|
|
int count, i;
|
|
|
|
|
|
|
|
count = ammo_inventory.NumObjects();
|
|
|
|
|
|
|
|
for (i = 1; i <= count; i++) {
|
|
|
|
Ammo *ammo = ammo_inventory.ObjectAt(i);
|
|
|
|
if (type == ammo->getName()) {
|
|
|
|
AmmoAmountChanged(ammo, amount_in_clip);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::AmmoAmountChanged(Ammo *ammo, int ammo_in_clip) {}
|
|
|
|
|
|
|
|
void Sentient::MeleeAttackStart(Event *ev)
|
|
|
|
{
|
|
|
|
in_melee_attack = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::MeleeAttackEnd(Event *ev)
|
|
|
|
{
|
|
|
|
in_melee_attack = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::WeaponKnockedFromHands(void)
|
|
|
|
{
|
|
|
|
str realname;
|
|
|
|
AliasListNode_t *ret;
|
|
|
|
|
|
|
|
realname = GetRandomAlias("snd_lostweapon", &ret);
|
|
|
|
if (realname.length() > 1) {
|
|
|
|
Sound(realname.c_str(), CHAN_VOICE);
|
|
|
|
} else {
|
|
|
|
Sound("snd_pain", CHAN_VOICE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-09 23:09:09 +02:00
|
|
|
bool Sentient::CanSee(Entity *ent, float fov, float vision_distance, bool bNoEnts)
|
2023-08-09 19:45:39 +02:00
|
|
|
{
|
|
|
|
float delta[2];
|
|
|
|
|
|
|
|
delta[0] = ent->centroid[0] - centroid[0];
|
|
|
|
delta[1] = ent->centroid[1] - centroid[1];
|
|
|
|
|
|
|
|
if ((vision_distance <= 0.0f) || VectorLength2DSquared(delta) <= (vision_distance * vision_distance)) {
|
|
|
|
if (gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum)
|
|
|
|
&& ((fov <= 0.0f || fov >= 360.0f) || (FovCheck(delta, cos(fov * (0.5 * M_PI / 180.0)))))) {
|
|
|
|
//
|
|
|
|
// Parent checking for subclass is absolute non-sense...
|
|
|
|
//
|
|
|
|
if (ent->IsSubclassOfPlayer()) {
|
|
|
|
Player *p = (Player *)ent;
|
|
|
|
|
|
|
|
Vector vStart = EyePosition();
|
|
|
|
Vector vEnd = p->EyePosition();
|
|
|
|
|
|
|
|
return G_SightTrace(vStart, vec_zero, vec_zero, vEnd, this, ent, MASK_CANSEE, 0, "Sentient::CanSee 1");
|
|
|
|
} else {
|
|
|
|
Vector vStart = EyePosition();
|
|
|
|
Vector vEnd = ent->centroid;
|
|
|
|
|
|
|
|
return G_SightTrace(vStart, vec_zero, vec_zero, vEnd, this, ent, MASK_CANSEE, 0, "Sentient::CanSee 2");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector Sentient::GunPosition(void)
|
|
|
|
{
|
|
|
|
Vector vPos;
|
|
|
|
|
|
|
|
if (activeWeaponList[WEAPON_MAIN]) {
|
|
|
|
activeWeaponList[WEAPON_MAIN]->GetMuzzlePosition(&vPos);
|
|
|
|
} else {
|
|
|
|
vPos = origin;
|
|
|
|
}
|
|
|
|
|
|
|
|
return vPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector Sentient::GunTarget(bool bNoCollision)
|
|
|
|
{
|
|
|
|
Vector vPos;
|
|
|
|
|
|
|
|
if (mTargetPos[0] && mTargetPos[1] && mTargetPos[2]) {
|
|
|
|
AnglesToAxis(angles, orientation);
|
|
|
|
vPos = GunPosition() + Vector(orientation[0]) * 2048.0f;
|
|
|
|
} else {
|
|
|
|
if (G_Random() > mAccuracy) {
|
|
|
|
float rand = G_Random(5.0f);
|
|
|
|
|
|
|
|
if (G_Random() <= 0.5f) {
|
|
|
|
vPos[0] = rand - 32.0f;
|
|
|
|
} else {
|
|
|
|
vPos[0] = rand + 32.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
rand = G_Random(5.0f);
|
|
|
|
|
|
|
|
if (G_Random() <= 0.5f) {
|
|
|
|
vPos[1] = rand - 32.0f;
|
|
|
|
} else {
|
|
|
|
vPos[1] = rand + 32.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
vPos[2] = -96.0f - G_Random(5.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
vPos += mTargetPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
return vPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::ChargeWeapon(weaponhand_t hand, firemode_t mode)
|
|
|
|
{
|
|
|
|
Weapon *activeWeapon;
|
|
|
|
|
2023-08-13 16:07:28 +02:00
|
|
|
if (charge_start_time != 0) {
|
|
|
|
// Already charging
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-08-09 19:45:39 +02:00
|
|
|
if (hand > MAX_ACTIVE_WEAPONS) {
|
|
|
|
warning(
|
|
|
|
"Sentient::ChargeWeapon",
|
|
|
|
"Weapon hand number \"%d\" is out of bounds of 0 to MAX_ACTIVE_WEAPONS:%d\n",
|
|
|
|
hand,
|
|
|
|
MAX_ACTIVE_WEAPONS
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// start charging the active weapon
|
|
|
|
activeWeapon = activeWeaponList[(int)hand];
|
|
|
|
|
2023-08-13 16:07:28 +02:00
|
|
|
if (activeWeapon && activeWeapon->ReadyToFire(mode) && activeWeapon->MuzzleClear()) {
|
2023-08-09 19:45:39 +02:00
|
|
|
charge_start_time = level.time;
|
2023-08-13 16:07:28 +02:00
|
|
|
activeWeapon->Charge(mode);
|
2023-08-09 19:45:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::ChargeWeapon(Event *ev)
|
|
|
|
{
|
|
|
|
firemode_t mode = FIRE_PRIMARY;
|
|
|
|
weaponhand_t hand = WEAPON_MAIN;
|
|
|
|
|
|
|
|
if (charge_start_time) {
|
|
|
|
// Charging has already been started, so return
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 0) {
|
|
|
|
hand = WeaponHandNameToNum(ev->GetString(1));
|
|
|
|
|
|
|
|
if (hand < 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() == 2) {
|
|
|
|
mode = WeaponModeNameToNum(ev->GetString(2));
|
|
|
|
|
|
|
|
if (mode < 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ChargeWeapon(hand, mode);
|
|
|
|
}
|
|
|
|
|
2023-08-12 00:48:35 +02:00
|
|
|
void Sentient::EventForceLandmineMeasure(Event *ev)
|
|
|
|
{
|
|
|
|
// Can be inherited by child classes
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::EventSetWeaponIdleState(Event *ev)
|
|
|
|
{
|
|
|
|
Weapon *weapon;
|
|
|
|
weaponhand_t hand = WEAPON_MAIN;
|
|
|
|
int state;
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 2) {
|
|
|
|
warning("Sentient::PingForMines", "Wrong number of arguments (setweaponidlestate # [weaponhand])\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ev->NumArgs() == 2) {
|
|
|
|
hand = WeaponHandNameToNum(ev->GetString(1));
|
|
|
|
if (hand == WEAPON_ERROR) {
|
|
|
|
hand = WEAPON_MAIN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
state = ev->GetInteger(1);
|
|
|
|
weapon = GetActiveWeapon(hand);
|
|
|
|
if (weapon) {
|
|
|
|
weapon->SetIdleState(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::EventPingForMines(Event *ev)
|
|
|
|
{
|
|
|
|
if (ev->NumArgs() > 0) {
|
|
|
|
warning("Sentient::PingForMines", "Wrong number of arguments, none expected\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Not sure why this is empty
|
|
|
|
}
|
|
|
|
|
2023-08-09 19:45:39 +02:00
|
|
|
void Sentient::ReloadWeapon(Event *ev)
|
|
|
|
{
|
|
|
|
Weapon *weapon;
|
|
|
|
weaponhand_t hand = WEAPON_MAIN;
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 0) {
|
|
|
|
hand = WeaponHandNameToNum(ev->GetString(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hand == WEAPON_ERROR) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
weapon = GetActiveWeapon(hand);
|
|
|
|
|
|
|
|
if (weapon) {
|
|
|
|
weapon->StartReloading();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::FireWeapon(int number, firemode_t mode)
|
|
|
|
{
|
|
|
|
Weapon *activeWeapon = activeWeaponList[number];
|
|
|
|
|
|
|
|
if (activeWeapon) {
|
|
|
|
if (mode == FIRE_SECONDARY && activeWeapon->GetZoom() && !activeWeapon->GetAutoZoom() && IsSubclassOfPlayer()) {
|
|
|
|
Player *p = (Player *)this;
|
|
|
|
p->ToggleZoom(activeWeapon->GetZoom());
|
|
|
|
} else {
|
|
|
|
activeWeapon->Fire(mode);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
gi.DPrintf("No active weapon in slot #: \"%i\"\n", number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::FireWeapon(Event *ev)
|
|
|
|
{
|
|
|
|
firemode_t mode = FIRE_PRIMARY;
|
|
|
|
int number = 0;
|
|
|
|
str modestring;
|
|
|
|
str side;
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 0) {
|
|
|
|
side = ev->GetString(1);
|
|
|
|
|
|
|
|
if (side.icmp("mainhand")) {
|
|
|
|
if (!side.icmp("offhand")) {
|
|
|
|
number = WEAPON_OFFHAND;
|
|
|
|
} else {
|
|
|
|
number = atoi(side);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
number = WEAPON_MAIN;
|
|
|
|
|
|
|
|
if (ev->NumArgs() == 2) {
|
|
|
|
modestring = ev->GetString(2);
|
|
|
|
|
|
|
|
if (!modestring.icmp("primary")) {
|
|
|
|
mode = FIRE_PRIMARY;
|
|
|
|
} else if (!modestring.icmp("secondary")) {
|
|
|
|
mode = FIRE_SECONDARY;
|
|
|
|
} else {
|
|
|
|
warning("Sentient::FireWeapon", "Invalid mode %s\n", modestring.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FireWeapon(number, mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::StopFireWeapon(Event *ev)
|
|
|
|
{
|
|
|
|
Weapon *activeWeapon;
|
|
|
|
int number = 0;
|
|
|
|
str side;
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 0) {
|
|
|
|
side = ev->GetString(1);
|
|
|
|
|
|
|
|
number = WeaponHandNameToNum(side);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((number > MAX_ACTIVE_WEAPONS) || (number < 0)) {
|
|
|
|
warning(
|
|
|
|
"Sentient::StopFireWeapon",
|
|
|
|
"Weapon number \"%d\" is out of bounds of 0 to MAX_ACTIVE_WEAPONS:%d\n",
|
|
|
|
number,
|
|
|
|
MAX_ACTIVE_WEAPONS
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
activeWeapon = activeWeaponList[number];
|
|
|
|
|
|
|
|
if (activeWeapon) {
|
|
|
|
activeWeapon->ForceIdle();
|
|
|
|
} else {
|
|
|
|
if (!activeWeapon) {
|
|
|
|
gi.DPrintf("No active weapon in slot #: \"%i\"\n", number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::ReleaseFireWeapon(int number, firemode_t mode)
|
|
|
|
{
|
|
|
|
float charge_time = level.time - charge_start_time;
|
|
|
|
|
|
|
|
charge_start_time = 0;
|
|
|
|
|
|
|
|
if ((number > MAX_ACTIVE_WEAPONS) || (number < 0)) {
|
|
|
|
warning(
|
|
|
|
"Sentient::FireWeapon",
|
|
|
|
"Weapon number \"%d\" is out of bounds of 0 to MAX_ACTIVE_WEAPONS:%d\n",
|
|
|
|
number,
|
|
|
|
MAX_ACTIVE_WEAPONS
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
if (activeWeaponList[number]) {
|
|
|
|
activeWeaponList[number]->ReleaseFire(mode, charge_time);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::ReleaseFireWeapon(Event *ev)
|
|
|
|
{
|
|
|
|
firemode_t mode = FIRE_PRIMARY;
|
|
|
|
int number = 0;
|
|
|
|
str modestring;
|
|
|
|
str side;
|
|
|
|
|
|
|
|
if (ev->NumArgs() > 0) {
|
|
|
|
side = ev->GetString(1);
|
|
|
|
|
|
|
|
if (side.icmp("mainhand")) {
|
|
|
|
if (!side.icmp("offhand")) {
|
|
|
|
number = WEAPON_OFFHAND;
|
|
|
|
} else {
|
|
|
|
number = atoi(side);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
number = WEAPON_MAIN;
|
|
|
|
|
|
|
|
if (ev->NumArgs() == 2) {
|
|
|
|
modestring = ev->GetString(2);
|
|
|
|
|
|
|
|
if (!modestring.icmp("primary")) {
|
|
|
|
mode = FIRE_PRIMARY;
|
|
|
|
} else if (!modestring.icmp("secondary")) {
|
|
|
|
mode = FIRE_SECONDARY;
|
|
|
|
} else {
|
|
|
|
warning("Sentient::ReleaseFireWeapon", "Invalid mode %s\n", modestring.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseFireWeapon(number, mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::Holster(qboolean putaway)
|
|
|
|
{
|
|
|
|
Weapon *rightWeap;
|
|
|
|
|
|
|
|
rightWeap = GetActiveWeapon(WEAPON_MAIN);
|
|
|
|
|
|
|
|
// Holster
|
|
|
|
if (putaway) {
|
|
|
|
if (rightWeap) {
|
|
|
|
rightWeap->SetPutAway(true);
|
|
|
|
holsteredWeapon = rightWeap;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!putaway) {
|
|
|
|
// Unholster
|
|
|
|
if (holsteredWeapon) {
|
|
|
|
useWeapon(holsteredWeapon, WEAPON_MAIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
holsteredWeapon = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::SafeHolster(qboolean putaway)
|
|
|
|
{
|
|
|
|
if (WeaponsOut()) {
|
|
|
|
if (putaway) {
|
|
|
|
weapons_holstered_by_code = qtrue;
|
|
|
|
Holster(qtrue);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (weapons_holstered_by_code) {
|
|
|
|
weapons_holstered_by_code = qfalse;
|
|
|
|
Holster(qfalse);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::AttachAllActiveWeapons(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_ACTIVE_WEAPONS; i++) {
|
|
|
|
Weapon *weap = activeWeaponList[i];
|
|
|
|
|
|
|
|
if (weap) {
|
|
|
|
weap->AttachToOwner((weaponhand_t)i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this->isSubclassOf(Player)) {
|
|
|
|
Player *player = (Player *)this;
|
|
|
|
player->UpdateWeapons();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::DetachAllActiveWeapons(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_ACTIVE_WEAPONS; i++) {
|
|
|
|
Weapon *weap = activeWeaponList[i];
|
|
|
|
|
|
|
|
if (weap) {
|
|
|
|
weap->DetachFromOwner();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int Sentient::NumWeapons(void)
|
|
|
|
{
|
|
|
|
int num;
|
|
|
|
int i;
|
|
|
|
Item *item;
|
|
|
|
int numweaps;
|
|
|
|
|
|
|
|
numweaps = 0;
|
|
|
|
|
|
|
|
num = inventory.NumObjects();
|
|
|
|
for (i = 1; i <= num; i++) {
|
|
|
|
item = (Item *)G_GetEntity(inventory.ObjectAt(i));
|
|
|
|
if (checkInheritance(&Weapon::ClassInfo, item->getClassname())) {
|
|
|
|
numweaps++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return numweaps;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::ChangeWeapon(Weapon *weapon, weaponhand_t hand)
|
|
|
|
{
|
|
|
|
if ((hand > MAX_ACTIVE_WEAPONS) || (hand < 0)) {
|
|
|
|
warning(
|
|
|
|
"Sentient::ChangeWeapon",
|
|
|
|
"Weapon hand number \"%d\" is out of bounds of 0 to MAX_ACTIVE_WEAPONS:%d\n",
|
|
|
|
hand,
|
|
|
|
MAX_ACTIVE_WEAPONS
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if weapon is already active in the slot
|
|
|
|
if (weapon == activeWeaponList[hand]) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ActivateWeapon(weapon, hand);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::DeactivateWeapon(weaponhand_t hand)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!activeWeaponList[hand]) {
|
|
|
|
warning("Sentient::DeactivateWeapon", "Tried to deactivate a non-active weapon in hand %d\n", hand);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
activeWeaponList[hand]->AttachToHolster(hand);
|
|
|
|
activeWeaponList[hand]->SetPutAway(false);
|
|
|
|
activeWeaponList[hand]->NewAnim("putaway");
|
|
|
|
|
|
|
|
// Check the player's inventory and detach any weapons that are already attached to that spot
|
|
|
|
for (i = 1; i <= inventory.NumObjects(); i++) {
|
|
|
|
Item *item = (Item *)G_GetEntity(inventory.ObjectAt(i));
|
|
|
|
|
|
|
|
if (item->IsSubclassOfWeapon()) {
|
|
|
|
Weapon *weap = (Weapon *)item;
|
|
|
|
|
|
|
|
if ((weap != activeWeaponList[hand])
|
|
|
|
&& (!str::cmp(weap->GetCurrentAttachToTag(), activeWeaponList[hand]->GetCurrentAttachToTag()))) {
|
|
|
|
weap->DetachFromOwner();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lastActiveWeapon.weapon = activeWeaponList[hand];
|
|
|
|
lastActiveWeapon.hand = hand;
|
|
|
|
activeWeaponList[hand] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::DeactivateWeapon(Weapon *weapon)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_ACTIVE_WEAPONS; i++) {
|
|
|
|
if (activeWeaponList[i] == weapon) {
|
|
|
|
activeWeaponList[i]->DetachFromOwner();
|
|
|
|
activeWeaponList[i]->SetPutAway(false);
|
|
|
|
activeWeaponList[i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::EventDeactivateWeapon(Event *ev)
|
|
|
|
{
|
|
|
|
// Deactivate the weapon
|
|
|
|
weaponhand_t hand;
|
|
|
|
str side;
|
|
|
|
|
|
|
|
side = ev->GetString(1);
|
|
|
|
|
|
|
|
hand = WeaponHandNameToNum(side);
|
|
|
|
|
|
|
|
if (hand == WEAPON_ERROR) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DeactivateWeapon(hand);
|
|
|
|
edict->s.eFlags |= EF_UNARMED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::ActivateWeapon(Weapon *weapon, weaponhand_t hand)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (hand == WEAPON_ERROR) {
|
|
|
|
gi.DPrintf("^~^~^ ActivateWeapon: bad weapon hand\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
activeWeaponList[hand] = weapon;
|
|
|
|
str holsterTag = weapon->GetHolsterTag();
|
|
|
|
|
|
|
|
// Check the player's inventory and detach any weapons that are currently attached to that tag.
|
|
|
|
for (i = 1; i <= inventory.NumObjects(); i++) {
|
|
|
|
Item *item = (Item *)G_GetEntity(inventory.ObjectAt(i));
|
|
|
|
|
|
|
|
if (item->isSubclassOf(Weapon)) {
|
|
|
|
Weapon *weap = (Weapon *)item;
|
|
|
|
|
|
|
|
if ((!str::cmp(holsterTag, weap->GetCurrentAttachToTag()))) {
|
|
|
|
weap->DetachFromOwner();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
weapon->AttachToOwner(hand);
|
|
|
|
weapon->NewAnim("raise");
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::ActivateLastActiveWeapon(void)
|
|
|
|
{
|
|
|
|
if (lastActiveWeapon.weapon && lastActiveWeapon.weapon != activeWeaponList[WEAPON_MAIN]) {
|
|
|
|
useWeapon(lastActiveWeapon.weapon, lastActiveWeapon.hand);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::EventActivateLastActiveWeapon(Event *ev)
|
|
|
|
{
|
|
|
|
if (!deadflag) {
|
|
|
|
ActivateLastActiveWeapon();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::EventToggleItemUse(Event *ev)
|
|
|
|
{
|
|
|
|
Weapon *item;
|
|
|
|
|
|
|
|
if (deadflag) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
item = GetActiveWeapon(WEAPON_MAIN);
|
|
|
|
|
|
|
|
if (item && item->IsSubclassOfInventoryItem()) {
|
|
|
|
if (lastActiveWeapon.weapon) {
|
|
|
|
ActivateLastActiveWeapon();
|
|
|
|
}
|
|
|
|
|
|
|
|
Holster(qtrue);
|
|
|
|
} else {
|
|
|
|
Event *ev = new Event(EV_Sentient_UseWeaponClass);
|
|
|
|
ev->AddString("item1");
|
|
|
|
|
|
|
|
ProcessEvent(ev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Weapon *Sentient::BestWeapon(Weapon *ignore, qboolean bGetItem, int iIgnoreClass)
|
|
|
|
{
|
|
|
|
Weapon *next;
|
|
|
|
int n;
|
|
|
|
int j;
|
|
|
|
int bestrank;
|
|
|
|
Weapon *bestweapon;
|
|
|
|
|
|
|
|
n = inventory.NumObjects();
|
|
|
|
|
|
|
|
// Search forewards until we find a weapon
|
|
|
|
bestweapon = NULL;
|
|
|
|
bestrank = -999999;
|
|
|
|
|
|
|
|
for (j = 1; j <= n; j++) {
|
|
|
|
next = (Weapon *)G_GetEntity(inventory.ObjectAt(j));
|
|
|
|
|
|
|
|
assert(next);
|
|
|
|
|
|
|
|
if ((next != ignore)
|
|
|
|
&& ((next->IsSubclassOfWeapon() && !(next->GetWeaponClass() & iIgnoreClass))
|
|
|
|
|| (next->IsSubclassOfItem() && bGetItem))
|
|
|
|
&& (next->GetRank() > bestrank)
|
|
|
|
&& (next->HasAmmo(FIRE_PRIMARY) || next->GetFireType(FIRE_SECONDARY) == FT_MELEE)) {
|
|
|
|
bestweapon = (Weapon *)next;
|
|
|
|
bestrank = bestweapon->GetRank();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bestweapon;
|
|
|
|
}
|
|
|
|
|
|
|
|
Weapon *Sentient::WorstWeapon(Weapon *ignore, qboolean bGetItem, int iIgnoreClass)
|
|
|
|
{
|
|
|
|
Weapon *next;
|
|
|
|
int n;
|
|
|
|
int j;
|
|
|
|
int iWorstRank;
|
|
|
|
Weapon *worstweapon;
|
|
|
|
|
|
|
|
n = inventory.NumObjects();
|
|
|
|
|
|
|
|
worstweapon = NULL;
|
|
|
|
iWorstRank = 999999;
|
|
|
|
|
|
|
|
for (j = 1; j <= n; j++) {
|
|
|
|
next = (Weapon *)G_GetEntity(inventory.ObjectAt(j));
|
|
|
|
|
|
|
|
assert(next);
|
|
|
|
|
|
|
|
if ((next != ignore)
|
|
|
|
&& ((next->IsSubclassOfWeapon() && !(next->GetWeaponClass() & iIgnoreClass))
|
|
|
|
|| (next->IsSubclassOfWeapon() && bGetItem))
|
|
|
|
&& (next->GetRank() < iWorstRank)
|
|
|
|
&& (next->HasAmmo(FIRE_PRIMARY) || next->GetFireType(FIRE_SECONDARY) == FT_MELEE)) {
|
|
|
|
worstweapon = (Weapon *)next;
|
|
|
|
iWorstRank = worstweapon->GetRank();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return worstweapon;
|
|
|
|
}
|
|
|
|
|
|
|
|
Weapon *Sentient::NextWeapon(Weapon *weapon)
|
|
|
|
{
|
|
|
|
Item *item;
|
|
|
|
int i;
|
|
|
|
int n;
|
|
|
|
int weaponorder;
|
|
|
|
Weapon *choice;
|
|
|
|
int choiceorder;
|
|
|
|
Weapon *bestchoice;
|
|
|
|
int bestorder;
|
|
|
|
Weapon *worstchoice;
|
|
|
|
int worstorder;
|
|
|
|
|
|
|
|
if (!inventory.ObjectInList(weapon->entnum)) {
|
|
|
|
ScriptError("NextWeapon", "Weapon not in list");
|
|
|
|
}
|
|
|
|
|
|
|
|
weaponorder = weapon->GetOrder();
|
|
|
|
bestchoice = weapon;
|
|
|
|
bestorder = 65535;
|
|
|
|
worstchoice = weapon;
|
|
|
|
worstorder = weaponorder;
|
|
|
|
|
|
|
|
n = inventory.NumObjects();
|
|
|
|
for (i = 1; i <= n; i++) {
|
|
|
|
item = (Item *)G_GetEntity(inventory.ObjectAt(i));
|
|
|
|
|
|
|
|
assert(item);
|
|
|
|
|
|
|
|
if (item->isSubclassOf(Weapon)) {
|
|
|
|
choice = (Weapon *)item;
|
|
|
|
if ((!choice->HasAmmo(FIRE_PRIMARY) && !choice->GetUseNoAmmo()) || !choice->AutoChange()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
choiceorder = choice->GetOrder();
|
|
|
|
if ((choiceorder > weaponorder) && (choiceorder < bestorder)) {
|
|
|
|
bestorder = choiceorder;
|
|
|
|
bestchoice = choice;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (choiceorder < worstorder) {
|
|
|
|
worstorder = choiceorder;
|
|
|
|
worstchoice = choice;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bestchoice == weapon) {
|
|
|
|
return worstchoice;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bestchoice;
|
|
|
|
}
|
|
|
|
|
|
|
|
Weapon *Sentient::PreviousWeapon(Weapon *weapon)
|
|
|
|
{
|
|
|
|
Item *item;
|
|
|
|
int i;
|
|
|
|
int n;
|
|
|
|
int weaponorder;
|
|
|
|
Weapon *choice;
|
|
|
|
int choiceorder;
|
|
|
|
Weapon *bestchoice;
|
|
|
|
int bestorder;
|
|
|
|
Weapon *worstchoice;
|
|
|
|
int worstorder;
|
|
|
|
|
|
|
|
if (!inventory.ObjectInList(weapon->entnum)) {
|
|
|
|
ScriptError("PreviousWeapon", "Weapon not in list");
|
|
|
|
}
|
|
|
|
|
|
|
|
weaponorder = weapon->GetOrder();
|
|
|
|
bestchoice = weapon;
|
|
|
|
bestorder = -65535;
|
|
|
|
worstchoice = weapon;
|
|
|
|
worstorder = weaponorder;
|
|
|
|
|
|
|
|
n = inventory.NumObjects();
|
|
|
|
for (i = 1; i <= n; i++) {
|
|
|
|
item = (Item *)G_GetEntity(inventory.ObjectAt(i));
|
|
|
|
|
|
|
|
assert(item);
|
|
|
|
|
|
|
|
if (item->isSubclassOf(Weapon)) {
|
|
|
|
choice = (Weapon *)item;
|
|
|
|
if ((!choice->HasAmmo(FIRE_PRIMARY) && !choice->GetUseNoAmmo()) || !choice->AutoChange()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
choiceorder = choice->GetOrder();
|
|
|
|
if ((choiceorder < weaponorder) && (choiceorder > bestorder)) {
|
|
|
|
bestorder = choiceorder;
|
|
|
|
bestchoice = choice;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (choiceorder > worstorder) {
|
|
|
|
worstorder = choiceorder;
|
|
|
|
worstchoice = choice;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bestchoice == weapon) {
|
|
|
|
return worstchoice;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bestchoice;
|
|
|
|
}
|
|
|
|
|
|
|
|
Weapon *Sentient::GetActiveWeapon(weaponhand_t hand) const
|
|
|
|
|
|
|
|
{
|
|
|
|
if ((hand > MAX_ACTIVE_WEAPONS) || (hand < 0)) {
|
|
|
|
warning(
|
|
|
|
"Sentient::GetActiveWeapon",
|
|
|
|
"Weapon hand number \"%d\" is out of bounds of 0 to MAX_ACTIVE_WEAPONS:%d\n",
|
|
|
|
hand,
|
|
|
|
MAX_ACTIVE_WEAPONS
|
|
|
|
);
|
|
|
|
return NULL;
|
|
|
|
} else {
|
|
|
|
return activeWeaponList[hand];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qboolean Sentient::IsActiveWeapon(Weapon *weapon)
|
|
|
|
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_ACTIVE_WEAPONS; i++) {
|
|
|
|
Weapon *activeWeap = activeWeaponList[i];
|
|
|
|
|
|
|
|
if (activeWeap == weapon) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::useWeapon(const char *weaponname, weaponhand_t hand)
|
|
|
|
{
|
|
|
|
Weapon *weapon;
|
|
|
|
|
|
|
|
assert(weaponname);
|
|
|
|
|
|
|
|
if (!weaponname) {
|
|
|
|
warning("Sentient::useWeapon", "weaponname is NULL\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the item in the sentient's inventory
|
|
|
|
weapon = (Weapon *)FindItem(weaponname);
|
|
|
|
|
|
|
|
// If it exists, then make the change to the slot number specified
|
|
|
|
if (weapon) {
|
|
|
|
useWeapon(weapon, hand);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::useWeapon(Weapon *weapon, weaponhand_t hand)
|
|
|
|
{
|
|
|
|
assert(weapon);
|
|
|
|
|
|
|
|
if (!weapon) {
|
|
|
|
warning("Sentient::useWeapon", "Null weapon used.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newActiveWeapon.weapon) {
|
|
|
|
newActiveWeapon.weapon = weapon;
|
|
|
|
newActiveWeapon.hand = hand;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!weapon->HasAmmo(FIRE_PRIMARY) && !weapon->GetUseNoAmmo()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (activeWeaponList[WEAPON_OFFHAND]) {
|
|
|
|
activeWeaponList[WEAPON_OFFHAND]->PutAway();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (activeWeaponList[WEAPON_MAIN] && activeWeaponList[WEAPON_MAIN] != weapon) {
|
|
|
|
activeWeaponList[WEAPON_MAIN]->PutAway();
|
|
|
|
}
|
|
|
|
|
|
|
|
newActiveWeapon.weapon = weapon;
|
|
|
|
newActiveWeapon.hand = hand;
|
|
|
|
|
|
|
|
//ChangeWeapon( weapon, hand );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::EventUseWeaponClass(Event *ev)
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
int weapon_class;
|
|
|
|
|
|
|
|
if (deadflag) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
name = ev->GetString(1);
|
|
|
|
weapon_class = G_WeaponClassNameToNum(name);
|
|
|
|
|
|
|
|
int num;
|
|
|
|
Weapon *pActive = GetActiveWeapon(WEAPON_MAIN);
|
|
|
|
Weapon *pMatch = NULL;
|
|
|
|
Weapon *pWeap = NULL;
|
|
|
|
|
|
|
|
num = inventory.NumObjects();
|
|
|
|
|
|
|
|
for (int i = 1; i <= num; i++) {
|
|
|
|
pWeap = (Weapon *)G_GetEntity(inventory.ObjectAt(i));
|
|
|
|
|
|
|
|
if (pWeap->IsSubclassOfWeapon() && (pWeap->GetWeaponClass() & weapon_class)
|
|
|
|
&& (pWeap->HasAmmo(FIRE_PRIMARY) || pWeap->GetUseNoAmmo())) {
|
|
|
|
if (!pMatch && (!pActive || pActive != pWeap)) {
|
|
|
|
pMatch = pWeap;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pActive) {
|
|
|
|
useWeapon(pWeap, WEAPON_MAIN);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pActive == pWeap) {
|
|
|
|
pActive = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pWeap = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pMatch) {
|
|
|
|
useWeapon(pMatch, WEAPON_MAIN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//====================
|
|
|
|
//ActivateNewWeapon
|
|
|
|
//====================
|
|
|
|
void Sentient::ActivateNewWeapon(Event *ev)
|
|
|
|
{
|
|
|
|
if (deadflag) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ActivateNewWeapon();
|
|
|
|
|
|
|
|
if (GetActiveWeapon(WEAPON_MAIN)) {
|
|
|
|
edict->s.eFlags &= ~EF_UNARMED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//====================
|
|
|
|
//ActivateNewWeapon
|
|
|
|
//====================
|
|
|
|
void Sentient::ActivateNewWeapon(void)
|
|
|
|
{
|
|
|
|
// Change the weapon to the currently active weapon as specified by useWeapon
|
|
|
|
ChangeWeapon(newActiveWeapon.weapon, newActiveWeapon.hand);
|
|
|
|
|
|
|
|
// Update weapons
|
|
|
|
UpdateWeapons();
|
|
|
|
|
|
|
|
// Clear out the newActiveWeapon
|
|
|
|
ClearNewActiveWeapon();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::PutawayWeapon(Event *ev)
|
|
|
|
{
|
|
|
|
Weapon *weapon;
|
|
|
|
weaponhand_t hand;
|
|
|
|
str side;
|
|
|
|
|
|
|
|
side = ev->GetString(1);
|
|
|
|
|
|
|
|
hand = WeaponHandNameToNum(side);
|
|
|
|
|
|
|
|
if (hand == WEAPON_ERROR) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
weapon = GetActiveWeapon(hand);
|
|
|
|
|
|
|
|
if (weapon->isSubclassOf(Weapon)) {
|
|
|
|
weapon->NewAnim("putaway");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::WeaponCommand(Event *ev)
|
|
|
|
{
|
|
|
|
weaponhand_t hand;
|
|
|
|
Weapon *weap;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (ev->NumArgs() < 2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
hand = WeaponHandNameToNum(ev->GetString(1));
|
|
|
|
weap = GetActiveWeapon(hand);
|
|
|
|
|
|
|
|
if (!weap) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Event *e;
|
|
|
|
e = new Event(ev->GetToken(2));
|
|
|
|
|
|
|
|
for (i = 3; i <= ev->NumArgs(); i++) {
|
|
|
|
e->AddToken(ev->GetToken(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
weap->ProcessEvent(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
qboolean Sentient::WeaponsOut(void)
|
|
|
|
{
|
|
|
|
return (GetActiveWeapon(WEAPON_OFFHAND) || GetActiveWeapon(WEAPON_MAIN));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::UpdateWeapons(void)
|
|
|
|
{
|
|
|
|
GetActiveWeapon(WEAPON_MAIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ammo *Sentient::FindAmmoByName(str name)
|
|
|
|
{
|
|
|
|
int count, i;
|
|
|
|
|
|
|
|
count = ammo_inventory.NumObjects();
|
|
|
|
|
|
|
|
for (i = 1; i <= count; i++) {
|
|
|
|
Ammo *ammo = ammo_inventory.ObjectAt(i);
|
|
|
|
if (name == ammo->getName()) {
|
|
|
|
return ammo;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::GetNewActiveWeapon(Event *ev)
|
|
|
|
{
|
|
|
|
ev->AddEntity(GetNewActiveWeapon());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sentient::GetActiveWeap(Event *ev)
|
|
|
|
{
|
|
|
|
weaponhand_t weaponhand;
|
|
|
|
Item *weapon;
|
|
|
|
|
|
|
|
weaponhand = (weaponhand_t)ev->GetInteger(1);
|
|
|
|
|
|
|
|
if (weaponhand < 0 && weaponhand > 2) {
|
|
|
|
ScriptError("Weaponhand number is out of allowed range 0 - 2 for getactiveweap!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
weapon = GetActiveWeapon(weaponhand);
|
|
|
|
|
|
|
|
ev->AddEntity(weapon);
|
|
|
|
}
|