📄 sentient.cpp
字号:
// 9 11/20/97 9:02p Jimdose
// Changed Container class to use entity # instead of void *
//
// 8 11/18/97 5:27p Markd
// Changed "ammo" command and also fixed some weapon checking
//
// 7 11/15/97 6:54p Markd
// Added InterpretCommand, Added "fire", "ammo" and "weapon" command
//
// 6 10/28/97 6:05p Jimdose
// Sentients now pick up nails from nail weapons.
//
// 5 10/27/97 3:29p Jimdose
// Removed dependency on quakedef.h
//
// 4 10/24/97 2:58p Jimdose
// Fixed bug where sentient was bound to weapon instead of weapon bound to
// sentient.
//
// 3 10/01/97 2:04p Jimdose
// Weapons are now bound to their owners when they are picked up.
//
// 2 9/26/97 6:47p Jimdose
// Added standard Ritual headers
//
// DESCRIPTION:
// Base class of entity that can carry other entities, and use weapons.
//
#include "g_local.h"
#include "entity.h"
#include "sentient.h"
#include "weapon.h"
#include "scriptmaster.h"
#include "ammo.h"
#include "armor.h"
#include "misc.h"
#include "inventoryitem.h"
#include "player.h"
#include "actor.h"
CLASS_DECLARATION( Entity, Sentient, NULL );
Event EV_Sentient_Attack( "fire" );
Event EV_Sentient_ReleaseAttack( "releasefire" );
Event EV_Sentient_GiveWeapon( "weapon" );
Event EV_Sentient_GiveAmmo( "ammo" );
Event EV_Sentient_GiveArmor( "armor" );
Event EV_Sentient_GiveItem( "item" );
Event EV_Sentient_GiveTargetname( "give" );
Event EV_Sentient_GiveInventoryItem( "invitem" );
Event EV_Sentient_GiveHealth( "health", EV_CHEAT );
Event EV_Sentient_TakeWeapon( "take_weapon" );
Event EV_Sentient_TakeAmmo( "take_ammo" );
Event EV_Sentient_TakeArmor( "take_armor" );
Event EV_Sentient_TakeItem( "take_item" );
Event EV_Sentient_WeaponPutAway( "weapon_putaway" );
Event EV_Sentient_WeaponReady( "weapon_ready" );
Event EV_Sentient_WeaponDoneFiring( "weapon_donefiring" );
Event EV_Sentient_AnimLoop( "animloop" );
Event EV_Sentient_UselessCheck( "useless_check" );
Event EV_Sentient_TurnOffShadow( "noshadow" );
Event EV_Sentient_Freeze( "freeze" );
Event EV_Sentient_UnFreeze( "unfreeze" );
Event EV_Sentient_ImpactDamage( "impact_damage" );
Event EV_Sentient_WeaponUse( "weaponuse", EV_CONSOLE );
Event EV_Sentient_SetDropWeapon( "dropweapon" );
Event EV_Sentient_DropWeaponNow( "dropweaponnow" );
ResponseDef Sentient::Responses[] =
{
{ &EV_Sentient_Attack, ( Response )Sentient::FireWeapon },
{ &EV_Sentient_ReleaseAttack, ( Response )Sentient::ReleaseFireWeapon },
{ &EV_Sentient_GiveWeapon, ( Response )Sentient::EventGiveWeapon },
{ &EV_Sentient_TakeWeapon, ( Response )Sentient::EventTakeWeapon },
{ &EV_Sentient_GiveAmmo, ( Response )Sentient::EventGiveAmmo },
{ &EV_Sentient_TakeAmmo, ( Response )Sentient::EventTakeAmmo },
{ &EV_Sentient_GiveArmor, ( Response )Sentient::EventGiveArmor },
{ &EV_Sentient_TakeArmor, ( Response )Sentient::EventTakeArmor },
{ &EV_Sentient_GiveItem, ( Response )Sentient::EventGiveItem },
{ &EV_Sentient_GiveInventoryItem,( Response )Sentient::EventGiveInventoryItem },
{ &EV_Sentient_GiveHealth, ( Response )Sentient::EventGiveHealth },
{ &EV_Sentient_GiveTargetname, ( Response )Sentient::EventGiveTargetname },
{ &EV_Sentient_WeaponPutAway, ( Response )Sentient::WeaponPutAway },
{ &EV_Sentient_WeaponReady, ( Response )Sentient::WeaponReady },
{ &EV_Sentient_WeaponDoneFiring, ( Response )Sentient::WeaponDoneFiring },
{ &EV_Sentient_AnimLoop, ( Response )Sentient::AnimLoop },
{ &EV_Damage, ( Response )Sentient::ArmorDamage },
{ &EV_Touch, ( Response )Sentient::SearchBody },
{ &EV_Sentient_UselessCheck, ( Response )Sentient::UselessCheck },
{ &EV_Sentient_TurnOffShadow, ( Response )Sentient::TurnOffShadow },
{ &EV_Sentient_Freeze, ( Response )Sentient::Freeze },
{ &EV_Sentient_UnFreeze, ( Response )Sentient::UnFreeze },
{ &EV_Sentient_ImpactDamage, ( Response )Sentient::ImpactDamage },
{ &EV_Sentient_WeaponUse, ( Response )Sentient::WeaponUse },
{ &EV_Sentient_SetDropWeapon, ( Response )Sentient::SetDropWeapon },
{ &EV_Sentient_DropWeaponNow, ( Response )Sentient::DropWeaponNowEvent },
{ &EV_Sentient_TakeItem, ( Response )Sentient::EventTakeItem },
{ NULL, NULL }
};
Container<Sentient *> SentientList;
Sentient::Sentient()
{
Vector defangles;
SentientList.AddObject( ( Sentient * )this );
inventory.ClearObjectList();
currentWeapon = NULL;
currentItem = NULL;
newWeapon = NULL;
animOverride = false;
dropweapon = true;
tempAnimEvent = NULL;
eyeposition = "0 0 64";
gunoffset = "0 0 56";
firedown = false;
firedowntime = 0;
// angles
defangles = Vector( 0, G_GetFloatArg( "angle", 0 ), 0 );
if (defangles.y == -1)
{
defangles = Vector( -90, 0, 0 );
}
else if (defangles.y == -2)
{
defangles = Vector( 90, 0, 0 );
}
angles = G_GetVectorArg( "angles", defangles );
setAngles( angles );
stopanimating_tillchange = false;
poweruptype = 0;
poweruptimer = 0;
sentientFrozen = false;
// HACK FIXME
//
// temporary shadow flag
//
edict->s.renderfx |= RF_XFLIP;
}
Sentient::~Sentient()
{
SentientList.RemoveObject( ( Sentient * )this );
FreeInventory();
}
Vector Sentient::EyePosition
(
void
)
{
Vector pos;
pos = worldorigin;
pos[ gravity_axis[ gravaxis ].x ] += eyeposition[ 0 ];
pos[ gravity_axis[ gravaxis ].y ] += eyeposition[ 1 ] * gravity_axis[ gravaxis ].sign;
pos[ gravity_axis[ gravaxis ].z ] += eyeposition[ 2 ] * gravity_axis[ gravaxis ].sign;
return pos;
}
Vector Sentient::GunPosition
(
void
)
{
Vector pos;
pos = worldorigin;
pos[ gravity_axis[ gravaxis ].x ] += gunoffset[ 0 ];
pos[ gravity_axis[ gravaxis ].y ] += gunoffset[ 1 ] * gravity_axis[ gravaxis ].sign;
pos[ gravity_axis[ gravaxis ].z ] += gunoffset[ 2 ] * gravity_axis[ gravaxis ].sign;
return pos;
}
inline void Sentient::GetGunOrientation
(
Vector pos,
Vector *forward,
Vector *right,
Vector *up
)
{
const gravityaxis_t &grav = gravity_axis[ gravaxis ];
if ( forward )
{
( *forward )[ grav.x ] = orientation[ 0 ][ 0 ];
( *forward )[ grav.y ] = orientation[ 0 ][ 1 ] * grav.sign;
( *forward )[ grav.z ] = orientation[ 0 ][ 2 ] * grav.sign;
}
if ( right )
{
( *right )[ grav.x ] = -orientation[ 1 ][ 0 ];
( *right )[ grav.y ] = - orientation[ 1 ][ 1 ] * grav.sign;
( *right )[ grav.z ] = - orientation[ 1 ][ 2 ] * grav.sign;
}
if ( up )
{
( *up )[ grav.x ] = orientation[ 2 ][ 0 ];
( *up )[ grav.y ] = orientation[ 2 ][ 1 ] * grav.sign;
( *up )[ grav.z ] = orientation[ 2 ][ 2 ] * grav.sign;
}
}
void Sentient::GetMuzzlePositionAndDirection
(
Vector *pos,
Vector *dir
)
{
*pos = Vector( "0 0 0" );
*dir = Vector( "0 0 0" );
if ( currentWeapon )
currentWeapon->GetMuzzlePosition( pos, dir );
}
void Sentient::EventGiveHealth
(
Event *ev
)
{
int group_num;
health = ev->GetFloat( 1 );
if ( isClient() )
{
for( group_num = 0; group_num < edict->s.numgroups ; group_num++ )
{
edict->s.groups[ group_num ] &= ~MDL_GROUP_SKINOFFSET_BIT0;
}
}
}
void Sentient::FireWeapon
(
Event *ev
)
{
if ( ( currentWeapon ) && currentWeapon->ReadyToFire() && currentWeapon->HasAmmo() )
{
currentWeapon->Fire();
}
}
void Sentient::ReleaseFireWeapon
(
Event *ev
)
{
// Only need to check if currentWeapon because FireWeapon checks for
// the weapon ready and if it has ammo.
if ( currentWeapon )
{
float fireholdtime = ev->GetFloat( 1 );
currentWeapon->ReleaseFire( fireholdtime );
}
}
void Sentient::AddItem
(
Item *object
)
{
inventory.AddObject( object->entnum );
if ( object->isSubclassOf( InventoryItem ) )
{
currentItem = (InventoryItem *)object;
}
//
// set our global game variables if client
//
if ( isClient() )
{
str fullname;
ScriptVariable * var;
fullname = str( "playeritem_" ) + object->getClassname();
var = gameVars.GetVariable( fullname.c_str() );
if ( !var )
{
gameVars.SetVariable( fullname.c_str(), 1 );
}
else
{
int amount;
amount = var->intValue() + 1;
var->setIntValue( amount );
}
var = levelVars.GetVariable( fullname.c_str() );
if ( !var )
{
levelVars.SetVariable( fullname.c_str(), 1 );
}
else
{
int amount;
amount = var->intValue() + 1;
var->setIntValue( amount );
}
}
}
void Sentient::RemoveItem
(
Item *object
)
{
Weapon *weapon;
inventory.RemoveObject( object->entnum );
if ( currentWeapon == object )
{
currentWeapon = NULL;
if ( newWeapon == object )
{
newWeapon = NULL;
weapon = BestWeapon();
}
else
{
weapon = newWeapon;
}
SetCurrentWeapon( weapon );
}
//
// set our global game variables if client
//
if ( isClient() )
{
str fullname;
ScriptVariable * var;
fullname = str( "playeritem_" ) + object->getClassname();
var = levelVars.GetVariable( fullname.c_str() );
if ( var )
{
int amount;
amount = var->intValue() - 1;
if ( amount < 0 )
amount = 0;
var->setIntValue( amount );
}
}
if ( currentItem == (InventoryItem *) object )
{
currentItem = NULL;
// Try to set the the current item
currentItem = (InventoryItem *)NextItem( NULL );
if (!currentItem)
{
currentItem = (InventoryItem *)PrevItem( NULL );
}
}
}
Item *Sentient::FindItem
(
const char *itemname
)
{
int num;
int i;
Item *item;
num = inventory.NumObjects();
for( i = 1; i <= num; i++ )
{
item = ( Item * )G_GetEntity( inventory.ObjectAt( i ) );
if ( !Q_stricmp( item->getClassname(), itemname ) )
{
return item;
}
}
return NULL;
}
void Sentient::FreeInventory
(
void
)
{
int num;
int i;
Item *item;
if ( currentWeapon )
currentWeapon->DetachFromOwner();
SetCurrentWeapon( NULL );
newWeapon = NULL;
num = inventory.NumObjects();
for( i = num; i > 0; i-- )
{
item = ( Item * )G_GetEntity( inventory.ObjectAt( i ) );
delete item;
}
inventory.ClearObjectList();
currentItem = NULL;
}
void Sentient::FreeInventoryOfType
(
const char *type
)
{
int num;
int i;
Item *item;
num = inventory.NumObjects();
for( i = num; i > 0; i-- )
{
item = ( Item * )G_GetEntity( inventory.ObjectAt( i ) );
if ( checkInheritance( type, item->getClassname() ) )
{
inventory.RemoveObject( item->entnum );
// If the current item is about to be deleted, then look for
// another item to be current
if ( currentItem == item )
{
currentItem = NULL;
// Try to set the the current item
currentItem = (InventoryItem *)NextItem( NULL );
if (!currentItem)
{
currentItem = (InventoryItem *)PrevItem( NULL );
}
}
delete item;
}
}
}
qboolean Sentient::HasItem
(
const char *itemname
)
{
return ( FindItem( itemname ) != NULL );
}
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;
}
Weapon * Sentient::WeaponNumber
(
int weaponnum
)
{
int num;
int i;
Item *item;
// make it so that 0 is our first weapon rather than 1
weaponnum++;
num = inventory.NumObjects();
for( i = 1; i <= num; i++ )
{
item = ( Item * )G_GetEntity( inventory.ObjectAt( i ) );
if ( item->isSubclassOf( Weapon ) )
{
weaponnum--;
if ( !weaponnum )
{
return ( Weapon * )item;
}
}
}
return NULL;
}
void Sentient::ChangeWeapon
(
Weapon *weapon
)
{
if ( weapon == currentWeapon )
{
return;
}
if ( currentWeapon )
{
if ( !weapon->ReadyToUse() )
{
return;
}
newWeapon = weapon;
if ( !currentWeapon->ReadyToChange() )
{
return;
}
currentWeapon->PutAway();
}
else
{
SetCurrentWeapon( weapon );
}
}
void Sentient::ForceChangeWeapon
(
Weapon *weapon
)
{
if ( newWeapon == weapon )
{
return;
}
if ( weapon == currentWeapon )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -