mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-19 12:14:35 +02:00
Switched Doom 3 weapons to native.
This commit is contained in:
@@ -2174,7 +2174,20 @@ void idActor::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir
|
||||
gameLocal.Error( "Unknown damageDef '%s'", damageDefName );
|
||||
}
|
||||
|
||||
int damage = damageDef->GetInt( "damage" ) * damageScale;
|
||||
// jmarshall - added min/max damage support.
|
||||
//int damage = damageDef->GetInt( "damage" ) * damageScale;
|
||||
int minDamage = damageDef->GetInt("minDamage", "-1");
|
||||
int maxDamage = damageDef->GetInt("maxDamage", "-1");
|
||||
int damage = -1;
|
||||
if (minDamage == -1 || maxDamage == -1) {
|
||||
int damageBase = damageDef->GetInt("damage");
|
||||
minDamage = damageBase - (damageBase * 0.2f);
|
||||
maxDamage = damageBase + (damageBase * 0.2f);
|
||||
}
|
||||
|
||||
damage = rvRandom::irand(minDamage, maxDamage) * damageScale;
|
||||
// jmarshall
|
||||
|
||||
damage = GetDamageForLocation( damage, location );
|
||||
|
||||
// inform the attacker that they hit someone
|
||||
|
||||
+46
-2
@@ -248,6 +248,8 @@ public:
|
||||
bool GetMasterPosition( idVec3 &masterOrigin, idMat3 &masterAxis ) const;
|
||||
void GetWorldVelocities( idVec3 &linearVelocity, idVec3 &angularVelocity ) const;
|
||||
|
||||
virtual void CallNativeEvent(idStr& name) {};
|
||||
|
||||
// physics
|
||||
// set a new physics object to be used by this entity
|
||||
void SetPhysics( idPhysics *phys );
|
||||
@@ -351,6 +353,48 @@ public:
|
||||
void ServerSendEvent( int eventId, const idBitMsg *msg, bool saveEvent, int excludeClient ) const;
|
||||
void ClientSendEvent( int eventId, const idBitMsg *msg ) const;
|
||||
|
||||
int GetIntKey(const char* key)
|
||||
{
|
||||
int value;
|
||||
spawnArgs.GetInt(key, "0", value);
|
||||
return value;
|
||||
}
|
||||
|
||||
float GetFloatKey(const char* key)
|
||||
{
|
||||
float value;
|
||||
spawnArgs.GetFloat(key, "0", value);
|
||||
return value;
|
||||
}
|
||||
|
||||
const char* GetKey(const char* key)
|
||||
{
|
||||
const char* value;
|
||||
|
||||
spawnArgs.GetString(key, "", &value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float idEntity::GetFloat(const char* key)
|
||||
{
|
||||
return spawnArgs.GetFloat(key, "0");
|
||||
}
|
||||
|
||||
int idEntity::GetInt(const char* key)
|
||||
{
|
||||
return spawnArgs.GetInt(key, "0");
|
||||
}
|
||||
|
||||
bool idEntity::GetBool(const char* key)
|
||||
{
|
||||
return spawnArgs.GetBool(key, "0");
|
||||
}
|
||||
|
||||
idVec3 idEntity::GetOrigin(void)
|
||||
{
|
||||
return GetLocalCoordinates(GetPhysics()->GetOrigin());
|
||||
}
|
||||
protected:
|
||||
renderEntity_t renderEntity; // used to present a model to the renderer
|
||||
int modelDefHandle; // handle to static renderer model
|
||||
@@ -390,7 +434,7 @@ private:
|
||||
void QuitTeam( void ); // leave the current team
|
||||
|
||||
void UpdatePVSAreas( void );
|
||||
|
||||
public:
|
||||
// events
|
||||
void Event_GetName( void );
|
||||
void Event_SetName( const char *name );
|
||||
@@ -511,7 +555,7 @@ protected:
|
||||
idAnimator animator;
|
||||
damageEffect_t * damageEffects;
|
||||
|
||||
private:
|
||||
public:
|
||||
void Event_GetJointHandle( const char *jointname );
|
||||
void Event_ClearAllJoints( void );
|
||||
void Event_ClearJoint( jointHandle_t jointnum );
|
||||
|
||||
@@ -2171,6 +2171,15 @@ gameReturn_t idGameLocal::RunFrame( const usercmd_t *clientCmds ) {
|
||||
|
||||
player = GetLocalPlayer();
|
||||
|
||||
for (int i = 0; i < delayRemoveEntities.Num(); i++)
|
||||
{
|
||||
if (gameLocal.time > delayRemoveEntities[i].removeTime)
|
||||
{
|
||||
delayRemoveEntities[i].entity->PostEventMS(&EV_Remove, 0);
|
||||
delayRemoveEntities.RemoveIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
if ( !isMultiplayer && g_stopTime.GetBool() ) {
|
||||
// clear any debug lines from a previous frame
|
||||
gameRenderWorld->DebugClearLines( time + 1 );
|
||||
@@ -4362,3 +4371,30 @@ void idGameLocal::GetMapLoadingGUI( char gui[ MAX_STRING_CHARS ] ) {
|
||||
sprintf(gui, "guis/loadscreenbeta.gui");
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idGameLocal::DelayRemoveEntity
|
||||
===============
|
||||
*/
|
||||
void idGameLocal::DelayRemoveEntity(idEntity* entity, int delay)
|
||||
{
|
||||
rvmGameDelayRemoveEntry_t entry;
|
||||
entry.entity = entity;
|
||||
entry.removeTime = gameLocal.time + delay;
|
||||
delayRemoveEntities.Append(entry);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idGameLocal::Spawn
|
||||
================
|
||||
*/
|
||||
idEntity* idGameLocal::Spawn(const char* classname)
|
||||
{
|
||||
idEntity* ent;
|
||||
idDict dict;
|
||||
|
||||
dict.Set("classname", classname);
|
||||
gameLocal.SpawnEntityDef(dict, &ent);
|
||||
return ent;
|
||||
}
|
||||
@@ -60,6 +60,7 @@ extern idSoundWorld * gameSoundWorld;
|
||||
|
||||
// the "gameversion" client command will print this plus compile date
|
||||
#define GAME_VERSION "baseDOOM-1"
|
||||
#define GAME_FRAMETIME 0.016 // 16 milliseconds
|
||||
|
||||
// classes used by idGameLocal
|
||||
class idEntity;
|
||||
@@ -238,6 +239,12 @@ private:
|
||||
int spawnId;
|
||||
};
|
||||
|
||||
struct rvmGameDelayRemoveEntry_t
|
||||
{
|
||||
int32_t removeTime;
|
||||
idEntity* entity;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
class idGameLocal : public idGame {
|
||||
@@ -369,15 +376,27 @@ public:
|
||||
// Initializes all map variables common to both save games and spawned games
|
||||
void LoadMap( const char *mapName, int randseed );
|
||||
|
||||
void DelayRemoveEntity(idEntity* entity, int delay);
|
||||
|
||||
void LocalMapRestart( void );
|
||||
void MapRestart( void );
|
||||
static void MapRestart_f( const idCmdArgs &args );
|
||||
float SysScriptTime(void) const
|
||||
{
|
||||
return MS2SEC(realClientTime);
|
||||
}
|
||||
float SysScriptFrameTime(void) const
|
||||
{
|
||||
return MS2SEC(time - previousTime);
|
||||
}
|
||||
bool NextMap( void ); // returns wether serverinfo settings have been modified
|
||||
static void NextMap_f( const idCmdArgs &args );
|
||||
|
||||
idMapFile * GetLevelMap( void );
|
||||
const char * GetMapName( void ) const;
|
||||
|
||||
idEntity* Spawn(const char* classname);
|
||||
|
||||
int NumAAS( void ) const;
|
||||
idAAS * GetAAS( int num ) const;
|
||||
idAAS * GetAAS( const char *name ) const;
|
||||
@@ -572,6 +591,8 @@ private:
|
||||
void UpdateLagometer( int aheadOfServer, int dupeUsercmds );
|
||||
|
||||
void GetMapLoadingGUI( char gui[ MAX_STRING_CHARS ] );
|
||||
|
||||
idList<rvmGameDelayRemoveEntry_t> delayRemoveEntities;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
@@ -741,4 +762,19 @@ const int CINEMATIC_SKIP_DELAY = SEC2MS( 2.0f );
|
||||
#include "script/Script_Interpreter.h"
|
||||
#include "script/Script_Thread.h"
|
||||
|
||||
#include "weapons/Weapon_fist.h"
|
||||
#include "weapons/Weapon_pistol.h"
|
||||
#include "weapons/Weapon_flashlight.h"
|
||||
#include "weapons/Weapon_pda.h"
|
||||
#include "weapons/Weapon_shotgun.h"
|
||||
#include "weapons/Weapon_double_shotgun.h"
|
||||
#include "weapons/Weapon_machinegun.h"
|
||||
#include "weapons/Weapon_plasmagun.h"
|
||||
#include "weapons/Weapon_chaingun.h"
|
||||
#include "weapons/Weapon_rocketlauncher.h"
|
||||
#include "weapons/Weapon_bfg.h"
|
||||
#include "weapons/Weapon_handgrenade.h"
|
||||
#include "weapons/Weapon_chainsaw.h"
|
||||
#include "weapons/Weapon_grabber.h"
|
||||
|
||||
#endif /* !__GAME_LOCAL_H__ */
|
||||
|
||||
@@ -674,6 +674,7 @@ private:
|
||||
void Event_GetPreviousWeapon( void );
|
||||
void Event_SelectWeapon( const char *weaponName );
|
||||
void Event_GetWeaponEntity( void );
|
||||
public:
|
||||
void Event_OpenPDA( void );
|
||||
void Event_InPDA( void );
|
||||
void Event_ExitTeleporter( void );
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef PREDICTED_VALUE_H_
|
||||
#define PREDICTED_VALUE_H_
|
||||
|
||||
#include "Game_local.h"
|
||||
|
||||
/*
|
||||
================================================
|
||||
A simple class to handle simple predictable values
|
||||
on multiplayer clients.
|
||||
|
||||
The class encapsulates the actual value to be stored
|
||||
as well as the client frame number on which it is set.
|
||||
|
||||
When reading predicted values from a snapshot, the actual
|
||||
value is only updated if the server has processed the client's
|
||||
usercmd for the frame in which the client predicted the value.
|
||||
Got that?
|
||||
================================================
|
||||
*/
|
||||
template< class type_ >
|
||||
class idPredictedValue
|
||||
{
|
||||
public:
|
||||
explicit idPredictedValue();
|
||||
explicit idPredictedValue( const type_ & value_ );
|
||||
|
||||
void Set( const type_ & newValue );
|
||||
|
||||
idPredictedValue< type_ >& operator=( const type_ & value );
|
||||
|
||||
idPredictedValue< type_ >& operator+=( const type_ & toAdd );
|
||||
idPredictedValue< type_ >& operator-=( const type_ & toSubtract );
|
||||
|
||||
bool UpdateFromSnapshot( const type_ & valueFromSnapshot, int clientNumber );
|
||||
|
||||
type_ Get() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
private:
|
||||
// Noncopyable
|
||||
idPredictedValue( const idPredictedValue< type_ >& other );
|
||||
idPredictedValue< type_ >& operator=( const idPredictedValue< type_ >& other );
|
||||
|
||||
type_ value;
|
||||
int clientPredictedMilliseconds; // The time in which the client predicted the value.
|
||||
|
||||
void UpdatePredictionTime();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef PREDICTED_VALUE_IMPL_H_
|
||||
#define PREDICTED_VALUE_IMPL_H_
|
||||
|
||||
#include "PredictedValue.h"
|
||||
#include "Player.h"
|
||||
|
||||
/*
|
||||
===============
|
||||
idPredictedValue::idPredictedValue
|
||||
===============
|
||||
*/
|
||||
template< class type_ >
|
||||
idPredictedValue< type_ >::idPredictedValue() :
|
||||
value(),
|
||||
clientPredictedMilliseconds( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idPredictedValue::idPredictedValue
|
||||
===============
|
||||
*/
|
||||
template< class type_ >
|
||||
idPredictedValue< type_ >::idPredictedValue( const type_ & value_ ) :
|
||||
value( value_ ),
|
||||
clientPredictedMilliseconds( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idPredictedValue::UpdatePredictionTime
|
||||
===============
|
||||
*/
|
||||
template< class type_ >
|
||||
void idPredictedValue< type_ >::UpdatePredictionTime()
|
||||
{
|
||||
//if( gameLocal.GetLocalPlayer() != NULL )
|
||||
//{
|
||||
// clientPredictedMilliseconds = gameLocal.GetLocalPlayer()->usercmd.clientGameMilliseconds;
|
||||
//}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idPredictedValue::Set
|
||||
===============
|
||||
*/
|
||||
template< class type_ >
|
||||
void idPredictedValue< type_ >::Set( const type_ & newValue )
|
||||
{
|
||||
value = newValue;
|
||||
UpdatePredictionTime();
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idPredictedValue::operator=
|
||||
===============
|
||||
*/
|
||||
template< class type_ >
|
||||
idPredictedValue< type_ >& idPredictedValue< type_ >::operator=( const type_ & newValue )
|
||||
{
|
||||
Set( newValue );
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idPredictedValue::operator+=
|
||||
===============
|
||||
*/
|
||||
template< class type_ >
|
||||
idPredictedValue< type_ >& idPredictedValue< type_ >::operator+=( const type_ & toAdd )
|
||||
{
|
||||
Set( value + toAdd );
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idPredictedValue::operator-=
|
||||
===============
|
||||
*/
|
||||
template< class type_ >
|
||||
idPredictedValue< type_ >& idPredictedValue< type_ >::operator-=( const type_ & toSubtract )
|
||||
{
|
||||
Set( value - toSubtract );
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idPredictedValue::UpdateFromSnapshot
|
||||
|
||||
Always updates the value for remote clients.
|
||||
|
||||
Only updates the actual value if the snapshot usercmd frame is newer than the one in which
|
||||
the client predicted this value.
|
||||
|
||||
Returns true if the value was set, false if not.
|
||||
===============
|
||||
*/
|
||||
template< class type_ >
|
||||
bool idPredictedValue< type_ >::UpdateFromSnapshot( const type_ & valueFromSnapshot, int clientNumber )
|
||||
{
|
||||
//if( clientNumber != gameLocal.GetLocalClientNum() )
|
||||
//{
|
||||
// value = valueFromSnapshot;
|
||||
// return true;
|
||||
//}
|
||||
//
|
||||
//if( gameLocal.GetLastClientUsercmdMilliseconds( clientNumber ) >= clientPredictedMilliseconds )
|
||||
//{
|
||||
// value = valueFromSnapshot;
|
||||
// return true;
|
||||
//}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
operator==
|
||||
|
||||
Overload for idPredictedValue.
|
||||
We only care if the values are equal, not the frame number.
|
||||
===============
|
||||
*/
|
||||
template< class firstType_, class secondType_ >
|
||||
bool operator==( const idPredictedValue< firstType_ >& lhs, const idPredictedValue< secondType_ >& rhs )
|
||||
{
|
||||
return lhs.Get() == rhs.Get();
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
operator!=
|
||||
|
||||
Overload for idPredictedValue.
|
||||
We only care if the values are equal, not the frame number.
|
||||
===============
|
||||
*/
|
||||
template< class firstType_, class secondType_ >
|
||||
bool operator!=( const idPredictedValue< firstType_ >& lhs, const idPredictedValue< secondType_ >& rhs )
|
||||
{
|
||||
return lhs.Get() != rhs.Get();
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
operator==
|
||||
|
||||
Overload for idPredictedValue.
|
||||
We only care if the values are equal, not the frame number.
|
||||
===============
|
||||
*/
|
||||
template< class firstType_, class secondType_ >
|
||||
bool operator==( const idPredictedValue< firstType_ >& lhs, const secondType_ & rhs )
|
||||
{
|
||||
return lhs.Get() == rhs;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
operator==
|
||||
|
||||
Overload for idPredictedValue.
|
||||
We only care if the values are equal, not the frame number.
|
||||
===============
|
||||
*/
|
||||
template< class firstType_, class secondType_ >
|
||||
bool operator==( const firstType_ lhs, const idPredictedValue< secondType_ >& rhs )
|
||||
{
|
||||
return lhs == rhs.Get();
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
operator!=
|
||||
|
||||
Overload for idPredictedValue.
|
||||
We only care if the values are equal, not the frame number.
|
||||
===============
|
||||
*/
|
||||
template< class firstType_, class secondType_ >
|
||||
bool operator!=( const idPredictedValue< firstType_ >& lhs, const secondType_ & rhs )
|
||||
{
|
||||
return lhs.Get() != rhs;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
operator!=
|
||||
|
||||
Overload for idPredictedValue.
|
||||
We only care if the values are equal, not the frame number.
|
||||
===============
|
||||
*/
|
||||
template< class firstType_, class secondType_ >
|
||||
bool operator!=( const firstType_ lhs, const idPredictedValue< secondType_ >& rhs )
|
||||
{
|
||||
return lhs != rhs.Get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
+2031
-1056
File diff suppressed because it is too large
Load Diff
+306
-166
@@ -1,27 +1,27 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
IceTech GPL Source Code
|
||||
Copyright (C) 2026 Justin Marshall
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the IceTech GPL Source Code (?IceTech Source Code?).
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
IceTech Source Code is free software: you can redistribute it and/or modify
|
||||
Doom 3 BFG Edition 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
IceTech Source Code is distributed in the hope that it will be useful,
|
||||
Doom 3 BFG Edition 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 IceTech Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the IceTech Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the IceTech Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing Justin Marshall, justinmarshall20@gmail.com
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
@@ -29,22 +29,18 @@ If you have questions concerning this license or the applicable additional terms
|
||||
#ifndef __GAME_WEAPON_H__
|
||||
#define __GAME_WEAPON_H__
|
||||
|
||||
#include "PredictedValue.h"
|
||||
class idWeapon;
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Player Weapon
|
||||
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
WP_READY,
|
||||
WP_OUTOFAMMO,
|
||||
WP_RELOAD,
|
||||
WP_HOLSTERED,
|
||||
WP_RISING,
|
||||
WP_LOWERING
|
||||
} weaponStatus_t;
|
||||
extern const idEventDef EV_Weapon_State;
|
||||
|
||||
typedef int ammo_t;
|
||||
static const int AMMO_NUMTYPES = 16;
|
||||
@@ -56,124 +52,276 @@ static const int LIGHTID_VIEW_MUZZLE_FLASH = 100;
|
||||
|
||||
class idMoveableItem;
|
||||
|
||||
class idWeapon : public idAnimatedEntity {
|
||||
public:
|
||||
CLASS_PROTOTYPE( idWeapon );
|
||||
typedef struct
|
||||
{
|
||||
char name[64];
|
||||
char particlename[128];
|
||||
bool active;
|
||||
int startTime;
|
||||
jointHandle_t joint; //The joint on which to attach the particle
|
||||
bool smoke; //Is this a smoke particle
|
||||
const idDeclParticle* particle; //Used for smoke particles
|
||||
idFuncEmitter* emitter; //Used for non-smoke particles
|
||||
} WeaponParticle_t;
|
||||
|
||||
idWeapon();
|
||||
typedef struct
|
||||
{
|
||||
char name[64];
|
||||
bool active;
|
||||
int startTime;
|
||||
jointHandle_t joint;
|
||||
int lightHandle;
|
||||
renderLight_t light;
|
||||
} WeaponLight_t;
|
||||
|
||||
class rvmWeaponObject : public idClass
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE(rvmWeaponObject);
|
||||
|
||||
virtual void Init(idWeapon* weapon);
|
||||
|
||||
void SetState(const char* state)
|
||||
{
|
||||
stateThread.SetState(state);
|
||||
}
|
||||
void AppendState(const char* state)
|
||||
{
|
||||
stateThread.PostState(state);
|
||||
}
|
||||
void Execute(void)
|
||||
{
|
||||
stateThread.Execute();
|
||||
}
|
||||
bool IsRunning(void)
|
||||
{
|
||||
return stateThread.IsExecuting();
|
||||
}
|
||||
bool IsStateRunning(const char* name)
|
||||
{
|
||||
return stateThread.CurrentStateIs(name);
|
||||
}
|
||||
|
||||
virtual void OwnerDied(void) {}
|
||||
|
||||
bool IsFiring();
|
||||
bool IsReloading();
|
||||
|
||||
stateResult_t Holstered(stateParms_t* parms)
|
||||
{
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
virtual bool IsHolstered(void)
|
||||
{
|
||||
return IsStateRunning("Holstered");
|
||||
}
|
||||
|
||||
protected:
|
||||
idWeapon* owner;
|
||||
|
||||
const idSoundShader* FindSound(const char* name);
|
||||
protected:
|
||||
rvStateThread stateThread;
|
||||
float next_attack;
|
||||
};
|
||||
|
||||
class idWeapon : public idAnimatedEntity
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE(idWeapon);
|
||||
|
||||
idWeapon();
|
||||
virtual ~idWeapon();
|
||||
|
||||
// Init
|
||||
void Spawn( void );
|
||||
void SetOwner( idPlayer *owner );
|
||||
idPlayer* GetOwner( void );
|
||||
virtual bool ShouldConstructScriptObjectAtSpawn( void ) const;
|
||||
void Spawn();
|
||||
void SetOwner(idPlayer* owner);
|
||||
idPlayer* GetOwner();
|
||||
virtual bool ShouldConstructScriptObjectAtSpawn() const;
|
||||
void SetFlashlightOwner(idPlayer* owner);
|
||||
|
||||
static void CacheWeapon( const char *weaponName );
|
||||
virtual idClass* InvokeChild() override
|
||||
{
|
||||
return currentWeaponObject;
|
||||
}
|
||||
|
||||
static void CacheWeapon(const char* weaponName);
|
||||
|
||||
// save games
|
||||
void Save( idSaveGame *savefile ) const; // archives object for save game file
|
||||
void Restore( idRestoreGame *savefile ); // unarchives object from save game file
|
||||
void Save(idSaveGame* savefile) const; // archives object for save game file
|
||||
void Restore(idRestoreGame* savefile); // unarchives object from save game file
|
||||
|
||||
// Weapon definition management
|
||||
void Clear( void );
|
||||
void GetWeaponDef( const char *objectname, int ammoinclip );
|
||||
bool IsLinked( void );
|
||||
bool IsWorldModelReady( void );
|
||||
void Clear();
|
||||
void GetWeaponDef(const char* objectname, int ammoinclip);
|
||||
bool IsWorldModelReady();
|
||||
|
||||
// GUIs
|
||||
const char * Icon( void ) const;
|
||||
void UpdateGUI( void );
|
||||
const char* Icon() const;
|
||||
void UpdateGUI();
|
||||
const char* PdaIcon() const;
|
||||
const char* DisplayName() const;
|
||||
const char* Description() const;
|
||||
|
||||
virtual void SetModel( const char *modelname );
|
||||
bool GetGlobalJointTransform( bool viewModel, const jointHandle_t jointHandle, idVec3 &offset, idMat3 &axis );
|
||||
void SetPushVelocity( const idVec3 &pushVelocity );
|
||||
bool UpdateSkin( void );
|
||||
virtual void SetModel(const char* modelname);
|
||||
bool GetGlobalJointTransform(bool viewModel, const jointHandle_t jointHandle, idVec3& offset, idMat3& axis);
|
||||
void SetPushVelocity(const idVec3& pushVelocity);
|
||||
bool UpdateSkin();
|
||||
|
||||
bool IsFiring()
|
||||
{
|
||||
return isFiring;
|
||||
}
|
||||
|
||||
// State control/player interface
|
||||
void Think( void );
|
||||
void Raise( void );
|
||||
void PutAway( void );
|
||||
void Reload( void );
|
||||
void LowerWeapon( void );
|
||||
void RaiseWeapon( void );
|
||||
void HideWeapon( void );
|
||||
void ShowWeapon( void );
|
||||
void HideWorldModel( void );
|
||||
void ShowWorldModel( void );
|
||||
void OwnerDied( void );
|
||||
void BeginAttack( void );
|
||||
void EndAttack( void );
|
||||
bool IsReady( void ) const;
|
||||
bool IsReloading( void ) const;
|
||||
bool IsHolstered( void ) const;
|
||||
bool ShowCrosshair( void ) const;
|
||||
idEntity * DropItem( const idVec3 &velocity, int activateDelay, int removeDelay, bool died );
|
||||
bool CanDrop( void ) const;
|
||||
void WeaponStolen( void );
|
||||
|
||||
// Script state management
|
||||
virtual idThread * ConstructScriptObject( void );
|
||||
virtual void DeconstructScriptObject( void );
|
||||
void SetState( const char *statename, int blendFrames );
|
||||
void UpdateScript( void );
|
||||
void EnterCinematic( void );
|
||||
void ExitCinematic( void );
|
||||
void NetCatchup( void );
|
||||
void Think();
|
||||
void Raise();
|
||||
void PutAway();
|
||||
void Reload();
|
||||
void LowerWeapon();
|
||||
void RaiseWeapon();
|
||||
void HideWeapon();
|
||||
void ShowWeapon();
|
||||
void HideWorldModel();
|
||||
void ShowWorldModel();
|
||||
void OwnerDied();
|
||||
void BeginAttack();
|
||||
void EndAttack();
|
||||
bool IsReady() const;
|
||||
bool IsReloading() const;
|
||||
bool IsHolstered() const;
|
||||
bool ShowCrosshair() const;
|
||||
idEntity* DropItem(const idVec3& velocity, int activateDelay, int removeDelay, bool died);
|
||||
bool CanDrop() const;
|
||||
void WeaponStolen();
|
||||
void ForceAmmoInClip();
|
||||
|
||||
// Visual presentation
|
||||
void PresentWeapon( bool showViewModel );
|
||||
int GetZoomFov( void );
|
||||
void GetWeaponAngleOffsets( int *average, float *scale, float *max );
|
||||
void GetWeaponTimeOffsets( float *time, float *scale );
|
||||
bool BloodSplat( float size );
|
||||
void PresentWeapon(bool showViewModel);
|
||||
int GetZoomFov();
|
||||
void GetWeaponAngleOffsets(int* average, float* scale, float* max);
|
||||
void GetWeaponTimeOffsets(float* time, float* scale);
|
||||
bool BloodSplat(float size);
|
||||
void SetIsPlayerFlashlight(bool bl)
|
||||
{
|
||||
isPlayerFlashlight = bl;
|
||||
}
|
||||
void FlashlightOn();
|
||||
void FlashlightOff();
|
||||
|
||||
// Ammo
|
||||
static ammo_t GetAmmoNumForName( const char *ammoname );
|
||||
static const char *GetAmmoNameForNum( ammo_t ammonum );
|
||||
static const char *GetAmmoPickupNameForNum( ammo_t ammonum );
|
||||
ammo_t GetAmmoType( void ) const;
|
||||
int AmmoAvailable( void ) const;
|
||||
int AmmoInClip( void ) const;
|
||||
void ResetAmmoClip( void );
|
||||
int ClipSize( void ) const;
|
||||
int LowAmmo( void ) const;
|
||||
int AmmoRequired( void ) const;
|
||||
static ammo_t GetAmmoNumForName(const char* ammoname);
|
||||
static const char* GetAmmoNameForNum(ammo_t ammonum);
|
||||
static const char* GetAmmoPickupNameForNum(ammo_t ammonum);
|
||||
ammo_t GetAmmoType() const;
|
||||
int AmmoAvailable() const;
|
||||
int AmmoInClip() const;
|
||||
void ResetAmmoClip();
|
||||
int ClipSize() const;
|
||||
int LowAmmo() const;
|
||||
int AmmoRequired() const;
|
||||
int AmmoCount() const;
|
||||
int GetGrabberState() const;
|
||||
|
||||
virtual void WriteToSnapshot( idBitMsgDelta &msg ) const;
|
||||
virtual void ReadFromSnapshot( const idBitMsgDelta &msg );
|
||||
// Flashlight
|
||||
idAnimatedEntity* GetWorldModel()
|
||||
{
|
||||
return worldModel.GetEntity();
|
||||
}
|
||||
|
||||
enum {
|
||||
virtual void WriteToSnapshot(idBitMsg& msg) const;
|
||||
virtual void ReadFromSnapshot(const idBitMsg& msg);
|
||||
|
||||
enum
|
||||
{
|
||||
EVENT_RELOAD = idEntity::EVENT_MAXEVENTS,
|
||||
EVENT_ENDRELOAD,
|
||||
EVENT_CHANGESKIN,
|
||||
EVENT_MAXEVENTS
|
||||
};
|
||||
virtual bool ClientReceiveEvent( int event, int time, const idBitMsg &msg );
|
||||
virtual bool ClientReceiveEvent(int event, int time, const idBitMsg& msg);
|
||||
|
||||
virtual void ClientPredictionThink( void );
|
||||
virtual void ClientPredictionThink();
|
||||
virtual void ClientThink(const int curTime, const float fraction, const bool predict);
|
||||
void MuzzleFlashLight();
|
||||
void RemoveMuzzleFlashlight();
|
||||
|
||||
// Get a global origin and axis suitable for the laser sight or bullet tracing
|
||||
// Returns false for hands, grenades, and chainsaw.
|
||||
// Can't be const because a frame may need to be created.
|
||||
bool GetMuzzlePositionWithHacks(idVec3& origin, idMat3& axis);
|
||||
|
||||
void GetProjectileLaunchOriginAndAxis(idVec3& origin, idMat3& axis);
|
||||
|
||||
const idDeclEntityDef* GetDeclEntityDef()
|
||||
{
|
||||
return weaponDef;
|
||||
}
|
||||
|
||||
friend class idPlayer;
|
||||
public:
|
||||
virtual void CallNativeEvent(idStr& name) override;
|
||||
|
||||
void Event_SetLightParm(int parmnum, float value);
|
||||
void Event_SetLightParms(float parm0, float parm1, float parm2, float parm3);
|
||||
|
||||
// script events
|
||||
void Event_Clear();
|
||||
void Event_GetOwner();
|
||||
void Event_SetWeaponStatus(float newStatus);
|
||||
void Event_WeaponReady();
|
||||
void Event_WeaponOutOfAmmo();
|
||||
void Event_WeaponReloading();
|
||||
void Event_WeaponHolstered();
|
||||
void Event_WeaponRising();
|
||||
void Event_WeaponLowering();
|
||||
void Event_UseAmmo(int amount);
|
||||
void Event_AddToClip(int amount);
|
||||
void Event_AmmoInClip();
|
||||
int AmmoAvailable();
|
||||
void Event_AmmoAvailable();
|
||||
void Event_TotalAmmoCount();
|
||||
void Event_ClipSize();
|
||||
void Event_PlayAnim(int channel, const char* animname, bool loop);
|
||||
void Event_PlayCycle(int channel, const char* animname);
|
||||
bool Event_AnimDone(int channel, int blendFrames);
|
||||
void Event_SetBlendFrames(int channel, int blendFrames);
|
||||
void Event_GetBlendFrames(int channel);
|
||||
void Event_Next();
|
||||
void Event_SetSkin(const char* skinname);
|
||||
void Event_Flashlight(int enable);
|
||||
void Event_GetLightParm(int parmnum);
|
||||
void Event_LaunchProjectiles(int num_projectiles, float spread, float fuseOffset, float launchPower, float dmgPower);
|
||||
idEntity* CreateProjectile();
|
||||
void Event_CreateProjectile();
|
||||
void Event_EjectBrass();
|
||||
void Event_Melee();
|
||||
void Event_GetWorldModel();
|
||||
void Event_AllowDrop(int allow);
|
||||
void Event_AutoReload();
|
||||
void Event_NetReload();
|
||||
bool Event_IsInvisible();
|
||||
void Event_NetEndReload();
|
||||
|
||||
void EnterCinematic();
|
||||
void ExitCinematic();
|
||||
void NetCatchup();
|
||||
|
||||
bool IsLinked()
|
||||
{
|
||||
return currentWeaponObject != NULL;
|
||||
}
|
||||
private:
|
||||
// script control
|
||||
idScriptBool WEAPON_ATTACK;
|
||||
idScriptBool WEAPON_RELOAD;
|
||||
idScriptBool WEAPON_NETRELOAD;
|
||||
idScriptBool WEAPON_NETENDRELOAD;
|
||||
idScriptBool WEAPON_NETFIRING;
|
||||
idScriptBool WEAPON_RAISEWEAPON;
|
||||
idScriptBool WEAPON_LOWERWEAPON;
|
||||
weaponStatus_t status;
|
||||
idThread * thread;
|
||||
idStr state;
|
||||
idStr idealState;
|
||||
int animBlendFrames;
|
||||
int animDoneTime;
|
||||
bool isPlayerFlashlight;
|
||||
bool isLinked;
|
||||
|
||||
// precreated projectile
|
||||
idEntity *projectileEnt;
|
||||
idEntity* projectileEnt;
|
||||
|
||||
idPlayer * owner;
|
||||
idPlayer* owner;
|
||||
idEntityPtr<idAnimatedEntity> worldModel;
|
||||
|
||||
// hiding (for GUIs and NPCs)
|
||||
@@ -186,6 +334,8 @@ private:
|
||||
bool hide;
|
||||
bool disabled;
|
||||
|
||||
bool isFlashLight;
|
||||
|
||||
// berserk
|
||||
int berserk;
|
||||
|
||||
@@ -196,7 +346,7 @@ private:
|
||||
// the view weapon render entity parms
|
||||
idVec3 viewWeaponOrigin;
|
||||
idMat3 viewWeaponAxis;
|
||||
|
||||
|
||||
// the muzzle bone's position, used for launching projectiles and trailing smoke
|
||||
idVec3 muzzleOrigin;
|
||||
idMat3 muzzleAxis;
|
||||
@@ -206,14 +356,17 @@ private:
|
||||
// weapon definition
|
||||
// we maintain local copies of the projectile and brass dictionaries so they
|
||||
// do not have to be copied across the DLL boundary when entities are spawned
|
||||
const idDeclEntityDef * weaponDef;
|
||||
const idDeclEntityDef * meleeDef;
|
||||
const idDeclEntityDef* weaponDef;
|
||||
const idDeclEntityDef* meleeDef;
|
||||
idDict projectileDict;
|
||||
float meleeDistance;
|
||||
idStr meleeDefName;
|
||||
idDict brassDict;
|
||||
int brassDelay;
|
||||
idStr icon;
|
||||
idStr pdaIcon;
|
||||
idStr displayName;
|
||||
idStr itemDesc;
|
||||
|
||||
// view weapon gui light
|
||||
renderLight_t guiLight;
|
||||
@@ -226,6 +379,9 @@ private:
|
||||
renderLight_t worldMuzzleFlash; // positioned on world weapon bone
|
||||
int worldMuzzleFlashHandle;
|
||||
|
||||
float fraccos;
|
||||
float fraccos2;
|
||||
|
||||
idVec3 flashColor;
|
||||
int muzzleFlashEnd;
|
||||
int flashTime;
|
||||
@@ -247,15 +403,15 @@ private:
|
||||
ammo_t ammoType;
|
||||
int ammoRequired; // amount of ammo to use each shot. 0 means weapon doesn't need ammo.
|
||||
int clipSize; // 0 means no reload
|
||||
int ammoClip;
|
||||
idPredictedValue< int > ammoClip;
|
||||
int lowAmmo; // if ammo in clip hits this threshold, snd_
|
||||
bool powerAmmo; // true if the clip reduction is a factor of the power setting when
|
||||
// a projectile is launched
|
||||
// a projectile is launched
|
||||
// mp client
|
||||
bool isFiring;
|
||||
|
||||
// zoom
|
||||
int zoomFov; // variable zoom fov per weapon
|
||||
int zoomFov; // variable zoom fov per weapon
|
||||
|
||||
// joints from models
|
||||
jointHandle_t barrelJointView;
|
||||
@@ -268,29 +424,34 @@ private:
|
||||
jointHandle_t barrelJointWorld;
|
||||
jointHandle_t ejectJointWorld;
|
||||
|
||||
jointHandle_t smokeJointView;
|
||||
|
||||
idHashTable<WeaponParticle_t> weaponParticles;
|
||||
idHashTable<WeaponLight_t> weaponLights;
|
||||
|
||||
// sound
|
||||
const idSoundShader * sndHum;
|
||||
const idSoundShader* sndHum;
|
||||
|
||||
// new style muzzle smokes
|
||||
const idDeclParticle * weaponSmoke; // null if it doesn't smoke
|
||||
const idDeclParticle* weaponSmoke; // null if it doesn't smoke
|
||||
int weaponSmokeStartTime; // set to gameLocal.time every weapon fire
|
||||
bool continuousSmoke; // if smoke is continuous ( chainsaw )
|
||||
const idDeclParticle * strikeSmoke; // striking something in melee
|
||||
int strikeSmokeStartTime; // timing
|
||||
idVec3 strikePos; // position of last melee strike
|
||||
const idDeclParticle* strikeSmoke; // striking something in melee
|
||||
int strikeSmokeStartTime; // timing
|
||||
idVec3 strikePos; // position of last melee strike
|
||||
idMat3 strikeAxis; // axis of last melee strike
|
||||
int nextStrikeFx; // used for sound and decal ( may use for strike smoke too )
|
||||
|
||||
// nozzle effects
|
||||
bool nozzleFx; // does this use nozzle effects ( parm5 at rest, parm6 firing )
|
||||
// this also assumes a nozzle light atm
|
||||
// this also assumes a nozzle light atm
|
||||
int nozzleFxFade; // time it takes to fade between the effects
|
||||
int lastAttack; // last time an attack occured
|
||||
renderLight_t nozzleGlow; // nozzle light
|
||||
int nozzleGlowHandle; // handle for nozzle light
|
||||
|
||||
idVec3 nozzleGlowColor; // color of the nozzle glow
|
||||
const idMaterial * nozzleGlowShader; // shader for glow light
|
||||
const idMaterial* nozzleGlowShader; // shader for glow light
|
||||
float nozzleGlowRadius; // radius of glow light
|
||||
|
||||
// weighting for viewmodel angles
|
||||
@@ -301,65 +462,44 @@ private:
|
||||
float weaponOffsetScale;
|
||||
|
||||
// flashlight
|
||||
void AlertMonsters( void );
|
||||
void AlertMonsters();
|
||||
|
||||
// Visual presentation
|
||||
void InitWorldModel( const idDeclEntityDef *def );
|
||||
void MuzzleFlashLight( void );
|
||||
void MuzzleRise( idVec3 &origin, idMat3 &axis );
|
||||
void UpdateNozzleFx( void );
|
||||
void UpdateFlashPosition( void );
|
||||
void InitWorldModel(const idDeclEntityDef* def);
|
||||
void MuzzleRise(idVec3& origin, idMat3& axis);
|
||||
void UpdateNozzleFx();
|
||||
void UpdateFlashPosition();
|
||||
|
||||
// script events
|
||||
void Event_Clear( void );
|
||||
void Event_GetOwner( void );
|
||||
void Event_WeaponState( const char *statename, int blendFrames );
|
||||
void Event_SetWeaponStatus( float newStatus );
|
||||
void Event_WeaponReady( void );
|
||||
void Event_WeaponOutOfAmmo( void );
|
||||
void Event_WeaponReloading( void );
|
||||
void Event_WeaponHolstered( void );
|
||||
void Event_WeaponRising( void );
|
||||
void Event_WeaponLowering( void );
|
||||
void Event_UseAmmo( int amount );
|
||||
void Event_AddToClip( int amount );
|
||||
void Event_AmmoInClip( void );
|
||||
void Event_AmmoAvailable( void );
|
||||
void Event_TotalAmmoCount( void );
|
||||
void Event_ClipSize( void );
|
||||
void Event_PlayAnim( int channel, const char *animname );
|
||||
void Event_PlayCycle( int channel, const char *animname );
|
||||
void Event_AnimDone( int channel, int blendFrames );
|
||||
void Event_SetBlendFrames( int channel, int blendFrames );
|
||||
void Event_GetBlendFrames( int channel );
|
||||
void Event_Next( void );
|
||||
void Event_SetSkin( const char *skinname );
|
||||
void Event_Flashlight( int enable );
|
||||
void Event_GetLightParm( int parmnum );
|
||||
void Event_SetLightParm( int parmnum, float value );
|
||||
void Event_SetLightParms( float parm0, float parm1, float parm2, float parm3 );
|
||||
void Event_LaunchProjectiles( int num_projectiles, float spread, float fuseOffset, float launchPower, float dmgPower );
|
||||
void Event_CreateProjectile( void );
|
||||
void Event_EjectBrass( void );
|
||||
void Event_Melee( void );
|
||||
void Event_GetWorldModel( void );
|
||||
void Event_AllowDrop( int allow );
|
||||
void Event_AutoReload( void );
|
||||
void Event_NetReload( void );
|
||||
void Event_IsInvisible( void );
|
||||
void Event_NetEndReload( void );
|
||||
//idGrabber grabber;
|
||||
int grabberState;
|
||||
public:
|
||||
void Event_Grabber(int enable);
|
||||
int Event_GrabberHasTarget();
|
||||
void Event_GrabberSetGrabDistance(float dist);
|
||||
void Event_LaunchProjectilesEllipse(int num_projectiles, float spreada, float spreadb, float fuseOffset, float power);
|
||||
void Event_LaunchPowerup(const char* powerup, float duration, int useAmmo);
|
||||
|
||||
void Event_StartWeaponSmoke();
|
||||
void Event_StopWeaponSmoke();
|
||||
|
||||
void Event_StartWeaponParticle(const char* name);
|
||||
void Event_StopWeaponParticle(const char* name);
|
||||
|
||||
void Event_StartWeaponLight(const char* name);
|
||||
void Event_StopWeaponLight(const char* name);
|
||||
private:
|
||||
rvmWeaponObject* currentWeaponObject;
|
||||
bool OutOfAmmo;
|
||||
};
|
||||
|
||||
ID_INLINE bool idWeapon::IsLinked( void ) {
|
||||
return isLinked;
|
||||
ID_INLINE bool idWeapon::IsWorldModelReady()
|
||||
{
|
||||
return (worldModel.GetEntity() != NULL);
|
||||
}
|
||||
|
||||
ID_INLINE bool idWeapon::IsWorldModelReady( void ) {
|
||||
return ( worldModel.GetEntity() != NULL );
|
||||
}
|
||||
|
||||
ID_INLINE idPlayer* idWeapon::GetOwner( void ) {
|
||||
ID_INLINE idPlayer* idWeapon::GetOwner()
|
||||
{
|
||||
return owner;
|
||||
}
|
||||
|
||||
#endif /* !__GAME_WEAPON_H__ */
|
||||
#endif /* !__GAME_WEAPON_H__ */
|
||||
@@ -0,0 +1,413 @@
|
||||
// Bot.cpp
|
||||
//
|
||||
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
idCVar bot_pathdebug( "bot_pathdebug", "0", CVAR_BOOL | CVAR_CHEAT, "force the bot to path to player" );
|
||||
idCVar bot_goaldist( "bot_goaldist", "20", CVAR_INTEGER | CVAR_CHEAT, "" );
|
||||
idCVar bot_debugnav( "bot_debugnav", "0", CVAR_BOOL | CVAR_CHEAT, "draws navmesh paths for the bot" );
|
||||
idCVar bot_showstate( "bot_showstate", "0", CVAR_BOOL | CVAR_CHEAT, "draws the bot state above the bot" );
|
||||
idCVar bot_debug( "bot_debug", "0", CVAR_BOOL, "shows debug info for the bot" );
|
||||
idCVar bot_skill("bot_skill", "3", CVAR_INTEGER, "");
|
||||
|
||||
CLASS_DECLARATION( idPlayer, rvmBot )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
===================
|
||||
rvmBot::rvmBot
|
||||
===================
|
||||
*/
|
||||
rvmBot::rvmBot()
|
||||
{
|
||||
//bs.action = NULL;
|
||||
hasSpawned = false;
|
||||
gameLocal.RegisterBot( this );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvmBot::~rvmBot
|
||||
===================
|
||||
*/
|
||||
rvmBot::~rvmBot()
|
||||
{
|
||||
gameLocal.UnRegisterBot( this );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
rvmBot::SetEnemy
|
||||
==================
|
||||
*/
|
||||
void rvmBot::SetEnemy( idPlayer* player, idVec3 origin)
|
||||
{
|
||||
if(bs.enemy == -1)
|
||||
{
|
||||
bs.enemy = player->entityNumber;
|
||||
bs.aggressiveAttackTime = gameLocal.SysScriptTime() + 2.0f;
|
||||
bs.lastenemyorigin = origin;
|
||||
//bs.action = &botAIBattleRetreat;
|
||||
stateThread.SetState("state_Attacked");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
rvmBot::BotUpdateInventory
|
||||
==================
|
||||
*/
|
||||
void rvmBot::BotUpdateInventory( void )
|
||||
{
|
||||
bs.inventory[INVENTORY_ARMOR] = inventory.armor;
|
||||
bs.inventory[INVENTORY_GAUNTLET] = 1;
|
||||
bs.inventory[INVENTORY_SHOTGUN] = HasWeapon( weapon_shotgun );
|
||||
bs.inventory[INVENTORY_MACHINEGUN] = HasWeapon( weapon_machinegun );
|
||||
bs.inventory[INVENTORY_GRENADELAUNCHER] = 0;
|
||||
bs.inventory[INVENTORY_ROCKETLAUNCHER] = HasWeapon( weapon_rocketlauncher );
|
||||
bs.inventory[INVENTORY_LIGHTNING] = 0;
|
||||
bs.inventory[INVENTORY_RAILGUN] = 0;
|
||||
bs.inventory[INVENTORY_PLASMAGUN] = HasWeapon( weapon_plasmagun );
|
||||
bs.inventory[INVENTORY_BFG10K] = 0;
|
||||
bs.inventory[INVENTORY_GRAPPLINGHOOK] = 0;
|
||||
bs.inventory[INVENTORY_SHELLS] = inventory.ammo[idWeapon::GetAmmoNumForName( "ammo_shells" )].Get();
|
||||
bs.inventory[INVENTORY_BULLETS] = inventory.ammo[idWeapon::GetAmmoNumForName( "ammo_clip" )].Get();
|
||||
bs.inventory[INVENTORY_GRENADES] = 0;
|
||||
bs.inventory[INVENTORY_CELLS] = inventory.ammo[idWeapon::GetAmmoNumForName( "ammo_cells" )].Get();
|
||||
bs.inventory[INVENTORY_LIGHTNINGAMMO] = 0;
|
||||
bs.inventory[INVENTORY_ROCKETS] = inventory.ammo[idWeapon::GetAmmoNumForName( "ammo_rockets" )].Get();
|
||||
bs.inventory[INVENTORY_SLUGS] = 0;
|
||||
bs.inventory[INVENTORY_BFGAMMO] = 0;
|
||||
bs.inventory[INVENTORY_HEALTH] = health;
|
||||
bs.inventory[INVENTORY_TELEPORTER] = 0;
|
||||
bs.inventory[INVENTORY_MEDKIT] = 0;
|
||||
bs.inventory[INVENTORY_QUAD] = 0;
|
||||
bs.inventory[INVENTORY_ENVIRONMENTSUIT] = 0;
|
||||
bs.inventory[INVENTORY_HASTE] = 0;
|
||||
bs.inventory[INVENTORY_INVISIBILITY] = 0;
|
||||
bs.inventory[INVENTORY_REGEN] = 0;
|
||||
bs.inventory[INVENTORY_FLIGHT] = 0;
|
||||
bs.inventory[INVENTORY_REDFLAG] = 0;
|
||||
bs.inventory[INVENTORY_BLUEFLAG] = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
rvmBot::Spawn
|
||||
===================
|
||||
*/
|
||||
void rvmBot::Spawn( void )
|
||||
{
|
||||
idStr botName;
|
||||
char filename[256];
|
||||
int errnum;
|
||||
|
||||
stateThread.SetOwner(this);
|
||||
|
||||
idPlayer::Spawn();
|
||||
|
||||
if( common->IsServer() )
|
||||
{
|
||||
weapon_machinegun = SlotForWeapon( "weapon_machinegun" );
|
||||
weapon_shotgun = SlotForWeapon( "weapon_shotgun" );
|
||||
weapon_plasmagun = SlotForWeapon( "weapon_plasmagun" );
|
||||
weapon_rocketlauncher = SlotForWeapon( "weapon_rocketlauncher" );
|
||||
|
||||
WP_MACHINEGUN = weapon_machinegun;
|
||||
WP_SHOTGUN = weapon_shotgun;
|
||||
WP_PLASMAGUN = weapon_plasmagun;
|
||||
WP_ROCKET_LAUNCHER = weapon_rocketlauncher;
|
||||
|
||||
botName = spawnArgs.GetString( "botname" );
|
||||
|
||||
aas = gameLocal.GetBotAAS();
|
||||
if( aas == NULL )
|
||||
{
|
||||
gameLocal.Error( "Missing AAS\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Load in the bot character.
|
||||
bs.character = botCharacterStatsManager.BotLoadCharacterFromFile( va( "bots/%s_c.c", botName.c_str() ), 1 );
|
||||
if( !bs.character )
|
||||
{
|
||||
gameLocal.Error( "Failed to load character file for bot %s\n", botName.c_str() );
|
||||
}
|
||||
|
||||
// Allocate the goal state.
|
||||
bs.gs = botGoalManager.BotAllocGoalState( entityNumber );
|
||||
|
||||
// Get the bot items weights file name.
|
||||
botCharacterStatsManager.Characteristic_String( bs.character, CHARACTERISTIC_ITEMWEIGHTS, filename, 256 );
|
||||
errnum = botGoalManager.BotLoadItemWeights( bs.gs, filename );
|
||||
if( errnum != BLERR_NOERROR )
|
||||
{
|
||||
gameLocal.Error( "Failed to load bot item weights!" );
|
||||
botGoalManager.BotFreeGoalState( bs.gs );
|
||||
return;
|
||||
}
|
||||
|
||||
//allocate a weapon state
|
||||
bs.ws = botWeaponInfoManager.BotAllocWeaponState();
|
||||
|
||||
//load the weapon weights
|
||||
botCharacterStatsManager.Characteristic_String( bs.character, CHARACTERISTIC_WEAPONWEIGHTS, filename, 256 );
|
||||
errnum = botWeaponInfoManager.BotLoadWeaponWeights( bs.ws, filename );
|
||||
if( errnum != BLERR_NOERROR )
|
||||
{
|
||||
// trap_BotFreeGoalState(bs->gs);
|
||||
botWeaponInfoManager.BotFreeWeaponState( bs.ws );
|
||||
return;
|
||||
}
|
||||
|
||||
bs.client = entityNumber;
|
||||
bs.entitynum = entityNumber;
|
||||
bs.setupcount = 4;
|
||||
bs.entergame_time = Bot_Time();
|
||||
|
||||
hasSpawned = true;
|
||||
|
||||
bs.botinput.respawn = true;
|
||||
|
||||
stateThread.SetState("state_Respawn");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvmBot::Think
|
||||
===================
|
||||
*/
|
||||
void rvmBot::BotMoveToGoalOrigin(idVec3 goalOrigin)
|
||||
{
|
||||
bs.botinput.dir = (goalOrigin - firstPersonViewOrigin);
|
||||
idAngles desiredAngles = bs.botinput.dir.ToAngles();
|
||||
if( bs.enemy >= 0 )
|
||||
{
|
||||
idPlayer* enemy = gameLocal.entities[bs.enemy]->Cast<idPlayer>();
|
||||
if( enemy )
|
||||
{
|
||||
desiredAngles = (enemy->firstPersonViewOrigin - firstPersonViewOrigin).ToAngles();
|
||||
}
|
||||
}
|
||||
|
||||
bs.botinput.viewangles = desiredAngles;
|
||||
|
||||
bs.botinput.speed = pm_runspeed.GetInteger();
|
||||
|
||||
bs.botinput.dir.Normalize();
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvmBot::SpawnToPoint
|
||||
===================
|
||||
*/
|
||||
void rvmBot::SpawnToPoint( const idVec3& spawn_origin, const idAngles& spawn_angles )
|
||||
{
|
||||
idPlayer::SpawnToPoint( spawn_origin, spawn_angles );
|
||||
|
||||
if( common->IsServer() )
|
||||
{
|
||||
bs.ltg_time = 0;
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
}
|
||||
}
|
||||
/*
|
||||
===================
|
||||
rvmBot::StateThreadChanged
|
||||
===================
|
||||
*/
|
||||
void rvmBot::StateThreadChanged(void) {
|
||||
// Ensure if we are switching states, pop the last goal.
|
||||
bs.ltg_time = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvmBot::ServerThink
|
||||
===================
|
||||
*/
|
||||
void rvmBot::ServerThink( void )
|
||||
{
|
||||
bs.origin = GetPhysics()->GetOrigin();
|
||||
bs.eye = GetEyePosition();
|
||||
bs.thinktime = Bot_Time();
|
||||
bs.botinput.actionflags = 0;
|
||||
|
||||
BotUpdateInventory();
|
||||
|
||||
if( bot_pathdebug.IsModified() )
|
||||
{
|
||||
if( bot_pathdebug.GetBool() )
|
||||
{
|
||||
bs.currentGoal.origin = gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin();
|
||||
bs.currentGoal.framenum = gameLocal.framenum;
|
||||
}
|
||||
|
||||
bot_pathdebug.ClearModified();
|
||||
bot_pathdebug.SetBool( false );
|
||||
}
|
||||
|
||||
stateThread.Execute();
|
||||
|
||||
// If we are moving along a set of waypoints, let's move along.
|
||||
aasPath_t path;
|
||||
//int myArea = aas->PointAreaNum(GetOrigin());
|
||||
int goalArea = aas->PointAreaNum( bs.currentGoal.origin );
|
||||
idVec3 org = bs.origin;
|
||||
int curAreaNum = aas->AdjustPositionAndGetArea( org );
|
||||
|
||||
if( bot_debug.GetBool() )
|
||||
{
|
||||
if (bs.useRandomPosition)
|
||||
{
|
||||
aas->ShowWalkPath(GetOrigin(), goalArea, bs.random_move_position);
|
||||
}
|
||||
else
|
||||
{
|
||||
aas->ShowWalkPath(GetOrigin(), goalArea, bs.currentGoal.origin);
|
||||
}
|
||||
|
||||
aas->ShowArea( GetOrigin() );
|
||||
}
|
||||
|
||||
if (bs.useRandomPosition)
|
||||
{
|
||||
aas->WalkPathToGoal(path, curAreaNum, org, goalArea, bs.random_move_position, TFL_WALK | TFL_AIR);
|
||||
}
|
||||
else
|
||||
{
|
||||
aas->WalkPathToGoal(path, curAreaNum, org, goalArea, bs.currentGoal.origin, TFL_WALK | TFL_AIR);
|
||||
}
|
||||
|
||||
idVec3 moveGoal = path.moveGoal;
|
||||
BotMoveToGoalOrigin(path.moveGoal);
|
||||
|
||||
bs.viewangles = bs.botinput.viewangles;
|
||||
|
||||
bs.useRandomPosition = false;
|
||||
bs.attackerEntity = NULL; // Has to be consumed immedaitly.
|
||||
bs.botinput.weapon = bs.weaponnum;
|
||||
}
|
||||
|
||||
/*
|
||||
=======================
|
||||
rvmBot::Damage
|
||||
=======================
|
||||
*/
|
||||
void rvmBot::Damage( idEntity* inflictor, idEntity* attacker, const idVec3& dir, const char* damageDefName, const float damageScale, const int location )
|
||||
{
|
||||
idPlayer::Damage( inflictor, attacker, dir, damageDefName, damageScale, location );
|
||||
|
||||
idPlayer* player = attacker->Cast<idPlayer>();
|
||||
if (health <= 0)
|
||||
{
|
||||
if (player)
|
||||
{
|
||||
BotSendChatMessage(DEATH, player->netname );
|
||||
}
|
||||
}
|
||||
|
||||
if (attacker == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
//bs.attackerEntity = attacker;
|
||||
SetEnemy(player, attacker->GetOrigin());
|
||||
}
|
||||
|
||||
/*
|
||||
=======================
|
||||
rvmBot::InflictedDamageEvent
|
||||
=======================
|
||||
*/
|
||||
void rvmBot::InflictedDamageEvent(idEntity* target) {
|
||||
idPlayer* player = target->Cast<idPlayer>();
|
||||
|
||||
// Don't flood the chat with death and insults.
|
||||
if (!player->IsBot() && player->health <= 0)
|
||||
{
|
||||
BotSendChatMessage(KILL, player->netname);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=======================
|
||||
rvmBot::PresenceTypeBoundingBox
|
||||
=======================
|
||||
*/
|
||||
void rvmBot::PresenceTypeBoundingBox( int presencetype, idVec3& mins, idVec3& maxs )
|
||||
{
|
||||
int index;
|
||||
//bounding box size for each presence type
|
||||
//idVec3 boxmins[3] = { {0, 0, 0}, {-15, -15, -24}, {-15, -15, -24} };
|
||||
//idVec3 boxmaxs[3] = { {0, 0, 0}, { 15, 15, 32}, { 15, 15, 8} };
|
||||
|
||||
idVec3 boxmins[3];
|
||||
idVec3 boxmaxs[3];
|
||||
|
||||
boxmins[0] = idVec3( 0, 0, 0 );
|
||||
boxmins[1] = idVec3( -15, -15, -24 );
|
||||
boxmins[2] = idVec3( -15, -15, -24 );
|
||||
|
||||
boxmaxs[0] = idVec3( 0, 0, 0 );
|
||||
boxmaxs[1] = idVec3( 15, 15, 32 );
|
||||
boxmaxs[2] = idVec3( 15, 15, 8 );
|
||||
|
||||
|
||||
if( presencetype == PRESENCE_NORMAL )
|
||||
{
|
||||
index = 1;
|
||||
}
|
||||
else if( presencetype == PRESENCE_CROUCH )
|
||||
{
|
||||
index = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
//botimport.Print(PRT_FATAL, "AAS_PresenceTypeBoundingBox: unknown presence type\n");
|
||||
index = 2;
|
||||
}
|
||||
mins = boxmins[index];
|
||||
maxs = boxmaxs[index];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
rvmBot::Think
|
||||
===================
|
||||
*/
|
||||
void rvmBot::Think( void )
|
||||
{
|
||||
if( !hasSpawned )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( common->IsServer() )
|
||||
{
|
||||
ServerThink();
|
||||
|
||||
if( bot_debug.GetBool() )
|
||||
{
|
||||
idVec4 color;
|
||||
color = idVec4(1, 1, 1, 1);
|
||||
if (bs.enemy >= 0)
|
||||
color = idVec4(1, 0, 0, 1);
|
||||
|
||||
idBounds bounds = idBounds( idVec3( -10, -10, -10 ), idVec3( 10, 10, 10 ) );
|
||||
common->RW()->DebugBounds( color, bounds, GetOrigin() );
|
||||
|
||||
idMat3 axis = viewAngles.ToMat3();
|
||||
common->RW()->DrawTextA(stateThread.GetState()->state.c_str(), GetOrigin(), 1.0f, color, axis);
|
||||
}
|
||||
}
|
||||
|
||||
deltaViewAngles.Zero();
|
||||
|
||||
idPlayer::Think();
|
||||
}
|
||||
@@ -0,0 +1,920 @@
|
||||
// Bot.h
|
||||
//
|
||||
|
||||
class rvmBotAIBotActionBase;
|
||||
|
||||
// These need to match items.def
|
||||
#define INVENTORY_ARMOR 1
|
||||
#define INVENTORY_GAUNTLET 4
|
||||
#define INVENTORY_SHOTGUN 5
|
||||
#define INVENTORY_MACHINEGUN 6
|
||||
#define INVENTORY_GRENADELAUNCHER 7
|
||||
#define INVENTORY_ROCKETLAUNCHER 8
|
||||
#define INVENTORY_LIGHTNING 9
|
||||
#define INVENTORY_RAILGUN 10
|
||||
#define INVENTORY_PLASMAGUN 11
|
||||
#define INVENTORY_BFG10K 13
|
||||
#define INVENTORY_GRAPPLINGHOOK 14
|
||||
#define INVENTORY_NAILGUN 15
|
||||
#define INVENTORY_PROXLAUNCHER 16
|
||||
#define INVENTORY_CHAINGUN 17
|
||||
#define INVENTORY_SHELLS 18
|
||||
#define INVENTORY_BULLETS 19
|
||||
#define INVENTORY_GRENADES 20
|
||||
#define INVENTORY_CELLS 21
|
||||
#define INVENTORY_LIGHTNINGAMMO 22
|
||||
#define INVENTORY_ROCKETS 23
|
||||
#define INVENTORY_SLUGS 24
|
||||
#define INVENTORY_BFGAMMO 25
|
||||
#define INVENTORY_NAILS 26
|
||||
#define INVENTORY_MINES 27
|
||||
#define INVENTORY_BELT 28
|
||||
#define INVENTORY_HEALTH 29
|
||||
#define INVENTORY_TELEPORTER 30
|
||||
#define INVENTORY_MEDKIT 31
|
||||
#define INVENTORY_KAMIKAZE 32
|
||||
#define INVENTORY_PORTAL 33
|
||||
#define INVENTORY_INVULNERABILITY 34
|
||||
#define INVENTORY_QUAD 35
|
||||
#define INVENTORY_ENVIRONMENTSUIT 36
|
||||
#define INVENTORY_HASTE 37
|
||||
#define INVENTORY_INVISIBILITY 38
|
||||
#define INVENTORY_REGEN 39
|
||||
#define INVENTORY_FLIGHT 40
|
||||
#define INVENTORY_SCOUT 41
|
||||
#define INVENTORY_GUARD 42
|
||||
#define INVENTORY_DOUBLER 43
|
||||
#define INVENTORY_AMMOREGEN 44
|
||||
#define INVENTORY_REDFLAG 45
|
||||
#define INVENTORY_BLUEFLAG 46
|
||||
#define INVENTORY_NEUTRALFLAG 47
|
||||
#define INVENTORY_REDCUBE 48
|
||||
#define INVENTORY_BLUECUBE 49
|
||||
#define INVENTORY_DOUBLESHOTGUN 50
|
||||
|
||||
#define MODELINDEX_DEFAULT 0
|
||||
#define MODELINDEX_ARMORSHARD 1
|
||||
#define MODELINDEX_ARMORCOMBAT 2
|
||||
#define MODELINDEX_ARMORBODY 3
|
||||
#define MODELINDEX_HEALTHSMALL 4
|
||||
#define MODELINDEX_HEALTH 5
|
||||
#define MODELINDEX_HEALTHLARGE 6
|
||||
#define MODELINDEX_HEALTHMEGA 7
|
||||
#define MODELINDEX_GAUNTLET 8
|
||||
#define MODELINDEX_SHOTGUN 9
|
||||
#define MODELINDEX_MACHINEGUN 10
|
||||
#define MODELINDEX_GRENADELAUNCHER 11
|
||||
#define MODELINDEX_ROCKETLAUNCHER 12
|
||||
#define MODELINDEX_LIGHTNING 13
|
||||
#define MODELINDEX_RAILGUN 14
|
||||
#define MODELINDEX_PLASMAGUN 15
|
||||
#define MODELINDEX_BFG10K 16
|
||||
#define MODELINDEX_GRAPPLINGHOOK 17
|
||||
#define MODELINDEX_SHELLS 18
|
||||
#define MODELINDEX_BULLETS 19
|
||||
#define MODELINDEX_GRENADES 20
|
||||
#define MODELINDEX_CELLS 21
|
||||
#define MODELINDEX_LIGHTNINGAMMO 22
|
||||
#define MODELINDEX_ROCKETS 23
|
||||
#define MODELINDEX_SLUGS 24
|
||||
#define MODELINDEX_BFGAMMO 25
|
||||
#define MODELINDEX_TELEPORTER 26
|
||||
#define MODELINDEX_MEDKIT 27
|
||||
#define MODELINDEX_QUAD 28
|
||||
#define MODELINDEX_ENVIRONMENTSUIT 29
|
||||
#define MODELINDEX_HASTE 30
|
||||
#define MODELINDEX_INVISIBILITY 31
|
||||
#define MODELINDEX_REGEN 32
|
||||
#define MODELINDEX_FLIGHT 33
|
||||
#define MODELINDEX_REDFLAG 34
|
||||
#define MODELINDEX_BLUEFLAG 35
|
||||
#define MODELINDEX_KAMIKAZE 36
|
||||
#define MODELINDEX_PORTAL 37
|
||||
#define MODELINDEX_INVULNERABILITY 38
|
||||
#define MODELINDEX_NAILS 39
|
||||
#define MODELINDEX_MINES 40
|
||||
#define MODELINDEX_BELT 41
|
||||
#define MODELINDEX_SCOUT 42
|
||||
#define MODELINDEX_GUARD 43
|
||||
#define MODELINDEX_DOUBLER 44
|
||||
#define MODELINDEX_AMMOREGEN 45
|
||||
#define MODELINDEX_NEUTRALFLAG 46
|
||||
#define MODELINDEX_REDCUBE 47
|
||||
#define MODELINDEX_BLUECUBE 48
|
||||
#define MODELINDEX_NAILGUN 49
|
||||
#define MODELINDEX_PROXLAUNCHER 50
|
||||
#define MODELINDEX_CHAINGUN 51
|
||||
#define MODELINDEX_POINTABLUE 52
|
||||
#define MODELINDEX_POINTBBLUE 53
|
||||
#define MODELINDEX_POINTARED 54
|
||||
#define MODELINDEX_POINTBRED 55
|
||||
#define MODELINDEX_POINTAWHITE 56
|
||||
#define MODELINDEX_POINTBWHITE 57
|
||||
#define MODELINDEX_POINTWHITE 58
|
||||
#define MODELINDEX_POINTRED 59
|
||||
#define MODELINDEX_POINTBLUE 60
|
||||
#define WEAPONINDEX_GAUNTLET 1
|
||||
#define WEAPONINDEX_MACHINEGUN 2
|
||||
#define WEAPONINDEX_SHOTGUN 3
|
||||
#define WEAPONINDEX_GRENADE_LAUNCHER 4
|
||||
#define WEAPONINDEX_ROCKET_LAUNCHER 5
|
||||
#define WEAPONINDEX_LIGHTNING 6
|
||||
#define WEAPONINDEX_RAILGUN 7
|
||||
#define WEAPONINDEX_PLASMAGUN 8
|
||||
#define WEAPONINDEX_BFG 9
|
||||
#define WEAPONINDEX_GRAPPLING_HOOK 10
|
||||
#define WEAPONINDEX_NAILGUN 11
|
||||
#define WEAPONINDEX_PROXLAUNCHER 12
|
||||
#define WEAPONINDEX_CHAINGUN 13
|
||||
|
||||
//enemy stuff
|
||||
#define ENEMY_HORIZONTAL_DIST 200
|
||||
#define ENEMY_HEIGHT 201
|
||||
|
||||
#define MAX_AVOIDGOALS 256
|
||||
#define MAX_GOALSTACK 8
|
||||
|
||||
#define GFL_NONE 0
|
||||
#define GFL_ITEM 1
|
||||
#define GFL_ROAM 2
|
||||
#define GFL_DROPPED 4
|
||||
|
||||
#define BLERR_NOERROR 0 //no error
|
||||
#define BLERR_LIBRARYNOTSETUP 1 //library not setup
|
||||
#define BLERR_INVALIDENTITYNUMBER 2 //invalid entity number
|
||||
#define BLERR_NOAASFILE 3 //no AAS file available
|
||||
#define BLERR_CANNOTOPENAASFILE 4 //cannot open AAS file
|
||||
#define BLERR_WRONGAASFILEID 5 //incorrect AAS file id
|
||||
#define BLERR_WRONGAASFILEVERSION 6 //incorrect AAS file version
|
||||
#define BLERR_CANNOTREADAASLUMP 7 //cannot read AAS file lump
|
||||
#define BLERR_CANNOTLOADICHAT 8 //cannot load initial chats
|
||||
#define BLERR_CANNOTLOADITEMWEIGHTS 9 //cannot load item weights
|
||||
#define BLERR_CANNOTLOADITEMCONFIG 10 //cannot load item config
|
||||
#define BLERR_CANNOTLOADWEAPONWEIGHTS 11 //cannot load weapon weights
|
||||
#define BLERR_CANNOTLOADWEAPONCONFIG 12 //cannot load weapon config
|
||||
|
||||
#define WT_BALANCE 1
|
||||
#define MAX_WEIGHTS 128
|
||||
|
||||
//fuzzy seperator
|
||||
struct fuzzyseperator_t
|
||||
{
|
||||
fuzzyseperator_t()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
inUse = false;
|
||||
index = 0;
|
||||
value = 0;
|
||||
type = 0;
|
||||
weight = 0;
|
||||
minweight = 0.0f;
|
||||
maxweight = 0.0f;
|
||||
child = nullptr;
|
||||
next = nullptr;
|
||||
}
|
||||
|
||||
bool inUse;
|
||||
int index;
|
||||
int value;
|
||||
int type;
|
||||
float weight;
|
||||
float minweight;
|
||||
float maxweight;
|
||||
fuzzyseperator_t* child;
|
||||
fuzzyseperator_t* next;
|
||||
};
|
||||
|
||||
//fuzzy weight
|
||||
struct weight_t
|
||||
{
|
||||
weight_t()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
name.Clear();
|
||||
firstseperator = nullptr;
|
||||
}
|
||||
|
||||
idStr name;
|
||||
fuzzyseperator_t* firstseperator;
|
||||
};
|
||||
|
||||
//weight configuration
|
||||
struct weightconfig_t
|
||||
{
|
||||
weightconfig_t()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
inUse = false;
|
||||
numweights = 0;
|
||||
filename.Clear();
|
||||
|
||||
for( int i = 0; i < MAX_WEIGHTS; i++ )
|
||||
{
|
||||
weights[i].Reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool inUse;
|
||||
int numweights;
|
||||
weight_t weights[MAX_WEIGHTS];
|
||||
idStr filename;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
#define BOTFILESBASEFOLDER "botfiles"
|
||||
//debug line colors
|
||||
#define LINECOLOR_NONE -1
|
||||
#define LINECOLOR_RED 1//0xf2f2f0f0L
|
||||
#define LINECOLOR_GREEN 2//0xd0d1d2d3L
|
||||
#define LINECOLOR_BLUE 3//0xf3f3f1f1L
|
||||
#define LINECOLOR_YELLOW 4//0xdcdddedfL
|
||||
#define LINECOLOR_ORANGE 5//0xe0e1e2e3L
|
||||
|
||||
//Print types
|
||||
#define PRT_MESSAGE 1
|
||||
#define PRT_WARNING 2
|
||||
#define PRT_ERROR 3
|
||||
#define PRT_FATAL 4
|
||||
#define PRT_EXIT 5
|
||||
|
||||
//console message types
|
||||
#define CMS_NORMAL 0
|
||||
#define CMS_CHAT 1
|
||||
|
||||
//action flags
|
||||
#define ACTION_ATTACK 0x0000001
|
||||
#define ACTION_USE 0x0000002
|
||||
#define ACTION_RESPAWN 0x0000008
|
||||
#define ACTION_JUMP 0x0000010
|
||||
#define ACTION_MOVEUP 0x0000020
|
||||
#define ACTION_CROUCH 0x0000080
|
||||
#define ACTION_MOVEDOWN 0x0000100
|
||||
#define ACTION_MOVEFORWARD 0x0000200
|
||||
#define ACTION_MOVEBACK 0x0000800
|
||||
#define ACTION_MOVELEFT 0x0001000
|
||||
#define ACTION_MOVERIGHT 0x0002000
|
||||
#define ACTION_DELAYEDJUMP 0x0008000
|
||||
#define ACTION_TALK 0x0010000
|
||||
#define ACTION_GESTURE 0x0020000
|
||||
#define ACTION_WALK 0x0080000
|
||||
#define ACTION_AFFIRMATIVE 0x0100000
|
||||
#define ACTION_NEGATIVE 0x0200000
|
||||
#define ACTION_GETFLAG 0x0800000
|
||||
#define ACTION_GUARDBASE 0x1000000
|
||||
#define ACTION_PATROL 0x2000000
|
||||
#define ACTION_FOLLOWME 0x8000000
|
||||
|
||||
|
||||
//#define DEBUG
|
||||
#define CTF
|
||||
|
||||
#define MAX_ITEMS 256
|
||||
//bot flags
|
||||
#define BFL_STRAFERIGHT 1 //strafe to the right
|
||||
#define BFL_ATTACKED 2 //bot has attacked last ai frame
|
||||
#define BFL_ATTACKJUMPED 4 //bot jumped during attack last frame
|
||||
#define BFL_AIMATENEMY 8 //bot aimed at the enemy this frame
|
||||
#define BFL_AVOIDRIGHT 16 //avoid obstacles by going to the right
|
||||
#define BFL_IDEALVIEWSET 32 //bot has ideal view angles set
|
||||
#define BFL_FIGHTSUICIDAL 64 //bot is in a suicidal fight
|
||||
//long term goal types
|
||||
#define LTG_TEAMHELP 1 //help a team mate
|
||||
#define LTG_TEAMACCOMPANY 2 //accompany a team mate
|
||||
#define LTG_DEFENDKEYAREA 3 //defend a key area
|
||||
#define LTG_GETFLAG 4 //get the enemy flag
|
||||
#define LTG_RUSHBASE 5 //rush to the base
|
||||
#define LTG_RETURNFLAG 6 //return the flag
|
||||
#define LTG_CAMP 7 //camp somewhere
|
||||
#define LTG_CAMPORDER 8 //ordered to camp somewhere
|
||||
#define LTG_PATROL 9 //patrol
|
||||
#define LTG_GETITEM 10 //get an item
|
||||
#define LTG_KILL 11 //kill someone
|
||||
#define LTG_HARVEST 12 //harvest skulls
|
||||
#define LTG_ATTACKENEMYBASE 13 //attack the enemy base
|
||||
#define LTG_MAKELOVE_UNDER 14
|
||||
#define LTG_MAKELOVE_ONTOP 15
|
||||
//some goal dedication times
|
||||
#define TEAM_HELP_TIME 60 //1 minute teamplay help time
|
||||
#define TEAM_ACCOMPANY_TIME 600 //10 minutes teamplay accompany time
|
||||
#define TEAM_DEFENDKEYAREA_TIME 600 //10 minutes ctf defend base time
|
||||
#define TEAM_CAMP_TIME 600 //10 minutes camping time
|
||||
#define TEAM_PATROL_TIME 600 //10 minutes patrolling time
|
||||
#define TEAM_LEAD_TIME 600 //10 minutes taking the lead
|
||||
#define TEAM_GETITEM_TIME 60 //1 minute
|
||||
#define TEAM_KILL_SOMEONE 180 //3 minute to kill someone
|
||||
#define TEAM_ATTACKENEMYBASE_TIME 600 //10 minutes
|
||||
#define TEAM_HARVEST_TIME 120 //2 minutes
|
||||
#define CTF_GETFLAG_TIME 600 //10 minutes ctf get flag time
|
||||
#define CTF_RUSHBASE_TIME 120 //2 minutes ctf rush base time
|
||||
#define CTF_RETURNFLAG_TIME 180 //3 minutes to return the flag
|
||||
#define CTF_ROAM_TIME 60 //1 minute ctf roam time
|
||||
//patrol flags
|
||||
#define PATROL_LOOP 1
|
||||
#define PATROL_REVERSE 2
|
||||
#define PATROL_BACK 4
|
||||
//teamplay task preference
|
||||
#define TEAMTP_DEFENDER 1
|
||||
#define TEAMTP_ATTACKER 2
|
||||
//CTF strategy
|
||||
#define CTFS_AGRESSIVE 1
|
||||
//copied from the aas file header
|
||||
#define PRESENCE_NONE 1
|
||||
#define PRESENCE_NORMAL 2
|
||||
#define PRESENCE_CROUCH 4
|
||||
//
|
||||
#define MAX_PROXMINES 64
|
||||
|
||||
|
||||
#define MAX_CHARACTERISTICS 80
|
||||
|
||||
#define CT_INTEGER 1
|
||||
#define CT_FLOAT 2
|
||||
#define CT_STRING 3
|
||||
|
||||
#define DEFAULT_CHARACTER "bots/default_c.c"
|
||||
|
||||
#define MAX_AVOIDGOALS 256
|
||||
#define MAX_GOALSTACK 8
|
||||
|
||||
#define GFL_NONE 0
|
||||
#define GFL_ITEM 1
|
||||
#define GFL_ROAM 2
|
||||
#define GFL_DROPPED 4
|
||||
#define MAX_EPAIRKEY 128
|
||||
|
||||
//characteristic value
|
||||
struct cvalue
|
||||
{
|
||||
cvalue()
|
||||
{
|
||||
integer = 0;
|
||||
_float = 0.0f;
|
||||
string = "";
|
||||
}
|
||||
|
||||
int integer;
|
||||
float _float;
|
||||
idStr string;
|
||||
};
|
||||
|
||||
//a characteristic
|
||||
struct bot_characteristic_t
|
||||
{
|
||||
bot_characteristic_t()
|
||||
{
|
||||
type = 0;
|
||||
}
|
||||
|
||||
char type; //characteristic type
|
||||
cvalue value; //characteristic value
|
||||
};
|
||||
|
||||
//a bot character
|
||||
struct bot_character_t
|
||||
{
|
||||
bot_character_t()
|
||||
{
|
||||
filename = "";
|
||||
inUse = false;
|
||||
skill = 0.0f;
|
||||
}
|
||||
|
||||
idStr filename;
|
||||
bool inUse;
|
||||
float skill;
|
||||
bot_characteristic_t c[MAX_CHARACTERISTICS];
|
||||
};
|
||||
|
||||
//the bot input, will be converted to an usercmd_t
|
||||
//the bot input, will be converted to an usercmd_t
|
||||
struct bot_input_t
|
||||
{
|
||||
bot_input_t()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
thinktime = 0;
|
||||
dir.Zero();
|
||||
speed = 0;
|
||||
viewangles.Zero();
|
||||
actionflags = 0;
|
||||
weapon = 0;
|
||||
lastWeaponNum = 0;
|
||||
respawn = false;
|
||||
}
|
||||
|
||||
float thinktime; //time since last output (in seconds)
|
||||
idVec3 dir; //movement direction
|
||||
float speed; //speed in the range [0, 400]
|
||||
idAngles viewangles; //the view angles
|
||||
int actionflags; //one of the ACTION_? flags
|
||||
int weapon; //weapon to use
|
||||
int lastWeaponNum;
|
||||
bool respawn;
|
||||
};
|
||||
|
||||
#if 0
|
||||
//entity state
|
||||
typedef struct bot_entitystate_s
|
||||
{
|
||||
int type; // entity type
|
||||
int flags; // entity flags
|
||||
vec3_t origin; // origin of the entity
|
||||
vec3_t angles; // angles of the model
|
||||
vec3_t old_origin; // for lerping
|
||||
vec3_t mins; // bounding box minimums
|
||||
vec3_t maxs; // bounding box maximums
|
||||
int groundent; // ground entity
|
||||
int solid; // solid type
|
||||
int modelindex; // model used
|
||||
int modelindex2; // weapons, CTF flags, etc
|
||||
int frame; // model frame number
|
||||
int event; // impulse events -- muzzle flashes, footsteps, etc
|
||||
int eventParm; // even parameter
|
||||
int powerups; // bit flags
|
||||
int weapon; // determines weapon and flash model, etc
|
||||
int legsAnim; // mask off ANIM_TOGGLEBIT
|
||||
int torsoAnim; // mask off ANIM_TOGGLEBIT
|
||||
} bot_entitystate_t;
|
||||
|
||||
//check points
|
||||
typedef struct bot_waypoint_s
|
||||
{
|
||||
int inuse;
|
||||
char name[32];
|
||||
bot_goal_t goal;
|
||||
struct bot_waypoint_s* next, * prev;
|
||||
} bot_waypoint_t;
|
||||
|
||||
//bot settings
|
||||
typedef struct bot_settings_s
|
||||
{
|
||||
char characterfile[MAX_QPATH];
|
||||
float skill;
|
||||
char team[MAX_QPATH];
|
||||
} bot_settings_t;
|
||||
|
||||
#define MAX_ACTIVATESTACK 8
|
||||
#define MAX_ACTIVATEAREAS 32
|
||||
|
||||
typedef struct bot_activategoal_s
|
||||
{
|
||||
int inuse;
|
||||
bot_goal_t goal; //goal to activate (buttons etc.)
|
||||
float time; //time to activate something
|
||||
float start_time; //time starting to activate something
|
||||
float justused_time; //time the goal was used
|
||||
int shoot; //true if bot has to shoot to activate
|
||||
int weapon; //weapon to be used for activation
|
||||
vec3_t target; //target to shoot at to activate something
|
||||
vec3_t origin; //origin of the blocking entity to activate
|
||||
int areas[MAX_ACTIVATEAREAS]; //routing areas disabled by blocking entity
|
||||
int numareas; //number of disabled routing areas
|
||||
int areasdisabled; //true if the areas are disabled for the routing
|
||||
struct bot_activategoal_s* next; //next activate goal on stack
|
||||
} bot_activategoal_t;
|
||||
|
||||
//bot state
|
||||
typedef struct bot_state_s
|
||||
{
|
||||
int inuse; //true if this state is used by a bot client
|
||||
int botthink_residual; //residual for the bot thinks
|
||||
int client; //client number of the bot
|
||||
int entitynum; //entity number of the bot
|
||||
playerState_t cur_ps; //current player state
|
||||
int last_eFlags; //last ps flags
|
||||
usercmd_t lastucmd; //usercmd from last frame
|
||||
int entityeventTime[1024]; //last entity event time
|
||||
//
|
||||
bot_settings_t settings; //several bot settings
|
||||
int ( *ainode )( struct bot_state_s* bs ); //current AI node
|
||||
float thinktime; //time the bot thinks this frame
|
||||
vec3_t origin; //origin of the bot
|
||||
vec3_t velocity; //velocity of the bot
|
||||
int presencetype; //presence type of the bot
|
||||
vec3_t eye; //eye coordinates of the bot
|
||||
int areanum; //the number of the area the bot is in
|
||||
int inventory[MAX_ITEMS]; //string with items amounts the bot has
|
||||
int tfl; //the travel flags the bot uses
|
||||
int flags; //several flags
|
||||
int respawn_wait; //wait until respawned
|
||||
int lasthealth; //health value previous frame
|
||||
int lastkilledplayer; //last killed player
|
||||
int lastkilledby; //player that last killed this bot
|
||||
int botdeathtype; //the death type of the bot
|
||||
int enemydeathtype; //the death type of the enemy
|
||||
int botsuicide; //true when the bot suicides
|
||||
int enemysuicide; //true when the enemy of the bot suicides
|
||||
int setupcount; //true when the bot has just been setup
|
||||
int map_restart; //true when the map is being restarted
|
||||
int entergamechat; //true when the bot used an enter game chat
|
||||
int num_deaths; //number of time this bot died
|
||||
int num_kills; //number of kills of this bot
|
||||
int revenge_enemy; //the revenge enemy
|
||||
int revenge_kills; //number of kills the enemy made
|
||||
int lastframe_health; //health value the last frame
|
||||
int lasthitcount; //number of hits last frame
|
||||
int chatto; //chat to all or team
|
||||
float walker; //walker charactertic
|
||||
float ltime; //local bot time
|
||||
float entergame_time; //time the bot entered the game
|
||||
float ltg_time; //long term goal time
|
||||
float nbg_time; //nearby goal time
|
||||
float respawn_time; //time the bot takes to respawn
|
||||
float respawnchat_time; //time the bot started a chat during respawn
|
||||
float chase_time; //time the bot will chase the enemy
|
||||
float enemyvisible_time; //time the enemy was last visible
|
||||
float check_time; //time to check for nearby items
|
||||
float stand_time; //time the bot is standing still
|
||||
float lastchat_time; //time the bot last selected a chat
|
||||
float kamikaze_time; //time to check for kamikaze usage
|
||||
float invulnerability_time; //time to check for invulnerability usage
|
||||
float standfindenemy_time; //time to find enemy while standing
|
||||
float attackstrafe_time; //time the bot is strafing in one dir
|
||||
float attackcrouch_time; //time the bot will stop crouching
|
||||
float attackchase_time; //time the bot chases during actual attack
|
||||
float attackjump_time; //time the bot jumped during attack
|
||||
float enemysight_time; //time before reacting to enemy
|
||||
float enemydeath_time; //time the enemy died
|
||||
float enemyposition_time; //time the position and velocity of the enemy were stored
|
||||
float defendaway_time; //time away while defending
|
||||
float defendaway_range; //max travel time away from defend area
|
||||
float rushbaseaway_time; //time away from rushing to the base
|
||||
float attackaway_time; //time away from attacking the enemy base
|
||||
float harvestaway_time; //time away from harvesting
|
||||
float ctfroam_time; //time the bot is roaming in ctf
|
||||
float killedenemy_time; //time the bot killed the enemy
|
||||
float arrive_time; //time arrived (at companion)
|
||||
float lastair_time; //last time the bot had air
|
||||
float teleport_time; //last time the bot teleported
|
||||
float camp_time; //last time camped
|
||||
float camp_range; //camp range
|
||||
float weaponchange_time; //time the bot started changing weapons
|
||||
float firethrottlewait_time; //amount of time to wait
|
||||
float firethrottleshoot_time; //amount of time to shoot
|
||||
float notblocked_time; //last time the bot was not blocked
|
||||
float blockedbyavoidspot_time; //time blocked by an avoid spot
|
||||
float predictobstacles_time; //last time the bot predicted obstacles
|
||||
int predictobstacles_goalareanum; //last goal areanum the bot predicted obstacles for
|
||||
vec3_t aimtarget;
|
||||
vec3_t enemyvelocity; //enemy velocity 0.5 secs ago during battle
|
||||
vec3_t enemyorigin; //enemy origin 0.5 secs ago during battle
|
||||
//
|
||||
int kamikazebody; //kamikaze body
|
||||
int proxmines[MAX_PROXMINES];
|
||||
int numproxmines;
|
||||
//
|
||||
bot_character_t* character; //the bot character
|
||||
int ms; //move state of the bot
|
||||
int gs; //goal state of the bot
|
||||
int cs; //chat state of the bot
|
||||
int ws; //weapon state of the bot
|
||||
//
|
||||
int enemy; //enemy entity number
|
||||
int lastenemyareanum; //last reachability area the enemy was in
|
||||
vec3_t lastenemyorigin; //last origin of the enemy in the reachability area
|
||||
int weaponnum; //current weapon number
|
||||
vec3_t viewangles; //current view angles
|
||||
vec3_t ideal_viewangles; //ideal view angles
|
||||
vec3_t viewanglespeed;
|
||||
//
|
||||
int ltgtype; //long term goal type
|
||||
// team goals
|
||||
int teammate; //team mate involved in this team goal
|
||||
int decisionmaker; //player who decided to go for this goal
|
||||
int ordered; //true if ordered to do something
|
||||
float order_time; //time ordered to do something
|
||||
int owndecision_time; //time the bot made it's own decision
|
||||
bot_goal_t teamgoal; //the team goal
|
||||
bot_goal_t altroutegoal; //alternative route goal
|
||||
float reachedaltroutegoal_time; //time the bot reached the alt route goal
|
||||
float teammessage_time; //time to message team mates what the bot is doing
|
||||
float teamgoal_time; //time to stop helping team mate
|
||||
float teammatevisible_time; //last time the team mate was NOT visible
|
||||
int teamtaskpreference; //team task preference
|
||||
// last ordered team goal
|
||||
int lastgoal_decisionmaker;
|
||||
int lastgoal_ltgtype;
|
||||
int lastgoal_teammate;
|
||||
bot_goal_t lastgoal_teamgoal;
|
||||
// for leading team mates
|
||||
int lead_teammate; //team mate the bot is leading
|
||||
bot_goal_t lead_teamgoal; //team goal while leading
|
||||
float lead_time; //time leading someone
|
||||
float leadvisible_time; //last time the team mate was visible
|
||||
float leadmessage_time; //last time a messaged was sent to the team mate
|
||||
float leadbackup_time; //time backing up towards team mate
|
||||
//
|
||||
char teamleader[32]; //netname of the team leader
|
||||
float askteamleader_time; //time asked for team leader
|
||||
float becometeamleader_time; //time the bot will become the team leader
|
||||
float teamgiveorders_time; //time to give team orders
|
||||
float lastflagcapture_time; //last time a flag was captured
|
||||
int numteammates; //number of team mates
|
||||
int redflagstatus; //0 = at base, 1 = not at base
|
||||
int blueflagstatus; //0 = at base, 1 = not at base
|
||||
int neutralflagstatus; //0 = at base, 1 = our team has flag, 2 = enemy team has flag, 3 = enemy team dropped the flag
|
||||
int flagstatuschanged; //flag status changed
|
||||
int forceorders; //true if forced to give orders
|
||||
int flagcarrier; //team mate carrying the enemy flag
|
||||
int ctfstrategy; //ctf strategy
|
||||
char subteam[32]; //sub team name
|
||||
float formation_dist; //formation team mate intervening space
|
||||
char formation_teammate[16]; //netname of the team mate the bot uses for relative positioning
|
||||
float formation_angle; //angle relative to the formation team mate
|
||||
vec3_t formation_dir; //the direction the formation is moving in
|
||||
vec3_t formation_origin; //origin the bot uses for relative positioning
|
||||
bot_goal_t formation_goal; //formation goal
|
||||
|
||||
bot_activategoal_t* activatestack; //first activate goal on the stack
|
||||
bot_activategoal_t activategoalheap[MAX_ACTIVATESTACK]; //activate goal heap
|
||||
|
||||
bot_waypoint_t* checkpoints; //check points
|
||||
bot_waypoint_t* patrolpoints; //patrol points
|
||||
bot_waypoint_t* curpatrolpoint; //current patrol point the bot is going for
|
||||
int patrolflags; //patrol flags
|
||||
|
||||
// jmarshall
|
||||
bot_goal_t currentgoal;
|
||||
|
||||
vec3_t currentMoveGoal;
|
||||
vec3_t movement_waypoints[NAV_MAX_PATHSTEPS];
|
||||
int numMovementWaypoints;
|
||||
int currentWaypoint;
|
||||
|
||||
vec3_t last_origin;
|
||||
vec3_t very_short_term_origin;
|
||||
|
||||
int stuck_time;
|
||||
|
||||
vec3_t last_enemy_visible_position;
|
||||
vec3_t random_move_position;
|
||||
// jmarshall end
|
||||
|
||||
bot_input_t input;
|
||||
} bot_state_t;
|
||||
|
||||
void BotUpdateInput( bot_state_t* bs, int time, int elapsed_time );
|
||||
qboolean BotIsDead( bot_state_t* bs );
|
||||
|
||||
void AIEnter_Respawn( bot_state_t* bs, char* s );
|
||||
|
||||
extern float floattime;
|
||||
#define FloatTime() floattime
|
||||
|
||||
|
||||
float Characteristic_BFloat( bot_character_t* ch, int index, float min, float max );
|
||||
void Characteristic_String( bot_character_t* ch, int index, char* buf, int size );
|
||||
|
||||
bot_character_t* BotLoadCharacterFromFile( char* charfile, int skill );
|
||||
|
||||
void BotInitLevelItems( void );
|
||||
|
||||
void BotChooseWeapon( bot_state_t* bs );
|
||||
|
||||
inline float AAS_Time()
|
||||
{
|
||||
return floattime;
|
||||
}
|
||||
|
||||
unsigned short int BotTravelTime( vec3_t start, vec3_t end );
|
||||
#endif
|
||||
|
||||
#define MAX_BOT_INVENTORY 256
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NULLMOVEFLAG = -1,
|
||||
MOVE_PRONE,
|
||||
MOVE_CROUCH,
|
||||
MOVE_WALK,
|
||||
MOVE_RUN2,
|
||||
MOVE_SPRINT,
|
||||
MOVE_JUMP,
|
||||
} botMoveFlags_t;
|
||||
|
||||
//
|
||||
// rvmBotUtil
|
||||
//
|
||||
class rvmBotUtil
|
||||
{
|
||||
public:
|
||||
static float random()
|
||||
{
|
||||
return ( ( rand() & 0x7fff ) / ( ( float )0x7fff ) );
|
||||
}
|
||||
|
||||
static float crandom()
|
||||
{
|
||||
return ( 2.0 * ( random() - 0.5 ) );
|
||||
}
|
||||
};
|
||||
|
||||
#include "Bot_char.h"
|
||||
#include "Bot_weights.h"
|
||||
#include "Bot_weapons.h"
|
||||
#include "Bot_goal.h"
|
||||
|
||||
struct bot_state_t
|
||||
{
|
||||
bot_state_t()
|
||||
{
|
||||
character = NULL;
|
||||
gs = 0;
|
||||
ws = 0;
|
||||
Reset();
|
||||
}
|
||||
void Reset()
|
||||
{
|
||||
attackerEntity = NULL;
|
||||
client = 0;
|
||||
entitynum = 0;
|
||||
setupcount = 0;
|
||||
entergame_time = 0;
|
||||
weaponnum = 0;
|
||||
lasthealth = 0;
|
||||
ltg_time = 0;
|
||||
weaponchange_time = 0;
|
||||
enemy = 0;
|
||||
enemyvisible_time = 0;
|
||||
enemysuicide = 0;
|
||||
enemysight_time = 0;
|
||||
check_time = 0;
|
||||
nbg_time = 0;
|
||||
enemydeath_time = 0;
|
||||
teleport_time = 0;
|
||||
flags = 0;
|
||||
firethrottlewait_time = 0;
|
||||
attackchase_time = 0;
|
||||
attackcrouch_time = 0;
|
||||
attackstrafe_time = 0;
|
||||
attackjump_time = 0;
|
||||
firethrottleshoot_time = 0;
|
||||
chase_time = 0;
|
||||
thinktime = 0;
|
||||
useRandomPosition = false;
|
||||
aimtarget.Zero();
|
||||
lastenemyorigin.Zero();
|
||||
origin.Zero();
|
||||
enemyorigin.Zero();
|
||||
random_move_position.Zero();
|
||||
last_enemy_visible_position.Zero();
|
||||
viewangles.Zero();
|
||||
eye.Zero();
|
||||
memset( &inventory[0], 0, sizeof( inventory ) );
|
||||
}
|
||||
|
||||
bot_character_t* character;
|
||||
int gs;
|
||||
int ws;
|
||||
int enemy;
|
||||
int client;
|
||||
idEntity* attackerEntity;
|
||||
int lasthealth;
|
||||
int entitynum;
|
||||
int setupcount;
|
||||
int ltg_time;
|
||||
int flags;
|
||||
int weaponnum;
|
||||
bool useRandomPosition;
|
||||
float thinktime;
|
||||
float chase_time;
|
||||
float attackjump_time;
|
||||
float attackcrouch_time;
|
||||
float attackstrafe_time;
|
||||
float attackchase_time;
|
||||
float firethrottlewait_time;
|
||||
float firethrottleshoot_time;
|
||||
float nbg_time; //nearby goal time
|
||||
float entergame_time;
|
||||
float weaponchange_time;
|
||||
float check_time;
|
||||
float teleport_time;
|
||||
float enemyvisible_time; //time the enemy was last visible
|
||||
int enemysuicide; //true when the enemy of the bot suicides
|
||||
float enemysight_time; //time before reacting to enemy
|
||||
float enemydeath_time; //time the enemy died
|
||||
float aggressiveAttackTime;
|
||||
idVec3 origin;
|
||||
idVec3 aimtarget;
|
||||
idVec3 random_move_position;
|
||||
idVec3 last_enemy_visible_position;
|
||||
idAngles viewangles;
|
||||
idVec3 enemyorigin;
|
||||
idVec3 eye;
|
||||
idVec3 lastenemyorigin;
|
||||
int inventory[MAX_BOT_INVENTORY];
|
||||
bot_goal_t currentGoal;
|
||||
bot_input_t botinput;
|
||||
};
|
||||
|
||||
#include "Bot_chat.h"
|
||||
|
||||
#define Bot_Time() ((float)gameLocal.time / 1000.0f)
|
||||
|
||||
//
|
||||
// rvmBot
|
||||
//
|
||||
class rvmBot : public idPlayer
|
||||
{
|
||||
public:
|
||||
friend class rvmBotAI;
|
||||
|
||||
CLASS_PROTOTYPE( rvmBot );
|
||||
|
||||
rvmBot();
|
||||
~rvmBot();
|
||||
|
||||
void Spawn( void );
|
||||
virtual void Think( void ) override;
|
||||
virtual void SpawnToPoint( const idVec3& spawn_origin, const idAngles& spawn_angles ) override;
|
||||
virtual void Damage( idEntity* inflictor, idEntity* attacker, const idVec3& dir, const char* damageDefName, const float damageScale, const int location ) override;
|
||||
virtual void InflictedDamageEvent(idEntity* target) override;
|
||||
virtual void StateThreadChanged(void) override;
|
||||
|
||||
void SetEnemy( idPlayer* player, idVec3 origin );
|
||||
|
||||
void BotInputFrame( idUserCmdMgr& cmdMgr );
|
||||
void Bot_ResetUcmd( usercmd_t& ucmd );
|
||||
|
||||
static void PresenceTypeBoundingBox( int presencetype, idVec3& mins, idVec3& maxs );
|
||||
private:
|
||||
void BotSendChatMessage(botChat_t chat, const char *targetName);
|
||||
|
||||
void BotInputToUserCommand( bot_input_t* bi, usercmd_t* ucmd, int time );
|
||||
|
||||
void BotMoveToGoalOrigin( idVec3 goalOrigin );
|
||||
|
||||
void ServerThink( void );
|
||||
void BotUpdateInventory( void );
|
||||
|
||||
bool HasWeapon( int index )
|
||||
{
|
||||
return inventory.weapons & ( 1 << index );
|
||||
}
|
||||
private:
|
||||
bot_state_t bs;
|
||||
bool hasSpawned;
|
||||
|
||||
private:
|
||||
int weapon_machinegun;
|
||||
int weapon_shotgun;
|
||||
int weapon_plasmagun;
|
||||
int weapon_rocketlauncher;
|
||||
protected:
|
||||
bool BotIsDead(bot_state_t* bs);
|
||||
bool BotReachedGoal(bot_state_t* bs, bot_goal_t* goal);
|
||||
int BotGetItemLongTermGoal(bot_state_t* bs, int tfl, bot_goal_t* goal);
|
||||
void BotChooseWeapon(bot_state_t* bs);
|
||||
int BotFindEnemy(bot_state_t* bs, int curenemy);
|
||||
bool EntityIsDead(idEntity* entity);
|
||||
float BotEntityVisible(int viewer, idVec3 eye, idAngles viewangles, float fov, int ent);
|
||||
float BotEntityVisibleTest(int viewer, idVec3 eye, idAngles viewangles, float fov, int ent, bool allowHeightTest);
|
||||
void BotUpdateBattleInventory(bot_state_t* bs, int enemy);
|
||||
float BotAggression(bot_state_t* bs);
|
||||
int BotWantsToRetreat(bot_state_t* bs);
|
||||
void BotBattleUseItems(bot_state_t* bs);
|
||||
void BotAimAtEnemy(bot_state_t* bs);
|
||||
void BotCheckAttack(bot_state_t* bs);
|
||||
bool BotWantsToChase(bot_state_t* bs);
|
||||
int BotNearbyGoal(bot_state_t* bs, int tfl, bot_goal_t* ltg, float range);
|
||||
void BotGetRandomPointNearPosition(idVec3 point, idVec3& randomPoint, float radius);
|
||||
int BotMoveInRandomDirection(bot_state_t* bs);
|
||||
void BotMoveToGoal(bot_state_t* bs, bot_goal_t* goal);
|
||||
|
||||
void MoveToCoverPoint(void);
|
||||
|
||||
static int WP_MACHINEGUN;
|
||||
static int WP_SHOTGUN;
|
||||
static int WP_PLASMAGUN;
|
||||
static int WP_ROCKET_LAUNCHER;
|
||||
private:
|
||||
stateResult_t state_Chase(stateParms_t* parms);
|
||||
stateResult_t state_BattleFight(stateParms_t* parms);
|
||||
stateResult_t state_BattleNBG(stateParms_t* parms);
|
||||
stateResult_t state_Retreat(stateParms_t* parms);
|
||||
stateResult_t state_Respawn(stateParms_t* parms);
|
||||
stateResult_t state_SeekNBG(stateParms_t* parms);
|
||||
stateResult_t state_SeekLTG(stateParms_t* parms);
|
||||
stateResult_t state_Attacked(stateParms_t* parms);
|
||||
private:
|
||||
idAAS* aas;
|
||||
};
|
||||
|
||||
extern idCVar bot_skill;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
// BotAI_Battle_Attacked.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
/*
|
||||
==================
|
||||
rvmBot::state_Attacked
|
||||
==================
|
||||
*/
|
||||
stateResult_t rvmBot::state_Attacked(stateParms_t* parms) {
|
||||
// respawn if dead.
|
||||
if (BotIsDead(&bs))
|
||||
{
|
||||
stateThread.SetState("state_Respawn");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
if (gameLocal.SysScriptTime() > bs.aggressiveAttackTime || bs.weaponnum == 0) {
|
||||
stateThread.SetState("state_Retreat");
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
// Ensure the target is a player.
|
||||
idPlayer *entinfo = gameLocal.entities[bs.enemy]->Cast<idPlayer>();
|
||||
if (!entinfo)
|
||||
{
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
// If our enemy is dead, search for another LTG.
|
||||
if (EntityIsDead(entinfo))
|
||||
{
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
bs.currentGoal.origin = bs.lastenemyorigin;
|
||||
|
||||
//aim at the enemy
|
||||
BotAimAtEnemy(&bs);
|
||||
|
||||
//attack the enemy if possible
|
||||
BotCheckAttack(&bs);
|
||||
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
// BotAI_Battle_Chase.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvmBot::state_Chase
|
||||
=====================
|
||||
*/
|
||||
stateResult_t rvmBot::state_Chase(stateParms_t* parms)
|
||||
{
|
||||
bot_goal_t goal;
|
||||
idVec3 target, dir;
|
||||
//bot_moveresult_t moveresult;
|
||||
float range;
|
||||
|
||||
//if (BotIsObserver(bs)) {
|
||||
// AIEnter_Observer(bs, "battle chase: observer");
|
||||
// return qfalse;
|
||||
//}
|
||||
//
|
||||
////if in the intermission
|
||||
//if (BotIntermission(bs)) {
|
||||
// AIEnter_Intermission(bs, "battle chase: intermission");
|
||||
// return qfalse;
|
||||
//}
|
||||
|
||||
// respawn if dead.
|
||||
if( BotIsDead( &bs ) )
|
||||
{
|
||||
stateThread.SetState("state_Respawn");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//if no enemy
|
||||
if( bs.enemy < 0 )
|
||||
{
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//if the enemy is visible
|
||||
if( BotEntityVisibleTest( bs.entitynum, bs.eye, bs.viewangles, 360, bs.enemy, false ) )
|
||||
{
|
||||
//AIEnter_Battle_Fight(bs, "battle chase");
|
||||
stateThread.SetState("state_BattleFight");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//if there is another enemy
|
||||
if( BotFindEnemy( &bs, -1 ) )
|
||||
{
|
||||
//AIEnter_Battle_Fight(bs, "battle chase: better enemy");
|
||||
//stateThread.SetState("state_BattleFight");
|
||||
stateThread.SetState("state_BattleFight");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
////there is no last enemy area
|
||||
//if (!bs.lastenemyareanum) {
|
||||
// AIEnter_Seek_LTG(bs, "battle chase: no enemy area");
|
||||
// return qfalse;
|
||||
//}
|
||||
// jmarshall
|
||||
//
|
||||
//bs.tfl = TFL_DEFAULT;
|
||||
//if (bot_grapple.integer) bs.tfl |= TFL_GRAPPLEHOOK;
|
||||
////if in lava or slime the bot should be able to get out
|
||||
//if (BotInLavaOrSlime(bs)) bs.tfl |= TFL_LAVA | TFL_SLIME;
|
||||
////
|
||||
//if (BotCanAndWantsToRocketJump(bs)) {
|
||||
// bs.tfl |= TFL_ROCKETJUMP;
|
||||
//}
|
||||
//map specific code
|
||||
//BotMapScripts(bs);
|
||||
// jmarshall end
|
||||
|
||||
//create the chase goal
|
||||
goal.entitynum = bs.enemy;
|
||||
// goal.areanum = bs.lastenemyareanum;
|
||||
VectorCopy( bs.lastenemyorigin, goal.origin );
|
||||
|
||||
goal.mins = idMath::CreateVector( -8, -8, -8 );
|
||||
goal.maxs = idMath::CreateVector( 8, 8, 8 );
|
||||
|
||||
// jmarshall - goal origin is last visible position
|
||||
{
|
||||
// Do a trace between the last_enemy_visible_position and the goal origin,
|
||||
// if for some reason we don't have line of sight to it, switch to LTG.
|
||||
trace_t trace;
|
||||
|
||||
gameLocal.Trace( trace, bs.last_enemy_visible_position, gameLocal.entities[bs.client]->GetOrigin(), CONTENTS_SOLID, 0 );
|
||||
|
||||
if( trace.fraction <= 0.9f )
|
||||
{
|
||||
//AIEnter_Seek_LTG(bs, "can't see last enemy position");
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
}
|
||||
VectorCopy( bs.last_enemy_visible_position, goal.origin );
|
||||
// jmarshall end
|
||||
|
||||
//if the last seen enemy spot is reached the enemy could not be found
|
||||
if( botGoalManager.BotTouchingGoal( bs.origin, &goal ) )
|
||||
{
|
||||
bs.chase_time = 0;
|
||||
}
|
||||
|
||||
//if there's no chase time left
|
||||
if( !bs.chase_time || bs.chase_time < Bot_Time() - 10 )
|
||||
{
|
||||
//AIEnter_Seek_LTG(bs, "battle chase: time out");
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
//check for nearby goals periodicly
|
||||
if( bs.check_time < Bot_Time() )
|
||||
{
|
||||
bs.check_time = Bot_Time() + 1;
|
||||
range = 150;
|
||||
//
|
||||
if( BotNearbyGoal( &bs, 0, &goal, range ) )
|
||||
{
|
||||
//the bot gets 5 seconds to pick up the nearby goal item
|
||||
bs.nbg_time = Bot_Time() + 0.1 * range + 1;
|
||||
//BotResetLastAvoidReach(bs.ms);
|
||||
//AIEnter_Battle_NBG(bs, "battle chase: nbg");
|
||||
stateThread.SetState("state_BattleNBG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
}
|
||||
|
||||
BotUpdateBattleInventory( &bs, bs.enemy );
|
||||
|
||||
////initialize the movement state
|
||||
//BotSetupForMovement(bs);
|
||||
|
||||
//move towards the goal
|
||||
//trap_BotMoveToGoal(&moveresult, bs.ms, &goal, bs.tfl);
|
||||
|
||||
if( idMath::FRandRange( 0.0f, 4.0f ) <= 2.0f )
|
||||
{
|
||||
BotMoveToGoal( &bs, &goal );
|
||||
}
|
||||
else
|
||||
{
|
||||
BotMoveInRandomDirection( &bs );
|
||||
}
|
||||
|
||||
|
||||
//if the movement failed
|
||||
//if (moveresult.failure) {
|
||||
// //reset the avoid reach, otherwise bot is stuck in current area
|
||||
// trap_BotResetAvoidReach(bs.ms);
|
||||
// //BotAI_Print(PRT_MESSAGE, "movement failure %d\n", moveresult.traveltype);
|
||||
// bs.ltg_time = 0;
|
||||
//}
|
||||
////
|
||||
//BotAIBlocked(bs, &moveresult, qfalse);
|
||||
//
|
||||
//if (moveresult.flags & (MOVERESULT_MOVEMENTVIEWSET | MOVERESULT_MOVEMENTVIEW | MOVERESULT_SWIMVIEW)) {
|
||||
// VectorCopy(moveresult.ideal_viewangles, bs.ideal_viewangles);
|
||||
//}
|
||||
|
||||
if( !( bs.flags & BFL_IDEALVIEWSET ) )
|
||||
{
|
||||
BotAimAtEnemy( &bs );
|
||||
// jmarshall
|
||||
//if (bs.chase_time > FloatTime() - 2) {
|
||||
// BotAimAtEnemy(bs);
|
||||
//}
|
||||
//else {
|
||||
// if (BotMovementViewTarget(bs.ms, &goal, bs.tfl, 300, target)) {
|
||||
// VectorSubtract(target, bs.origin, dir);
|
||||
// vectoangles(dir, bs.viewangles);
|
||||
// }
|
||||
// //else {
|
||||
// // vectoangles(moveresult.movedir, bs.ideal_viewangles);
|
||||
// //}
|
||||
//}
|
||||
// jmarshall end
|
||||
// bs.ideal_viewangles[2] *= 0.5; // jmarshall <-- view angles!
|
||||
}
|
||||
|
||||
if (BotEntityVisible(bs.entitynum, bs.eye, bs.viewangles, 360, bs.enemy))
|
||||
{
|
||||
//attack the enemy if possible
|
||||
BotCheckAttack(&bs);
|
||||
}
|
||||
|
||||
//if the weapon is used for the bot movement
|
||||
//if (moveresult.flags & MOVERESULT_MOVEMENTWEAPON) bs.weaponnum = moveresult.weapon;
|
||||
//if the bot is in the area the enemy was last seen in
|
||||
//if (bs.areanum == bs.lastenemyareanum) bs.chase_time = 0;
|
||||
//if the bot wants to retreat (the bot could have been damage during the chase)
|
||||
if( BotWantsToRetreat( &bs ) )
|
||||
{
|
||||
//AIEnter_Battle_Retreat(bs, "battle chase: wants to retreat");
|
||||
stateThread.SetState("state_Retreat");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
// BotAI_Battle_Fight.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvmBot::state_BattleFight
|
||||
=====================
|
||||
*/
|
||||
stateResult_t rvmBot::state_BattleFight(stateParms_t* parms)
|
||||
{
|
||||
int areanum;
|
||||
idVec3 target;
|
||||
idPlayer* entinfo;
|
||||
|
||||
// respawn if dead.
|
||||
if( BotIsDead( &bs ) )
|
||||
{
|
||||
stateThread.SetState("state_Respawn");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//if there is another better enemy
|
||||
if( BotFindEnemy( &bs, bs.enemy ) )
|
||||
{
|
||||
common->DPrintf( "found new better enemy\n" );
|
||||
}
|
||||
|
||||
//if no enemy
|
||||
if( bs.enemy < 0 )
|
||||
{
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//BotEntityInfo(bs.enemy, &entinfo);
|
||||
entinfo = gameLocal.entities[bs.enemy]->Cast<idPlayer>();// &g_entities[bs.enemy];
|
||||
|
||||
//if the enemy is dead
|
||||
if( bs.enemydeath_time )
|
||||
{
|
||||
if( bs.enemydeath_time < Bot_Time() - 1.0 )
|
||||
{
|
||||
bs.enemydeath_time = 0;
|
||||
if( bs.enemysuicide )
|
||||
{
|
||||
// jmarshall - bot chat
|
||||
//BotChat_EnemySuicide(bs);
|
||||
// jmarshall end
|
||||
}
|
||||
// jmarshall - bot chat stand
|
||||
// if (bs.lastkilledplayer == bs.enemy && BotChat_Kill(bs)) {
|
||||
// bs.stand_time = FloatTime() + BotChatTime(bs);
|
||||
// AIEnter_Stand(bs, "battle fight: enemy dead");
|
||||
// }
|
||||
// else {
|
||||
bs.ltg_time = 0;
|
||||
//AIEnter_Seek_LTG(bs, "battle fight: enemy dead");
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
// }
|
||||
// jmarshall end
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( EntityIsDead( entinfo ) )
|
||||
{
|
||||
bs.enemydeath_time = Bot_Time();
|
||||
}
|
||||
}
|
||||
// jmarshall - isinvisible
|
||||
//if the enemy is invisible and not shooting the bot looses track easily
|
||||
//if (entinfo->IsInvisible() && !entinfo->IsShooting()) {
|
||||
// if (rvmBotUtil::random() < 0.2) {
|
||||
// stateThread.SetState("state_SeekLTG");
|
||||
// return;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
target = entinfo->GetOrigin();
|
||||
|
||||
//update the reachability area and origin if possible
|
||||
//areanum = BotPointAreaNum(target);
|
||||
//if (areanum && trap_AAS_AreaReachability(areanum)) {
|
||||
// VectorCopy(target, bs.lastenemyorigin);
|
||||
// bs.lastenemyareanum = areanum;
|
||||
//}
|
||||
// bs.lastenemyareanum = areanum;
|
||||
|
||||
//update the attack inventory values
|
||||
BotUpdateBattleInventory( &bs, bs.enemy );
|
||||
|
||||
//if the bot's health decreased
|
||||
// jmarshall - bot chat
|
||||
//if (bs.lastframe_health > bs.inventory[INVENTORY_HEALTH]) {
|
||||
// if (BotChat_HitNoDeath(bs)) {
|
||||
// bs.stand_time = FloatTime() + BotChatTime(bs);
|
||||
// AIEnter_Stand(bs, "battle fight: chat health decreased");
|
||||
// return qfalse;
|
||||
// }
|
||||
//}
|
||||
|
||||
//if the bot hit someone
|
||||
//if (bs.cur_ps.persistant[PERS_HITS] > bs.lasthitcount) {
|
||||
// if (BotChat_HitNoKill(bs)) {
|
||||
// bs.stand_time = FloatTime() + BotChatTime(bs);
|
||||
// AIEnter_Stand(bs, "battle fight: chat hit someone");
|
||||
// return qfalse;
|
||||
// }
|
||||
//}
|
||||
// jmarshall end
|
||||
|
||||
//if the enemy is not visible
|
||||
if( !BotEntityVisible( bs.entitynum, bs.eye, bs.viewangles, 360, bs.enemy ) )
|
||||
{
|
||||
if( BotWantsToChase( &bs ) )
|
||||
{
|
||||
//AIEnter_Battle_Chase(bs, "battle fight: enemy out of sight");
|
||||
stateThread.SetState("state_Chase");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
//AIEnter_Seek_LTG(bs, "battle fight: enemy out of sight");
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
}
|
||||
//use holdable items
|
||||
BotBattleUseItems( &bs );
|
||||
//
|
||||
//bs.tfl = TFL_DEFAULT;
|
||||
//if (bot_grapple.integer) bs.tfl |= TFL_GRAPPLEHOOK;
|
||||
////if in lava or slime the bot should be able to get out
|
||||
//if (BotInLavaOrSlime(bs)) bs.tfl |= TFL_LAVA | TFL_SLIME;
|
||||
////
|
||||
//if (BotCanAndWantsToRocketJump(bs)) {
|
||||
// bs.tfl |= TFL_ROCKETJUMP;
|
||||
//}
|
||||
//choose the best weapon to fight with
|
||||
BotChooseWeapon( &bs );
|
||||
|
||||
// Move randomly around our AAS area.
|
||||
BotMoveInRandomDirection(&bs);
|
||||
|
||||
//aim at the enemy
|
||||
BotAimAtEnemy( &bs );
|
||||
|
||||
//attack the enemy if possible
|
||||
BotCheckAttack( &bs );
|
||||
|
||||
//if the bot wants to retreat
|
||||
if( !( bs.flags & BFL_FIGHTSUICIDAL ) )
|
||||
{
|
||||
if( BotWantsToRetreat( &bs ) )
|
||||
{
|
||||
//AIEnter_Battle_Retreat(bs, "battle fight: wants to retreat");
|
||||
stateThread.SetState("state_Retreat");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
}
|
||||
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
// BotAI_Battle_NBG.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvmBot::state_BattleNBG
|
||||
=====================
|
||||
*/
|
||||
stateResult_t rvmBot::state_BattleNBG(stateParms_t* parms)
|
||||
{
|
||||
int areanum;
|
||||
bot_goal_t goal;
|
||||
//aas_entityinfo_t entinfo;
|
||||
idEntity* entinfo;
|
||||
//bot_moveresult_t moveresult;
|
||||
float attack_skill;
|
||||
idVec3 target, dir;
|
||||
|
||||
//if (BotIsObserver(bs)) {
|
||||
// AIEnter_Observer(bs, "battle nbg: observer");
|
||||
// return qfalse;
|
||||
//}
|
||||
////if in the intermission
|
||||
//if (BotIntermission(bs)) {
|
||||
// AIEnter_Intermission(bs, "battle nbg: intermission");
|
||||
// return qfalse;
|
||||
//}
|
||||
|
||||
// respawn if dead.
|
||||
if( BotIsDead( &bs ) )
|
||||
{
|
||||
stateThread.SetState("state_Respawn");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
// if no enemy.
|
||||
if( bs.enemy < 0 )
|
||||
{
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//BotEntityInfo(bs.enemy, &entinfo);
|
||||
entinfo = gameLocal.entities[bs.enemy]->Cast<idPlayer>();
|
||||
if( entinfo->health <= 0 )
|
||||
{
|
||||
//AIEnter_Seek_NBG(bs, "battle nbg: enemy dead");
|
||||
stateThread.SetState("state_SeekNBG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//bs.tfl = TFL_DEFAULT;
|
||||
//if (bot_grapple.integer) bs.tfl |= TFL_GRAPPLEHOOK;
|
||||
////if in lava or slime the bot should be able to get out
|
||||
//if (BotInLavaOrSlime(bs)) bs.tfl |= TFL_LAVA | TFL_SLIME;
|
||||
////
|
||||
//if (BotCanAndWantsToRocketJump(bs)) {
|
||||
// bs.tfl |= TFL_ROCKETJUMP;
|
||||
//}
|
||||
////map specific code
|
||||
//BotMapScripts(bs);
|
||||
|
||||
//update the last time the enemy was visible
|
||||
if( BotEntityVisible( bs.entitynum, bs.eye, bs.viewangles, 360, bs.enemy ) )
|
||||
{
|
||||
bs.enemyvisible_time = Bot_Time();
|
||||
//VectorCopy(entinfo->GetOrigin(), target);
|
||||
target = entinfo->GetOrigin();
|
||||
// if not a player enemy
|
||||
if( bs.enemy >= MAX_CLIENTS )
|
||||
{
|
||||
#ifdef MISSIONPACK
|
||||
// if attacking an obelisk
|
||||
if( bs.enemy == redobelisk.entitynum ||
|
||||
bs.enemy == blueobelisk.entitynum )
|
||||
{
|
||||
target[2] += 16;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
//update the reachability area and origin if possible
|
||||
//areanum = BotPointAreaNum(target);
|
||||
//if (areanum && trap_AAS_AreaReachability(areanum)) {
|
||||
VectorCopy( target, bs.lastenemyorigin );
|
||||
// bs.lastenemyareanum = areanum;
|
||||
//}
|
||||
}
|
||||
|
||||
//if the bot has no goal or touches the current goal
|
||||
if( !botGoalManager.BotGetTopGoal( bs.gs, &goal ) )
|
||||
{
|
||||
bs.nbg_time = 0;
|
||||
}
|
||||
else if( BotReachedGoal( &bs, &goal ) )
|
||||
{
|
||||
bs.nbg_time = 0;
|
||||
}
|
||||
//
|
||||
if( bs.nbg_time < Bot_Time() )
|
||||
{
|
||||
//pop the current goal from the stack
|
||||
botGoalManager.BotPopGoal( bs.gs );
|
||||
//if the bot still has a goal
|
||||
if( botGoalManager.BotGetTopGoal( bs.gs, &goal ) )
|
||||
{
|
||||
//AIEnter_Battle_Retreat(bs, "battle nbg: time out");
|
||||
stateThread.SetState("state_Retreat");
|
||||
}
|
||||
else
|
||||
{
|
||||
//AIEnter_Battle_Fight(bs, "battle nbg: time out");
|
||||
stateThread.SetState("state_BattleFight");
|
||||
}
|
||||
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//move towards the goal
|
||||
BotMoveToGoal( &bs, &goal );
|
||||
|
||||
//initialize the movement state
|
||||
//BotSetupForMovement(bs);
|
||||
////move towards the goal
|
||||
//trap_BotMoveToGoal(&moveresult, bs.ms, &goal, bs.tfl);
|
||||
////if the movement failed
|
||||
//if (moveresult.failure) {
|
||||
// //reset the avoid reach, otherwise bot is stuck in current area
|
||||
// trap_BotResetAvoidReach(bs.ms);
|
||||
// //BotAI_Print(PRT_MESSAGE, "movement failure %d\n", moveresult.traveltype);
|
||||
// bs.nbg_time = 0;
|
||||
//}
|
||||
////
|
||||
//BotAIBlocked(bs, &moveresult, qfalse);
|
||||
|
||||
//update the attack inventory values
|
||||
BotUpdateBattleInventory( &bs, bs.enemy );
|
||||
|
||||
//choose the best weapon to fight with
|
||||
BotChooseWeapon( &bs );
|
||||
|
||||
//if the view is fixed for the movement
|
||||
//if (moveresult.flags & (MOVERESULT_MOVEMENTVIEW | MOVERESULT_SWIMVIEW)) {
|
||||
// VectorCopy(moveresult.ideal_viewangles, bs.ideal_viewangles);
|
||||
//}
|
||||
//else if (!(moveresult.flags & MOVERESULT_MOVEMENTVIEWSET)
|
||||
// && !(bs.flags & BFL_IDEALVIEWSET)) {
|
||||
// attack_skill = trap_Characteristic_BFloat(bs.character, CHARACTERISTIC_ATTACK_SKILL, 0, 1);
|
||||
// //if the bot is skilled anough and the enemy is visible
|
||||
// if (attack_skill > 0.3) {
|
||||
// //&& BotEntityVisible(bs.entitynum, bs.eye, bs.viewangles, 360, bs.enemy)
|
||||
// BotAimAtEnemy(bs);
|
||||
// }
|
||||
// else {
|
||||
// if (trap_BotMovementViewTarget(bs.ms, &goal, bs.tfl, 300, target)) {
|
||||
// VectorSubtract(target, bs.origin, dir);
|
||||
// vectoangles(dir, bs.ideal_viewangles);
|
||||
// }
|
||||
// else {
|
||||
// vectoangles(moveresult.movedir, bs.ideal_viewangles);
|
||||
// }
|
||||
// bs.ideal_viewangles[2] *= 0.5;
|
||||
// }
|
||||
//}
|
||||
//if (attack_skill > 0.3) {
|
||||
//&& BotEntityVisible(bs.entitynum, bs.eye, bs.viewangles, 360, bs.enemy)
|
||||
BotAimAtEnemy( &bs );
|
||||
//}
|
||||
|
||||
//if the weapon is used for the bot movement
|
||||
//if (moveresult.flags & MOVERESULT_MOVEMENTWEAPON) bs.weaponnum = moveresult.weapon;
|
||||
//attack the enemy if possible
|
||||
BotCheckAttack( &bs );
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
// BotAI_Battle_Retreat.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvmBot::state_Retreat
|
||||
=====================
|
||||
*/
|
||||
stateResult_t rvmBot::state_Retreat(stateParms_t* parms)
|
||||
{
|
||||
bot_goal_t goal;
|
||||
idPlayer* entinfo;
|
||||
rvmBot* owner;
|
||||
idVec3 target, dir;
|
||||
float attack_skill, range;
|
||||
|
||||
// respawn if dead.
|
||||
if( BotIsDead( &bs ) )
|
||||
{
|
||||
stateThread.SetState("state_Respawn");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
// if no enemy.
|
||||
if( bs.enemy < 0 )
|
||||
{
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
// Ensure the target is a player.
|
||||
entinfo = gameLocal.entities[bs.enemy]->Cast<idPlayer>();
|
||||
if( !entinfo )
|
||||
{
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
owner = gameLocal.entities[bs.entitynum]->Cast<rvmBot>();
|
||||
|
||||
// If our enemy is dead, search for another LTG.
|
||||
if( EntityIsDead( entinfo ) )
|
||||
{
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//if there is another better enemy
|
||||
if( BotFindEnemy( &bs, bs.enemy ) )
|
||||
{
|
||||
common->DPrintf( "found new better enemy\n" );
|
||||
}
|
||||
|
||||
//update the attack inventory values
|
||||
BotUpdateBattleInventory( &bs, bs.enemy );
|
||||
|
||||
//if the bot doesn't want to retreat anymore... probably picked up some nice items
|
||||
if( BotWantsToChase( &bs ) )
|
||||
{
|
||||
//empty the goal stack, when chasing, only the enemy is the goal
|
||||
botGoalManager.BotEmptyGoalStack( bs.gs );
|
||||
|
||||
//go chase the enemy
|
||||
//AIEnter_Battle_Chase(bs, "battle retreat: wants to chase");
|
||||
stateThread.SetState("state_Chase");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//update the last time the enemy was visible
|
||||
if( BotEntityVisible( bs.entitynum, bs.eye, bs.viewangles, 360, bs.enemy ) )
|
||||
{
|
||||
bs.enemyvisible_time = Bot_Time();
|
||||
target = entinfo->GetOrigin();
|
||||
bs.lastenemyorigin = target;
|
||||
}
|
||||
|
||||
//if the enemy is NOT visible for 4 seconds
|
||||
if( bs.enemyvisible_time < Bot_Time() - 4 )
|
||||
{
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
//else if the enemy is NOT visible
|
||||
else if( bs.enemyvisible_time < Bot_Time() )
|
||||
{
|
||||
//if there is another enemy
|
||||
if( BotFindEnemy( &bs, -1 ) )
|
||||
{
|
||||
//AIEnter_Battle_Fight(bs, "battle retreat: another enemy");
|
||||
stateThread.SetState("state_BattleFight");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
}
|
||||
|
||||
//use holdable items
|
||||
BotBattleUseItems( &bs );
|
||||
|
||||
//get the current long term goal while retreating
|
||||
if( !BotGetItemLongTermGoal( &bs, 0, &bs.currentGoal ) )
|
||||
{
|
||||
//AIEnter_Battle_SuicidalFight(bs, "battle retreat: no way out");
|
||||
stateThread.SetState("state_BattleFight");
|
||||
bs.flags |= BFL_FIGHTSUICIDAL;
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//check for nearby goals periodicly
|
||||
if( bs.check_time < Bot_Time() )
|
||||
{
|
||||
bs.check_time = Bot_Time() + 1;
|
||||
range = 150;
|
||||
|
||||
//
|
||||
if( BotNearbyGoal( &bs, 0, &goal, range ) )
|
||||
{
|
||||
//trap_BotResetLastAvoidReach(bs.ms);
|
||||
//time the bot gets to pick up the nearby goal item
|
||||
bs.nbg_time = Bot_Time() + range / 100 + 1;
|
||||
//AIEnter_Battle_NBG(bs, "battle retreat: nbg");
|
||||
stateThread.SetState("state_BattleNBG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
}
|
||||
|
||||
MoveToCoverPoint();
|
||||
|
||||
if (bot_skill.GetInteger() > 1)
|
||||
{
|
||||
bs.firethrottlewait_time = 0;
|
||||
}
|
||||
|
||||
BotChooseWeapon( &bs );
|
||||
|
||||
BotAimAtEnemy( &bs );
|
||||
|
||||
//attack the enemy if possible
|
||||
BotCheckAttack( &bs );
|
||||
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// BotAI_SeekLTG.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvmBot::state_SeekLTG
|
||||
=====================
|
||||
*/
|
||||
stateResult_t rvmBot::state_SeekLTG(stateParms_t* parms)
|
||||
{
|
||||
if( BotIsDead( &bs ) )
|
||||
{
|
||||
stateThread.SetState("state_Respawn");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
BotGetItemLongTermGoal( &bs, 0, &bs.currentGoal );
|
||||
|
||||
// No Enemy.
|
||||
bs.enemy = -1;
|
||||
|
||||
//if there is an enemy
|
||||
if( BotFindEnemy( &bs, -1 ) )
|
||||
{
|
||||
if( BotWantsToRetreat( &bs ) )
|
||||
{
|
||||
//keep the current long term goal and retreat
|
||||
//AIEnter_Battle_Retreat(bs, "seek ltg: found enemy");
|
||||
stateThread.SetState("state_Retreat");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
//trap_BotResetLastAvoidReach(bs.ms);
|
||||
//empty the goal stack
|
||||
botGoalManager.BotEmptyGoalStack( bs.gs );
|
||||
|
||||
//go fight
|
||||
stateThread.SetState("state_BattleFight");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
}
|
||||
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
// BotAI_Seek_NBG.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvmBot::state_SeekNBG
|
||||
=====================
|
||||
*/
|
||||
stateResult_t rvmBot::state_SeekNBG(stateParms_t* parms)
|
||||
{
|
||||
bot_goal_t goal;
|
||||
idVec3 target, dir;
|
||||
//bot_moveresult_t moveresult;
|
||||
|
||||
//if (BotIsObserver(bs)) {
|
||||
// AIEnter_Observer(bs, "seek nbg: observer");
|
||||
// return qfalse;
|
||||
//}
|
||||
////if in the intermission
|
||||
//if (BotIntermission(bs)) {
|
||||
// AIEnter_Intermission(bs, "seek nbg: intermision");
|
||||
// return qfalse;
|
||||
//}
|
||||
|
||||
// respawn if dead.
|
||||
if( BotIsDead( &bs ) )
|
||||
{
|
||||
stateThread.SetState("state_Respawn");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//bs.tfl = TFL_DEFAULT;
|
||||
//if (bot_grapple.integer) bs.tfl |= TFL_GRAPPLEHOOK;
|
||||
////if in lava or slime the bot should be able to get out
|
||||
//if (BotInLavaOrSlime(bs)) bs.tfl |= TFL_LAVA | TFL_SLIME;
|
||||
////
|
||||
//if (BotCanAndWantsToRocketJump(bs)) {
|
||||
// bs.tfl |= TFL_ROCKETJUMP;
|
||||
//}
|
||||
////map specific code
|
||||
//BotMapScripts(bs);
|
||||
//no enemy
|
||||
bs.enemy = -1;
|
||||
//if the bot has no goal
|
||||
if( !botGoalManager.BotGetTopGoal( bs.gs, &goal ) )
|
||||
{
|
||||
bs.nbg_time = 0;
|
||||
}
|
||||
//if the bot touches the current goal
|
||||
else if( BotReachedGoal( &bs, &goal ) )
|
||||
{
|
||||
BotChooseWeapon( &bs );
|
||||
bs.nbg_time = 0;
|
||||
}
|
||||
|
||||
if( bs.nbg_time < Bot_Time() )
|
||||
{
|
||||
//pop the current goal from the stack
|
||||
botGoalManager.BotPopGoal( bs.gs );
|
||||
//check for new nearby items right away
|
||||
//NOTE: we canNOT reset the check_time to zero because it would create an endless loop of node switches
|
||||
bs.check_time = Bot_Time() + 0.05;
|
||||
//go back to seek ltg
|
||||
// AIEnter_Seek_LTG(bs, "seek nbg: time out");
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
|
||||
//predict obstacles
|
||||
//if (BotAIPredictObstacles(bs, &goal))
|
||||
// return qfalse;
|
||||
////initialize the movement state
|
||||
//BotSetupForMovement(bs);
|
||||
////move towards the goal
|
||||
//trap_BotMoveToGoal(&moveresult, bs.ms, &goal, bs.tfl);
|
||||
////if the movement failed
|
||||
//if (moveresult.failure) {
|
||||
// //reset the avoid reach, otherwise bot is stuck in current area
|
||||
// trap_BotResetAvoidReach(bs.ms);
|
||||
// bs.nbg_time = 0;
|
||||
//}
|
||||
BotMoveToGoal( &bs, &goal );
|
||||
|
||||
//check if the bot is blocked
|
||||
//BotAIBlocked(bs, &moveresult, qtrue);
|
||||
////
|
||||
//BotClearPath(bs, &moveresult);
|
||||
|
||||
// jmarshall - fix look at code.
|
||||
//if the viewangles are used for the movement
|
||||
//if (moveresult.flags & (MOVERESULT_MOVEMENTVIEWSET | MOVERESULT_MOVEMENTVIEW | MOVERESULT_SWIMVIEW)) {
|
||||
// VectorCopy(moveresult.ideal_viewangles, bs.ideal_viewangles);
|
||||
//}
|
||||
////if waiting for something
|
||||
//else if (moveresult.flags & MOVERESULT_WAITING) {
|
||||
// if (random() < bs.thinktime * 0.8) {
|
||||
// BotRoamGoal(bs, target);
|
||||
// VectorSubtract(target, bs.origin, dir);
|
||||
// vectoangles(dir, bs.ideal_viewangles);
|
||||
// bs.ideal_viewangles[2] *= 0.5;
|
||||
// }
|
||||
//}
|
||||
//else if (!(bs.flags & BFL_IDEALVIEWSET)) {
|
||||
// if (!trap_BotGetSecondGoal(bs.gs, &goal)) trap_BotGetTopGoal(bs.gs, &goal);
|
||||
// if (trap_BotMovementViewTarget(bs.ms, &goal, bs.tfl, 300, target)) {
|
||||
// VectorSubtract(target, bs.origin, dir);
|
||||
// vectoangles(dir, bs.ideal_viewangles);
|
||||
// }
|
||||
// //FIXME: look at cluster portals?
|
||||
// else vectoangles(moveresult.movedir, bs.ideal_viewangles);
|
||||
// bs.ideal_viewangles[2] *= 0.5;
|
||||
//}
|
||||
////if the weapon is used for the bot movement
|
||||
//if (moveresult.flags & MOVERESULT_MOVEMENTWEAPON) bs.weaponnum = moveresult.weapon;
|
||||
// jmarshall end
|
||||
//if there is an enemy
|
||||
if( BotFindEnemy( &bs, -1 ) )
|
||||
{
|
||||
if( BotWantsToRetreat( &bs ) )
|
||||
{
|
||||
//keep the current long term goal and retreat
|
||||
//AIEnter_Battle_NBG(bs, "seek nbg: found enemy");
|
||||
stateThread.SetState("state_BattleNBG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
//trap_BotResetLastAvoidReach(bs.ms);
|
||||
//empty the goal stack
|
||||
botGoalManager.BotEmptyGoalStack( bs.gs );
|
||||
//go fight
|
||||
//AIEnter_Battle_Fight(bs, "seek nbg: found enemy");
|
||||
stateThread.SetState("state_BattleFight");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// BotAI_respawn.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvmBot::state_Respawn
|
||||
=====================
|
||||
*/
|
||||
stateResult_t rvmBot::state_Respawn(stateParms_t* parms)
|
||||
{
|
||||
if (parms->stage == 0)
|
||||
{
|
||||
bs.botinput.respawn = true;
|
||||
parms->stage = 1;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
if (parms->stage == 1)
|
||||
{
|
||||
if (spectating)
|
||||
{
|
||||
return SRESULT_WAIT; // Wait until we have moved from spectator back into the game.
|
||||
}
|
||||
}
|
||||
|
||||
bs.botinput.respawn = false;
|
||||
stateThread.SetState("state_SeekLTG");
|
||||
return SRESULT_DONE_FRAME;
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
// Bot_Input.cpp
|
||||
//
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
/*
|
||||
==============
|
||||
rvmBot::BotInputToUserCommand
|
||||
==============
|
||||
*/
|
||||
void rvmBot::BotInputToUserCommand(bot_input_t* bi, usercmd_t* ucmd, int time)
|
||||
{
|
||||
idVec3 forward, right;
|
||||
|
||||
short temp;
|
||||
int j;
|
||||
|
||||
//clear the whole structure
|
||||
// memset(ucmd, 0, sizeof(usercmd_t));
|
||||
//
|
||||
//common->Printf("dir = %f %f %f speed = %f\n", bi->dir[0], bi->dir[1], bi->dir[2], bi->speed);
|
||||
//the duration for the user command in milli seconds
|
||||
//
|
||||
if (bi->actionflags & ACTION_DELAYEDJUMP)
|
||||
{
|
||||
bi->actionflags |= ACTION_JUMP;
|
||||
bi->actionflags &= ~ACTION_DELAYEDJUMP;
|
||||
}
|
||||
//set the buttons
|
||||
if (bi->actionflags & ACTION_RESPAWN)
|
||||
{
|
||||
ucmd->buttons = BUTTON_ATTACK;
|
||||
}
|
||||
if (bi->actionflags & ACTION_ATTACK)
|
||||
{
|
||||
ucmd->buttons |= BUTTON_ATTACK;
|
||||
}
|
||||
//if (bi->actionflags & ACTION_TALK) ucmd->buttons |= BUTTON_TALK;
|
||||
//if (bi->actionflags & ACTION_GESTURE) ucmd->buttons |= BUTTON_GESTURE;
|
||||
//if (bi->actionflags & ACTION_USE) ucmd->buttons |= BUTTON_USE_HOLDABLE;
|
||||
if (bi->actionflags & ACTION_WALK)
|
||||
{
|
||||
ucmd->buttons |= BUTTON_RUN;
|
||||
}
|
||||
//if (bi->actionflags & ACTION_AFFIRMATIVE) ucmd->buttons |= BUTTON_AFFIRMATIVE;
|
||||
//if (bi->actionflags & ACTION_NEGATIVE) ucmd->buttons |= BUTTON_NEGATIVE;
|
||||
//if (bi->actionflags & ACTION_GETFLAG) ucmd->buttons |= BUTTON_GETFLAG;
|
||||
//if (bi->actionflags & ACTION_GUARDBASE) ucmd->buttons |= BUTTON_GUARDBASE;
|
||||
//if (bi->actionflags & ACTION_PATROL) ucmd->buttons |= BUTTON_PATROL;
|
||||
//if (bi->actionflags & ACTION_FOLLOWME) ucmd->buttons |= BUTTON_FOLLOWME;
|
||||
//
|
||||
ucmd->impulse |= bi->weapon;
|
||||
if (bi->lastWeaponNum != bi->weapon)
|
||||
{
|
||||
//ucmd->flags = UCF_IMPULSE_SEQUENCE;
|
||||
bi->lastWeaponNum = bi->weapon;
|
||||
}
|
||||
else
|
||||
{
|
||||
//ucmd->flags = 0;
|
||||
}
|
||||
|
||||
idAngles botViewAngles = viewAngles;
|
||||
|
||||
{
|
||||
int i;
|
||||
float move;
|
||||
float angMod = (1.0f / 12.0f);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
move = idMath::AngleDelta(bi->viewangles[i], botViewAngles[i]);
|
||||
botViewAngles[i] += (move * angMod);
|
||||
}
|
||||
}
|
||||
|
||||
//set the view angles
|
||||
//NOTE: the ucmd->angles are the angles WITHOUT the delta angles
|
||||
ucmd->angles[0] = ANGLE2SHORT(botViewAngles[0] - deltaViewAngles[0]);
|
||||
ucmd->angles[1] = ANGLE2SHORT(botViewAngles[1] - deltaViewAngles[1]);
|
||||
ucmd->angles[2] = ANGLE2SHORT(botViewAngles[2] - deltaViewAngles[2]);
|
||||
|
||||
bi->viewangles.ToVectors(&forward, &right, NULL);
|
||||
|
||||
//bot input speed is in the range [0, 400]
|
||||
bi->speed = bi->speed * 127 / 400;
|
||||
//set the view independent movement
|
||||
ucmd->forwardmove = idMath::ClampChar(DotProduct(forward, bi->dir) * bi->speed);
|
||||
ucmd->rightmove = idMath::ClampChar(DotProduct(right, bi->dir) * bi->speed);
|
||||
//ucmd->upmove = abs(forward[2]) * bi->dir[2] * bi->speed;
|
||||
|
||||
//normal keyboard movement
|
||||
if (bi->actionflags & ACTION_MOVEFORWARD)
|
||||
{
|
||||
ucmd->forwardmove += 127;
|
||||
}
|
||||
if (bi->actionflags & ACTION_MOVEBACK)
|
||||
{
|
||||
ucmd->forwardmove -= 127;
|
||||
}
|
||||
if (bi->actionflags & ACTION_MOVELEFT)
|
||||
{
|
||||
ucmd->rightmove -= 127;
|
||||
}
|
||||
if (bi->actionflags & ACTION_MOVERIGHT)
|
||||
{
|
||||
ucmd->rightmove += 127;
|
||||
}
|
||||
|
||||
//jump/moveup
|
||||
if (bi->actionflags & ACTION_JUMP)
|
||||
ucmd->buttons |= BUTTON_JUMP;
|
||||
|
||||
// ucmd->upmove += 127;
|
||||
//
|
||||
////crouch/movedown
|
||||
//if (bi->actionflags & ACTION_CROUCH)
|
||||
// ucmd->upmove -= 127;
|
||||
//
|
||||
//Com_Printf("forward = %d right = %d up = %d\n", ucmd.forwardmove, ucmd.rightmove, ucmd.upmove);
|
||||
//Com_Printf("ucmd->serverTime = %d\n", ucmd->serverTime);
|
||||
|
||||
if( bi->respawn )
|
||||
{
|
||||
ucmd->buttons |= BUTTON_ATTACK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmBot::ResetUcmd
|
||||
================
|
||||
*/
|
||||
void rvmBot::Bot_ResetUcmd( usercmd_t& ucmd )
|
||||
{
|
||||
ucmd.forwardmove = 0;
|
||||
ucmd.rightmove = 0;
|
||||
//ucmd.upmove = 0;
|
||||
ucmd.impulse = 0;
|
||||
//ucmd.flags = 0;
|
||||
memset( &ucmd.buttons, 0, sizeof( ucmd.buttons ) );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
rvmBot::BotInputFrame
|
||||
========================
|
||||
*/
|
||||
void rvmBot::BotInputFrame( idUserCmdMgr& cmdMgr )
|
||||
{
|
||||
usercmd_t botcmd = { }; //(usercmd_t&)cmdMgr.GetUserCmdForPlayer(entityNumber); // gameLocal.usercmds[entityNumber];
|
||||
|
||||
Bot_ResetUcmd( botcmd );
|
||||
BotInputToUserCommand( &bs.botinput, &botcmd, gameLocal.time );
|
||||
|
||||
cmdMgr.PutUserCmdForPlayer( entityNumber, botcmd );
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
// Bot_char.cpp
|
||||
//
|
||||
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
idBotCharacterStatsManager botCharacterStatsManager;
|
||||
|
||||
/*
|
||||
====================
|
||||
idBotCharacterStatsManager::idBotCharacterStatsManager
|
||||
====================
|
||||
*/
|
||||
idBotCharacterStatsManager::idBotCharacterStatsManager()
|
||||
{
|
||||
default_char_profile = nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idBotCharacterStatsManager::Init
|
||||
====================
|
||||
*/
|
||||
void idBotCharacterStatsManager::Init( void )
|
||||
{
|
||||
default_char_profile = BotLoadCharacterFromFile( "bots/default_c.c", 1 );
|
||||
if( default_char_profile == NULL )
|
||||
{
|
||||
common->FatalError( "Failed to load default characteristic def file\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============================
|
||||
idBotCharacterStatsManager::AllocBotCharacter
|
||||
============================
|
||||
*/
|
||||
bot_character_t* idBotCharacterStatsManager::AllocBotCharacter( void )
|
||||
{
|
||||
bot_character_t* ch = NULL;
|
||||
|
||||
for( int i = 0; i < MAX_CHAR_STATS; i++ )
|
||||
{
|
||||
if( charStatsList[i].inUse == false )
|
||||
{
|
||||
charStatsList[i].inUse = true;
|
||||
ch = &charStatsList[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( ch == nullptr )
|
||||
{
|
||||
gameLocal.Error( "idBotCharacterStatsManager::AllocBotCharacter: Too many bot characters!" );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if( default_char_profile == NULL )
|
||||
{
|
||||
memset( &ch->c[0], 0, MAX_CHARACTERISTICS * sizeof( bot_characteristic_t ) );
|
||||
ch->filename = "";
|
||||
ch->inUse = false;
|
||||
ch->skill = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//memcpy( ch, default_char_profile, sizeof( bot_character_t ) + MAX_CHARACTERISTICS * sizeof( bot_characteristic_t ) );
|
||||
*ch = *default_char_profile;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
/*
|
||||
============================
|
||||
idBotCharacterStatsManager::FreeCharacterFile
|
||||
============================
|
||||
*/
|
||||
void idBotCharacterStatsManager::FreeCharacterFile( bot_character_t* ch )
|
||||
{
|
||||
ch->inUse = false;
|
||||
}
|
||||
|
||||
/*
|
||||
============================
|
||||
idBotCharacterStatsManager::BotLoadCharacterFromFile
|
||||
============================
|
||||
*/
|
||||
bot_character_t* idBotCharacterStatsManager::BotLoadCharacterFromFile( const char* charfile, int skill )
|
||||
{
|
||||
int indent, index;
|
||||
bool foundcharacter;
|
||||
bot_character_t* ch;
|
||||
idParser parser;
|
||||
idToken token;
|
||||
|
||||
foundcharacter = false;
|
||||
|
||||
// Check to see if we already loaded this bot file.
|
||||
for( int i = 0; i < MAX_CHAR_STATS; i++ )
|
||||
{
|
||||
if(charStatsList[i].inUse && charStatsList[i].filename == charfile )
|
||||
{
|
||||
return &charStatsList[i];
|
||||
}
|
||||
}
|
||||
|
||||
rvmScopedLexerBaseFolder scopedBaseFolder( BOTFILESBASEFOLDER );
|
||||
|
||||
//a bot character is parsed in two phases
|
||||
if( !parser.LoadFile( charfile ) )
|
||||
{
|
||||
common->Warning( "BotLoadCharacterFromFile: counldn't load %s\n", charfile );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ch = AllocBotCharacter();
|
||||
ch->filename = charfile;
|
||||
|
||||
while( parser.ReadToken( &token ) )
|
||||
{
|
||||
if( token == "skill" )
|
||||
{
|
||||
if( !parser.ExpectTokenType( TT_NUMBER, 0, &token ) )
|
||||
{
|
||||
FreeCharacterFile( ch );
|
||||
parser.Warning( "Expected token type number\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !parser.ExpectTokenString( "{" ) )
|
||||
{
|
||||
FreeCharacterFile( ch );
|
||||
parser.Warning( "Expected token {\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//if it's the correct skill
|
||||
if( skill < 0 || token.GetIntValue() == skill )
|
||||
{
|
||||
foundcharacter = true;
|
||||
ch->skill = token.GetIntValue();
|
||||
while( parser.ReadToken( &token ) )
|
||||
{
|
||||
if( token == "}" )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( token.type != TT_NUMBER || !( token.subtype & TT_INTEGER ) )
|
||||
{
|
||||
FreeCharacterFile( ch );
|
||||
parser.Error( "expected integer index, found %s\n", token.c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
index = token.GetIntValue();
|
||||
if( index < 0 || index > MAX_CHARACTERISTICS )
|
||||
{
|
||||
FreeCharacterFile( ch );
|
||||
parser.Error( "characteristic index out of range [0, %d]\n", MAX_CHARACTERISTICS );
|
||||
return NULL;
|
||||
}
|
||||
// jmarshall - not sure what we loose by removing this check, basically duplicate definition check?
|
||||
//if (ch->c[index].type)
|
||||
//{
|
||||
// G_Error("characteristic %d already initialized\n", index);
|
||||
// trap_PC_FreeSource(source);
|
||||
// BotFreeCharacterStrings(ch);
|
||||
// //FreeMemory(ch);
|
||||
// return NULL;
|
||||
//}
|
||||
// jmarshall end
|
||||
|
||||
if( !parser.ReadToken( &token ) )
|
||||
{
|
||||
FreeCharacterFile( ch );
|
||||
parser.Error( "Unexpected EOF during parse characesistic" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( token.type == TT_NUMBER )
|
||||
{
|
||||
if( token.subtype & TT_FLOAT )
|
||||
{
|
||||
ch->c[index].value._float = token.GetFloatValue();
|
||||
ch->c[index].type = CT_FLOAT;
|
||||
}
|
||||
else
|
||||
{
|
||||
ch->c[index].value.integer = token.GetIntValue();
|
||||
ch->c[index].type = CT_INTEGER;
|
||||
}
|
||||
}
|
||||
else if( token.type == TT_STRING )
|
||||
{
|
||||
token.StripDoubleQuotes();
|
||||
ch->c[index].value.string = token;
|
||||
ch->c[index].type = CT_STRING;
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeCharacterFile( ch );
|
||||
gameLocal.Error( "expected integer, float or string, found %s\n", token.c_str() );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
indent = 1;
|
||||
while( indent )
|
||||
{
|
||||
if( !parser.ReadToken( &token ) )
|
||||
{
|
||||
FreeCharacterFile( ch );
|
||||
return NULL;
|
||||
}
|
||||
if( token == "{" )
|
||||
{
|
||||
indent++;
|
||||
}
|
||||
else if( token == "}" )
|
||||
{
|
||||
indent--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeCharacterFile( ch );
|
||||
gameLocal.Error( "unknown definition %s\n", token.c_str() );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( !foundcharacter )
|
||||
{
|
||||
FreeCharacterFile( ch );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============================
|
||||
idBotCharacterStatsManager::CheckCharacteristicIndex
|
||||
============================
|
||||
*/
|
||||
int idBotCharacterStatsManager::CheckCharacteristicIndex( bot_character_t* ch, int index )
|
||||
{
|
||||
if( index < 0 || index >= MAX_CHARACTERISTICS )
|
||||
{
|
||||
gameLocal.Error( "characteristic %d does not exist\n", index );
|
||||
return false;
|
||||
}
|
||||
if( !ch->c[index].type )
|
||||
{
|
||||
gameLocal.Error( "characteristic %d is not initialized\n", index );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============================
|
||||
idBotCharacterStatsManager::Characteristic_Float
|
||||
============================
|
||||
*/
|
||||
float idBotCharacterStatsManager::Characteristic_Float( bot_character_t* ch, int index )
|
||||
{
|
||||
if( !ch )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
//check if the index is in range
|
||||
if( !CheckCharacteristicIndex( ch, index ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( ch->c[index].type == CT_INTEGER )
|
||||
{
|
||||
//an integer will be converted to a float
|
||||
return ( float )ch->c[index].value.integer;
|
||||
}
|
||||
else if( ch->c[index].type == CT_FLOAT )
|
||||
{
|
||||
//floats are just returned
|
||||
return ch->c[index].value._float;
|
||||
}
|
||||
|
||||
//cannot convert a string pointer to a float
|
||||
gameLocal.Error( "characteristic %d is not a float\n", index );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
============================
|
||||
Characteristic_String
|
||||
============================
|
||||
*/
|
||||
void idBotCharacterStatsManager::Characteristic_String( bot_character_t* ch, int index, char* buf, int size )
|
||||
{
|
||||
//check if the index is in range
|
||||
if( !CheckCharacteristicIndex( ch, index ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//an integer will be converted to a float
|
||||
if( ch->c[index].type == CT_STRING )
|
||||
{
|
||||
strcpy( buf, ch->c[index].value.string );
|
||||
buf[size - 1] = '\0';
|
||||
return;
|
||||
}
|
||||
gameLocal.Error( "characteristic %d is not a string\n", index );
|
||||
}
|
||||
|
||||
/*
|
||||
============================
|
||||
idBotCharacterStatsManager::Characteristic_BFloat
|
||||
============================
|
||||
*/
|
||||
float idBotCharacterStatsManager::Characteristic_BFloat( bot_character_t* ch, int index, float min, float max )
|
||||
{
|
||||
float value;
|
||||
|
||||
if( min > max )
|
||||
{
|
||||
gameLocal.Error( "cannot bound characteristic %d between %f and %f\n", index, min, max );
|
||||
return 0;
|
||||
}
|
||||
|
||||
value = Characteristic_Float( ch, index );
|
||||
if( value < min )
|
||||
{
|
||||
return min;
|
||||
}
|
||||
if( value > max )
|
||||
{
|
||||
return max;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
// Bot_char.h
|
||||
//
|
||||
|
||||
#define MAX_CHAR_STATS 256
|
||||
|
||||
//========================================================
|
||||
//========================================================
|
||||
//name
|
||||
#define CHARACTERISTIC_NAME 0 //string
|
||||
//gender of the bot
|
||||
#define CHARACTERISTIC_GENDER 1 //string ("male", "female", "it")
|
||||
//attack skill
|
||||
// > 0.0 && < 0.2 = don't move
|
||||
// > 0.3 && < 1.0 = aim at enemy during retreat
|
||||
// > 0.0 && < 0.4 = only move forward/backward
|
||||
// >= 0.4 && < 1.0 = circle strafing
|
||||
// > 0.7 && < 1.0 = random strafe direction change
|
||||
#define CHARACTERISTIC_ATTACK_SKILL 2 //float [0, 1]
|
||||
//weapon weight file
|
||||
#define CHARACTERISTIC_WEAPONWEIGHTS 3 //string
|
||||
//view angle difference to angle change factor
|
||||
#define CHARACTERISTIC_VIEW_FACTOR 4 //float <0, 1]
|
||||
//maximum view angle change
|
||||
#define CHARACTERISTIC_VIEW_MAXCHANGE 5 //float [1, 360]
|
||||
//reaction time in seconds
|
||||
#define CHARACTERISTIC_REACTIONTIME 6 //float [0, 5]
|
||||
//accuracy when aiming
|
||||
#define CHARACTERISTIC_AIM_ACCURACY 7 //float [0, 1]
|
||||
//weapon specific aim accuracy
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_MACHINEGUN 8 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_SHOTGUN 9 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_ROCKETLAUNCHER 10 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_GRENADELAUNCHER 11 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_LIGHTNING 12
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_PLASMAGUN 13 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_RAILGUN 14
|
||||
#define CHARACTERISTIC_AIM_ACCURACY_BFG10K 15 //float [0, 1]
|
||||
//skill when aiming
|
||||
// > 0.0 && < 0.9 = aim is affected by enemy movement
|
||||
// > 0.4 && <= 0.8 = enemy linear leading
|
||||
// > 0.8 && <= 1.0 = enemy exact movement leading
|
||||
// > 0.5 && <= 1.0 = prediction shots when enemy is not visible
|
||||
// > 0.6 && <= 1.0 = splash damage by shooting nearby geometry
|
||||
#define CHARACTERISTIC_AIM_SKILL 16 //float [0, 1]
|
||||
//weapon specific aim skill
|
||||
#define CHARACTERISTIC_AIM_SKILL_ROCKETLAUNCHER 17 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_SKILL_GRENADELAUNCHER 18 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_SKILL_PLASMAGUN 19 //float [0, 1]
|
||||
#define CHARACTERISTIC_AIM_SKILL_BFG10K 20 //float [0, 1]
|
||||
//========================================================
|
||||
//chat
|
||||
//========================================================
|
||||
//file with chats
|
||||
#define CHARACTERISTIC_CHAT_FILE 21 //string
|
||||
//name of the chat character
|
||||
#define CHARACTERISTIC_CHAT_NAME 22 //string
|
||||
//characters per minute type speed
|
||||
#define CHARACTERISTIC_CHAT_CPM 23 //integer [1, 4000]
|
||||
//tendency to insult/praise
|
||||
#define CHARACTERISTIC_CHAT_INSULT 24 //float [0, 1]
|
||||
//tendency to chat misc
|
||||
#define CHARACTERISTIC_CHAT_MISC 25 //float [0, 1]
|
||||
//tendency to chat at start or end of level
|
||||
#define CHARACTERISTIC_CHAT_STARTENDLEVEL 26 //float [0, 1]
|
||||
//tendency to chat entering or exiting the game
|
||||
#define CHARACTERISTIC_CHAT_ENTEREXITGAME 27 //float [0, 1]
|
||||
//tendency to chat when killed someone
|
||||
#define CHARACTERISTIC_CHAT_KILL 28 //float [0, 1]
|
||||
//tendency to chat when died
|
||||
#define CHARACTERISTIC_CHAT_DEATH 29 //float [0, 1]
|
||||
//tendency to chat when enemy suicides
|
||||
#define CHARACTERISTIC_CHAT_ENEMYSUICIDE 30 //float [0, 1]
|
||||
//tendency to chat when hit while talking
|
||||
#define CHARACTERISTIC_CHAT_HITTALKING 31 //float [0, 1]
|
||||
//tendency to chat when bot was hit but didn't dye
|
||||
#define CHARACTERISTIC_CHAT_HITNODEATH 32 //float [0, 1]
|
||||
//tendency to chat when bot hit the enemy but enemy didn't dye
|
||||
#define CHARACTERISTIC_CHAT_HITNOKILL 33 //float [0, 1]
|
||||
//tendency to randomly chat
|
||||
#define CHARACTERISTIC_CHAT_RANDOM 34 //float [0, 1]
|
||||
//tendency to reply
|
||||
#define CHARACTERISTIC_CHAT_REPLY 35 //float [0, 1]
|
||||
//========================================================
|
||||
//movement
|
||||
//========================================================
|
||||
//tendency to crouch
|
||||
#define CHARACTERISTIC_CROUCHER 36 //float [0, 1]
|
||||
//tendency to jump
|
||||
#define CHARACTERISTIC_JUMPER 37 //float [0, 1]
|
||||
//tendency to walk
|
||||
#define CHARACTERISTIC_WALKER 48 //float [0, 1]
|
||||
//tendency to jump using a weapon
|
||||
#define CHARACTERISTIC_WEAPONJUMPING 38 //float [0, 1]
|
||||
//tendency to use the grapple hook when available
|
||||
#define CHARACTERISTIC_GRAPPLE_USER 39 //float [0, 1] //use this!!
|
||||
//========================================================
|
||||
//goal
|
||||
//========================================================
|
||||
//item weight file
|
||||
#define CHARACTERISTIC_ITEMWEIGHTS 40 //string
|
||||
//the aggression of the bot
|
||||
#define CHARACTERISTIC_AGGRESSION 41 //float [0, 1]
|
||||
//the self preservation of the bot (rockets near walls etc.)
|
||||
#define CHARACTERISTIC_SELFPRESERVATION 42 //float [0, 1]
|
||||
//how likely the bot is to take revenge
|
||||
#define CHARACTERISTIC_VENGEFULNESS 43 //float [0, 1] //use this!!
|
||||
//tendency to camp
|
||||
#define CHARACTERISTIC_CAMPER 44 //float [0, 1]
|
||||
//========================================================
|
||||
//========================================================
|
||||
//tendency to get easy frags
|
||||
#define CHARACTERISTIC_EASY_FRAGGER 45 //float [0, 1]
|
||||
//how alert the bot is (view distance)
|
||||
#define CHARACTERISTIC_ALERTNESS 46 //float [0, 1]
|
||||
//how much the bot fires it's weapon
|
||||
#define CHARACTERISTIC_FIRETHROTTLE 47 //float [0, 1]
|
||||
|
||||
//
|
||||
// idBotCharacterStatsManager
|
||||
//
|
||||
class idBotCharacterStatsManager
|
||||
{
|
||||
public:
|
||||
idBotCharacterStatsManager();
|
||||
|
||||
// Inits the stats manager.
|
||||
void Init( void );
|
||||
|
||||
// Loads a character file.
|
||||
bot_character_t* BotLoadCharacterFromFile( const char* charfile, int skill );
|
||||
|
||||
// Free character file.
|
||||
void FreeCharacterFile( bot_character_t* ch );
|
||||
|
||||
// Returns the default character stats profile.
|
||||
bot_character_t* GetDefaultCharProfile( void )
|
||||
{
|
||||
return default_char_profile;
|
||||
}
|
||||
|
||||
int CheckCharacteristicIndex( bot_character_t* ch, int index );
|
||||
float Characteristic_Float( bot_character_t* ch, int index );
|
||||
void Characteristic_String( bot_character_t* ch, int index, char* buf, int size );
|
||||
float Characteristic_BFloat( bot_character_t* ch, int index, float min, float max );
|
||||
private:
|
||||
bot_character_t* AllocBotCharacter( void );
|
||||
|
||||
bot_character_t* default_char_profile;
|
||||
|
||||
bot_character_t charStatsList[MAX_CHAR_STATS];
|
||||
};
|
||||
|
||||
extern idBotCharacterStatsManager botCharacterStatsManager;
|
||||
@@ -0,0 +1,54 @@
|
||||
// Bot_Chat.cpp
|
||||
//
|
||||
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
const char *bot_kill_insult[] = {
|
||||
"%s: Try aiming next time %s",
|
||||
"%s: Trust me when I say this %s, you suck.",
|
||||
"%s: Maybe you should go back to go cart racing %s?",
|
||||
"%s: Your technique reminds me of a story %s, a very dull one."
|
||||
};
|
||||
|
||||
const char* bot_death_insult[] = {
|
||||
"%s: Mmmmmmm. Was it good for you too %s?",
|
||||
"%s: Well I guess %s won the lottery.",
|
||||
"%s: My mother fragged me once %s. Once.",
|
||||
"%s: I'm gonna pull out your bowels %s",
|
||||
"%s: Beginners luck %s... Again",
|
||||
"%s: So %s... you're up to what ... 3 frags an hour?"
|
||||
};
|
||||
|
||||
const char* bot_death_praise[] = {
|
||||
"%s: %s not bad for an amateur.",
|
||||
"%s: %s alright that was pretty good. Your still a dousche.",
|
||||
"%s: That was definitely ... um ... pretty good %s",
|
||||
"%s: I've seen better %s, but not many.",
|
||||
"%s: Take a moment to reflect on your accomplishment %s",
|
||||
"%s: Your pretty good for a dousche %s"
|
||||
};
|
||||
|
||||
/*
|
||||
====================
|
||||
rvmBot::BotSendChatMessage
|
||||
====================
|
||||
*/
|
||||
void rvmBot::BotSendChatMessage(botChat_t chat, const char* targetName) {
|
||||
switch (chat)
|
||||
{
|
||||
case KILL:
|
||||
gameLocal.mpGame.AddChatLine(bot_kill_insult[rvRandom::irand(0, 3)], netname.c_str(), targetName);
|
||||
break;
|
||||
case DEATH:
|
||||
if (rvRandom::irand(0, 10) < 5)
|
||||
{
|
||||
gameLocal.mpGame.AddChatLine(bot_death_insult[rvRandom::irand(0, 5)], netname.c_str(), targetName);
|
||||
}
|
||||
else
|
||||
{
|
||||
gameLocal.mpGame.AddChatLine(bot_death_praise[rvRandom::irand(0, 5)], netname.c_str(), targetName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// Bot_chat.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
enum botChat_t {
|
||||
KILL = 0,
|
||||
DEATH,
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,342 @@
|
||||
// Bot_goal.h
|
||||
//
|
||||
|
||||
#define MAX_BOT_ITEM_INFOS 2
|
||||
#define MAX_BOT_ITEM_INFO 256
|
||||
#define MAX_BOT_LEVEL_ITEMS 256
|
||||
|
||||
//#define DEBUG_AI_GOAL
|
||||
#ifdef RANDOMIZE
|
||||
#define UNDECIDEDFUZZY
|
||||
#endif //RANDOMIZE
|
||||
#define DROPPEDWEIGHT
|
||||
//minimum avoid goal time
|
||||
#define AVOID_MINIMUM_TIME 10
|
||||
//default avoid goal time
|
||||
#define AVOID_DEFAULT_TIME 30
|
||||
//avoid dropped goal time
|
||||
#define AVOID_DROPPED_TIME 10
|
||||
//
|
||||
#define TRAVELTIME_SCALE 0.01
|
||||
//item flags
|
||||
#define IFL_NOTFREE 1 //not in free for all
|
||||
#define IFL_NOTTEAM 2 //not in team play
|
||||
#define IFL_NOTSINGLE 4 //not in single player
|
||||
#define IFL_NOTBOT 8 //bot should never go for this
|
||||
#define IFL_ROAM 16 //bot roam goal
|
||||
|
||||
//a bot goal
|
||||
struct bot_goal_t
|
||||
{
|
||||
bot_goal_t()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
origin.Zero();
|
||||
areanum = 0;
|
||||
mins.Zero();
|
||||
maxs.Zero();
|
||||
entitynum = 0;
|
||||
number = 0;
|
||||
flags = 0;
|
||||
iteminfo = 0;
|
||||
framenum = -1;
|
||||
}
|
||||
|
||||
int framenum;
|
||||
idVec3 origin; //origin of the goal
|
||||
int areanum; //area number of the goal
|
||||
idVec3 mins, maxs; //mins and maxs of the goal
|
||||
int entitynum; //number of the goal entity
|
||||
int number; //goal number
|
||||
int flags; //goal flags
|
||||
int iteminfo; //item information
|
||||
};
|
||||
|
||||
//location in the map "target_location"
|
||||
struct maplocation_t
|
||||
{
|
||||
maplocation_t()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
origin.Zero();
|
||||
areanum = 0;
|
||||
name = "";
|
||||
next = nullptr;
|
||||
}
|
||||
|
||||
idVec3 origin;
|
||||
int areanum;
|
||||
idStr name;
|
||||
maplocation_t* next;
|
||||
};
|
||||
|
||||
//camp spots "info_camp"
|
||||
struct campspot_t
|
||||
{
|
||||
campspot_t()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
origin.Zero();
|
||||
areanum = 0;
|
||||
name = "";
|
||||
range = 0;
|
||||
weight = 0;
|
||||
random = 0;
|
||||
}
|
||||
|
||||
idVec3 origin;
|
||||
int areanum;
|
||||
idStr name;
|
||||
float range;
|
||||
float weight;
|
||||
float wait;
|
||||
float random;
|
||||
};
|
||||
|
||||
struct levelitem_t
|
||||
{
|
||||
levelitem_t()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
number = 0;
|
||||
iteminfo = 0;
|
||||
flags = 0;
|
||||
weight = 0;
|
||||
origin.Zero();
|
||||
goalorigin.Zero();
|
||||
item = nullptr;
|
||||
timeout = 0;
|
||||
prev = nullptr;
|
||||
next = nullptr;
|
||||
}
|
||||
|
||||
idStr name;
|
||||
int number; //number of the level item
|
||||
int iteminfo; //index into the item info
|
||||
int flags; //item flags
|
||||
float weight; //fixed roam weight
|
||||
idVec3 origin; //origin of the item
|
||||
idVec3 goalorigin; //goal origin within the area
|
||||
//int entitynum; //entity number
|
||||
idItem* item;
|
||||
float timeout; //item is removed after this time
|
||||
levelitem_t* prev, * next;
|
||||
};
|
||||
|
||||
struct iteminfo_t
|
||||
{
|
||||
iteminfo_t()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
classname = "";
|
||||
name = "";
|
||||
model = "";
|
||||
modelindex = 0;
|
||||
type = 0;
|
||||
index = 0;
|
||||
respawntime = 0;
|
||||
mins.Zero();
|
||||
maxs.Zero();
|
||||
number = 0;
|
||||
}
|
||||
|
||||
idStr classname; //classname of the item
|
||||
idStr name; //name of the item
|
||||
idStr model; //model of the item
|
||||
int modelindex; //model index
|
||||
int type; //item type
|
||||
int index; //index in the inventory
|
||||
float respawntime; //respawn time
|
||||
idVec3 mins; //mins of the item
|
||||
idVec3 maxs; //maxs of the item
|
||||
int number; //number of the item info
|
||||
};
|
||||
|
||||
//
|
||||
// itemconfig_t
|
||||
//
|
||||
struct itemconfig_t
|
||||
{
|
||||
itemconfig_t()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset( void )
|
||||
{
|
||||
numiteminfo = 0;
|
||||
for( int i = 0; i < MAX_BOT_ITEM_INFO; i++ )
|
||||
{
|
||||
iteminfo[i].Reset();
|
||||
}
|
||||
}
|
||||
|
||||
int numiteminfo;
|
||||
iteminfo_t iteminfo[MAX_BOT_ITEM_INFO];
|
||||
};
|
||||
|
||||
//goal state
|
||||
struct bot_goalstate_t
|
||||
{
|
||||
bot_goalstate_t()
|
||||
{
|
||||
itemweightindex = NULL;
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
itemweightconfig = NULL;
|
||||
|
||||
if( itemweightindex != NULL )
|
||||
{
|
||||
delete itemweightindex;
|
||||
}
|
||||
itemweightindex = NULL;
|
||||
client = -1;
|
||||
lastreachabilityarea = 0;
|
||||
goalstacktop = 0;
|
||||
|
||||
for( int i = 0; i < MAX_AVOIDGOALS; i++ )
|
||||
{
|
||||
avoidgoals[i] = 0;
|
||||
avoidgoaltimes[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
~bot_goalstate_t()
|
||||
{
|
||||
if( itemweightindex != NULL )
|
||||
{
|
||||
delete itemweightindex;
|
||||
}
|
||||
|
||||
itemweightindex = NULL;
|
||||
}
|
||||
|
||||
bool InUse()
|
||||
{
|
||||
return client != -1;
|
||||
}
|
||||
|
||||
weightconfig_t* itemweightconfig; //weight config
|
||||
int* itemweightindex; //index from item to weight
|
||||
|
||||
int client; //client using this goal state
|
||||
int lastreachabilityarea; //last area with reachabilities the bot was in
|
||||
|
||||
bot_goal_t goalstack[MAX_GOALSTACK]; //goal stack
|
||||
int goalstacktop; //the top of the goal stack
|
||||
|
||||
int avoidgoals[MAX_AVOIDGOALS]; //goals to avoid
|
||||
float avoidgoaltimes[MAX_AVOIDGOALS]; //times to avoid the goals
|
||||
};
|
||||
|
||||
class idBotGoalManager
|
||||
{
|
||||
public:
|
||||
idBotGoalManager();
|
||||
|
||||
int BotSetupGoalAI( void );
|
||||
|
||||
void InitLevelItems( void );
|
||||
void UpdateEntityItems( void );
|
||||
|
||||
void BotPushGoal( int goalstate, bot_goal_t* goal );
|
||||
void BotPopGoal( int goalstate );
|
||||
void BotEmptyGoalStack( int goalstate );
|
||||
|
||||
int BotLoadItemWeights( int goalstate, char* filename );
|
||||
void BotResetGoalState( int goalstate );
|
||||
|
||||
int BotItemGoalInVisButNotVisible( int viewer, idVec3 eye, idAngles viewangles, bot_goal_t* goal );
|
||||
|
||||
int BotChooseLTGItem( int goalstate, idVec3 origin, int* inventory, int travelflags );
|
||||
int BotChooseNBGItem( int goalstate, idVec3 origin, int* inventory, int travelflags, bot_goal_t* ltg, float maxtime );
|
||||
|
||||
int BotTouchingGoal( idVec3 origin, bot_goal_t* goal );
|
||||
|
||||
int BotAllocGoalState( int client );
|
||||
|
||||
void BotGoalName( int number, char* name, int size );
|
||||
|
||||
void BotFreeGoalState( int handle );
|
||||
void BotShutdownGoalAI( void );
|
||||
void BotFreeItemWeights( int goalstate );
|
||||
public:
|
||||
bool BotNearGoal( idVec3 p1, idVec3 p2 );
|
||||
int BotGetTopGoal( int goalstate, bot_goal_t* goal );
|
||||
int BotGetSecondGoal( int goalstate, bot_goal_t* goal );
|
||||
public:
|
||||
void BotDumpGoalStack( int goalstate );
|
||||
public:
|
||||
int BotGetLevelItemGoal( int index, char* name, bot_goal_t* goal );
|
||||
void BotSetAvoidGoalTime( int goalstate, int number, float avoidtime );
|
||||
float BotAvoidGoalTime( int goalstate, int number );
|
||||
void BotResetAvoidGoals( int goalstate );
|
||||
void BotDumpAvoidGoals( int goalstate );
|
||||
void BotAddToAvoidGoals( bot_goalstate_t* gs, int number, float avoidtime );
|
||||
void BotRemoveFromAvoidGoals( int goalstate, int number );
|
||||
int BotGetMapLocationGoal( char* name, bot_goal_t* goal );
|
||||
int BotGetNextCampSpotGoal( int num, bot_goal_t* goal );
|
||||
void BotFindEntityForLevelItem( levelitem_t* li );
|
||||
private:
|
||||
|
||||
levelitem_t* AllocLevelItem( void );
|
||||
void FreeLevelItem( levelitem_t* li );
|
||||
|
||||
void AddLevelItemToList( levelitem_t* li );
|
||||
void RemoveLevelItemFromList( levelitem_t* li );
|
||||
|
||||
void BotFreeInfoEntities( void );
|
||||
|
||||
void BotInitInfoEntities( void );
|
||||
|
||||
void InitLevelItemHeap( void );
|
||||
int* ItemWeightIndex( weightconfig_t* iwc, itemconfig_t* ic );
|
||||
itemconfig_t* LoadItemConfig( char* filename );
|
||||
void BotSaveGoalFuzzyLogic( int goalstate, char* filename );
|
||||
void BotMutateGoalFuzzyLogic( int goalstate, float range );
|
||||
bot_goalstate_t* BotGoalStateFromHandle( int handle );
|
||||
void BotInterbreedGoalFuzzyLogic( int parent1, int parent2, int child );
|
||||
private:
|
||||
void ParseItemInfo( idParser& parser, iteminfo_t* itemInfo );
|
||||
private:
|
||||
bot_goalstate_t botgoalstates[MAX_CLIENTS + 1];
|
||||
|
||||
//item configuration
|
||||
itemconfig_t itemconfiglocal;
|
||||
itemconfig_t* itemconfig;
|
||||
|
||||
//level items
|
||||
levelitem_t levelitemheap[MAX_BOT_LEVEL_ITEMS];
|
||||
levelitem_t* freelevelitems;
|
||||
levelitem_t* levelitems;
|
||||
int numlevelitems;
|
||||
|
||||
//map locations
|
||||
idList<maplocation_t> maplocations;
|
||||
idList<campspot_t> campspots;
|
||||
};
|
||||
|
||||
extern idBotGoalManager botGoalManager;
|
||||
@@ -0,0 +1,492 @@
|
||||
// Bot_weapons.cpp
|
||||
//
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
idCVar bot_weaponsfile( "bot_weaponsfile", "weapons.c", CVAR_GAME | CVAR_CHEAT, "which file to load the weapons weights from" );
|
||||
|
||||
idBotWeaponInfoManager botWeaponInfoManager;
|
||||
|
||||
/*
|
||||
=========================
|
||||
idBotWeaponInfoManager::BotValidWeaponNumber
|
||||
=========================
|
||||
*/
|
||||
int idBotWeaponInfoManager::BotValidWeaponNumber( int weaponnum )
|
||||
{
|
||||
if( weaponnum <= 0 || weaponnum > BOT_MAX_WEAPONS )
|
||||
{
|
||||
gameLocal.Error( "weapon number out of range\n" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
idBotWeaponInfoManager::BotWeaponStateFromHandle
|
||||
=========================
|
||||
*/
|
||||
bot_weaponstate_t* idBotWeaponInfoManager::BotWeaponStateFromHandle( int handle )
|
||||
{
|
||||
if( handle <= 0 || handle > MAX_CLIENTS )
|
||||
{
|
||||
gameLocal.Error( "move state handle %d out of range\n", handle );
|
||||
}
|
||||
|
||||
return &botweaponstates[handle];
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idBotWeaponInfoManager::ParseProjectileInfo
|
||||
========================
|
||||
*/
|
||||
void idBotWeaponInfoManager::ParseProjectileInfo( idParser& parser, projectileinfo_t& newProjectileInfo )
|
||||
{
|
||||
idToken token;
|
||||
idToken valueToken;
|
||||
|
||||
parser.ExpectTokenString( "{" );
|
||||
|
||||
while( true )
|
||||
{
|
||||
if( !parser.ReadToken( &token ) )
|
||||
{
|
||||
parser.Error( "Unexpected end of file found while parsing weaponinfo!" );
|
||||
}
|
||||
|
||||
if( token == "}" )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( !parser.ReadToken( &valueToken ) )
|
||||
{
|
||||
parser.Error( "Failed to read value token, encountered EOF parsing weapon info!" );
|
||||
}
|
||||
|
||||
if( token == "name" )
|
||||
{
|
||||
newProjectileInfo.name = valueToken; // name of the projectile
|
||||
}
|
||||
else if( token == "model" )
|
||||
{
|
||||
newProjectileInfo.model = valueToken; // model of the projectile
|
||||
}
|
||||
else if( token == "flags" )
|
||||
{
|
||||
newProjectileInfo.flags = valueToken.GetIntValue(); // special flags
|
||||
}
|
||||
else if( token == "gravity" )
|
||||
{
|
||||
newProjectileInfo.gravity = valueToken.GetFloatValue(); // amount of gravity applied to the projectile [0,1]
|
||||
}
|
||||
else if( token == "damage" )
|
||||
{
|
||||
newProjectileInfo.damage = valueToken.GetIntValue(); // damage of the projectile
|
||||
}
|
||||
else if( token == "radius" )
|
||||
{
|
||||
newProjectileInfo.radius = valueToken.GetFloatValue(); // radius of damage
|
||||
}
|
||||
else if( token == "visdamage" )
|
||||
{
|
||||
newProjectileInfo.visdamage = valueToken.GetIntValue(); // damage of the projectile to visible entities
|
||||
}
|
||||
else if( token == "damagetype" )
|
||||
{
|
||||
newProjectileInfo.damagetype = valueToken.GetIntValue(); // type of damage (combination of the DAMAGETYPE_? flags)
|
||||
}
|
||||
else if( token == "healthinc" )
|
||||
{
|
||||
newProjectileInfo.healthinc = valueToken.GetIntValue(); // health increase the owner gets
|
||||
}
|
||||
else if( token == "push" )
|
||||
{
|
||||
newProjectileInfo.push = valueToken.GetFloatValue(); // amount a player is pushed away from the projectile impact
|
||||
}
|
||||
else if( token == "detonation" )
|
||||
{
|
||||
newProjectileInfo.detonation = valueToken.GetFloatValue(); // time before projectile explodes after fire pressed
|
||||
}
|
||||
else if( token == "bounce" )
|
||||
{
|
||||
newProjectileInfo.bounce = valueToken.GetFloatValue(); // amount the projectile bounces
|
||||
}
|
||||
else if( token == "bouncefric" )
|
||||
{
|
||||
newProjectileInfo.bouncefric = valueToken.GetFloatValue(); // amount the bounce decreases per bounce
|
||||
}
|
||||
else if( token == "bouncestop" )
|
||||
{
|
||||
newProjectileInfo.bouncestop = valueToken.GetFloatValue(); // minimum bounce value before bouncing stops
|
||||
}
|
||||
else
|
||||
{
|
||||
parser.Error( "ParseProjectileInfo: Unexpected token %s\n", token.c_str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idBotWeaponInfoManager::ParseWeaponInfo
|
||||
========================
|
||||
*/
|
||||
void idBotWeaponInfoManager::ParseWeaponInfo( idParser& parser, weaponinfo_t& newWeaponInfo )
|
||||
{
|
||||
idToken token;
|
||||
idToken valueToken;
|
||||
|
||||
parser.ExpectTokenString( "{" );
|
||||
|
||||
while( true )
|
||||
{
|
||||
if( !parser.ReadToken( &token ) )
|
||||
{
|
||||
parser.Error( "Unexpected end of file found while parsing weaponinfo!" );
|
||||
}
|
||||
|
||||
if( token == "}" )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( !parser.ReadToken( &valueToken ) )
|
||||
{
|
||||
parser.Error( "Failed to read value token, encountered EOF parsing weapon info!" );
|
||||
}
|
||||
|
||||
if( token == "number" )
|
||||
{
|
||||
newWeaponInfo.number = valueToken.GetIntValue(); //weapon number
|
||||
}
|
||||
else if( token == "name" )
|
||||
{
|
||||
newWeaponInfo.name = valueToken; //name of the weapon
|
||||
}
|
||||
else if( token == "level" )
|
||||
{
|
||||
newWeaponInfo.level = valueToken.GetIntValue();
|
||||
}
|
||||
else if( token == "model" )
|
||||
{
|
||||
newWeaponInfo.model = valueToken; //model of the weapon
|
||||
}
|
||||
else if( token == "weaponindex" )
|
||||
{
|
||||
newWeaponInfo.weaponindex = valueToken.GetIntValue(); //index of weapon in inventory
|
||||
}
|
||||
else if( token == "flags" )
|
||||
{
|
||||
newWeaponInfo.flags = valueToken.GetIntValue(); //special flags
|
||||
}
|
||||
else if( token == "projectile" )
|
||||
{
|
||||
newWeaponInfo.projectile = valueToken; //projectile used by the weapon
|
||||
}
|
||||
else if( token == "numprojectiles" )
|
||||
{
|
||||
newWeaponInfo.numprojectiles = valueToken.GetIntValue(); //number of projectiles
|
||||
}
|
||||
else if( token == "hspread" )
|
||||
{
|
||||
newWeaponInfo.hspread = valueToken.GetFloatValue(); //horizontal spread of projectiles (degrees from middle)
|
||||
}
|
||||
else if( token == "vspread" )
|
||||
{
|
||||
newWeaponInfo.vspread = valueToken.GetFloatValue(); //vertical spread of projectiles (degrees from middle)
|
||||
}
|
||||
else if( token == "speed" )
|
||||
{
|
||||
newWeaponInfo.speed = valueToken.GetFloatValue(); //speed of the projectile (0 = instant hit)
|
||||
}
|
||||
else
|
||||
{
|
||||
parser.Error( "ParseWeaponInfo: Unexpected token %s\n", token.c_str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idBotWeaponInfoManager::LoadWeaponConfig
|
||||
========================
|
||||
*/
|
||||
void idBotWeaponInfoManager::LoadWeaponConfig( char* filename )
|
||||
{
|
||||
idParser parser;
|
||||
idToken token;
|
||||
int j;
|
||||
|
||||
if( !parser.LoadFile( filename ) )
|
||||
{
|
||||
gameLocal.Error( "Failed to load bot weapon config %s\n", filename );
|
||||
}
|
||||
|
||||
while( parser.ReadToken( &token ) )
|
||||
{
|
||||
if( token == "weaponinfo" )
|
||||
{
|
||||
weaponinfo_t newWeaponInfo;
|
||||
ParseWeaponInfo( parser, newWeaponInfo );
|
||||
|
||||
if( newWeaponInfo.number < 0 || newWeaponInfo.number >= BOT_MAX_WEAPONS )
|
||||
{
|
||||
parser.Error( "weapon info number %d out of range\n", newWeaponInfo.number );
|
||||
return;
|
||||
}
|
||||
|
||||
weaponinfo[newWeaponInfo.number] = newWeaponInfo;
|
||||
weaponinfo[newWeaponInfo.number].valid = true;
|
||||
}
|
||||
else if( token == "projectileinfo" )
|
||||
{
|
||||
projectileinfo_t newProjectileInfo;
|
||||
|
||||
ParseProjectileInfo( parser, newProjectileInfo );
|
||||
|
||||
projectileinfo.Append( newProjectileInfo );
|
||||
}
|
||||
else
|
||||
{
|
||||
parser.Error( "LoadWeaponConfig: Unknown definintion %s", token.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
// fix up weapons.
|
||||
for( int i = 0; i < BOT_MAX_WEAPONS; i++ )
|
||||
{
|
||||
if( !weaponinfo[i].valid )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( weaponinfo[i].name.Length() <= 0 )
|
||||
{
|
||||
parser.Error( "weapon %d has no name\n", i );
|
||||
return;
|
||||
}
|
||||
|
||||
if( weaponinfo[i].projectile.Length() <= 0 )
|
||||
{
|
||||
parser.Error( "weapon %s has no projectile\n", weaponinfo[i].name );
|
||||
return;
|
||||
}
|
||||
|
||||
//find the projectile info and copy it to the weapon info
|
||||
for( j = 0; j < projectileinfo.Num(); j++ )
|
||||
{
|
||||
if( projectileinfo[j].name == weaponinfo[i].projectile )
|
||||
{
|
||||
memcpy( &weaponinfo[i].proj, &projectileinfo[j], sizeof( projectileinfo_t ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( j == projectileinfo.Num() )
|
||||
{
|
||||
parser.Error( "weapon %s uses undefined projectile\n", weaponinfo[i].name.c_str() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idBotWeaponInfoManager::Init
|
||||
========================
|
||||
*/
|
||||
void idBotWeaponInfoManager::Init( void )
|
||||
{
|
||||
rvmScopedLexerBaseFolder scopedBaseFolder( BOTFILESBASEFOLDER );
|
||||
|
||||
LoadWeaponConfig( ( char* )bot_weaponsfile.GetString() );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
WeaponWeightIndex
|
||||
=====================
|
||||
*/
|
||||
void idBotWeaponInfoManager::WeaponWeightIndex( weightconfig_t* wwc, bot_weaponstate_t* weaponState )
|
||||
{
|
||||
for( int i = 0; i < BOT_MAX_WEAPONS; i++ )
|
||||
{
|
||||
weaponState->weaponweightindex[i] = botFuzzyWeightManager.FindFuzzyWeight( wwc, ( char* )weaponinfo[i].name.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
idBotWeaponInfoManager::WeaponWeightIndex
|
||||
=====================
|
||||
*/
|
||||
void idBotWeaponInfoManager::BotFreeWeaponWeights( int weaponstate )
|
||||
{
|
||||
bot_weaponstate_t* ws;
|
||||
|
||||
ws = BotWeaponStateFromHandle( weaponstate );
|
||||
if( !ws )
|
||||
{
|
||||
return;
|
||||
}
|
||||
// if (ws->weaponweightconfig)
|
||||
// FreeWeightConfig(ws->weaponweightconfig);
|
||||
// if (ws->weaponweightindex) FreeMemory(ws->weaponweightindex);
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
BotLoadWeaponWeights
|
||||
=====================
|
||||
*/
|
||||
int idBotWeaponInfoManager::BotLoadWeaponWeights( int weaponstate, char* filename )
|
||||
{
|
||||
bot_weaponstate_t* ws;
|
||||
|
||||
ws = BotWeaponStateFromHandle( weaponstate );
|
||||
if( !ws )
|
||||
{
|
||||
return BLERR_CANNOTLOADWEAPONWEIGHTS;
|
||||
}
|
||||
|
||||
BotFreeWeaponWeights( weaponstate );
|
||||
|
||||
ws->weaponweightconfig = botFuzzyWeightManager.ReadWeightConfig( filename );
|
||||
if( !ws->weaponweightconfig )
|
||||
{
|
||||
gameLocal.Error( "couldn't load weapon config %s\n", filename );
|
||||
return BLERR_CANNOTLOADWEAPONWEIGHTS;
|
||||
}
|
||||
|
||||
WeaponWeightIndex( ws->weaponweightconfig, ws );
|
||||
return BLERR_NOERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
idBotWeaponInfoManager::BotGetWeaponInfo
|
||||
=====================
|
||||
*/
|
||||
void idBotWeaponInfoManager::BotGetWeaponInfo( int weaponstate, int weapon, weaponinfo_t* weaponinfo )
|
||||
{
|
||||
bot_weaponstate_t* ws;
|
||||
|
||||
if( !BotValidWeaponNumber( weapon ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
ws = BotWeaponStateFromHandle( weaponstate );
|
||||
if( !ws )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
*weaponinfo = this->weaponinfo[weapon];
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
idBotWeaponInfoManager::BotChooseBestFightWeapon
|
||||
=====================
|
||||
*/
|
||||
int idBotWeaponInfoManager::BotChooseBestFightWeapon( int weaponstate, int* inventory )
|
||||
{
|
||||
int i, index, bestweapon;
|
||||
float weight, bestweight;
|
||||
bot_weaponstate_t* ws;
|
||||
|
||||
ws = BotWeaponStateFromHandle( weaponstate );
|
||||
if( !ws )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//if the bot has no weapon weight configuration
|
||||
if( !ws->weaponweightconfig )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bestweight = 0;
|
||||
bestweapon = 0;
|
||||
for( i = 0; i < BOT_MAX_WEAPONS; i++ )
|
||||
{
|
||||
if( !weaponinfo[i].valid )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
index = ws->weaponweightindex[i];
|
||||
if( index < 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
weight = botFuzzyWeightManager.FuzzyWeight( inventory, ws->weaponweightconfig, index );
|
||||
if( weight > bestweight )
|
||||
{
|
||||
bestweight = weight;
|
||||
bestweapon = i;
|
||||
}
|
||||
}
|
||||
return bestweapon;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
idBotWeaponInfoManager::BotResetWeaponState
|
||||
=====================
|
||||
*/
|
||||
void idBotWeaponInfoManager::BotResetWeaponState( int weaponstate )
|
||||
{
|
||||
weightconfig_t* weaponweightconfig;
|
||||
int* weaponweightindex;
|
||||
bot_weaponstate_t* ws;
|
||||
|
||||
ws = BotWeaponStateFromHandle( weaponstate );
|
||||
if( !ws )
|
||||
{
|
||||
return;
|
||||
}
|
||||
weaponweightconfig = ws->weaponweightconfig;
|
||||
weaponweightindex = ws->weaponweightindex;
|
||||
|
||||
//Com_Memset(ws, 0, sizeof(bot_weaponstate_t));
|
||||
ws->weaponweightconfig = weaponweightconfig;
|
||||
memcpy( ws->weaponweightindex, weaponweightindex, sizeof( int ) * BOT_MAX_WEAPONS );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
idBotWeaponInfoManager::BotAllocWeaponState
|
||||
=====================
|
||||
*/
|
||||
int idBotWeaponInfoManager::BotAllocWeaponState( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 1; i <= MAX_CLIENTS; i++ )
|
||||
{
|
||||
if( !botweaponstates[i].inUse )
|
||||
{
|
||||
botweaponstates[i].Reset();
|
||||
botweaponstates[i].inUse = true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
idBotWeaponInfoManager::BotAllocWeaponState
|
||||
=====================
|
||||
*/
|
||||
void idBotWeaponInfoManager::BotFreeWeaponState( int ws )
|
||||
{
|
||||
botweaponstates[ws].inUse = false;
|
||||
botweaponstates[ws].Reset();
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
// Bot_weapons.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#define BOT_MAX_WEAPONS 32
|
||||
|
||||
//projectile flags
|
||||
#define PFL_WINDOWDAMAGE 1 //projectile damages through window
|
||||
#define PFL_RETURN 2 //set when projectile returns to owner
|
||||
//weapon flags
|
||||
#define WFL_FIRERELEASED 1 //set when projectile is fired with key-up event
|
||||
//damage types
|
||||
#define DAMAGETYPE_IMPACT 1 //damage on impact
|
||||
#define DAMAGETYPE_RADIAL 2 //radial damage
|
||||
#define DAMAGETYPE_VISIBLE 4 //damage to all entities visible to the projectile
|
||||
|
||||
struct projectileinfo_t
|
||||
{
|
||||
projectileinfo_t()
|
||||
{
|
||||
name = "";
|
||||
model = "";
|
||||
flags = 0;
|
||||
gravity = 0;
|
||||
damage = 0;
|
||||
radius = 0;
|
||||
visdamage = 0;
|
||||
damagetype = 0;
|
||||
healthinc = 0;
|
||||
push = 0;
|
||||
detonation = 0;
|
||||
bounce = 0;
|
||||
bouncefric = 0;
|
||||
bouncestop = 0;
|
||||
}
|
||||
idStr name;
|
||||
idStr model;
|
||||
int flags;
|
||||
float gravity;
|
||||
int damage;
|
||||
float radius;
|
||||
int visdamage;
|
||||
int damagetype;
|
||||
int healthinc;
|
||||
float push;
|
||||
float detonation;
|
||||
float bounce;
|
||||
float bouncefric;
|
||||
float bouncestop;
|
||||
};
|
||||
|
||||
struct weaponinfo_t
|
||||
{
|
||||
weaponinfo_t()
|
||||
{
|
||||
valid = 0;
|
||||
number = 0;
|
||||
name = "";
|
||||
model = "";
|
||||
level = 0;
|
||||
weaponindex = 0;
|
||||
flags = 0;
|
||||
projectile = "";
|
||||
numprojectiles = 0;
|
||||
hspread = 0;
|
||||
vspread = 0;
|
||||
speed = 0;
|
||||
acceleration = 0;
|
||||
recoil.Zero();
|
||||
offset.Zero();
|
||||
angleoffset.Zero();
|
||||
extrazvelocity = 0;
|
||||
ammoamount = 0;
|
||||
ammoindex = 0;
|
||||
activate = 0;
|
||||
reload = 0;
|
||||
spinup = 0;
|
||||
spindown = 0;
|
||||
}
|
||||
|
||||
int valid; //true if the weapon info is valid
|
||||
int number; //number of the weapon
|
||||
idStr name;
|
||||
idStr model;
|
||||
int level;
|
||||
int weaponindex;
|
||||
int flags;
|
||||
idStr projectile;
|
||||
int numprojectiles;
|
||||
float hspread;
|
||||
float vspread;
|
||||
float speed;
|
||||
float acceleration;
|
||||
idVec3 recoil;
|
||||
idVec3 offset;
|
||||
idVec3 angleoffset;
|
||||
float extrazvelocity;
|
||||
int ammoamount;
|
||||
int ammoindex;
|
||||
float activate;
|
||||
float reload;
|
||||
float spinup;
|
||||
float spindown;
|
||||
projectileinfo_t proj; //pointer to the used projectile
|
||||
};
|
||||
|
||||
struct bot_weaponstate_t
|
||||
{
|
||||
bot_weaponstate_t()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
inUse = false;
|
||||
weaponweightconfig = NULL;
|
||||
for( int i = 0; i < BOT_MAX_WEAPONS; i++ )
|
||||
{
|
||||
weaponweightindex[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool inUse;
|
||||
weightconfig_t* weaponweightconfig;
|
||||
int weaponweightindex[BOT_MAX_WEAPONS]; //weapon weight index
|
||||
};
|
||||
|
||||
//
|
||||
// idBotWeaponInfoManager
|
||||
//
|
||||
class idBotWeaponInfoManager
|
||||
{
|
||||
public:
|
||||
void Init( void );
|
||||
|
||||
int BotLoadWeaponWeights( int weaponstate, char* filename );
|
||||
void BotGetWeaponInfo( int weaponstate, int weapon, weaponinfo_t* weaponinfo );
|
||||
int BotChooseBestFightWeapon( int weaponstate, int* inventory );
|
||||
void BotResetWeaponState( int weaponstate );
|
||||
int BotAllocWeaponState( void );
|
||||
void BotFreeWeaponState( int ws );
|
||||
private:
|
||||
int BotValidWeaponNumber( int weaponnum );
|
||||
bot_weaponstate_t* BotWeaponStateFromHandle( int handle );
|
||||
void WeaponWeightIndex( weightconfig_t* wwc, bot_weaponstate_t* weaponState );
|
||||
void BotFreeWeaponWeights( int weaponstate );
|
||||
private:
|
||||
void LoadWeaponConfig( char* filename );
|
||||
|
||||
void ParseWeaponInfo( idParser& parser, weaponinfo_t& newWeaponInfo );
|
||||
void ParseProjectileInfo( idParser& parser, projectileinfo_t& newProjectileInfo );
|
||||
private:
|
||||
idList<projectileinfo_t> projectileinfo;
|
||||
bot_weaponstate_t botweaponstates[MAX_CLIENTS + 1];
|
||||
|
||||
weaponinfo_t weaponinfo[BOT_MAX_WEAPONS];
|
||||
};
|
||||
|
||||
extern idBotWeaponInfoManager botWeaponInfoManager;
|
||||
@@ -0,0 +1,915 @@
|
||||
// Bot_wieghts.cpp
|
||||
//
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
idBotFuzzyWeightManager botFuzzyWeightManager;
|
||||
|
||||
/*
|
||||
========================
|
||||
idBotFuzzyWeightManager::Init
|
||||
========================
|
||||
*/
|
||||
void idBotFuzzyWeightManager::Init( void )
|
||||
{
|
||||
memset( &fuzzyseperators[0], 0, sizeof( fuzzyseperators ) );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idBotFuzzyWeightManager::AllocFuzzyWeight
|
||||
========================
|
||||
*/
|
||||
fuzzyseperator_t* idBotFuzzyWeightManager::AllocFuzzyWeight( void )
|
||||
{
|
||||
for( int i = 0; i < MAX_FUZZY_OPERATORS; i++ )
|
||||
{
|
||||
if( fuzzyseperators[i].inUse == false )
|
||||
{
|
||||
memset( &fuzzyseperators[i], 0, sizeof( fuzzyseperator_t ) );
|
||||
fuzzyseperators[i].inUse = true;
|
||||
return &fuzzyseperators[i];
|
||||
}
|
||||
}
|
||||
|
||||
gameLocal.Error( "AllocFuzzyWeight: Not enough fuzzy weights\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
idBotFuzzyWeightManager::ReadValue
|
||||
========================
|
||||
*/
|
||||
bool idBotFuzzyWeightManager::ReadValue( idParser& source, float* value )
|
||||
{
|
||||
idToken token;
|
||||
|
||||
if( !source.ReadToken( &token ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( token == "-" )
|
||||
{
|
||||
source.Warning( "negative value set to zero\n" );
|
||||
if( !source.ExpectTokenType( TT_NUMBER, 0, &token ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( token.type != TT_NUMBER )
|
||||
{
|
||||
source.Error( "invalid return value %s\n", token.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
*value = token.GetFloatValue();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idBotFuzzyWeightManager::ReadFuzzyWeight
|
||||
===================
|
||||
*/
|
||||
int idBotFuzzyWeightManager::ReadFuzzyWeight( idParser& source, fuzzyseperator_t* fs )
|
||||
{
|
||||
if( source.CheckTokenString( "balance" ) )
|
||||
{
|
||||
fs->type = WT_BALANCE;
|
||||
|
||||
if( !source.ExpectTokenString( "(" ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !ReadValue( source, &fs->weight ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !source.ExpectTokenString( "," ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !ReadValue( source, &fs->minweight ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !source.ExpectTokenString( "," ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !ReadValue( source, &fs->maxweight ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !source.ExpectTokenString( ")" ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fs->type = 0;
|
||||
|
||||
if( !ReadValue( source, &fs->weight ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fs->minweight = fs->weight;
|
||||
fs->maxweight = fs->weight;
|
||||
}
|
||||
|
||||
if( !source.ExpectTokenString( ";" ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idBotFuzzyWeightManager::FreeFuzzySeperators_r
|
||||
===================
|
||||
*/
|
||||
void idBotFuzzyWeightManager::FreeFuzzySeperators_r( fuzzyseperator_t* fs )
|
||||
{
|
||||
if( !fs )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( fs->child )
|
||||
{
|
||||
FreeFuzzySeperators_r( fs->child );
|
||||
}
|
||||
if( fs->next )
|
||||
{
|
||||
FreeFuzzySeperators_r( fs->next );
|
||||
}
|
||||
|
||||
fs->inUse = false;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
FreeWeightConfig2
|
||||
===================
|
||||
*/
|
||||
void idBotFuzzyWeightManager::FreeWeightConfig2( weightconfig_t* config )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < config->numweights; i++ )
|
||||
{
|
||||
FreeFuzzySeperators_r( config->weights[i].firstseperator );
|
||||
// jmarshall - todo
|
||||
//if (config->weights[i].name)
|
||||
// FreeMemory(config->weights[i].name);
|
||||
// jmarshall end
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idBotFuzzyWeightManager::FreeWeightConfig
|
||||
===================
|
||||
*/
|
||||
void idBotFuzzyWeightManager::FreeWeightConfig( weightconfig_t* config )
|
||||
{
|
||||
//if (!LibVarGetValue("bot_reloadcharacters"))
|
||||
// return;
|
||||
|
||||
FreeWeightConfig2( config );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idBotFuzzyWeightManager::ReadFuzzySeperators_r
|
||||
===================
|
||||
*/
|
||||
fuzzyseperator_t* idBotFuzzyWeightManager::ReadFuzzySeperators_r( idParser& source )
|
||||
{
|
||||
int newindent, index, founddefault;
|
||||
bool def;
|
||||
idToken token;
|
||||
fuzzyseperator_t* fs, * lastfs, * firstfs;
|
||||
|
||||
founddefault = false;
|
||||
firstfs = NULL;
|
||||
lastfs = NULL;
|
||||
if( !source.ExpectTokenString( "(" ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !source.ExpectTokenType( TT_NUMBER, TT_INTEGER, &token ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
index = token.GetIntValue();
|
||||
|
||||
if( !source.ExpectTokenString( ")" ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !source.ExpectTokenString( "{" ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !source.ExpectAnyToken( &token ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
def = ( token == "default" ); //!strcmp(token.string, "default");
|
||||
if( def || ( token == "case" ) )
|
||||
{
|
||||
fs = AllocFuzzyWeight();
|
||||
fs->index = index;
|
||||
if( lastfs )
|
||||
{
|
||||
lastfs->next = fs;
|
||||
}
|
||||
else
|
||||
{
|
||||
firstfs = fs;
|
||||
}
|
||||
lastfs = fs;
|
||||
if( def )
|
||||
{
|
||||
if( founddefault )
|
||||
{
|
||||
FreeFuzzySeperators_r( firstfs );
|
||||
gameLocal.Error( "switch already has a default\n" );
|
||||
return NULL;
|
||||
}
|
||||
fs->value = MAX_INVENTORYVALUE;
|
||||
founddefault = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !source.ExpectTokenType( TT_NUMBER, TT_INTEGER, &token ) )
|
||||
{
|
||||
FreeFuzzySeperators_r( firstfs );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fs->value = token.GetIntValue();
|
||||
}
|
||||
|
||||
if( !source.ExpectTokenString( ":" ) || !source.ExpectAnyToken( &token ) )
|
||||
{
|
||||
FreeFuzzySeperators_r( firstfs );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newindent = false;
|
||||
if( token == "{" )
|
||||
{
|
||||
newindent = true;
|
||||
if( !source.ExpectAnyToken( &token ) )
|
||||
{
|
||||
FreeFuzzySeperators_r( firstfs );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( token == "return" )
|
||||
{
|
||||
if( !ReadFuzzyWeight( source, fs ) )
|
||||
{
|
||||
FreeFuzzySeperators_r( firstfs );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if( token == "switch" )
|
||||
{
|
||||
fs->child = ReadFuzzySeperators_r( source );
|
||||
if( !fs->child )
|
||||
{
|
||||
FreeFuzzySeperators_r( firstfs );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gameLocal.Error( "invalid name %s\n", token.c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( newindent )
|
||||
{
|
||||
if( !source.ExpectTokenString( "}" ) )
|
||||
{
|
||||
FreeFuzzySeperators_r( firstfs );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gameLocal.Error( "invalid name %s\n", token.c_str() );
|
||||
FreeFuzzySeperators_r( firstfs );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !source.ExpectAnyToken( &token ) )
|
||||
{
|
||||
FreeFuzzySeperators_r( firstfs );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
while( token != "}" );
|
||||
|
||||
if( !founddefault )
|
||||
{
|
||||
source.Warning( "switch without default\n" );
|
||||
fs = AllocFuzzyWeight();
|
||||
fs->index = index;
|
||||
fs->value = MAX_INVENTORYVALUE;
|
||||
fs->weight = 0;
|
||||
fs->next = NULL;
|
||||
fs->child = NULL;
|
||||
if( lastfs )
|
||||
{
|
||||
lastfs->next = fs;
|
||||
}
|
||||
else
|
||||
{
|
||||
firstfs = fs;
|
||||
}
|
||||
lastfs = fs;
|
||||
}
|
||||
|
||||
return firstfs;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
idBotFuzzyWeightManager::ReadWeightConfig
|
||||
=====================
|
||||
*/
|
||||
weightconfig_t* idBotFuzzyWeightManager::ReadWeightConfig( char* filename )
|
||||
{
|
||||
int newindent, avail = 0, n;
|
||||
idToken token;
|
||||
idParser source;
|
||||
fuzzyseperator_t* fs;
|
||||
weightconfig_t* config = NULL;
|
||||
|
||||
avail = -1;
|
||||
for( n = 0; n < MAX_WEIGHT_FILES; n++ )
|
||||
{
|
||||
config = &weightFileList[n];
|
||||
|
||||
if( config->inUse )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( config->filename == filename )
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
||||
avail = n;
|
||||
break;
|
||||
}
|
||||
|
||||
if( avail == -1 )
|
||||
{
|
||||
gameLocal.Error( "weightFileList was full trying to load %s\n", filename );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rvmScopedLexerBaseFolder scopedBaseFolder( BOTFILESBASEFOLDER );
|
||||
|
||||
if( !source.LoadFile( filename ) )
|
||||
{
|
||||
gameLocal.Error( "couldn't load %s\n", filename );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
config = &weightFileList[avail];
|
||||
config->Reset();
|
||||
|
||||
config->filename = filename;
|
||||
|
||||
//parse the item config file
|
||||
while( source.ReadToken( &token ) )
|
||||
{
|
||||
if( token == "weight" )
|
||||
{
|
||||
if( config->numweights >= MAX_WEIGHTS )
|
||||
{
|
||||
gameLocal.Error( "too many fuzzy weights\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
if( !source.ExpectTokenType( TT_STRING, 0, &token ) )
|
||||
{
|
||||
FreeWeightConfig( config );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
token.StripDoubleQuotes();
|
||||
config->weights[config->numweights].name = token.c_str();
|
||||
|
||||
if( !source.ExpectAnyToken( &token ) )
|
||||
{
|
||||
FreeWeightConfig( config );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newindent = false;
|
||||
if( token == "{" )
|
||||
{
|
||||
newindent = true;
|
||||
if( !source.ExpectAnyToken( &token ) )
|
||||
{
|
||||
FreeWeightConfig( config );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( token == "switch" )
|
||||
{
|
||||
fs = ReadFuzzySeperators_r( source );
|
||||
if( !fs )
|
||||
{
|
||||
FreeWeightConfig( config );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
config->weights[config->numweights].firstseperator = fs;
|
||||
}
|
||||
else if( token == "return" )
|
||||
{
|
||||
fs = ( fuzzyseperator_t* )AllocFuzzyWeight();
|
||||
fs->index = 0;
|
||||
fs->value = MAX_INVENTORYVALUE;
|
||||
fs->next = NULL;
|
||||
fs->child = NULL;
|
||||
if( !ReadFuzzyWeight( source, fs ) )
|
||||
{
|
||||
FreeWeightConfig( config );
|
||||
return NULL;
|
||||
}
|
||||
config->weights[config->numweights].firstseperator = fs;
|
||||
}
|
||||
else
|
||||
{
|
||||
gameLocal.Error( "invalid name %s\n", token.c_str() );
|
||||
FreeWeightConfig( config );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( newindent )
|
||||
{
|
||||
if( !source.ExpectTokenString( "}" ) )
|
||||
{
|
||||
FreeWeightConfig( config );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
config->numweights++;
|
||||
}
|
||||
else
|
||||
{
|
||||
gameLocal.Error( "invalid name %s\n", token.c_str() );
|
||||
FreeWeightConfig( config );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//if the file was located in a pak file
|
||||
common->Printf( "idBotFuzzyWeightManager::ReadWeightConfig: loaded %s\n", filename );
|
||||
config->inUse = true;
|
||||
return config;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
idBotFuzzyWeightManager::FindFuzzyWeight
|
||||
==================
|
||||
*/
|
||||
int idBotFuzzyWeightManager::FindFuzzyWeight( weightconfig_t* wc, char* name )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < wc->numweights; i++ )
|
||||
{
|
||||
if( wc->weights[i].name == name )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
idBotFuzzyWeightManager::FuzzyWeight_r
|
||||
==================
|
||||
*/
|
||||
float idBotFuzzyWeightManager::FuzzyWeight_r( int* inventory, fuzzyseperator_t* fs )
|
||||
{
|
||||
float scale, w1, w2;
|
||||
|
||||
if( inventory[fs->index] < fs->value )
|
||||
{
|
||||
if( fs->child )
|
||||
{
|
||||
return FuzzyWeight_r( inventory, fs->child );
|
||||
}
|
||||
else
|
||||
{
|
||||
return fs->weight;
|
||||
}
|
||||
}
|
||||
else if( fs->next )
|
||||
{
|
||||
if( inventory[fs->index] < fs->next->value )
|
||||
{
|
||||
//first weight
|
||||
if( fs->child )
|
||||
{
|
||||
w1 = FuzzyWeight_r( inventory, fs->child );
|
||||
}
|
||||
else
|
||||
{
|
||||
w1 = fs->weight;
|
||||
}
|
||||
|
||||
//second weight
|
||||
if( fs->next->child )
|
||||
{
|
||||
w2 = FuzzyWeight_r( inventory, fs->next->child );
|
||||
}
|
||||
else
|
||||
{
|
||||
w2 = fs->next->weight;
|
||||
}
|
||||
|
||||
//the scale factor
|
||||
scale = ( inventory[fs->index] - fs->value ) / ( fs->next->value - fs->value );
|
||||
|
||||
//scale between the two weights
|
||||
return scale * w1 + ( 1 - scale ) * w2;
|
||||
}
|
||||
return FuzzyWeight_r( inventory, fs->next );
|
||||
}
|
||||
return fs->weight;
|
||||
}
|
||||
|
||||
/*
|
||||
============================
|
||||
idBotFuzzyWeightManager::FuzzyWeightUndecided_r
|
||||
============================
|
||||
*/
|
||||
float idBotFuzzyWeightManager::FuzzyWeightUndecided_r( int* inventory, fuzzyseperator_t* fs )
|
||||
{
|
||||
float scale, w1, w2;
|
||||
|
||||
if( inventory[fs->index] < fs->value )
|
||||
{
|
||||
if( fs->child )
|
||||
{
|
||||
return FuzzyWeightUndecided_r( inventory, fs->child );
|
||||
}
|
||||
else
|
||||
{
|
||||
return fs->minweight + rvmBotUtil::random() * ( fs->maxweight - fs->minweight );
|
||||
}
|
||||
}
|
||||
else if( fs->next )
|
||||
{
|
||||
if( inventory[fs->index] < fs->next->value )
|
||||
{
|
||||
//first weight
|
||||
if( fs->child )
|
||||
{
|
||||
w1 = FuzzyWeightUndecided_r( inventory, fs->child );
|
||||
}
|
||||
else
|
||||
{
|
||||
w1 = fs->minweight + rvmBotUtil::random() * ( fs->maxweight - fs->minweight );
|
||||
}
|
||||
|
||||
//second weight
|
||||
if( fs->next->child )
|
||||
{
|
||||
w2 = FuzzyWeight_r( inventory, fs->next->child );
|
||||
}
|
||||
else
|
||||
{
|
||||
w2 = fs->next->minweight + rvmBotUtil::random() * ( fs->next->maxweight - fs->next->minweight );
|
||||
}
|
||||
|
||||
//the scale factor
|
||||
scale = ( inventory[fs->index] - fs->value ) / ( fs->next->value - fs->value );
|
||||
|
||||
//scale between the two weights
|
||||
return scale * w1 + ( 1 - scale ) * w2;
|
||||
}
|
||||
return FuzzyWeightUndecided_r( inventory, fs->next );
|
||||
}
|
||||
return fs->weight;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
idBotFuzzyWeightManager::FuzzyWeight
|
||||
=================
|
||||
*/
|
||||
float idBotFuzzyWeightManager::FuzzyWeight( int* inventory, weightconfig_t* wc, int weightnum )
|
||||
{
|
||||
return FuzzyWeight_r( inventory, wc->weights[weightnum].firstseperator );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
idBotFuzzyWeightManager::FuzzyWeightUndecided
|
||||
=================
|
||||
*/
|
||||
float idBotFuzzyWeightManager::FuzzyWeightUndecided( int* inventory, weightconfig_t* wc, int weightnum )
|
||||
{
|
||||
return FuzzyWeightUndecided_r( inventory, wc->weights[weightnum].firstseperator );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idBotFuzzyWeightManager::EvolveFuzzySeperator_r
|
||||
====================
|
||||
*/
|
||||
void idBotFuzzyWeightManager::EvolveFuzzySeperator_r( fuzzyseperator_t* fs )
|
||||
{
|
||||
if( fs->child )
|
||||
{
|
||||
EvolveFuzzySeperator_r( fs->child );
|
||||
}
|
||||
else if( fs->type == WT_BALANCE )
|
||||
{
|
||||
//every once in a while an evolution leap occurs, mutation
|
||||
if( rvmBotUtil::random() < 0.01 )
|
||||
{
|
||||
fs->weight += rvmBotUtil::crandom() * ( fs->maxweight - fs->minweight );
|
||||
}
|
||||
else
|
||||
{
|
||||
fs->weight += rvmBotUtil::crandom() * ( fs->maxweight - fs->minweight ) * 0.5;
|
||||
}
|
||||
|
||||
//modify bounds if necesary because of mutation
|
||||
if( fs->weight < fs->minweight )
|
||||
{
|
||||
fs->minweight = fs->weight;
|
||||
}
|
||||
else if( fs->weight > fs->maxweight )
|
||||
{
|
||||
fs->maxweight = fs->weight;
|
||||
}
|
||||
}
|
||||
if( fs->next )
|
||||
{
|
||||
EvolveFuzzySeperator_r( fs->next );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idBotFuzzyWeightManager::EvolveWeightConfig
|
||||
====================
|
||||
*/
|
||||
void idBotFuzzyWeightManager::EvolveWeightConfig( weightconfig_t* config )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < config->numweights; i++ )
|
||||
{
|
||||
EvolveFuzzySeperator_r( config->weights[i].firstseperator );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idBotFuzzyWeightManager::ScaleWeight
|
||||
====================
|
||||
*/
|
||||
void idBotFuzzyWeightManager::ScaleFuzzySeperator_r( fuzzyseperator_t* fs, float scale )
|
||||
{
|
||||
if( fs->child )
|
||||
{
|
||||
ScaleFuzzySeperator_r( fs->child, scale );
|
||||
}
|
||||
else if( fs->type == WT_BALANCE )
|
||||
{
|
||||
fs->weight = ( fs->maxweight + fs->minweight ) * scale;
|
||||
|
||||
//get the weight between bounds
|
||||
if( fs->weight < fs->minweight )
|
||||
{
|
||||
fs->weight = fs->minweight;
|
||||
}
|
||||
else if( fs->weight > fs->maxweight )
|
||||
{
|
||||
fs->weight = fs->maxweight;
|
||||
}
|
||||
}
|
||||
if( fs->next )
|
||||
{
|
||||
ScaleFuzzySeperator_r( fs->next, scale );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idBotFuzzyWeightManager::ScaleWeight
|
||||
====================
|
||||
*/
|
||||
void idBotFuzzyWeightManager::ScaleWeight( weightconfig_t* config, char* name, float scale )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( scale < 0 )
|
||||
{
|
||||
scale = 0;
|
||||
}
|
||||
else if( scale > 1 )
|
||||
{
|
||||
scale = 1;
|
||||
}
|
||||
for( i = 0; i < config->numweights; i++ )
|
||||
{
|
||||
if( config->weights[i].name == name )
|
||||
{
|
||||
ScaleFuzzySeperator_r( config->weights[i].firstseperator, scale );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idBotFuzzyWeightManager::ScaleFuzzySeperatorBalanceRange_r
|
||||
====================
|
||||
*/
|
||||
void idBotFuzzyWeightManager::ScaleFuzzySeperatorBalanceRange_r( fuzzyseperator_t* fs, float scale )
|
||||
{
|
||||
if( fs->child )
|
||||
{
|
||||
ScaleFuzzySeperatorBalanceRange_r( fs->child, scale );
|
||||
}
|
||||
else if( fs->type == WT_BALANCE )
|
||||
{
|
||||
float mid = ( fs->minweight + fs->maxweight ) * 0.5;
|
||||
//get the weight between bounds
|
||||
fs->maxweight = mid + ( fs->maxweight - mid ) * scale;
|
||||
fs->minweight = mid + ( fs->minweight - mid ) * scale;
|
||||
if( fs->maxweight < fs->minweight )
|
||||
{
|
||||
fs->maxweight = fs->minweight;
|
||||
}
|
||||
}
|
||||
if( fs->next )
|
||||
{
|
||||
ScaleFuzzySeperatorBalanceRange_r( fs->next, scale );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idBotFuzzyWeightManager::ScaleFuzzyBalanceRange
|
||||
====================
|
||||
*/
|
||||
void idBotFuzzyWeightManager::ScaleFuzzyBalanceRange( weightconfig_t* config, float scale )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( scale < 0 )
|
||||
{
|
||||
scale = 0;
|
||||
}
|
||||
else if( scale > 100 )
|
||||
{
|
||||
scale = 100;
|
||||
}
|
||||
for( i = 0; i < config->numweights; i++ )
|
||||
{
|
||||
ScaleFuzzySeperatorBalanceRange_r( config->weights[i].firstseperator, scale );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idBotFuzzyWeightManager::InterbreedFuzzySeperator_r
|
||||
====================
|
||||
*/
|
||||
int idBotFuzzyWeightManager::InterbreedFuzzySeperator_r( fuzzyseperator_t* fs1, fuzzyseperator_t* fs2, fuzzyseperator_t* fsout )
|
||||
{
|
||||
if( fs1->child )
|
||||
{
|
||||
if( !fs2->child || !fsout->child )
|
||||
{
|
||||
gameLocal.Error( "cannot interbreed weight configs, unequal child\n" );
|
||||
return false;
|
||||
}
|
||||
if( !InterbreedFuzzySeperator_r( fs2->child, fs2->child, fsout->child ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if( fs1->type == WT_BALANCE )
|
||||
{
|
||||
if( fs2->type != WT_BALANCE || fsout->type != WT_BALANCE )
|
||||
{
|
||||
gameLocal.Error( "cannot interbreed weight configs, unequal balance\n" );
|
||||
return false;
|
||||
}
|
||||
fsout->weight = ( fs1->weight + fs2->weight ) / 2;
|
||||
if( fsout->weight > fsout->maxweight )
|
||||
{
|
||||
fsout->maxweight = fsout->weight;
|
||||
}
|
||||
if( fsout->weight > fsout->minweight )
|
||||
{
|
||||
fsout->minweight = fsout->weight;
|
||||
}
|
||||
}
|
||||
if( fs1->next )
|
||||
{
|
||||
if( !fs2->next || !fsout->next )
|
||||
{
|
||||
gameLocal.Error( "cannot interbreed weight configs, unequal next\n" );
|
||||
return false;
|
||||
}
|
||||
if( !InterbreedFuzzySeperator_r( fs1->next, fs2->next, fsout->next ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idBotFuzzyWeightManager::InterbreedWeightConfigs
|
||||
====================
|
||||
*/
|
||||
void idBotFuzzyWeightManager::InterbreedWeightConfigs( weightconfig_t* config1, weightconfig_t* config2, weightconfig_t* configout )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( config1->numweights != config2->numweights ||
|
||||
config1->numweights != configout->numweights )
|
||||
{
|
||||
gameLocal.Error( "cannot interbreed weight configs, unequal numweights\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
for( i = 0; i < config1->numweights; i++ )
|
||||
{
|
||||
InterbreedFuzzySeperator_r( config1->weights[i].firstseperator,
|
||||
config2->weights[i].firstseperator,
|
||||
configout->weights[i].firstseperator );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=======================
|
||||
idBotFuzzyWeightManager::BotShutdownWeights
|
||||
=======================
|
||||
*/
|
||||
void idBotFuzzyWeightManager::BotShutdownWeights( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < MAX_WEIGHT_FILES; i++ )
|
||||
{
|
||||
weightFileList[i].inUse = false;
|
||||
//if (weightFileList[i])
|
||||
//{
|
||||
// FreeWeightConfig2(weightFileList[i]);
|
||||
// weightFileList[i] = NULL;
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// Bot_weights.h
|
||||
//
|
||||
|
||||
#define MAX_INVENTORYVALUE 999999
|
||||
#define EVALUATERECURSIVELY
|
||||
|
||||
#define MAX_WEIGHT_FILES 128
|
||||
#define MAX_FUZZY_OPERATORS 8192
|
||||
|
||||
class idBotFuzzyWeightManager
|
||||
{
|
||||
public:
|
||||
// Init the fuzzy weight manager.
|
||||
void Init( void );
|
||||
|
||||
// Parses a weight config file.
|
||||
weightconfig_t* ReadWeightConfig( char* filename );
|
||||
|
||||
void BotShutdownWeights( void );
|
||||
|
||||
// Fuzzy Weight simulation functions.
|
||||
int FindFuzzyWeight( weightconfig_t* wc, char* name );
|
||||
float FuzzyWeight( int* inventory, weightconfig_t* wc, int weightnum );
|
||||
float FuzzyWeightUndecided( int* inventory, weightconfig_t* wc, int weightnum );
|
||||
void EvolveFuzzySeperator_r( fuzzyseperator_t* fs );
|
||||
void EvolveWeightConfig( weightconfig_t* config );
|
||||
void ScaleWeight( weightconfig_t* config, char* name, float scale );
|
||||
void ScaleFuzzyBalanceRange( weightconfig_t* config, float scale );
|
||||
void InterbreedWeightConfigs( weightconfig_t* config1, weightconfig_t* config2, weightconfig_t* configout );
|
||||
void FreeWeightConfig( weightconfig_t* config );
|
||||
private:
|
||||
fuzzyseperator_t* AllocFuzzyWeight( void );
|
||||
bool ReadValue( idParser& source, float* value );
|
||||
int ReadFuzzyWeight( idParser& source, fuzzyseperator_t* fs );
|
||||
|
||||
int InterbreedFuzzySeperator_r( fuzzyseperator_t* fs1, fuzzyseperator_t* fs2, fuzzyseperator_t* fsout );
|
||||
|
||||
fuzzyseperator_t* ReadFuzzySeperators_r( idParser& source );
|
||||
|
||||
void FreeWeightConfig2( weightconfig_t* config );
|
||||
void FreeFuzzySeperators_r( fuzzyseperator_t* fs );
|
||||
|
||||
void ScaleFuzzySeperatorBalanceRange_r( fuzzyseperator_t* fs, float scale );
|
||||
|
||||
void ScaleFuzzySeperator_r( fuzzyseperator_t* fs, float scale );
|
||||
float FuzzyWeight_r( int* inventory, fuzzyseperator_t* fs );
|
||||
float FuzzyWeightUndecided_r( int* inventory, fuzzyseperator_t* fs );
|
||||
|
||||
weightconfig_t weightFileList[MAX_WEIGHT_FILES];
|
||||
fuzzyseperator_t fuzzyseperators[MAX_FUZZY_OPERATORS];
|
||||
};
|
||||
|
||||
extern idBotFuzzyWeightManager botFuzzyWeightManager;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,10 +7,10 @@
|
||||
|
||||
This file has been generated with the Type Info Generator v1.1 (c) 2004 id Software
|
||||
|
||||
1178 constants
|
||||
131 enums
|
||||
536 classes/structs/unions
|
||||
37 templates
|
||||
1172 constants
|
||||
130 enums
|
||||
556 classes/structs/unions
|
||||
38 templates
|
||||
7 max inheritance level for 'idAI_Vagary'
|
||||
|
||||
===================================================================================
|
||||
@@ -952,12 +952,6 @@ static constantInfo_t constantInfo[] = {
|
||||
{ "int", "idProjectile::LAUNCHED", "2" },
|
||||
{ "int", "idProjectile::FIZZLED", "3" },
|
||||
{ "int", "idProjectile::EXPLODED", "4" },
|
||||
{ "int", "WP_READY", "0" },
|
||||
{ "int", "WP_OUTOFAMMO", "1" },
|
||||
{ "int", "WP_RELOAD", "2" },
|
||||
{ "int", "WP_HOLSTERED", "3" },
|
||||
{ "int", "WP_RISING", "4" },
|
||||
{ "int", "WP_LOWERING", "5" },
|
||||
{ "static const int", "AMMO_NUMTYPES", "16" },
|
||||
{ "static const int", "LIGHTID_WORLD_MUZZLE_FLASH", "1" },
|
||||
{ "static const int", "LIGHTID_VIEW_MUZZLE_FLASH", "100" },
|
||||
@@ -2381,17 +2375,7 @@ static enumValueInfo_t idProjectile_projectileState_t_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static enumValueInfo_t weaponStatus_t_typeInfo[] = {
|
||||
{ "WP_READY", 0 },
|
||||
{ "WP_OUTOFAMMO", 1 },
|
||||
{ "WP_RELOAD", 2 },
|
||||
{ "WP_HOLSTERED", 3 },
|
||||
{ "WP_RISING", 4 },
|
||||
{ "WP_LOWERING", 5 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static enumValueInfo_t idWeapon_enum_108_typeInfo[] = {
|
||||
static enumValueInfo_t idWeapon_enum_107_typeInfo[] = {
|
||||
{ "EVENT_RELOAD", 2 },
|
||||
{ "EVENT_ENDRELOAD", 3 },
|
||||
{ "EVENT_CHANGESKIN", 4 },
|
||||
@@ -2399,13 +2383,13 @@ static enumValueInfo_t idWeapon_enum_108_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static enumValueInfo_t idLight_enum_109_typeInfo[] = {
|
||||
static enumValueInfo_t idLight_enum_108_typeInfo[] = {
|
||||
{ "EVENT_BECOMEBROKEN", 2 },
|
||||
{ "EVENT_MAXEVENTS", 3 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static enumValueInfo_t idItem_enum_110_typeInfo[] = {
|
||||
static enumValueInfo_t idItem_enum_109_typeInfo[] = {
|
||||
{ "EVENT_PICKUP", 2 },
|
||||
{ "EVENT_RESPAWN", 3 },
|
||||
{ "EVENT_RESPAWNFX", 4 },
|
||||
@@ -2420,7 +2404,7 @@ static enumValueInfo_t playerIconType_t_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static enumValueInfo_t enum_112_typeInfo[] = {
|
||||
static enumValueInfo_t enum_111_typeInfo[] = {
|
||||
{ "BERSERK", 0 },
|
||||
{ "INVISIBILITY", 1 },
|
||||
{ "MEGAHEALTH", 2 },
|
||||
@@ -2429,7 +2413,7 @@ static enumValueInfo_t enum_112_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static enumValueInfo_t enum_113_typeInfo[] = {
|
||||
static enumValueInfo_t enum_112_typeInfo[] = {
|
||||
{ "SPEED", 0 },
|
||||
{ "PROJECTILE_DAMAGE", 1 },
|
||||
{ "MELEE_DAMAGE", 2 },
|
||||
@@ -2437,7 +2421,7 @@ static enumValueInfo_t enum_113_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static enumValueInfo_t enum_114_typeInfo[] = {
|
||||
static enumValueInfo_t enum_113_typeInfo[] = {
|
||||
{ "INFLUENCE_NONE", 0 },
|
||||
{ "INFLUENCE_LEVEL1", 1 },
|
||||
{ "INFLUENCE_LEVEL2", 2 },
|
||||
@@ -2445,7 +2429,7 @@ static enumValueInfo_t enum_114_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static enumValueInfo_t idPlayer_enum_115_typeInfo[] = {
|
||||
static enumValueInfo_t idPlayer_enum_114_typeInfo[] = {
|
||||
{ "EVENT_IMPULSE", 2 },
|
||||
{ "EVENT_EXIT_TELEPORTER", 3 },
|
||||
{ "EVENT_ABORT_TELEPORTER", 4 },
|
||||
@@ -2502,7 +2486,7 @@ static enumValueInfo_t moverState_t_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static enumValueInfo_t idExplodingBarrel_enum_121_typeInfo[] = {
|
||||
static enumValueInfo_t idExplodingBarrel_enum_120_typeInfo[] = {
|
||||
{ "EVENT_EXPLODE", 2 },
|
||||
{ "EVENT_MAXEVENTS", 3 },
|
||||
{ NULL, 0 }
|
||||
@@ -2516,7 +2500,7 @@ static enumValueInfo_t idExplodingBarrel_explode_state_t_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static enumValueInfo_t idSecurityCamera_enum_123_typeInfo[] = {
|
||||
static enumValueInfo_t idSecurityCamera_enum_122_typeInfo[] = {
|
||||
{ "SCANNING", 0 },
|
||||
{ "LOSINGINTEREST", 1 },
|
||||
{ "ALERT", 2 },
|
||||
@@ -2524,7 +2508,7 @@ static enumValueInfo_t idSecurityCamera_enum_123_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static enumValueInfo_t idBrittleFracture_enum_124_typeInfo[] = {
|
||||
static enumValueInfo_t idBrittleFracture_enum_123_typeInfo[] = {
|
||||
{ "EVENT_PROJECT_DECAL", 2 },
|
||||
{ "EVENT_SHATTER", 3 },
|
||||
{ "EVENT_MAXEVENTS", 4 },
|
||||
@@ -2591,7 +2575,7 @@ static enumValueInfo_t stopEvent_t_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static enumValueInfo_t enum_130_typeInfo[] = {
|
||||
static enumValueInfo_t enum_129_typeInfo[] = {
|
||||
{ "OP_RETURN", 0 },
|
||||
{ "OP_UINC_F", 1 },
|
||||
{ "OP_UINCP_F", 2 },
|
||||
@@ -2827,30 +2811,29 @@ static enumTypeInfo_t enumTypeInfo[] = {
|
||||
{ "idPlayerStart::enum_104", idPlayerStart_enum_104_typeInfo },
|
||||
{ "idProjectile::enum_105", idProjectile_enum_105_typeInfo },
|
||||
{ "idProjectile::projectileState_t", idProjectile_projectileState_t_typeInfo },
|
||||
{ "weaponStatus_t", weaponStatus_t_typeInfo },
|
||||
{ "idWeapon::enum_108", idWeapon_enum_108_typeInfo },
|
||||
{ "idLight::enum_109", idLight_enum_109_typeInfo },
|
||||
{ "idItem::enum_110", idItem_enum_110_typeInfo },
|
||||
{ "idWeapon::enum_107", idWeapon_enum_107_typeInfo },
|
||||
{ "idLight::enum_108", idLight_enum_108_typeInfo },
|
||||
{ "idItem::enum_109", idItem_enum_109_typeInfo },
|
||||
{ "playerIconType_t", playerIconType_t_typeInfo },
|
||||
{ "enum_111", enum_111_typeInfo },
|
||||
{ "enum_112", enum_112_typeInfo },
|
||||
{ "enum_113", enum_113_typeInfo },
|
||||
{ "enum_114", enum_114_typeInfo },
|
||||
{ "idPlayer::enum_115", idPlayer_enum_115_typeInfo },
|
||||
{ "idPlayer::enum_114", idPlayer_enum_114_typeInfo },
|
||||
{ "idMover::moveStage_t", idMover_moveStage_t_typeInfo },
|
||||
{ "idMover::moverCommand_t", idMover_moverCommand_t_typeInfo },
|
||||
{ "idMover::moverDir_t", idMover_moverDir_t_typeInfo },
|
||||
{ "idElevator::elevatorState_t", idElevator_elevatorState_t_typeInfo },
|
||||
{ "moverState_t", moverState_t_typeInfo },
|
||||
{ "idExplodingBarrel::enum_121", idExplodingBarrel_enum_121_typeInfo },
|
||||
{ "idExplodingBarrel::enum_120", idExplodingBarrel_enum_120_typeInfo },
|
||||
{ "idExplodingBarrel::explode_state_t", idExplodingBarrel_explode_state_t_typeInfo },
|
||||
{ "idSecurityCamera::enum_123", idSecurityCamera_enum_123_typeInfo },
|
||||
{ "idBrittleFracture::enum_124", idBrittleFracture_enum_124_typeInfo },
|
||||
{ "idSecurityCamera::enum_122", idSecurityCamera_enum_122_typeInfo },
|
||||
{ "idBrittleFracture::enum_123", idBrittleFracture_enum_123_typeInfo },
|
||||
{ "moveType_t", moveType_t_typeInfo },
|
||||
{ "moveCommand_t", moveCommand_t_typeInfo },
|
||||
{ "talkState_t", talkState_t_typeInfo },
|
||||
{ "moveStatus_t", moveStatus_t_typeInfo },
|
||||
{ "stopEvent_t", stopEvent_t_typeInfo },
|
||||
{ "enum_130", enum_130_typeInfo },
|
||||
{ "enum_129", enum_129_typeInfo },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
@@ -2945,6 +2928,10 @@ static classVariableInfo_t idMath_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvRandom_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t idRandom_typeInfo[] = {
|
||||
{ ": int", "seed", (intptr_t)(&((idRandom *)0)->seed), sizeof( ((idRandom *)0)->seed ) },
|
||||
{ NULL, 0 }
|
||||
@@ -4001,9 +3988,9 @@ static classVariableInfo_t glRaytracingVec3_t_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t glRaytracingLight_s_class_171_typeInfo[] = {
|
||||
// { "float", "pad1", (intptr_t)(&((glRaytracingLight_s::class_171 *)0)->pad1), sizeof( ((glRaytracingLight_s::class_171 *)0)->pad1 ) },
|
||||
// { "float", "volumetricScattering", (intptr_t)(&((glRaytracingLight_s::class_171 *)0)->volumetricScattering), sizeof( ((glRaytracingLight_s::class_171 *)0)->volumetricScattering ) },
|
||||
static classVariableInfo_t glRaytracingLight_s_class_172_typeInfo[] = {
|
||||
// { "float", "pad1", (intptr_t)(&((glRaytracingLight_s::class_172 *)0)->pad1), sizeof( ((glRaytracingLight_s::class_172 *)0)->pad1 ) },
|
||||
// { "float", "volumetricScattering", (intptr_t)(&((glRaytracingLight_s::class_172 *)0)->volumetricScattering), sizeof( ((glRaytracingLight_s::class_172 *)0)->volumetricScattering ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
@@ -5120,11 +5107,11 @@ static classVariableInfo_t frameLookup_t_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t class_280_class_280_typeInfo[] = {
|
||||
// { "const idSoundShader *", "soundShader", (intptr_t)(&((class_280::class_280 *)0)->soundShader), sizeof( ((class_280::class_280 *)0)->soundShader ) },
|
||||
// { "const function_t *", "function", (intptr_t)(&((class_280::class_280 *)0)->function), sizeof( ((class_280::class_280 *)0)->function ) },
|
||||
// { "const idDeclSkin *", "skin", (intptr_t)(&((class_280::class_280 *)0)->skin), sizeof( ((class_280::class_280 *)0)->skin ) },
|
||||
// { "int", "index", (intptr_t)(&((class_280::class_280 *)0)->index), sizeof( ((class_280::class_280 *)0)->index ) },
|
||||
static classVariableInfo_t class_281_class_281_typeInfo[] = {
|
||||
// { "const idSoundShader *", "soundShader", (intptr_t)(&((class_281::class_281 *)0)->soundShader), sizeof( ((class_281::class_281 *)0)->soundShader ) },
|
||||
// { "const function_t *", "function", (intptr_t)(&((class_281::class_281 *)0)->function), sizeof( ((class_281::class_281 *)0)->function ) },
|
||||
// { "const idDeclSkin *", "skin", (intptr_t)(&((class_281::class_281 *)0)->skin), sizeof( ((class_281::class_281 *)0)->skin ) },
|
||||
// { "int", "index", (intptr_t)(&((class_281::class_281 *)0)->index), sizeof( ((class_281::class_281 *)0)->index ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
@@ -5462,6 +5449,12 @@ static classVariableInfo_t idEventQueue_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmGameDelayRemoveEntry_t_typeInfo[] = {
|
||||
{ "int32_t", "removeTime", (intptr_t)(&((rvmGameDelayRemoveEntry_t *)0)->removeTime), sizeof( ((rvmGameDelayRemoveEntry_t *)0)->removeTime ) },
|
||||
{ "idEntity *", "entity", (intptr_t)(&((rvmGameDelayRemoveEntry_t *)0)->entity), sizeof( ((rvmGameDelayRemoveEntry_t *)0)->entity ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t idGameLocal_typeInfo[] = {
|
||||
{ ": idDict", "serverInfo", (intptr_t)(&((idGameLocal *)0)->serverInfo), sizeof( ((idGameLocal *)0)->serverInfo ) },
|
||||
{ "int", "numClients", (intptr_t)(&((idGameLocal *)0)->numClients), sizeof( ((idGameLocal *)0)->numClients ) },
|
||||
@@ -5547,6 +5540,7 @@ static classVariableInfo_t idGameLocal_typeInfo[] = {
|
||||
{ "idDict", "newInfo", (intptr_t)(&((idGameLocal *)0)->newInfo), sizeof( ((idGameLocal *)0)->newInfo ) },
|
||||
{ "idStrList", "shakeSounds", (intptr_t)(&((idGameLocal *)0)->shakeSounds), sizeof( ((idGameLocal *)0)->shakeSounds ) },
|
||||
{ "byte[16384]", "lagometer", (intptr_t)(&((idGameLocal *)0)->lagometer), sizeof( ((idGameLocal *)0)->lagometer ) },
|
||||
{ "idList < rvmGameDelayRemoveEntry_t >", "delayRemoveEntities", (intptr_t)(&((idGameLocal *)0)->delayRemoveEntities), sizeof( ((idGameLocal *)0)->delayRemoveEntities ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
@@ -6772,20 +6766,39 @@ static classVariableInfo_t idDebris_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t WeaponParticle_t_typeInfo[] = {
|
||||
{ "char[64]", "name", (intptr_t)(&((WeaponParticle_t *)0)->name), sizeof( ((WeaponParticle_t *)0)->name ) },
|
||||
{ "char[128]", "particlename", (intptr_t)(&((WeaponParticle_t *)0)->particlename), sizeof( ((WeaponParticle_t *)0)->particlename ) },
|
||||
{ "bool", "active", (intptr_t)(&((WeaponParticle_t *)0)->active), sizeof( ((WeaponParticle_t *)0)->active ) },
|
||||
{ "int", "startTime", (intptr_t)(&((WeaponParticle_t *)0)->startTime), sizeof( ((WeaponParticle_t *)0)->startTime ) },
|
||||
{ "jointHandle_t", "joint", (intptr_t)(&((WeaponParticle_t *)0)->joint), sizeof( ((WeaponParticle_t *)0)->joint ) },
|
||||
{ "bool", "smoke", (intptr_t)(&((WeaponParticle_t *)0)->smoke), sizeof( ((WeaponParticle_t *)0)->smoke ) },
|
||||
{ "const idDeclParticle *", "particle", (intptr_t)(&((WeaponParticle_t *)0)->particle), sizeof( ((WeaponParticle_t *)0)->particle ) },
|
||||
{ "idFuncEmitter *", "emitter", (intptr_t)(&((WeaponParticle_t *)0)->emitter), sizeof( ((WeaponParticle_t *)0)->emitter ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t WeaponLight_t_typeInfo[] = {
|
||||
{ "char[64]", "name", (intptr_t)(&((WeaponLight_t *)0)->name), sizeof( ((WeaponLight_t *)0)->name ) },
|
||||
{ "bool", "active", (intptr_t)(&((WeaponLight_t *)0)->active), sizeof( ((WeaponLight_t *)0)->active ) },
|
||||
{ "int", "startTime", (intptr_t)(&((WeaponLight_t *)0)->startTime), sizeof( ((WeaponLight_t *)0)->startTime ) },
|
||||
{ "jointHandle_t", "joint", (intptr_t)(&((WeaponLight_t *)0)->joint), sizeof( ((WeaponLight_t *)0)->joint ) },
|
||||
{ "int", "lightHandle", (intptr_t)(&((WeaponLight_t *)0)->lightHandle), sizeof( ((WeaponLight_t *)0)->lightHandle ) },
|
||||
{ "renderLight_t", "light", (intptr_t)(&((WeaponLight_t *)0)->light), sizeof( ((WeaponLight_t *)0)->light ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponObject_typeInfo[] = {
|
||||
{ ": idWeapon *", "owner", (intptr_t)(&((rvmWeaponObject *)0)->owner), sizeof( ((rvmWeaponObject *)0)->owner ) },
|
||||
{ ": rvStateThread", "stateThread", (intptr_t)(&((rvmWeaponObject *)0)->stateThread), sizeof( ((rvmWeaponObject *)0)->stateThread ) },
|
||||
{ "float", "next_attack", (intptr_t)(&((rvmWeaponObject *)0)->next_attack), sizeof( ((rvmWeaponObject *)0)->next_attack ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t idWeapon_typeInfo[] = {
|
||||
{ ": idScriptBool", "WEAPON_ATTACK", (intptr_t)(&((idWeapon *)0)->WEAPON_ATTACK), sizeof( ((idWeapon *)0)->WEAPON_ATTACK ) },
|
||||
{ "idScriptBool", "WEAPON_RELOAD", (intptr_t)(&((idWeapon *)0)->WEAPON_RELOAD), sizeof( ((idWeapon *)0)->WEAPON_RELOAD ) },
|
||||
{ "idScriptBool", "WEAPON_NETRELOAD", (intptr_t)(&((idWeapon *)0)->WEAPON_NETRELOAD), sizeof( ((idWeapon *)0)->WEAPON_NETRELOAD ) },
|
||||
{ "idScriptBool", "WEAPON_NETENDRELOAD", (intptr_t)(&((idWeapon *)0)->WEAPON_NETENDRELOAD), sizeof( ((idWeapon *)0)->WEAPON_NETENDRELOAD ) },
|
||||
{ "idScriptBool", "WEAPON_NETFIRING", (intptr_t)(&((idWeapon *)0)->WEAPON_NETFIRING), sizeof( ((idWeapon *)0)->WEAPON_NETFIRING ) },
|
||||
{ "idScriptBool", "WEAPON_RAISEWEAPON", (intptr_t)(&((idWeapon *)0)->WEAPON_RAISEWEAPON), sizeof( ((idWeapon *)0)->WEAPON_RAISEWEAPON ) },
|
||||
{ "idScriptBool", "WEAPON_LOWERWEAPON", (intptr_t)(&((idWeapon *)0)->WEAPON_LOWERWEAPON), sizeof( ((idWeapon *)0)->WEAPON_LOWERWEAPON ) },
|
||||
{ "weaponStatus_t", "status", (intptr_t)(&((idWeapon *)0)->status), sizeof( ((idWeapon *)0)->status ) },
|
||||
{ "idThread *", "thread", (intptr_t)(&((idWeapon *)0)->thread), sizeof( ((idWeapon *)0)->thread ) },
|
||||
{ "idStr", "state", (intptr_t)(&((idWeapon *)0)->state), sizeof( ((idWeapon *)0)->state ) },
|
||||
{ "idStr", "idealState", (intptr_t)(&((idWeapon *)0)->idealState), sizeof( ((idWeapon *)0)->idealState ) },
|
||||
{ "int", "animBlendFrames", (intptr_t)(&((idWeapon *)0)->animBlendFrames), sizeof( ((idWeapon *)0)->animBlendFrames ) },
|
||||
{ ": int", "animBlendFrames", (intptr_t)(&((idWeapon *)0)->animBlendFrames), sizeof( ((idWeapon *)0)->animBlendFrames ) },
|
||||
{ "int", "animDoneTime", (intptr_t)(&((idWeapon *)0)->animDoneTime), sizeof( ((idWeapon *)0)->animDoneTime ) },
|
||||
{ "bool", "isPlayerFlashlight", (intptr_t)(&((idWeapon *)0)->isPlayerFlashlight), sizeof( ((idWeapon *)0)->isPlayerFlashlight ) },
|
||||
{ "bool", "isLinked", (intptr_t)(&((idWeapon *)0)->isLinked), sizeof( ((idWeapon *)0)->isLinked ) },
|
||||
{ "idEntity *", "projectileEnt", (intptr_t)(&((idWeapon *)0)->projectileEnt), sizeof( ((idWeapon *)0)->projectileEnt ) },
|
||||
{ "idPlayer *", "owner", (intptr_t)(&((idWeapon *)0)->owner), sizeof( ((idWeapon *)0)->owner ) },
|
||||
@@ -6798,6 +6811,7 @@ static classVariableInfo_t idWeapon_typeInfo[] = {
|
||||
{ "float", "hideOffset", (intptr_t)(&((idWeapon *)0)->hideOffset), sizeof( ((idWeapon *)0)->hideOffset ) },
|
||||
{ "bool", "hide", (intptr_t)(&((idWeapon *)0)->hide), sizeof( ((idWeapon *)0)->hide ) },
|
||||
{ "bool", "disabled", (intptr_t)(&((idWeapon *)0)->disabled), sizeof( ((idWeapon *)0)->disabled ) },
|
||||
{ "bool", "isFlashLight", (intptr_t)(&((idWeapon *)0)->isFlashLight), sizeof( ((idWeapon *)0)->isFlashLight ) },
|
||||
{ "int", "berserk", (intptr_t)(&((idWeapon *)0)->berserk), sizeof( ((idWeapon *)0)->berserk ) },
|
||||
{ "idVec3", "playerViewOrigin", (intptr_t)(&((idWeapon *)0)->playerViewOrigin), sizeof( ((idWeapon *)0)->playerViewOrigin ) },
|
||||
{ "idMat3", "playerViewAxis", (intptr_t)(&((idWeapon *)0)->playerViewAxis), sizeof( ((idWeapon *)0)->playerViewAxis ) },
|
||||
@@ -6814,12 +6828,17 @@ static classVariableInfo_t idWeapon_typeInfo[] = {
|
||||
{ "idDict", "brassDict", (intptr_t)(&((idWeapon *)0)->brassDict), sizeof( ((idWeapon *)0)->brassDict ) },
|
||||
{ "int", "brassDelay", (intptr_t)(&((idWeapon *)0)->brassDelay), sizeof( ((idWeapon *)0)->brassDelay ) },
|
||||
{ "idStr", "icon", (intptr_t)(&((idWeapon *)0)->icon), sizeof( ((idWeapon *)0)->icon ) },
|
||||
{ "idStr", "pdaIcon", (intptr_t)(&((idWeapon *)0)->pdaIcon), sizeof( ((idWeapon *)0)->pdaIcon ) },
|
||||
{ "idStr", "displayName", (intptr_t)(&((idWeapon *)0)->displayName), sizeof( ((idWeapon *)0)->displayName ) },
|
||||
{ "idStr", "itemDesc", (intptr_t)(&((idWeapon *)0)->itemDesc), sizeof( ((idWeapon *)0)->itemDesc ) },
|
||||
{ "renderLight_t", "guiLight", (intptr_t)(&((idWeapon *)0)->guiLight), sizeof( ((idWeapon *)0)->guiLight ) },
|
||||
{ "int", "guiLightHandle", (intptr_t)(&((idWeapon *)0)->guiLightHandle), sizeof( ((idWeapon *)0)->guiLightHandle ) },
|
||||
{ "renderLight_t", "muzzleFlash", (intptr_t)(&((idWeapon *)0)->muzzleFlash), sizeof( ((idWeapon *)0)->muzzleFlash ) },
|
||||
{ "int", "muzzleFlashHandle", (intptr_t)(&((idWeapon *)0)->muzzleFlashHandle), sizeof( ((idWeapon *)0)->muzzleFlashHandle ) },
|
||||
{ "renderLight_t", "worldMuzzleFlash", (intptr_t)(&((idWeapon *)0)->worldMuzzleFlash), sizeof( ((idWeapon *)0)->worldMuzzleFlash ) },
|
||||
{ "int", "worldMuzzleFlashHandle", (intptr_t)(&((idWeapon *)0)->worldMuzzleFlashHandle), sizeof( ((idWeapon *)0)->worldMuzzleFlashHandle ) },
|
||||
{ "float", "fraccos", (intptr_t)(&((idWeapon *)0)->fraccos), sizeof( ((idWeapon *)0)->fraccos ) },
|
||||
{ "float", "fraccos2", (intptr_t)(&((idWeapon *)0)->fraccos2), sizeof( ((idWeapon *)0)->fraccos2 ) },
|
||||
{ "idVec3", "flashColor", (intptr_t)(&((idWeapon *)0)->flashColor), sizeof( ((idWeapon *)0)->flashColor ) },
|
||||
{ "int", "muzzleFlashEnd", (intptr_t)(&((idWeapon *)0)->muzzleFlashEnd), sizeof( ((idWeapon *)0)->muzzleFlashEnd ) },
|
||||
{ "int", "flashTime", (intptr_t)(&((idWeapon *)0)->flashTime), sizeof( ((idWeapon *)0)->flashTime ) },
|
||||
@@ -6835,7 +6854,7 @@ static classVariableInfo_t idWeapon_typeInfo[] = {
|
||||
{ "ammo_t", "ammoType", (intptr_t)(&((idWeapon *)0)->ammoType), sizeof( ((idWeapon *)0)->ammoType ) },
|
||||
{ "int", "ammoRequired", (intptr_t)(&((idWeapon *)0)->ammoRequired), sizeof( ((idWeapon *)0)->ammoRequired ) },
|
||||
{ "int", "clipSize", (intptr_t)(&((idWeapon *)0)->clipSize), sizeof( ((idWeapon *)0)->clipSize ) },
|
||||
{ "int", "ammoClip", (intptr_t)(&((idWeapon *)0)->ammoClip), sizeof( ((idWeapon *)0)->ammoClip ) },
|
||||
{ "idPredictedValue < int >", "ammoClip", (intptr_t)(&((idWeapon *)0)->ammoClip), sizeof( ((idWeapon *)0)->ammoClip ) },
|
||||
{ "int", "lowAmmo", (intptr_t)(&((idWeapon *)0)->lowAmmo), sizeof( ((idWeapon *)0)->lowAmmo ) },
|
||||
{ "bool", "powerAmmo", (intptr_t)(&((idWeapon *)0)->powerAmmo), sizeof( ((idWeapon *)0)->powerAmmo ) },
|
||||
{ "bool", "isFiring", (intptr_t)(&((idWeapon *)0)->isFiring), sizeof( ((idWeapon *)0)->isFiring ) },
|
||||
@@ -6848,6 +6867,9 @@ static classVariableInfo_t idWeapon_typeInfo[] = {
|
||||
{ "jointHandle_t", "flashJointWorld", (intptr_t)(&((idWeapon *)0)->flashJointWorld), sizeof( ((idWeapon *)0)->flashJointWorld ) },
|
||||
{ "jointHandle_t", "barrelJointWorld", (intptr_t)(&((idWeapon *)0)->barrelJointWorld), sizeof( ((idWeapon *)0)->barrelJointWorld ) },
|
||||
{ "jointHandle_t", "ejectJointWorld", (intptr_t)(&((idWeapon *)0)->ejectJointWorld), sizeof( ((idWeapon *)0)->ejectJointWorld ) },
|
||||
{ "jointHandle_t", "smokeJointView", (intptr_t)(&((idWeapon *)0)->smokeJointView), sizeof( ((idWeapon *)0)->smokeJointView ) },
|
||||
{ "idHashTable < WeaponParticle_t >", "weaponParticles", (intptr_t)(&((idWeapon *)0)->weaponParticles), sizeof( ((idWeapon *)0)->weaponParticles ) },
|
||||
{ "idHashTable < WeaponLight_t >", "weaponLights", (intptr_t)(&((idWeapon *)0)->weaponLights), sizeof( ((idWeapon *)0)->weaponLights ) },
|
||||
{ "const idSoundShader *", "sndHum", (intptr_t)(&((idWeapon *)0)->sndHum), sizeof( ((idWeapon *)0)->sndHum ) },
|
||||
{ "const idDeclParticle *", "weaponSmoke", (intptr_t)(&((idWeapon *)0)->weaponSmoke), sizeof( ((idWeapon *)0)->weaponSmoke ) },
|
||||
{ "int", "weaponSmokeStartTime", (intptr_t)(&((idWeapon *)0)->weaponSmokeStartTime), sizeof( ((idWeapon *)0)->weaponSmokeStartTime ) },
|
||||
@@ -6870,6 +6892,9 @@ static classVariableInfo_t idWeapon_typeInfo[] = {
|
||||
{ "float", "weaponAngleOffsetMax", (intptr_t)(&((idWeapon *)0)->weaponAngleOffsetMax), sizeof( ((idWeapon *)0)->weaponAngleOffsetMax ) },
|
||||
{ "float", "weaponOffsetTime", (intptr_t)(&((idWeapon *)0)->weaponOffsetTime), sizeof( ((idWeapon *)0)->weaponOffsetTime ) },
|
||||
{ "float", "weaponOffsetScale", (intptr_t)(&((idWeapon *)0)->weaponOffsetScale), sizeof( ((idWeapon *)0)->weaponOffsetScale ) },
|
||||
{ "int", "grabberState", (intptr_t)(&((idWeapon *)0)->grabberState), sizeof( ((idWeapon *)0)->grabberState ) },
|
||||
{ ": rvmWeaponObject *", "currentWeaponObject", (intptr_t)(&((idWeapon *)0)->currentWeaponObject), sizeof( ((idWeapon *)0)->currentWeaponObject ) },
|
||||
{ "bool", "OutOfAmmo", (intptr_t)(&((idWeapon *)0)->OutOfAmmo), sizeof( ((idWeapon *)0)->OutOfAmmo ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
@@ -8056,6 +8081,125 @@ static classVariableInfo_t idThread_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponFist_typeInfo[] = {
|
||||
{ "bool", "side", (intptr_t)(&((rvmWeaponFist *)0)->side), sizeof( ((rvmWeaponFist *)0)->side ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponPistol_typeInfo[] = {
|
||||
{ ": float", "spread", (intptr_t)(&((rvmWeaponPistol *)0)->spread), sizeof( ((rvmWeaponPistol *)0)->spread ) },
|
||||
{ "const idSoundShader *", "snd_lowammo", (intptr_t)(&((rvmWeaponPistol *)0)->snd_lowammo), sizeof( ((rvmWeaponPistol *)0)->snd_lowammo ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponFlashlight_typeInfo[] = {
|
||||
{ "bool", "on", (intptr_t)(&((rvmWeaponFlashlight *)0)->on), sizeof( ((rvmWeaponFlashlight *)0)->on ) },
|
||||
{ "float", "intensity", (intptr_t)(&((rvmWeaponFlashlight *)0)->intensity), sizeof( ((rvmWeaponFlashlight *)0)->intensity ) },
|
||||
{ "idStr", "skin_on", (intptr_t)(&((rvmWeaponFlashlight *)0)->skin_on), sizeof( ((rvmWeaponFlashlight *)0)->skin_on ) },
|
||||
{ "idStr", "skin_on_invis", (intptr_t)(&((rvmWeaponFlashlight *)0)->skin_on_invis), sizeof( ((rvmWeaponFlashlight *)0)->skin_on_invis ) },
|
||||
{ "idStr", "skin_off", (intptr_t)(&((rvmWeaponFlashlight *)0)->skin_off), sizeof( ((rvmWeaponFlashlight *)0)->skin_off ) },
|
||||
{ "idStr", "skin_off_invis", (intptr_t)(&((rvmWeaponFlashlight *)0)->skin_off_invis), sizeof( ((rvmWeaponFlashlight *)0)->skin_off_invis ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponPDA_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponShotgun_typeInfo[] = {
|
||||
{ ": float", "spread", (intptr_t)(&((rvmWeaponShotgun *)0)->spread), sizeof( ((rvmWeaponShotgun *)0)->spread ) },
|
||||
{ "const idSoundShader *", "snd_lowammo", (intptr_t)(&((rvmWeaponShotgun *)0)->snd_lowammo), sizeof( ((rvmWeaponShotgun *)0)->snd_lowammo ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponDoubleShotgun_typeInfo[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponMachineGun_typeInfo[] = {
|
||||
{ ": float", "spread", (intptr_t)(&((rvmWeaponMachineGun *)0)->spread), sizeof( ((rvmWeaponMachineGun *)0)->spread ) },
|
||||
{ "const idSoundShader *", "snd_lowammo", (intptr_t)(&((rvmWeaponMachineGun *)0)->snd_lowammo), sizeof( ((rvmWeaponMachineGun *)0)->snd_lowammo ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponPlasmaGun_typeInfo[] = {
|
||||
{ ": float", "spread", (intptr_t)(&((rvmWeaponPlasmaGun *)0)->spread), sizeof( ((rvmWeaponPlasmaGun *)0)->spread ) },
|
||||
{ "const idSoundShader *", "snd_lowammo", (intptr_t)(&((rvmWeaponPlasmaGun *)0)->snd_lowammo), sizeof( ((rvmWeaponPlasmaGun *)0)->snd_lowammo ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponChainGun_typeInfo[] = {
|
||||
{ ": idAnimatedEntity *", "world_model", (intptr_t)(&((rvmWeaponChainGun *)0)->world_model), sizeof( ((rvmWeaponChainGun *)0)->world_model ) },
|
||||
{ "jointHandle_t", "world_barrel_joint", (intptr_t)(&((rvmWeaponChainGun *)0)->world_barrel_joint), sizeof( ((rvmWeaponChainGun *)0)->world_barrel_joint ) },
|
||||
{ "jointHandle_t", "barrel_joint", (intptr_t)(&((rvmWeaponChainGun *)0)->barrel_joint), sizeof( ((rvmWeaponChainGun *)0)->barrel_joint ) },
|
||||
{ "float", "barrel_angle", (intptr_t)(&((rvmWeaponChainGun *)0)->barrel_angle), sizeof( ((rvmWeaponChainGun *)0)->barrel_angle ) },
|
||||
{ "float", "current_rate", (intptr_t)(&((rvmWeaponChainGun *)0)->current_rate), sizeof( ((rvmWeaponChainGun *)0)->current_rate ) },
|
||||
{ "float", "start_rate", (intptr_t)(&((rvmWeaponChainGun *)0)->start_rate), sizeof( ((rvmWeaponChainGun *)0)->start_rate ) },
|
||||
{ "float", "end_rate", (intptr_t)(&((rvmWeaponChainGun *)0)->end_rate), sizeof( ((rvmWeaponChainGun *)0)->end_rate ) },
|
||||
{ "float", "spin_start", (intptr_t)(&((rvmWeaponChainGun *)0)->spin_start), sizeof( ((rvmWeaponChainGun *)0)->spin_start ) },
|
||||
{ "float", "spin_end", (intptr_t)(&((rvmWeaponChainGun *)0)->spin_end), sizeof( ((rvmWeaponChainGun *)0)->spin_end ) },
|
||||
{ "float", "spread", (intptr_t)(&((rvmWeaponChainGun *)0)->spread), sizeof( ((rvmWeaponChainGun *)0)->spread ) },
|
||||
{ "int", "numSkipFrames", (intptr_t)(&((rvmWeaponChainGun *)0)->numSkipFrames), sizeof( ((rvmWeaponChainGun *)0)->numSkipFrames ) },
|
||||
{ "const idSoundShader *", "snd_windup", (intptr_t)(&((rvmWeaponChainGun *)0)->snd_windup), sizeof( ((rvmWeaponChainGun *)0)->snd_windup ) },
|
||||
{ "const idSoundShader *", "snd_winddown", (intptr_t)(&((rvmWeaponChainGun *)0)->snd_winddown), sizeof( ((rvmWeaponChainGun *)0)->snd_winddown ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponRocketLauncher_typeInfo[] = {
|
||||
{ "float", "spread", (intptr_t)(&((rvmWeaponRocketLauncher *)0)->spread), sizeof( ((rvmWeaponRocketLauncher *)0)->spread ) },
|
||||
{ "idStr", "skin_invisible", (intptr_t)(&((rvmWeaponRocketLauncher *)0)->skin_invisible), sizeof( ((rvmWeaponRocketLauncher *)0)->skin_invisible ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponBFG_typeInfo[] = {
|
||||
{ "float", "spread", (intptr_t)(&((rvmWeaponBFG *)0)->spread), sizeof( ((rvmWeaponBFG *)0)->spread ) },
|
||||
{ "float", "fuse_start", (intptr_t)(&((rvmWeaponBFG *)0)->fuse_start), sizeof( ((rvmWeaponBFG *)0)->fuse_start ) },
|
||||
{ "float", "fuse_end", (intptr_t)(&((rvmWeaponBFG *)0)->fuse_end), sizeof( ((rvmWeaponBFG *)0)->fuse_end ) },
|
||||
{ "float", "powerLevel", (intptr_t)(&((rvmWeaponBFG *)0)->powerLevel), sizeof( ((rvmWeaponBFG *)0)->powerLevel ) },
|
||||
{ "float", "fire_time", (intptr_t)(&((rvmWeaponBFG *)0)->fire_time), sizeof( ((rvmWeaponBFG *)0)->fire_time ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponHandgrenade_typeInfo[] = {
|
||||
{ ": float", "spread", (intptr_t)(&((rvmWeaponHandgrenade *)0)->spread), sizeof( ((rvmWeaponHandgrenade *)0)->spread ) },
|
||||
{ "float", "fuse_start", (intptr_t)(&((rvmWeaponHandgrenade *)0)->fuse_start), sizeof( ((rvmWeaponHandgrenade *)0)->fuse_start ) },
|
||||
{ "idStr", "skin_nade", (intptr_t)(&((rvmWeaponHandgrenade *)0)->skin_nade), sizeof( ((rvmWeaponHandgrenade *)0)->skin_nade ) },
|
||||
{ "idStr", "skin_nade_invis", (intptr_t)(&((rvmWeaponHandgrenade *)0)->skin_nade_invis), sizeof( ((rvmWeaponHandgrenade *)0)->skin_nade_invis ) },
|
||||
{ "idStr", "skin_nonade", (intptr_t)(&((rvmWeaponHandgrenade *)0)->skin_nonade), sizeof( ((rvmWeaponHandgrenade *)0)->skin_nonade ) },
|
||||
{ "idStr", "skin_nonade_invis", (intptr_t)(&((rvmWeaponHandgrenade *)0)->skin_nonade_invis), sizeof( ((rvmWeaponHandgrenade *)0)->skin_nonade_invis ) },
|
||||
{ "idProjectile *", "projectile", (intptr_t)(&((rvmWeaponHandgrenade *)0)->projectile), sizeof( ((rvmWeaponHandgrenade *)0)->projectile ) },
|
||||
{ "boolean", "show_grenade", (intptr_t)(&((rvmWeaponHandgrenade *)0)->show_grenade), sizeof( ((rvmWeaponHandgrenade *)0)->show_grenade ) },
|
||||
{ ": float", "fuse_end", (intptr_t)(&((rvmWeaponHandgrenade *)0)->fuse_end), sizeof( ((rvmWeaponHandgrenade *)0)->fuse_end ) },
|
||||
{ "float", "current_time", (intptr_t)(&((rvmWeaponHandgrenade *)0)->current_time), sizeof( ((rvmWeaponHandgrenade *)0)->current_time ) },
|
||||
{ "float", "time_held", (intptr_t)(&((rvmWeaponHandgrenade *)0)->time_held), sizeof( ((rvmWeaponHandgrenade *)0)->time_held ) },
|
||||
{ "float", "power", (intptr_t)(&((rvmWeaponHandgrenade *)0)->power), sizeof( ((rvmWeaponHandgrenade *)0)->power ) },
|
||||
{ "boolean", "exploded", (intptr_t)(&((rvmWeaponHandgrenade *)0)->exploded), sizeof( ((rvmWeaponHandgrenade *)0)->exploded ) },
|
||||
{ "const idSoundShader *", "snd_lowammo", (intptr_t)(&((rvmWeaponHandgrenade *)0)->snd_lowammo), sizeof( ((rvmWeaponHandgrenade *)0)->snd_lowammo ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponChainsaw_typeInfo[] = {
|
||||
{ ": bool", "side", (intptr_t)(&((rvmWeaponChainsaw *)0)->side), sizeof( ((rvmWeaponChainsaw *)0)->side ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classVariableInfo_t rvmWeaponGrabber_typeInfo[] = {
|
||||
{ "const idSoundShader *", "snd_fireloop", (intptr_t)(&((rvmWeaponGrabber *)0)->snd_fireloop), sizeof( ((rvmWeaponGrabber *)0)->snd_fireloop ) },
|
||||
{ "const idSoundShader *", "snd_electroloop", (intptr_t)(&((rvmWeaponGrabber *)0)->snd_electroloop), sizeof( ((rvmWeaponGrabber *)0)->snd_electroloop ) },
|
||||
{ "const idSoundShader *", "snd_mainfire", (intptr_t)(&((rvmWeaponGrabber *)0)->snd_mainfire), sizeof( ((rvmWeaponGrabber *)0)->snd_mainfire ) },
|
||||
{ "const idSoundShader *", "snd_cangrab", (intptr_t)(&((rvmWeaponGrabber *)0)->snd_cangrab), sizeof( ((rvmWeaponGrabber *)0)->snd_cangrab ) },
|
||||
{ "const idSoundShader *", "snd_warning", (intptr_t)(&((rvmWeaponGrabber *)0)->snd_warning), sizeof( ((rvmWeaponGrabber *)0)->snd_warning ) },
|
||||
{ "const idSoundShader *", "snd_stopfire", (intptr_t)(&((rvmWeaponGrabber *)0)->snd_stopfire), sizeof( ((rvmWeaponGrabber *)0)->snd_stopfire ) },
|
||||
{ ": float", "next_attack", (intptr_t)(&((rvmWeaponGrabber *)0)->next_attack), sizeof( ((rvmWeaponGrabber *)0)->next_attack ) },
|
||||
{ "float", "fireStartTime", (intptr_t)(&((rvmWeaponGrabber *)0)->fireStartTime), sizeof( ((rvmWeaponGrabber *)0)->fireStartTime ) },
|
||||
{ "bool", "warningBeep1", (intptr_t)(&((rvmWeaponGrabber *)0)->warningBeep1), sizeof( ((rvmWeaponGrabber *)0)->warningBeep1 ) },
|
||||
{ "bool", "warningBeep2", (intptr_t)(&((rvmWeaponGrabber *)0)->warningBeep2), sizeof( ((rvmWeaponGrabber *)0)->warningBeep2 ) },
|
||||
{ "bool", "warningBeep3", (intptr_t)(&((rvmWeaponGrabber *)0)->warningBeep3), sizeof( ((rvmWeaponGrabber *)0)->warningBeep3 ) },
|
||||
{ "bool", "warningBeep4", (intptr_t)(&((rvmWeaponGrabber *)0)->warningBeep4), sizeof( ((rvmWeaponGrabber *)0)->warningBeep4 ) },
|
||||
{ "float", "grabberState", (intptr_t)(&((rvmWeaponGrabber *)0)->grabberState), sizeof( ((rvmWeaponGrabber *)0)->grabberState ) },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static classTypeInfo_t classTypeInfo[] = {
|
||||
// { "BITT< unsigned int B >", "", sizeof(BITT< unsigned int B >), BITT_unsigned_int_B__typeInfo },
|
||||
{ "sysEvent_t", "", sizeof(sysEvent_t), sysEvent_t_typeInfo },
|
||||
@@ -8081,6 +8225,7 @@ static classTypeInfo_t classTypeInfo[] = {
|
||||
{ "idSIMDProcessor", "", sizeof(idSIMDProcessor), idSIMDProcessor_typeInfo },
|
||||
{ "idMath::_flint", "", sizeof(idMath::_flint), idMath__flint_typeInfo },
|
||||
{ "idMath", "", sizeof(idMath), idMath_typeInfo },
|
||||
{ "rvRandom", "", sizeof(rvRandom), rvRandom_typeInfo },
|
||||
{ "idRandom", "", sizeof(idRandom), idRandom_typeInfo },
|
||||
{ "idRandom2", "", sizeof(idRandom2), idRandom2_typeInfo },
|
||||
{ "idComplex", "", sizeof(idComplex), idComplex_typeInfo },
|
||||
@@ -8228,7 +8373,7 @@ static classTypeInfo_t classTypeInfo[] = {
|
||||
{ "glRaytracingMeshDesc_t", "", sizeof(glRaytracingMeshDesc_t), glRaytracingMeshDesc_t_typeInfo },
|
||||
{ "glRaytracingInstanceDesc_t", "", sizeof(glRaytracingInstanceDesc_t), glRaytracingInstanceDesc_t_typeInfo },
|
||||
{ "glRaytracingVec3_t", "", sizeof(glRaytracingVec3_t), glRaytracingVec3_t_typeInfo },
|
||||
// { "glRaytracingLight_s::class_171", "", sizeof(glRaytracingLight_s::class_171), glRaytracingLight_s_class_171_typeInfo },
|
||||
// { "glRaytracingLight_s::class_172", "", sizeof(glRaytracingLight_s::class_172), glRaytracingLight_s_class_172_typeInfo },
|
||||
{ "glRaytracingLight_t", "", sizeof(glRaytracingLight_t), glRaytracingLight_t_typeInfo },
|
||||
{ "glRaytracingLightingPassDesc_t", "", sizeof(glRaytracingLightingPassDesc_t), glRaytracingLightingPassDesc_t_typeInfo },
|
||||
{ "QD3D12NeuralPOMImageRGBA8", "", sizeof(QD3D12NeuralPOMImageRGBA8), QD3D12NeuralPOMImageRGBA8_typeInfo },
|
||||
@@ -8337,7 +8482,7 @@ static classTypeInfo_t classTypeInfo[] = {
|
||||
{ "jointAnimInfo_t", "", sizeof(jointAnimInfo_t), jointAnimInfo_t_typeInfo },
|
||||
{ "jointMod_t", "", sizeof(jointMod_t), jointMod_t_typeInfo },
|
||||
{ "frameLookup_t", "", sizeof(frameLookup_t), frameLookup_t_typeInfo },
|
||||
// { "class_280::class_280", "", sizeof(class_280::class_280), class_280_class_280_typeInfo },
|
||||
// { "class_281::class_281", "", sizeof(class_281::class_281), class_281_class_281_typeInfo },
|
||||
{ "frameCommand_t", "", sizeof(frameCommand_t), frameCommand_t_typeInfo },
|
||||
{ "animFlags_t", "", sizeof(animFlags_t), animFlags_t_typeInfo },
|
||||
{ "idModelExport", "", sizeof(idModelExport), idModelExport_typeInfo },
|
||||
@@ -8370,6 +8515,7 @@ static classTypeInfo_t classTypeInfo[] = {
|
||||
{ "spawnSpot_t", "", sizeof(spawnSpot_t), spawnSpot_t_typeInfo },
|
||||
{ "idEventQueue", "", sizeof(idEventQueue), idEventQueue_typeInfo },
|
||||
// { "idEntityPtr< class type >", "", sizeof(idEntityPtr< class type >), idEntityPtr_class_type__typeInfo },
|
||||
{ "rvmGameDelayRemoveEntry_t", "", sizeof(rvmGameDelayRemoveEntry_t), rvmGameDelayRemoveEntry_t_typeInfo },
|
||||
{ "idGameLocal", "idGame", sizeof(idGameLocal), idGameLocal_typeInfo },
|
||||
{ "idGameError", "idException", sizeof(idGameError), idGameError_typeInfo },
|
||||
{ "idForce", "idClass", sizeof(idForce), idForce_typeInfo },
|
||||
@@ -8490,6 +8636,10 @@ static classTypeInfo_t classTypeInfo[] = {
|
||||
{ "beamTarget_t", "", sizeof(beamTarget_t), beamTarget_t_typeInfo },
|
||||
{ "idBFGProjectile", "idProjectile", sizeof(idBFGProjectile), idBFGProjectile_typeInfo },
|
||||
{ "idDebris", "idEntity", sizeof(idDebris), idDebris_typeInfo },
|
||||
// { "idPredictedValue< class type_ >", "", sizeof(idPredictedValue< class type_ >), idPredictedValue_class_type___typeInfo },
|
||||
{ "WeaponParticle_t", "", sizeof(WeaponParticle_t), WeaponParticle_t_typeInfo },
|
||||
{ "WeaponLight_t", "", sizeof(WeaponLight_t), WeaponLight_t_typeInfo },
|
||||
{ "rvmWeaponObject", "idClass", sizeof(rvmWeaponObject), rvmWeaponObject_typeInfo },
|
||||
{ "idWeapon", "idAnimatedEntity", sizeof(idWeapon), idWeapon_typeInfo },
|
||||
{ "idLight", "idEntity", sizeof(idLight), idLight_typeInfo },
|
||||
{ "idWorldspawn", "idEntity", sizeof(idWorldspawn), idWorldspawn_typeInfo },
|
||||
@@ -8593,6 +8743,20 @@ static classTypeInfo_t classTypeInfo[] = {
|
||||
{ "prstack_t", "", sizeof(prstack_t), prstack_t_typeInfo },
|
||||
{ "idInterpreter", "", sizeof(idInterpreter), idInterpreter_typeInfo },
|
||||
{ "idThread", "idClass", sizeof(idThread), idThread_typeInfo },
|
||||
{ "rvmWeaponFist", "rvmWeaponObject", sizeof(rvmWeaponFist), rvmWeaponFist_typeInfo },
|
||||
{ "rvmWeaponPistol", "rvmWeaponObject", sizeof(rvmWeaponPistol), rvmWeaponPistol_typeInfo },
|
||||
{ "rvmWeaponFlashlight", "rvmWeaponObject", sizeof(rvmWeaponFlashlight), rvmWeaponFlashlight_typeInfo },
|
||||
{ "rvmWeaponPDA", "rvmWeaponObject", sizeof(rvmWeaponPDA), rvmWeaponPDA_typeInfo },
|
||||
{ "rvmWeaponShotgun", "rvmWeaponObject", sizeof(rvmWeaponShotgun), rvmWeaponShotgun_typeInfo },
|
||||
{ "rvmWeaponDoubleShotgun", "rvmWeaponObject", sizeof(rvmWeaponDoubleShotgun), rvmWeaponDoubleShotgun_typeInfo },
|
||||
{ "rvmWeaponMachineGun", "rvmWeaponObject", sizeof(rvmWeaponMachineGun), rvmWeaponMachineGun_typeInfo },
|
||||
{ "rvmWeaponPlasmaGun", "rvmWeaponObject", sizeof(rvmWeaponPlasmaGun), rvmWeaponPlasmaGun_typeInfo },
|
||||
{ "rvmWeaponChainGun", "rvmWeaponObject", sizeof(rvmWeaponChainGun), rvmWeaponChainGun_typeInfo },
|
||||
{ "rvmWeaponRocketLauncher", "rvmWeaponObject", sizeof(rvmWeaponRocketLauncher), rvmWeaponRocketLauncher_typeInfo },
|
||||
{ "rvmWeaponBFG", "rvmWeaponObject", sizeof(rvmWeaponBFG), rvmWeaponBFG_typeInfo },
|
||||
{ "rvmWeaponHandgrenade", "rvmWeaponObject", sizeof(rvmWeaponHandgrenade), rvmWeaponHandgrenade_typeInfo },
|
||||
{ "rvmWeaponChainsaw", "rvmWeaponObject", sizeof(rvmWeaponChainsaw), rvmWeaponChainsaw_typeInfo },
|
||||
{ "rvmWeaponGrabber", "rvmWeaponObject", sizeof(rvmWeaponGrabber), rvmWeaponGrabber_typeInfo },
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
@@ -312,17 +312,17 @@ stateResult_t rvStateThread::Execute( void )
|
||||
stateName = call->state;
|
||||
stateStage = call->parms.stage;
|
||||
|
||||
if( g_debugState.GetBool() )
|
||||
{
|
||||
if( call->parms.stage )
|
||||
{
|
||||
gameLocal.Printf( "%s: %s (%d)\n", ((idEntity *)owner)->GetClassname(), call->state.c_str(), call->parms.stage );
|
||||
}
|
||||
else
|
||||
{
|
||||
gameLocal.Printf( "%s: %s\n", ((idEntity*)owner)->GetClassname(), call->state.c_str() );
|
||||
}
|
||||
}
|
||||
//if( g_debugState.GetBool() )
|
||||
//{
|
||||
// if( call->parms.stage )
|
||||
// {
|
||||
// gameLocal.Printf( "%s: %s (%d)\n", ((idEntity *)owner)->GetClassname(), call->state.c_str(), call->parms.stage );
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// gameLocal.Printf( "%s: %s\n", ((idEntity*)owner)->GetClassname(), call->state.c_str() );
|
||||
// }
|
||||
//}
|
||||
|
||||
// Actually call the state function
|
||||
lastResult = ( stateResult_t )owner->Invoke( call->state, &call->parms );
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
// Weapon_BFG.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponBFG )
|
||||
END_CLASS
|
||||
|
||||
#define BFG_MINRELEASETIME 0.05
|
||||
#define BFG_FUSE 2.0
|
||||
#define BFG_SHORTFUSE 0.5
|
||||
#define BFG_MAXPOWER 4.0
|
||||
#define BFG_FIRERATE 4
|
||||
#define BFG_FIREDELAY 4
|
||||
#define BFG_NUMPROJECTILES 1
|
||||
|
||||
// blend times
|
||||
#define BFG_IDLE_TO_LOWER 4
|
||||
#define BFG_IDLE_TO_FIRE 4
|
||||
#define BFG_IDLE_TO_RELOAD 4
|
||||
#define BFG_RAISE_TO_IDLE 4
|
||||
#define BFG_FIRE_TO_IDLE 4
|
||||
#define BFG_RELOAD_TO_IDLE 4
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponBFG::Init
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponBFG::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
|
||||
next_attack = 0;
|
||||
fuse_start = 0;
|
||||
fuse_end = 0;
|
||||
powerLevel = 0;
|
||||
fire_time = 0;
|
||||
spread = weapon->GetFloat( "spread" );
|
||||
owner->Event_SetGuiFloat( "powerlevel", 0 );
|
||||
owner->Event_SetGuiFloat( "overcharge", 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponBFG::Raise
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponBFG::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, BFG_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponBFG::Lower
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponBFG::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponBFG::Idle
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponBFG::Idle( stateParms_t* parms )
|
||||
{
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
|
||||
if( !owner->AmmoInClip() )
|
||||
{
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle_empty" );
|
||||
owner->Event_WeaponOutOfAmmo();
|
||||
}
|
||||
else
|
||||
{
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
owner->Event_WeaponReady();
|
||||
}
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponBFG::Fire
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponBFG::Fire( stateParms_t* parms )
|
||||
{
|
||||
float time_held;
|
||||
float power = 0.0f;
|
||||
float intensity;
|
||||
int ammoClip = owner->AmmoInClip();
|
||||
|
||||
enum FIRE_State
|
||||
{
|
||||
FIRE_NOTSET = 0,
|
||||
FIRE_FUSING,
|
||||
FIRE_SHORTFUSE,
|
||||
FIRE_SHORTFUSEWAIT,
|
||||
FIRE_FIRE,
|
||||
FIRE_FIRE_ANIMWAIT,
|
||||
FIRE_FIRE_COOLDOWN,
|
||||
FIRE_DONE
|
||||
};
|
||||
|
||||
if( ammoClip == 0 && owner->AmmoAvailable() && parms->stage == 0 )
|
||||
{
|
||||
//owner->WeaponState( WP_RELOAD, PISTOL_IDLE_TO_RELOAD );
|
||||
owner->Reload();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case FIRE_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "fire_begin", false );
|
||||
fuse_start = gameLocal.time;
|
||||
fuse_end = gameLocal.time + SEC2MS( BFG_FUSE );
|
||||
parms->stage = FIRE_FUSING;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_FUSING:
|
||||
if( !owner->IsFiring() )
|
||||
{
|
||||
parms->stage = FIRE_FIRE;
|
||||
}
|
||||
else if( gameLocal.time > gameLocal.time + SEC2MS( BFG_MINRELEASETIME ) && !owner->IsFiring() )
|
||||
{
|
||||
parms->stage = FIRE_SHORTFUSE;
|
||||
}
|
||||
else if( gameLocal.time >= fuse_end )
|
||||
{
|
||||
parms->stage = FIRE_SHORTFUSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
powerLevel = ( gameLocal.time - fuse_start ) / BFG_FUSE;
|
||||
owner->Event_SetColor( powerLevel, powerLevel, powerLevel );
|
||||
owner->Event_SetGuiFloat( "powerlevel", powerLevel );
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_SHORTFUSE:
|
||||
if( owner->IsFiring() )
|
||||
{
|
||||
fuse_end = gameLocal.time + SEC2MS( BFG_SHORTFUSE );
|
||||
parms->stage = FIRE_SHORTFUSEWAIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
parms->stage = FIRE_FIRE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_SHORTFUSEWAIT:
|
||||
if( !owner->IsFiring() || gameLocal.time >= fuse_end )
|
||||
{
|
||||
powerLevel = ( gameLocal.time - fuse_start ) / BFG_FUSE;
|
||||
owner->Event_SetGuiFloat( "powerlevel", powerLevel );
|
||||
parms->stage = FIRE_FIRE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_FIRE:
|
||||
if( gameLocal.time >= fuse_end )
|
||||
{
|
||||
OverCharge();
|
||||
parms->stage = FIRE_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_held = gameLocal.time - fuse_start;
|
||||
if( power > BFG_MAXPOWER )
|
||||
{
|
||||
power = BFG_MAXPOWER;
|
||||
}
|
||||
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "fire", false );
|
||||
fire_time = gameLocal.time;
|
||||
|
||||
owner->Event_LaunchProjectiles( BFG_NUMPROJECTILES, spread, 0, 1, 1 );
|
||||
parms->stage = FIRE_FIRE_ANIMWAIT;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_FIRE_ANIMWAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, BFG_FIRE_TO_IDLE ) )
|
||||
{
|
||||
parms->stage = FIRE_FIRE_COOLDOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
intensity = 1 - ( ( gameLocal.time - fire_time ) / 0.5 );
|
||||
if( intensity < 0 )
|
||||
{
|
||||
intensity = 0;
|
||||
}
|
||||
owner->Event_SetColor( intensity, intensity, intensity );
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_FIRE_COOLDOWN:
|
||||
if( powerLevel <= 0 )
|
||||
{
|
||||
parms->stage = FIRE_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
powerLevel -= SEC2MS( 0.05 ); // TODO: DELTA TIME THIS!!
|
||||
owner->Event_SetGuiFloat( "powerlevel", powerLevel );
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_DONE:
|
||||
owner->Event_SetGuiFloat( "powerlevel", 0 );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponBFG::OverCharge
|
||||
===============
|
||||
*/
|
||||
|
||||
void rvmWeaponBFG::OverCharge()
|
||||
{
|
||||
idStr entname;
|
||||
idEntity* explosion;
|
||||
idVec3 forward;
|
||||
idAngles angles;
|
||||
idPlayer* player;
|
||||
|
||||
player = owner->GetOwner();
|
||||
|
||||
owner->Event_AllowDrop( false );
|
||||
owner->Event_UseAmmo( owner->ClipSize() );
|
||||
|
||||
angles = player->viewAngles;
|
||||
forward = angles.ToForward();
|
||||
|
||||
entname = owner->GetKey( "def_overcharge" );
|
||||
//explosion = sys.spawn(entname);
|
||||
{
|
||||
idDict spawnArgs;
|
||||
|
||||
spawnArgs.Set( "classname", entname );
|
||||
gameLocal.SpawnEntityDef( spawnArgs, &explosion );
|
||||
}
|
||||
explosion->Event_SetOrigin( owner->GetOrigin() + forward * 16 );
|
||||
explosion->Event_SetShaderParm( /*SHADERPARM_TIMEOFFSET*/4, -gameLocal.time );
|
||||
gameLocal.DelayRemoveEntity( explosion, 2 );
|
||||
|
||||
owner->Event_StartSound( "snd_explode", SND_CHANNEL_ANY, false );
|
||||
gameLocal.RadiusDamage( owner->GetOrigin(), owner, owner->GetOwner(), nullptr, nullptr, "damage_bfg_overcharge", 1.0 );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponBFG::Reload
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponBFG::Reload( stateParms_t* parms )
|
||||
{
|
||||
enum RELOAD_State
|
||||
{
|
||||
RELOAD_NOTSET = 0,
|
||||
RELOAD_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RELOAD_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "reload", false );
|
||||
parms->stage = RELOAD_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RELOAD_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
owner->Event_AddToClip( owner->ClipSize() );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Weapon_bfg.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponBFG : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponBFG );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
private:
|
||||
void OverCharge();
|
||||
|
||||
float spread;
|
||||
|
||||
float fuse_start;
|
||||
float fuse_end;
|
||||
float powerLevel;
|
||||
float fire_time;
|
||||
};
|
||||
@@ -0,0 +1,324 @@
|
||||
// Weapon_chaingun.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponChainGun )
|
||||
END_CLASS
|
||||
|
||||
#define CHAINGUN_FIRE_SKIPFRAMES 7 // 6 shots per second
|
||||
#define CHAINGUN_LOWAMMO 10
|
||||
#define CHAINGUN_NUMPROJECTILES 1
|
||||
#define CHAINGUN_BARREL_SPEED ( 60 * ( USERCMD_HZ / CHAINGUN_FIRE_SKIPFRAMES ) )
|
||||
#define CHAINGUN_BARREL_ACCEL_TIME 0.4
|
||||
#define CHAINGUN_BARREL_DECCEL_TIME 1.0
|
||||
#define CHAINGUN_BARREL_ACCEL ( CHAINGUN_BARREL_SPEED / CHAINGUN_BARREL_ACCEL_TIME )
|
||||
#define CHAINGUN_BARREL_DECCEL ( CHAINGUN_BARREL_SPEED / CHAINGUN_BARREL_DECCEL_TIME )
|
||||
|
||||
// blend times
|
||||
#define CHAINGUN_IDLE_TO_LOWER 4
|
||||
#define CHAINGUN_IDLE_TO_FIRE 0
|
||||
#define CHAINGUN_IDLE_TO_RELOAD 4
|
||||
#define CHAINGUN_RAISE_TO_IDLE 0
|
||||
#define CHAINGUN_WINDDOWN_TO_IDLE 0
|
||||
#define CHAINGUN_RELOAD_TO_IDLE 0
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainGun::Init
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponChainGun::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
|
||||
world_model = ( idAnimatedEntity* )owner->GetWorldModel();
|
||||
world_barrel_joint = owner->GetAnimator()->GetJointHandle( "toob" );
|
||||
barrel_joint = owner->GetAnimator()->GetJointHandle( "spinner" );
|
||||
barrel_angle = 0;
|
||||
current_rate = 0;
|
||||
start_rate = 0;
|
||||
end_rate = 0;
|
||||
spin_start = 0;
|
||||
numSkipFrames = 0;
|
||||
spin_end = 0;
|
||||
spread = weapon->GetFloat( "spread" ); // weapon->GetFloat("spread")
|
||||
snd_windup = FindSound( "snd_windup" );
|
||||
snd_winddown = FindSound( "snd_winddown" );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainGun::UpdateBarrel
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponChainGun::UpdateBarrel()
|
||||
{
|
||||
float currentTime;
|
||||
//float t;
|
||||
idAngles ang;
|
||||
|
||||
currentTime = gameLocal.time;
|
||||
//if (currentTime < spin_end) {
|
||||
// t = (currentTime - spin_start) / (spin_end - spin_start);
|
||||
// current_rate = start_rate + t * (end_rate - start_rate);
|
||||
//}
|
||||
//else {
|
||||
current_rate = end_rate;
|
||||
//}
|
||||
|
||||
if( current_rate )
|
||||
{
|
||||
barrel_angle = barrel_angle + current_rate * GAME_FRAMETIME;
|
||||
|
||||
ang.pitch = 0;
|
||||
ang.yaw = 0;
|
||||
ang.roll = barrel_angle;
|
||||
owner->Event_SetJointAngle( barrel_joint, JOINTMOD_LOCAL, ang );
|
||||
|
||||
ang.yaw = barrel_angle;
|
||||
ang.roll = 0;
|
||||
world_model->Event_SetJointAngle( world_barrel_joint, JOINTMOD_LOCAL, ang );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainGun::SpinUp
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponChainGun::SpinUp()
|
||||
{
|
||||
start_rate = current_rate;
|
||||
end_rate = CHAINGUN_BARREL_SPEED;
|
||||
spin_start = gameLocal.time;
|
||||
spin_end = spin_start + ( end_rate - current_rate ) / CHAINGUN_BARREL_ACCEL;
|
||||
owner->Event_StartSound( "snd_windup", SND_CHANNEL_BODY3, false );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainGun::SpinDown
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponChainGun::SpinDown()
|
||||
{
|
||||
start_rate = current_rate;
|
||||
end_rate = 0;
|
||||
spin_start = gameLocal.time;
|
||||
spin_end = spin_start + ( current_rate - end_rate ) / CHAINGUN_BARREL_DECCEL;
|
||||
owner->Event_StartSound( "snd_winddown", SND_CHANNEL_BODY3, false );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainGun::Raise
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponChainGun::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, CHAINGUN_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainGun::Lower
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponChainGun::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainGun::Idle
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponChainGun::Idle( stateParms_t* parms )
|
||||
{
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
|
||||
if( !owner->AmmoInClip() )
|
||||
{
|
||||
owner->Event_WeaponOutOfAmmo();
|
||||
}
|
||||
else
|
||||
{
|
||||
owner->Event_WeaponReady();
|
||||
}
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainGun::Fire
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponChainGun::Fire( stateParms_t* parms )
|
||||
{
|
||||
float ammoClip;
|
||||
// float currentTime;
|
||||
// float skip;
|
||||
|
||||
ammoClip = owner->AmmoInClip();
|
||||
|
||||
enum FireState
|
||||
{
|
||||
FIRE_NOTSET = 0,
|
||||
FIRE_SPIN1,
|
||||
FIRE_FIRE,
|
||||
FIRE_SKIPFRAMES
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case FIRE_NOTSET:
|
||||
SpinUp();
|
||||
UpdateBarrel();
|
||||
if( current_rate >= end_rate )
|
||||
{
|
||||
if( ammoClip > 0 )
|
||||
{
|
||||
parms->stage = FIRE_SPIN1;
|
||||
}
|
||||
else
|
||||
{
|
||||
parms->stage = 0;
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_SPIN1:
|
||||
owner->Event_StartSound( "snd_spin", SND_CHANNEL_BODY3, false );
|
||||
parms->stage = FIRE_FIRE;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_FIRE:
|
||||
owner->Event_LaunchProjectiles( CHAINGUN_NUMPROJECTILES, spread, 0, 1, 1 );
|
||||
owner->Event_StartSound( "snd_fire", SND_CHANNEL_BODY3, false );
|
||||
if( ammoClip == CHAINGUN_LOWAMMO )
|
||||
{
|
||||
owner->Event_StartSound( "snd_lowammo", SND_CHANNEL_ITEM, false );
|
||||
}
|
||||
numSkipFrames = 0;
|
||||
parms->stage = FIRE_SKIPFRAMES;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_SKIPFRAMES:
|
||||
UpdateBarrel();
|
||||
numSkipFrames++;
|
||||
if( numSkipFrames >= CHAINGUN_FIRE_SKIPFRAMES )
|
||||
{
|
||||
if( owner->IsFiring() )
|
||||
{
|
||||
parms->stage = FIRE_FIRE;
|
||||
numSkipFrames = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SpinDown();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainGun::Reload
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponChainGun::Reload( stateParms_t* parms )
|
||||
{
|
||||
enum RELOAD_State
|
||||
{
|
||||
RELOAD_NOTSET = 0,
|
||||
RELOAD_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RELOAD_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "reload", false );
|
||||
parms->stage = RELOAD_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RELOAD_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
owner->Event_AddToClip( owner->ClipSize() );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// Weapon_chaingun.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponChainGun : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponChainGun );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
private:
|
||||
void UpdateBarrel();
|
||||
void SpinUp();
|
||||
void SpinDown();
|
||||
private:
|
||||
idAnimatedEntity* world_model;
|
||||
jointHandle_t world_barrel_joint;
|
||||
jointHandle_t barrel_joint;
|
||||
float barrel_angle;
|
||||
float current_rate;
|
||||
float start_rate;
|
||||
float end_rate;
|
||||
float spin_start;
|
||||
float spin_end;
|
||||
float spread;
|
||||
int numSkipFrames;
|
||||
|
||||
const idSoundShader* snd_windup;
|
||||
const idSoundShader* snd_winddown;
|
||||
};
|
||||
@@ -0,0 +1,225 @@
|
||||
// Weapon_chainsaw.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponChainsaw )
|
||||
END_CLASS
|
||||
|
||||
#define CHAINSAW_FIRERATE 0.1
|
||||
|
||||
// blend times
|
||||
#define CHAINSAW_IDLE_TO_LOWER 4
|
||||
#define CHAINSAW_IDLE_TO_FIRE 4
|
||||
#define CHAINSAW_RAISE_TO_IDLE 4
|
||||
#define CHAINSAW_FIRE_TO_IDLE 4
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainsaw::Init
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponChainsaw::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
|
||||
next_attack = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainsaw::Raise
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponChainsaw::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, CHAINSAW_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainsaw::Lower
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponChainsaw::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainsaw::Idle
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponChainsaw::Idle( stateParms_t* parms )
|
||||
{
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
owner->Event_WeaponReady();
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainsaw::Reload
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponChainsaw::Reload( stateParms_t* parms )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponChainsaw::Fire
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponChainsaw::Fire( stateParms_t* parms )
|
||||
{
|
||||
float currentTime;
|
||||
|
||||
if( parms->stage == 0 )
|
||||
{
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "melee_start", false );
|
||||
owner->Event_Melee();
|
||||
owner->Event_StartSound( "snd_startattack", SND_CHANNEL_WEAPON, false );
|
||||
parms->stage = 1;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
if( parms->stage == 1 )
|
||||
{
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 3 ) )
|
||||
{
|
||||
parms->stage = 2;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
if( parms->stage == 2 )
|
||||
{
|
||||
owner->Event_StartSound( "snd_attack", SND_CHANNEL_WEAPON, false );
|
||||
parms->stage = 3;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
if( parms->stage == 3 )
|
||||
{
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
parms->stage = 4;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
if( parms->stage == 4 )
|
||||
{
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "melee_loop" );
|
||||
next_attack = gameLocal.SysScriptTime();
|
||||
|
||||
parms->stage = 5;
|
||||
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
if( parms->stage == 5 )
|
||||
{
|
||||
if( owner->IsFiring() )
|
||||
{
|
||||
currentTime = gameLocal.SysScriptTime();
|
||||
if( currentTime >= next_attack )
|
||||
{
|
||||
owner->Event_Melee();
|
||||
next_attack = currentTime + CHAINSAW_FIRERATE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
parms->stage = 6;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
}
|
||||
|
||||
if( parms->stage == 6 )
|
||||
{
|
||||
owner->Event_StartSound( "snd_stopattack", SND_CHANNEL_WEAPON, false );
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "melee_end", false );
|
||||
parms->stage = 7;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
if( !owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Weapon_chainsaw.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponChainsaw : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponChainsaw );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
private:
|
||||
bool side;
|
||||
};
|
||||
@@ -0,0 +1,252 @@
|
||||
// Weapon_double_shotgun.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponDoubleShotgun )
|
||||
END_CLASS
|
||||
|
||||
|
||||
//#define SHOTGUN_DOUBLE_FIRERATE 1.333
|
||||
#define SHOTGUN_DOUBLE_FIRERATE 2.2
|
||||
|
||||
#define SHOTGUN_DOUBLE_REQUIRED 2
|
||||
|
||||
// blend times
|
||||
#define SHOTGUN_DOUBLE_IDLE_TO_IDLE 0
|
||||
#define SHOTGUN_DOUBLE_IDLE_TO_LOWER 4
|
||||
#define SHOTGUN_DOUBLE_IDLE_TO_FIRE 0
|
||||
#define SHOTGUN_DOUBLE_IDLE_TO_RELOAD 4
|
||||
#define SHOTGUN_DOUBLE_IDLE_TO_NOAMMO 4
|
||||
#define SHOTGUN_DOUBLE_NOAMMO_TO_RELOAD 4
|
||||
#define SHOTGUN_DOUBLE_NOAMMO_TO_IDLE 4
|
||||
#define SHOTGUN_DOUBLE_RAISE_TO_IDLE 4
|
||||
#define SHOTGUN_DOUBLE_FIRE_TO_IDLE 4
|
||||
#define SHOTGUN_DOUBLE_RELOAD_TO_IDLE 4
|
||||
#define SHOTGUN_DOUBLE_RELOAD_TO_FIRE 4
|
||||
|
||||
|
||||
//Shotgun Projectile Information
|
||||
#define SHOTGUN_CENTER_PROJECTILES 8
|
||||
//#define SHOTGUN_CENTER_PROJECTILES 7
|
||||
#define SHOTGUN_BIG_PROJECTILES 12
|
||||
//#define SHOTGUN_BIG_PROJECTILES 13
|
||||
|
||||
#define SHOTGUN_CENTER_WIDTH 5
|
||||
#define SHOTGUN_CENTER_HEIGHT 10
|
||||
//#define SHOTGUN_CENTER_HEIGHT 12
|
||||
#define SHOTGUN_BIG_WIDTH 22
|
||||
//#define SHOTGUN_BIG_WIDTH 25
|
||||
#define SHOTGUN_BIG_HEIGHT 15
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponDoubleShotgun::Init
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponDoubleShotgun::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
|
||||
next_attack = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponDoubleShotgun::Raise
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponDoubleShotgun::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, SHOTGUN_DOUBLE_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponDoubleShotgun::Lower
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponDoubleShotgun::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponDoubleShotgun::Idle
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponDoubleShotgun::Idle( stateParms_t* parms )
|
||||
{
|
||||
//float currentTime = 0;
|
||||
float clip_size;
|
||||
|
||||
clip_size = owner->ClipSize();
|
||||
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
owner->Event_WeaponReady();
|
||||
if( !owner->AmmoInClip() )
|
||||
{
|
||||
owner->Event_WeaponOutOfAmmo();
|
||||
}
|
||||
else
|
||||
{
|
||||
owner->Event_WeaponReady();
|
||||
}
|
||||
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponDoubleShotgun::Fire
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponDoubleShotgun::Fire( stateParms_t* parms )
|
||||
{
|
||||
int ammoClip = owner->AmmoInClip();
|
||||
|
||||
enum FIRE_State
|
||||
{
|
||||
FIRE_NOTSET = 0,
|
||||
FIRE_WAIT
|
||||
};
|
||||
|
||||
if( ammoClip == 0 && owner->AmmoAvailable() && parms->stage == 0 )
|
||||
{
|
||||
//owner->WeaponState( WP_RELOAD, PISTOL_IDLE_TO_RELOAD );
|
||||
owner->Reload();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case FIRE_NOTSET:
|
||||
//if (ammoClip == SHOTGUN_LOWAMMO) {
|
||||
// int length;
|
||||
// owner->StartSoundShader(snd_lowammo, SND_CHANNEL_ITEM, 0, false, &length);
|
||||
//}
|
||||
|
||||
//owner->Event_LaunchProjectiles(SHOTGUN_NUMPROJECTILES, spread, 0, 1, 1);
|
||||
owner->Event_LaunchProjectilesEllipse( SHOTGUN_CENTER_PROJECTILES, SHOTGUN_CENTER_WIDTH, SHOTGUN_CENTER_HEIGHT, 0, 1.0 );
|
||||
owner->Event_LaunchProjectilesEllipse( SHOTGUN_BIG_PROJECTILES, SHOTGUN_BIG_WIDTH, SHOTGUN_BIG_HEIGHT, 0, 1.0 );
|
||||
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "fire", false );
|
||||
parms->stage = FIRE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, SHOTGUN_DOUBLE_FIRE_TO_IDLE ) )
|
||||
{
|
||||
owner->Event_WeaponReloading();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponDoubleShotgun::Reload
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponDoubleShotgun::Reload( stateParms_t* parms )
|
||||
{
|
||||
enum RELOAD_State
|
||||
{
|
||||
RELOAD_NOTSET = 0,
|
||||
RELOAD_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RELOAD_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "reload_start", false );
|
||||
parms->stage = RELOAD_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RELOAD_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
owner->Event_AddToClip( owner->ClipSize() );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponDoubleShotgun::EjectBrass
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponDoubleShotgun::EjectBrass( void )
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Weapon_double_shotgun.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponDoubleShotgun : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponDoubleShotgun );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
|
||||
void EjectBrass( void );
|
||||
private:
|
||||
|
||||
};
|
||||
@@ -0,0 +1,185 @@
|
||||
// weapon_fist.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponFist )
|
||||
END_CLASS
|
||||
|
||||
#define RIFLE_NUMPROJECTILES 1
|
||||
|
||||
// blend times
|
||||
#define FISTS_IDLE_TO_LOWER 4
|
||||
#define FISTS_IDLE_TO_PUNCH 0
|
||||
#define FISTS_RAISE_TO_IDLE 4
|
||||
#define FISTS_PUNCH_TO_IDLE 1
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFist::Init
|
||||
================
|
||||
*/
|
||||
void rvmWeaponFist::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFist::Raise
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponFist::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, FISTS_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFist::Lower
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponFist::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFist::Idle
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponFist::Idle( stateParms_t* parms )
|
||||
{
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFist::Fire
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponFist::Fire( stateParms_t* parms )
|
||||
{
|
||||
enum FIRE_State
|
||||
{
|
||||
FIRE_NOTSET = 0,
|
||||
FIRE_MELEE,
|
||||
FIRE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case FIRE_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, GetFireAnim(), false );
|
||||
parms->stage = FIRE_MELEE;
|
||||
parms->Wait( 0.1f );
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_MELEE:
|
||||
owner->Event_Melee();
|
||||
parms->stage = FIRE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
side = !side;
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFist::Reload
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponFist::Reload( stateParms_t* parms )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFist::GetFireAnim
|
||||
================
|
||||
*/
|
||||
const char* rvmWeaponFist::GetFireAnim()
|
||||
{
|
||||
if( side )
|
||||
{
|
||||
return "punch_left";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "punch_right";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Weapon_fist.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponFist : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponFist );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
private:
|
||||
const char* GetFireAnim();
|
||||
bool side;
|
||||
};
|
||||
@@ -0,0 +1,254 @@
|
||||
// Weapon_flashlight.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponFlashlight )
|
||||
END_CLASS
|
||||
|
||||
// blend times
|
||||
#define FLASHLIGHT_IDLE_TO_LOWER 4
|
||||
#define FLASHLIGHT_IDLE_TO_FIRE 2
|
||||
#define FLASHLIGHT_IDLE_TO_RELOAD 4
|
||||
#define FLASHLIGHT_RAISE_TO_IDLE 4
|
||||
#define FLASHLIGHT_FIRE_TO_IDLE 4
|
||||
#define FLASHLIGHT_RELOAD_TO_IDLE 4
|
||||
|
||||
#define FLASHLIGHT_MIN_SKIN_INTENSITY 0.2
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFlashlight::Init
|
||||
================
|
||||
*/
|
||||
void rvmWeaponFlashlight::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
|
||||
skin_on = owner->GetKey( "skin_on" );
|
||||
skin_on_invis = owner->GetKey( "skin_on_invis" );
|
||||
skin_off = owner->GetKey( "skin_off" );
|
||||
skin_off_invis = owner->GetKey( "skin_off_invis" );
|
||||
|
||||
intensity = 1.0;
|
||||
|
||||
owner->Event_SetLightParm( 3, 1.0 );
|
||||
owner->Event_SetShaderParm( 3, 1.0 );
|
||||
|
||||
on = true;
|
||||
|
||||
UpdateSkin();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFlashlight::UpdateLightIntensity
|
||||
================
|
||||
*/
|
||||
void rvmWeaponFlashlight::UpdateLightIntensity( void )
|
||||
{
|
||||
// TODO this has to interact with scripts somehow
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFlashlight::UpdateSkin
|
||||
================
|
||||
*/
|
||||
void rvmWeaponFlashlight::UpdateSkin( void )
|
||||
{
|
||||
if( on && ( intensity > FLASHLIGHT_MIN_SKIN_INTENSITY ) )
|
||||
{
|
||||
if( !owner->Event_IsInvisible() )
|
||||
{
|
||||
owner->Event_SetSkin( skin_on );
|
||||
}
|
||||
else
|
||||
{
|
||||
owner->Event_SetSkin( skin_on_invis );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !owner->Event_IsInvisible() )
|
||||
{
|
||||
owner->Event_SetSkin( skin_off );
|
||||
}
|
||||
else
|
||||
{
|
||||
owner->Event_SetSkin( skin_off_invis );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFlashlight::Raise
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponFlashlight::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, FLASHLIGHT_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFlashlight::Lower
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponFlashlight::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFlashlight::Idle
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponFlashlight::Idle( stateParms_t* parms )
|
||||
{
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
owner->Event_WeaponReady();
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFlashlight::Fire
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponFlashlight::Fire( stateParms_t* parms )
|
||||
{
|
||||
enum FIRE_State
|
||||
{
|
||||
FIRE_NOTSET = 0,
|
||||
FIRE_MELEE,
|
||||
FIRE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case FIRE_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "fire", false );
|
||||
parms->stage = FIRE_MELEE;
|
||||
parms->Wait( 0.1f );
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_MELEE:
|
||||
owner->Event_Melee();
|
||||
parms->stage = FIRE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, FLASHLIGHT_FIRE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponFlashlight::Reload
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponFlashlight::Reload( stateParms_t* parms )
|
||||
{
|
||||
enum RELOAD_State
|
||||
{
|
||||
RELOAD_NOTSET = 0,
|
||||
RELOAD_TOGGLEFLASHLIGHT,
|
||||
RELOAD_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RELOAD_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "reload", false );
|
||||
parms->stage = RELOAD_TOGGLEFLASHLIGHT;
|
||||
parms->Wait( 0.2f );
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RELOAD_TOGGLEFLASHLIGHT:
|
||||
on = !on;
|
||||
UpdateSkin();
|
||||
owner->Event_Flashlight( on );
|
||||
parms->stage = RELOAD_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RELOAD_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, FLASHLIGHT_RELOAD_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Weapon_flashlight.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponFlashlight : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponFlashlight );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
private:
|
||||
void UpdateSkin( void );
|
||||
void UpdateLightIntensity( void );
|
||||
|
||||
bool on;
|
||||
float intensity;
|
||||
idStr skin_on;
|
||||
idStr skin_on_invis;
|
||||
idStr skin_off;
|
||||
idStr skin_off_invis;
|
||||
};
|
||||
@@ -0,0 +1,400 @@
|
||||
// Weapon_grabber.cpp
|
||||
//
|
||||
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponGrabber )
|
||||
END_CLASS
|
||||
|
||||
// blend times
|
||||
#define GRABBER_IDLE_TO_LOWER 4
|
||||
#define GRABBER_IDLE_TO_OPEN 4
|
||||
#define GRABBER_IDLE_TO_OPENFIRE 4
|
||||
#define GRABBER_OPEN_TO_CLOSE 4
|
||||
#define GRABBER_OPEN_TO_FIRE 4
|
||||
#define GRABBER_CLOSE_TO_OPEN 4
|
||||
#define GRABBER_CLOSE_TO_IDLE 4
|
||||
#define GRABBER_OPENFIRE_TO_FIRE 2
|
||||
#define GRABBER_FIRE_TO_CLOSE 4
|
||||
#define GRABBER_RAISE_TO_IDLE 4
|
||||
|
||||
#define WARNING_BEEP_1 1.5
|
||||
#define WARNING_BEEP_2 2.25
|
||||
#define WARNING_BEEP_3 2.50
|
||||
#define WARNING_BEEP_4 2.75
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponGrabber::Init
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponGrabber::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
|
||||
next_attack = 0;
|
||||
|
||||
snd_fireloop = FindSound( "snd_fireloop" );
|
||||
snd_electroloop = FindSound( "snd_electroloop" );
|
||||
snd_mainfire = FindSound( "snd_mainfire" );
|
||||
snd_cangrab = FindSound( "snd_cangrab" );
|
||||
snd_warning = FindSound( "snd_warning" );
|
||||
snd_stopfire = FindSound( "snd_stopfire" );
|
||||
|
||||
owner->Event_Grabber( true );
|
||||
|
||||
grabberState = -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponGrabber::Raise
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponGrabber::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, GRABBER_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponGrabber::Lower
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponGrabber::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
/*
|
||||
===============
|
||||
rvmWeaponGrabber::CanFire
|
||||
|
||||
Original grabber logic had this, so we prevent the fire action from going unless grabState is 1 or 2.
|
||||
|
||||
grabState = grabberHasTarget();
|
||||
if ( grabState == 1 || grabState == 2 ) {
|
||||
if(WEAPON_ATTACK) {
|
||||
weaponState( "GrabberOpenFire", GRABBER_IDLE_TO_OPENFIRE );
|
||||
}
|
||||
}
|
||||
===============
|
||||
*/
|
||||
//bool rvmWeaponGrabber::CanFire()
|
||||
//{
|
||||
// int grabState = owner->Event_GrabberHasTarget();
|
||||
// return grabState == 1 || grabState == 2;
|
||||
//}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponGrabber::Idle
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponGrabber::Idle( stateParms_t* parms )
|
||||
{
|
||||
int grabState = 0;
|
||||
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT,
|
||||
IDLE_GRABBER_OPEN,
|
||||
IDLE_GRABBER_OPEN_WAIT,
|
||||
};
|
||||
|
||||
UpdateGuiLight();
|
||||
|
||||
grabState = owner->Event_GrabberHasTarget();
|
||||
if( grabState == 1 || grabState == 2 )
|
||||
{
|
||||
parms->stage = IDLE_GRABBER_OPEN;
|
||||
}
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
owner->Event_WeaponReady();
|
||||
if( !owner->AmmoInClip() )
|
||||
{
|
||||
owner->Event_WeaponOutOfAmmo();
|
||||
}
|
||||
else
|
||||
{
|
||||
owner->Event_WeaponReady();
|
||||
}
|
||||
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_GRABBER_OPEN:
|
||||
owner->StartSoundShader( snd_fireloop, SND_CHANNEL_BODY3, 0, false, NULL );
|
||||
owner->StartSoundShader( snd_electroloop, SND_CHANNEL_BODY2, 0, false, NULL );
|
||||
owner->StartSoundShader( snd_mainfire, SND_CHANNEL_BODY, 0, false, NULL );
|
||||
|
||||
StartWarningSound();
|
||||
StartActive();
|
||||
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "open", false );
|
||||
parms->stage = IDLE_GRABBER_OPEN_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_GRABBER_OPEN_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
//owner->WeaponState( WP_FIRE, GRABBER_OPEN_TO_CLOSE );
|
||||
owner->BeginAttack();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
grabState = owner->Event_GrabberHasTarget();
|
||||
if( grabState == 3 )
|
||||
{
|
||||
//owner->WeaponState( WP_FIRE, GRABBER_OPEN_TO_CLOSE );
|
||||
owner->BeginAttack();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateGuiLight();
|
||||
UpdateWarningSound();
|
||||
return SRESULT_WAIT;;
|
||||
}
|
||||
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvmWeaponGrabber::StartWarningSound
|
||||
=====================
|
||||
*/
|
||||
void rvmWeaponGrabber::StartWarningSound()
|
||||
{
|
||||
fireStartTime = gameLocal.realClientTime;
|
||||
warningBeep1 = false;
|
||||
warningBeep2 = false;
|
||||
warningBeep3 = false;
|
||||
warningBeep4 = false;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvmWeaponGrabber::StartActive
|
||||
=====================
|
||||
*/
|
||||
void rvmWeaponGrabber::StartActive()
|
||||
{
|
||||
owner->Event_StartWeaponParticle( "barrel_upper" );
|
||||
owner->Event_StartWeaponLight( "light_barrel_upper" );
|
||||
owner->Event_StartWeaponLight( "light_barrel_lower" );
|
||||
owner->Event_StartWeaponLight( "light_side" );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvmWeaponGrabber::StopActive
|
||||
=====================
|
||||
*/
|
||||
void rvmWeaponGrabber::StopActive()
|
||||
{
|
||||
owner->Event_StopWeaponParticle( "barrel_upper" );
|
||||
|
||||
owner->Event_StopWeaponLight( "light_barrel_upper" );
|
||||
owner->Event_StopWeaponLight( "light_barrel_lower" );
|
||||
owner->Event_StopWeaponLight( "light_side" );
|
||||
}
|
||||
|
||||
/*
|
||||
==================== =
|
||||
rvmWeaponGrabber::UpdateGuiLight
|
||||
==================== =
|
||||
*/
|
||||
void rvmWeaponGrabber::UpdateGuiLight()
|
||||
{
|
||||
|
||||
float newState = owner->Event_GrabberHasTarget();
|
||||
if( newState != grabberState )
|
||||
{
|
||||
grabberState = newState;
|
||||
if( grabberState == 0 )
|
||||
{
|
||||
owner->Event_StartWeaponLight( "gLightBlue" );
|
||||
owner->Event_StopWeaponLight( "gLightYellow" );
|
||||
owner->Event_StopWeaponLight( "gLightRed" );
|
||||
}
|
||||
else if( grabberState == 1 )
|
||||
{
|
||||
//startSound("snd_cangrab", SND_CHANNEL_ITEM, false);
|
||||
owner->StartSoundShader( snd_cangrab, SND_CHANNEL_ITEM, 0, false, NULL );
|
||||
owner->Event_StartWeaponLight( "gLightYellow" );
|
||||
owner->Event_StopWeaponLight( "gLightBlue" );
|
||||
owner->Event_StopWeaponLight( "gLightRed" );
|
||||
}
|
||||
else if( grabberState == 2 )
|
||||
{
|
||||
owner->Event_StartWeaponLight( "gLightRed" );
|
||||
owner->Event_StopWeaponLight( "gLightBlue" );
|
||||
owner->Event_StopWeaponLight( "gLightYellow" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvmWeaponGrabber::UpdateWarningSound
|
||||
=====================
|
||||
*/
|
||||
void rvmWeaponGrabber::UpdateWarningSound()
|
||||
{
|
||||
float currentTime;
|
||||
float elapsed;
|
||||
|
||||
currentTime = gameLocal.realClientTime;
|
||||
elapsed = currentTime - fireStartTime;
|
||||
|
||||
if( elapsed > WARNING_BEEP_1 && !warningBeep1 )
|
||||
{
|
||||
owner->StartSoundShader( snd_warning, SND_CHANNEL_ITEM, 0, false, NULL );
|
||||
warningBeep1 = true;
|
||||
}
|
||||
if( elapsed > WARNING_BEEP_2 && !warningBeep2 )
|
||||
{
|
||||
owner->StartSoundShader( snd_warning, SND_CHANNEL_ITEM, 0, false, NULL );
|
||||
warningBeep2 = true;
|
||||
}
|
||||
if( elapsed > WARNING_BEEP_3 && !warningBeep3 )
|
||||
{
|
||||
owner->StartSoundShader( snd_warning, SND_CHANNEL_ITEM, 0, false, NULL );
|
||||
warningBeep3 = true;
|
||||
}
|
||||
if( elapsed > WARNING_BEEP_4 && !warningBeep4 )
|
||||
{
|
||||
owner->StartSoundShader( snd_warning, SND_CHANNEL_ITEM, 0, false, NULL );
|
||||
warningBeep4 = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponGrabber::Fire
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponGrabber::Fire( stateParms_t* parms )
|
||||
{
|
||||
//int grabState;
|
||||
//
|
||||
//grabState = owner->Event_GrabberHasTarget();
|
||||
//
|
||||
//enum FIRE_State
|
||||
//{
|
||||
// FIRE_NOTSET = 0,
|
||||
// FIRE_WAIT_GRABSTATE,
|
||||
// FIRE_ACTUALLY_FIRE,
|
||||
// FIRE_WAIT
|
||||
//};
|
||||
//
|
||||
//switch( parms->stage )
|
||||
//{
|
||||
// case FIRE_NOTSET:
|
||||
// next_attack = MS2SEC( gameLocal.realClientTime );
|
||||
// owner->Event_PlayAnim( ANIMCHANNEL_ALL, "idleopen", true );
|
||||
// parms->stage = FIRE_WAIT_GRABSTATE;
|
||||
// return SRESULT_WAIT;
|
||||
//
|
||||
// case FIRE_WAIT_GRABSTATE:
|
||||
// if( grabState == 3 || grabState == 0 )
|
||||
// {
|
||||
// parms->stage = FIRE_ACTUALLY_FIRE;
|
||||
// }
|
||||
// return SRESULT_WAIT;
|
||||
//
|
||||
// case FIRE_ACTUALLY_FIRE:
|
||||
// StopActive();
|
||||
//
|
||||
// // Stops fire loop sound
|
||||
// owner->StartSoundShader( snd_stopfire, SND_CHANNEL_BODY3, 0, false, NULL );
|
||||
// owner->StopSound( SND_CHANNEL_BODY2, false );
|
||||
//
|
||||
// owner->Event_StartWeaponSmoke();
|
||||
// owner->Event_PlayAnim( ANIMCHANNEL_ALL, "fire", true );
|
||||
// break;
|
||||
//
|
||||
// case FIRE_WAIT:
|
||||
// if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
// {
|
||||
// owner->WeaponState( WP_IDLE, GRABBER_CLOSE_TO_IDLE );
|
||||
// firingState = 0;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// UpdateGuiLight();
|
||||
// }
|
||||
// break;
|
||||
//}
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponGrabber::Reload
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponGrabber::Reload( stateParms_t* parms )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Weapon_grabber.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponGrabber : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponGrabber );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
private:
|
||||
void StartActive();
|
||||
void StopActive();
|
||||
|
||||
void StartWarningSound();
|
||||
void UpdateWarningSound();
|
||||
|
||||
void UpdateGuiLight();
|
||||
|
||||
const idSoundShader* snd_fireloop;
|
||||
const idSoundShader* snd_electroloop;
|
||||
const idSoundShader* snd_mainfire;
|
||||
const idSoundShader* snd_cangrab;
|
||||
const idSoundShader* snd_warning;
|
||||
const idSoundShader* snd_stopfire;
|
||||
private:
|
||||
float next_attack;
|
||||
|
||||
float fireStartTime;
|
||||
bool warningBeep1;
|
||||
bool warningBeep2;
|
||||
bool warningBeep3;
|
||||
bool warningBeep4;
|
||||
|
||||
float grabberState;
|
||||
};
|
||||
@@ -0,0 +1,384 @@
|
||||
// Weapon_handgrenade.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponHandgrenade )
|
||||
END_CLASS
|
||||
|
||||
#define HANDGRENADE_MINRELEASETIME 0.05
|
||||
#define HANDGRENADE_FUSE 3
|
||||
#define HANDGRENADE_QUICKTHROWTIME .2
|
||||
#define HANDGRENADE_MINPOWER 1.5
|
||||
#define HANDGRENADE_MAXPOWER 6
|
||||
#define HANDGRENADE_QUICKTHROWLAUNCH 0.55
|
||||
#define HANDGRENADE_NORMALTHROWLAUNCH 0.3
|
||||
#define HANDGRENADE_NUMPROJECTILES 1
|
||||
|
||||
// blend times
|
||||
#define HANDGRENADE_IDLE_TO_LOWER 4
|
||||
#define HANDGRENADE_IDLE_TO_FIRE 4
|
||||
#define HANDGRENADE_RAISE_TO_IDLE 4
|
||||
#define HANDGRENADE_FIRE_TO_IDLE 4
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponHandgrenade::Init
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponHandgrenade::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
|
||||
projectile = NULL;
|
||||
spread = owner->GetFloatKey( "spread" );
|
||||
skin_nade = owner->GetKey( "skin_nade" );
|
||||
skin_nade_invis = owner->GetKey( "skin_nade_invis" );
|
||||
skin_nonade = owner->GetKey( "skin_nonade" );
|
||||
skin_nonade_invis = owner->GetKey( "skin_nonade_invis" );
|
||||
|
||||
GrenadeNade();
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponHandgrenade::GrenadeNade
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponHandgrenade::GrenadeNade( void )
|
||||
{
|
||||
show_grenade = true;
|
||||
UpdateSkin();
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponHandgrenade::GrenadeNoNade
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponHandgrenade::GrenadeNoNade( void )
|
||||
{
|
||||
show_grenade = false;
|
||||
UpdateSkin();
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponHandgrenade::GrenadeNoNade
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponHandgrenade::UpdateSkin()
|
||||
{
|
||||
if( !show_grenade )
|
||||
{
|
||||
if( owner->Event_IsInvisible() )
|
||||
{
|
||||
owner->Event_SetSkin( skin_nonade_invis );
|
||||
}
|
||||
else
|
||||
{
|
||||
owner->Event_SetSkin( skin_nonade );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( owner->Event_IsInvisible() )
|
||||
{
|
||||
owner->Event_SetSkin( skin_nade_invis );
|
||||
}
|
||||
else
|
||||
{
|
||||
owner->Event_SetSkin( skin_nade );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponHandgrenade::Raise
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponHandgrenade::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, HANDGRENADE_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponHandgrenade::Lower
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponHandgrenade::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponHandgrenade::Idle
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponHandgrenade::Idle( stateParms_t* parms )
|
||||
{
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
owner->Event_WeaponReady();
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
/*
|
||||
===============
|
||||
rvmWeaponHandgrenade::OwnerDied
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponHandgrenade::OwnerDied( void )
|
||||
{
|
||||
float time_held;
|
||||
|
||||
if( projectile )
|
||||
{
|
||||
time_held = gameLocal.SysScriptTime() - fuse_start;
|
||||
projectile->Show();
|
||||
projectile->Unbind();
|
||||
|
||||
// allow grenade to drop
|
||||
owner->Event_LaunchProjectiles( HANDGRENADE_NUMPROJECTILES, spread, time_held, 0, 1.0 );
|
||||
|
||||
projectile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponHandgrenade::Fire
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponHandgrenade::Fire( stateParms_t* parms )
|
||||
{
|
||||
if( parms->stage == 0 )
|
||||
{
|
||||
projectile = ( idProjectile* )owner->CreateProjectile();
|
||||
|
||||
if( projectile )
|
||||
{
|
||||
projectile->Event_StartSound( "snd_throw", SND_CHANNEL_BODY, true );
|
||||
}
|
||||
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "throw_start", false );
|
||||
|
||||
current_time = gameLocal.SysScriptTime();
|
||||
fuse_start = current_time;
|
||||
fuse_end = current_time + HANDGRENADE_FUSE;
|
||||
parms->stage = 1;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
if( parms->stage == 1 )
|
||||
{
|
||||
if( current_time < fuse_end )
|
||||
{
|
||||
if( ( current_time > fuse_start + HANDGRENADE_MINRELEASETIME ) )
|
||||
{
|
||||
parms->stage = 2;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
current_time = gameLocal.SysScriptTime();
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
parms->stage = 2;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
if( parms->stage == 2 )
|
||||
{
|
||||
time_held = current_time - fuse_start;
|
||||
power = time_held + HANDGRENADE_MINPOWER;
|
||||
if( power > HANDGRENADE_MAXPOWER )
|
||||
{
|
||||
power = HANDGRENADE_MAXPOWER;
|
||||
}
|
||||
|
||||
if( time_held < HANDGRENADE_QUICKTHROWTIME )
|
||||
{
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "throw_quick", false );
|
||||
parms->Wait( HANDGRENADE_QUICKTHROWLAUNCH );
|
||||
exploded = false;
|
||||
}
|
||||
else if( time_held < HANDGRENADE_FUSE )
|
||||
{
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "throw", false );
|
||||
parms->Wait( HANDGRENADE_NORMALTHROWLAUNCH );
|
||||
exploded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no anim. grenade just blows up
|
||||
ExplodeInHand();
|
||||
exploded = true;
|
||||
}
|
||||
|
||||
parms->stage = 3;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
if( parms->stage == 3 )
|
||||
{
|
||||
if( !exploded )
|
||||
{
|
||||
GrenadeNoNade();
|
||||
current_time = gameLocal.SysScriptTime();
|
||||
if( projectile )
|
||||
{
|
||||
projectile->Show();
|
||||
projectile->Unbind();
|
||||
owner->Event_LaunchProjectiles( HANDGRENADE_NUMPROJECTILES, spread, current_time - fuse_start, power, 1.0 );
|
||||
projectile = NULL;
|
||||
}
|
||||
|
||||
parms->stage = 4;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
parms->stage = 5;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
if( parms->stage == 4 )
|
||||
{
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, HANDGRENADE_FIRE_TO_IDLE ) )
|
||||
{
|
||||
parms->stage = 5;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
if( !owner->AmmoAvailable() )
|
||||
{
|
||||
stateThread.Clear();
|
||||
stateThread.SetState( "Holstered" );
|
||||
owner->GetOwner()->NextWeapon();
|
||||
}
|
||||
else
|
||||
{
|
||||
GrenadeNade();
|
||||
}
|
||||
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponHandgrenade::Reload
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponHandgrenade::Reload( stateParms_t* parms )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponHandgrenade::ExplodeInHand
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponHandgrenade::ExplodeInHand()
|
||||
{
|
||||
idStr entname;
|
||||
idEntity* explosion;
|
||||
idVec3 forward;
|
||||
idAngles angles;
|
||||
idPlayer* owner;
|
||||
|
||||
if( projectile )
|
||||
{
|
||||
projectile->Event_Remove();
|
||||
projectile = NULL;
|
||||
}
|
||||
|
||||
owner = this->owner->GetOwner();
|
||||
|
||||
GrenadeNoNade();
|
||||
this->owner->Event_StartSound( "snd_explode", SND_CHANNEL_ANY, false );
|
||||
|
||||
//if( !common->IsClient() )
|
||||
{
|
||||
this->owner->Event_UseAmmo( HANDGRENADE_NUMPROJECTILES );
|
||||
|
||||
angles = owner->viewAngles;
|
||||
forward = angles.ToForward();
|
||||
|
||||
entname = this->owner->GetKey( "def_explode_inhand" );
|
||||
explosion = gameLocal.Spawn( entname );
|
||||
explosion->SetOrigin( this->owner->GetOrigin() + forward * 16 );
|
||||
explosion->SetShaderParm( SHADERPARM_TIMEOFFSET, -gameLocal.SysScriptTime() );
|
||||
gameLocal.DelayRemoveEntity( explosion, 2 );
|
||||
|
||||
// this should kill us
|
||||
gameLocal.RadiusDamage( this->owner->GetOrigin(), this->owner, owner, NULL, NULL, this->owner->GetKey( "def_damage_inhand" ), 1.0f );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Weapon_handgrenade.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponHandgrenade : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponHandgrenade );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
virtual void OwnerDied( void ) override;
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
private:
|
||||
void GrenadeNade( void );
|
||||
void GrenadeNoNade( void );
|
||||
void UpdateSkin();
|
||||
|
||||
void ExplodeInHand();
|
||||
private:
|
||||
float spread;
|
||||
float fuse_start;
|
||||
idStr skin_nade;
|
||||
idStr skin_nade_invis;
|
||||
idStr skin_nonade;
|
||||
idStr skin_nonade_invis;
|
||||
idProjectile* projectile;
|
||||
|
||||
boolean show_grenade;
|
||||
private:
|
||||
float fuse_end;
|
||||
float current_time;
|
||||
float time_held;
|
||||
float power;
|
||||
boolean exploded;
|
||||
|
||||
|
||||
const idSoundShader* snd_lowammo;
|
||||
};
|
||||
@@ -0,0 +1,205 @@
|
||||
// Weapon_machinegun.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponMachineGun )
|
||||
END_CLASS
|
||||
|
||||
#define MACHINEGUN_FIRERATE 0.1 // ~10 per second
|
||||
#define MACHINEGUN_LOWAMMO 10
|
||||
#define MACHINEGUN_NUMPROJECTILES 1
|
||||
|
||||
// blend times
|
||||
#define MACHINEGUN_IDLE_TO_LOWER 4
|
||||
#define MACHINEGUN_IDLE_TO_FIRE 0
|
||||
#define MACHINEGUN_IDLE_TO_RELOAD 4
|
||||
#define MACHINEGUN_RAISE_TO_IDLE 4
|
||||
#define MACHINEGUN_FIRE_TO_IDLE 0
|
||||
#define MACHINEGUN_RELOAD_TO_IDLE 4
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponMachineGun::Init
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponMachineGun::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
|
||||
next_attack = 0;
|
||||
spread = weapon->GetFloat( "spread" );
|
||||
|
||||
snd_lowammo = FindSound( "snd_lowammo" );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponMachineGun::Raise
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponMachineGun::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, MACHINEGUN_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponMachineGun::Lower
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponMachineGun::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponMachineGun::Idle
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponMachineGun::Idle( stateParms_t* parms )
|
||||
{
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
owner->Event_WeaponReady();
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponMachineGun::Fire
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponMachineGun::Fire( stateParms_t* parms )
|
||||
{
|
||||
int ammoClip = owner->AmmoInClip();
|
||||
|
||||
enum FIRE_State
|
||||
{
|
||||
FIRE_NOTSET = 0,
|
||||
FIRE_WAIT
|
||||
};
|
||||
|
||||
if( ammoClip == 0 && owner->AmmoAvailable() && parms->stage == 0 )
|
||||
{
|
||||
//owner->WeaponState( WP_RELOAD, PISTOL_IDLE_TO_RELOAD );
|
||||
owner->Reload();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case FIRE_NOTSET:
|
||||
next_attack = gameLocal.realClientTime + MS2SEC( MACHINEGUN_FIRERATE );
|
||||
owner->Event_LaunchProjectiles( MACHINEGUN_NUMPROJECTILES, spread, 0, 1, 1 );
|
||||
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "fire", false );
|
||||
parms->stage = FIRE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, MACHINEGUN_FIRE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponMachineGun::Reload
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponMachineGun::Reload( stateParms_t* parms )
|
||||
{
|
||||
enum RELOAD_State
|
||||
{
|
||||
RELOAD_NOTSET = 0,
|
||||
RELOAD_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RELOAD_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "reload", false );
|
||||
parms->stage = RELOAD_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RELOAD_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
owner->Event_AddToClip( owner->ClipSize() );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Weapon_machinegun.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponMachineGun : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponMachineGun );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
private:
|
||||
float spread;
|
||||
|
||||
const idSoundShader* snd_lowammo;
|
||||
};
|
||||
@@ -0,0 +1,133 @@
|
||||
// Weapon_pda.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponPDA )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponPDA::Init
|
||||
================
|
||||
*/
|
||||
void rvmWeaponPDA::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponPDA::Raise
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponPDA::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponPDA::Lower
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponPDA::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponPDA::Idle
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponPDA::Idle( stateParms_t* parms )
|
||||
{
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
owner->GetOwner()->Event_OpenPDA();
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
if( !owner->GetOwner()->objectiveSystemOpen )
|
||||
{
|
||||
//owner->WeaponState( WP_LOWERING, 0 );
|
||||
owner->LowerWeapon();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponPDA::Fire
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponPDA::Fire( stateParms_t* parms )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvmWeaponPDA::Reload
|
||||
================
|
||||
*/
|
||||
stateResult_t rvmWeaponPDA::Reload( stateParms_t* parms )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Weapon_pda.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponPDA : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponPDA );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
};
|
||||
@@ -0,0 +1,217 @@
|
||||
// Weapon_pistol.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponPistol )
|
||||
END_CLASS
|
||||
|
||||
#define PISTOL_FIRERATE 0.4
|
||||
#define PISTOL_LOWAMMO 4
|
||||
#define PISTOL_NUMPROJECTILES 1
|
||||
|
||||
// blend times
|
||||
#define PISTOL_IDLE_TO_LOWER 2
|
||||
#define PISTOL_IDLE_TO_FIRE 1
|
||||
#define PISTOL_IDLE_TO_RELOAD 3
|
||||
#define PISTOL_RAISE_TO_IDLE 3
|
||||
#define PISTOL_FIRE_TO_IDLE 4
|
||||
#define PISTOL_RELOAD_TO_IDLE 40
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponPistol::Init
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponPistol::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
|
||||
next_attack = 0;
|
||||
spread = weapon->GetFloat( "spread" );
|
||||
snd_lowammo = FindSound( "snd_lowammo" );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponPistol::Raise
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponPistol::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, PISTOL_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponPistol::Lower
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponPistol::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponPistol::Idle
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponPistol::Idle( stateParms_t* parms )
|
||||
{
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
owner->Event_WeaponReady();
|
||||
if( !owner->AmmoInClip() )
|
||||
{
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle_empty" );
|
||||
}
|
||||
else
|
||||
{
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
}
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponPistol::Fire
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponPistol::Fire( stateParms_t* parms )
|
||||
{
|
||||
int ammoClip = owner->AmmoInClip();
|
||||
|
||||
enum FIRE_State
|
||||
{
|
||||
FIRE_NOTSET = 0,
|
||||
FIRE_WAIT
|
||||
};
|
||||
|
||||
if( ammoClip == 0 && owner->AmmoAvailable() && parms->stage == 0 )
|
||||
{
|
||||
//owner->WeaponState( WP_RELOAD, PISTOL_IDLE_TO_RELOAD );
|
||||
owner->Reload();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case FIRE_NOTSET:
|
||||
next_attack = gameLocal.realClientTime + SEC2MS( PISTOL_FIRERATE );
|
||||
|
||||
if( ammoClip == PISTOL_LOWAMMO )
|
||||
{
|
||||
int length;
|
||||
owner->StartSoundShader( snd_lowammo, SND_CHANNEL_ITEM, 0, false, &length );
|
||||
}
|
||||
|
||||
owner->Event_LaunchProjectiles( PISTOL_NUMPROJECTILES, spread, 0, 1, 1 );
|
||||
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "fire", false );
|
||||
parms->stage = FIRE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, PISTOL_FIRE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponPistol::Reload
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponPistol::Reload( stateParms_t* parms )
|
||||
{
|
||||
enum RELOAD_State
|
||||
{
|
||||
RELOAD_NOTSET = 0,
|
||||
RELOAD_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RELOAD_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "reload", false );
|
||||
parms->stage = RELOAD_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RELOAD_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
owner->Event_AddToClip( owner->ClipSize() );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Weapon_pistol.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponPistol : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponPistol );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
private:
|
||||
float spread;
|
||||
|
||||
const idSoundShader* snd_lowammo;
|
||||
};
|
||||
@@ -0,0 +1,205 @@
|
||||
// Weapon_plasmagun.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponPlasmaGun )
|
||||
END_CLASS
|
||||
|
||||
#define PLASMAGUN_FIRERATE 0.125 //changed by Tim
|
||||
#define PLASMAGUN_LOWAMMO 10
|
||||
#define PLASMAGUN_NUMPROJECTILES 1
|
||||
|
||||
// blend times
|
||||
#define PLASMAGUN_IDLE_TO_LOWER 4
|
||||
#define PLASMAGUN_IDLE_TO_FIRE 1
|
||||
#define PLASMAGUN_IDLE_TO_RELOAD 4
|
||||
#define PLASMAGUN_RAISE_TO_IDLE 4
|
||||
#define PLASMAGUN_FIRE_TO_IDLE 4
|
||||
#define PLASMAGUN_RELOAD_TO_IDLE 4
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponPlasmaGun::Init
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponPlasmaGun::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
|
||||
next_attack = 0;
|
||||
spread = weapon->GetFloat( "spread" );
|
||||
snd_lowammo = FindSound( "snd_lowammo" );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponPlasmaGun::Raise
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponPlasmaGun::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, PLASMAGUN_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponPlasmaGun::Lower
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponPlasmaGun::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponPlasmaGun::Idle
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponPlasmaGun::Idle( stateParms_t* parms )
|
||||
{
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
owner->Event_WeaponReady();
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponPlasmaGun::Fire
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponPlasmaGun::Fire( stateParms_t* parms )
|
||||
{
|
||||
int ammoClip = owner->AmmoInClip();
|
||||
|
||||
enum FIRE_State
|
||||
{
|
||||
FIRE_NOTSET = 0,
|
||||
FIRE_WAIT
|
||||
};
|
||||
|
||||
if( ammoClip == 0 && owner->AmmoAvailable() && parms->stage == 0 )
|
||||
{
|
||||
//owner->WeaponState( WP_RELOAD, PISTOL_IDLE_TO_RELOAD );
|
||||
owner->Reload();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case FIRE_NOTSET:
|
||||
next_attack = gameLocal.time + SEC2MS( PLASMAGUN_FIRERATE );
|
||||
owner->Event_LaunchProjectiles( PLASMAGUN_NUMPROJECTILES, spread, 0, 1, 1 );
|
||||
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "fire", false );
|
||||
parms->stage = FIRE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, PLASMAGUN_FIRE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponPlasmaGun::Reload
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponPlasmaGun::Reload( stateParms_t* parms )
|
||||
{
|
||||
enum RELOAD_State
|
||||
{
|
||||
RELOAD_NOTSET = 0,
|
||||
RELOAD_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RELOAD_NOTSET:
|
||||
owner->Event_WeaponReloading();
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "reload", false );
|
||||
parms->stage = RELOAD_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RELOAD_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, PLASMAGUN_RELOAD_TO_IDLE ) )
|
||||
{
|
||||
owner->Event_AddToClip( owner->ClipSize() );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Weapon_plasmagun.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponPlasmaGun : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponPlasmaGun );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
private:
|
||||
float spread;
|
||||
|
||||
const idSoundShader* snd_lowammo;
|
||||
};
|
||||
@@ -0,0 +1,235 @@
|
||||
// Weapon_rocketlauncher.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponRocketLauncher )
|
||||
END_CLASS
|
||||
|
||||
#define ROCKETLAUNCHER_LOWAMMO 1
|
||||
#define ROCKETLAUNCHER_NUMPROJECTILES 1
|
||||
#define ROCKETLAUNCHER_FIREDELAY 1 // was .75 changed again by Tim to 1
|
||||
|
||||
// blend times
|
||||
#define ROCKETLAUNCHER_IDLE_TO_LOWER 4
|
||||
#define ROCKETLAUNCHER_IDLE_TO_FIRE 0
|
||||
#define ROCKETLAUNCHER_IDLE_TO_RELOAD 4
|
||||
#define ROCKETLAUNCHER_RAISE_TO_IDLE 4
|
||||
#define ROCKETLAUNCHER_FIRE_TO_IDLE 0
|
||||
#define ROCKETLAUNCHER_RELOAD_TO_IDLE 4
|
||||
#define ROCKETLAUNCHER_RELOAD_FRAME 34 // how many frames from the end of "reload" to fill the clip
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponRocketLauncher::Init
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponRocketLauncher::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
|
||||
next_attack = 0;
|
||||
spread = weapon->GetFloat( "spread" );
|
||||
skin_invisible = weapon->GetKey( "skin_invisible" );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponRocketLauncher::UpdateSkin
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponRocketLauncher::UpdateSkin()
|
||||
{
|
||||
idStr skinname;
|
||||
int ammoClip;
|
||||
|
||||
if( owner->Event_IsInvisible() )
|
||||
{
|
||||
skinname = skin_invisible;
|
||||
}
|
||||
else
|
||||
{
|
||||
ammoClip = owner->AmmoInClip();
|
||||
if( ammoClip > 5 )
|
||||
{
|
||||
// can happen in MP - weapon Raising with slightly out-of-sync ammoClip
|
||||
ammoClip = 5;
|
||||
}
|
||||
if( ammoClip < 0 )
|
||||
{
|
||||
ammoClip = 0;
|
||||
}
|
||||
skinname = va( "skins/models/weapons/%drox.skin", ammoClip );
|
||||
}
|
||||
owner->Event_SetSkin( skinname );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponRocketLauncher::Raise
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponRocketLauncher::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, ROCKETLAUNCHER_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponRocketLauncher::Lower
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponRocketLauncher::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
/*
|
||||
===============
|
||||
rvmWeaponRocketLauncher::Idle
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponRocketLauncher::Idle( stateParms_t* parms )
|
||||
{
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
owner->Event_WeaponReady();
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponRocketLauncher::Fire
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponRocketLauncher::Fire( stateParms_t* parms )
|
||||
{
|
||||
int ammoClip = owner->AmmoInClip();
|
||||
|
||||
enum FIRE_State
|
||||
{
|
||||
FIRE_NOTSET = 0,
|
||||
FIRE_WAIT
|
||||
};
|
||||
|
||||
if( ammoClip == 0 && owner->AmmoAvailable() && parms->stage == 0 )
|
||||
{
|
||||
//owner->WeaponState( WP_RELOAD, PISTOL_IDLE_TO_RELOAD );
|
||||
owner->Reload();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case FIRE_NOTSET:
|
||||
next_attack = gameLocal.realClientTime + SEC2MS( ROCKETLAUNCHER_FIREDELAY );
|
||||
owner->Event_LaunchProjectiles( ROCKETLAUNCHER_NUMPROJECTILES, spread, 0, 1, 1 );
|
||||
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "fire", false );
|
||||
parms->stage = FIRE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, ROCKETLAUNCHER_FIRE_TO_IDLE ) )
|
||||
{
|
||||
UpdateSkin();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponRocketLauncher::Reload
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponRocketLauncher::Reload( stateParms_t* parms )
|
||||
{
|
||||
enum RELOAD_State
|
||||
{
|
||||
RELOAD_NOTSET = 0,
|
||||
RELOAD_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RELOAD_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "reload", false );
|
||||
parms->stage = RELOAD_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RELOAD_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
owner->Event_AddToClip( owner->ClipSize() );
|
||||
UpdateSkin();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Weapon_rocketlauncher.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponRocketLauncher : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponRocketLauncher );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
private:
|
||||
void UpdateSkin();
|
||||
|
||||
float spread;
|
||||
idStr skin_invisible;
|
||||
};
|
||||
@@ -0,0 +1,245 @@
|
||||
// Weapon_shotgun.cpp
|
||||
//
|
||||
|
||||
#pragma hdrstop
|
||||
#include "precompiled.h"
|
||||
#include "../Game_local.h"
|
||||
|
||||
CLASS_DECLARATION( rvmWeaponObject, rvmWeaponShotgun )
|
||||
END_CLASS
|
||||
|
||||
#define SHOTGUN_FIRERATE 1.333
|
||||
#define SHOTGUN_LOWAMMO 2
|
||||
#define SHOTGUN_RELOADRATE 2
|
||||
#define SHOTGUN_NUMPROJECTILES 13
|
||||
|
||||
// blend times
|
||||
#define SHOTGUN_IDLE_TO_IDLE 0
|
||||
#define SHOTGUN_IDLE_TO_LOWER 4
|
||||
#define SHOTGUN_IDLE_TO_FIRE 1
|
||||
#define SHOTGUN_IDLE_TO_RELOAD 4
|
||||
#define SHOTGUN_IDLE_TO_NOAMMO 4
|
||||
#define SHOTGUN_NOAMMO_TO_RELOAD 4
|
||||
#define SHOTGUN_NOAMMO_TO_IDLE 4
|
||||
#define SHOTGUN_RAISE_TO_IDLE 1
|
||||
#define SHOTGUN_FIRE_TO_IDLE 4
|
||||
#define SHOTGUN_RELOAD_TO_IDLE 4
|
||||
#define SHOTGUN_RELOAD_TO_FIRE 4
|
||||
#define SHOTGUN_RELOAD_TO_LOWER 2
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponShotgun::Init
|
||||
===============
|
||||
*/
|
||||
void rvmWeaponShotgun::Init( idWeapon* weapon )
|
||||
{
|
||||
rvmWeaponObject::Init( weapon );
|
||||
|
||||
next_attack = 0;
|
||||
spread = weapon->GetFloat( "spread" ); // weapon->GetFloat("spread")
|
||||
snd_lowammo = FindSound( "snd_lowammo" );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponShotgun::Raise
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponShotgun::Raise( stateParms_t* parms )
|
||||
{
|
||||
enum RisingState
|
||||
{
|
||||
RISING_NOTSET = 0,
|
||||
RISING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RISING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
|
||||
parms->stage = RISING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RISING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, SHOTGUN_RAISE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponShotgun::Lower
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponShotgun::Lower( stateParms_t* parms )
|
||||
{
|
||||
enum LoweringState
|
||||
{
|
||||
LOWERING_NOTSET = 0,
|
||||
LOWERING_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case LOWERING_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
|
||||
parms->stage = LOWERING_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case LOWERING_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
SetState( "Holstered" );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponShotgun::Idle
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponShotgun::Idle( stateParms_t* parms )
|
||||
{
|
||||
enum IdleState
|
||||
{
|
||||
IDLE_NOTSET = 0,
|
||||
IDLE_WAIT
|
||||
};
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case IDLE_NOTSET:
|
||||
owner->Event_WeaponReady();
|
||||
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
|
||||
parms->stage = IDLE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case IDLE_WAIT:
|
||||
// Do nothing.
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
/*
|
||||
===============
|
||||
rvmWeaponShotgun::Fire
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponShotgun::Fire( stateParms_t* parms )
|
||||
{
|
||||
int ammoClip = owner->AmmoInClip();
|
||||
|
||||
enum FIRE_State
|
||||
{
|
||||
FIRE_NOTSET = 0,
|
||||
FIRE_WAIT
|
||||
};
|
||||
|
||||
if( ammoClip == 0 && owner->AmmoAvailable() && parms->stage == 0 )
|
||||
{
|
||||
//owner->WeaponState( WP_RELOAD, PISTOL_IDLE_TO_RELOAD );
|
||||
owner->Reload();
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case FIRE_NOTSET:
|
||||
next_attack = gameLocal.realClientTime + SEC2MS( SHOTGUN_FIRERATE );
|
||||
|
||||
if( ammoClip == SHOTGUN_LOWAMMO )
|
||||
{
|
||||
int length;
|
||||
owner->StartSoundShader( snd_lowammo, SND_CHANNEL_ITEM, 0, false, &length );
|
||||
}
|
||||
|
||||
owner->Event_LaunchProjectiles( SHOTGUN_NUMPROJECTILES, spread, 0, 1, 1 );
|
||||
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "fire", false );
|
||||
parms->stage = FIRE_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case FIRE_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, SHOTGUN_FIRE_TO_IDLE ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
rvmWeaponShotgun::Reload
|
||||
===============
|
||||
*/
|
||||
stateResult_t rvmWeaponShotgun::Reload( stateParms_t* parms )
|
||||
{
|
||||
float ammoClip;
|
||||
float ammoAvail;
|
||||
float clip_size;
|
||||
|
||||
clip_size = owner->ClipSize();
|
||||
|
||||
enum RELOAD_State
|
||||
{
|
||||
RELOAD_NOTSET = 0,
|
||||
RELOAD_WAIT,
|
||||
RELOAD_END
|
||||
};
|
||||
|
||||
ammoAvail = owner->AmmoAvailable();
|
||||
ammoClip = owner->AmmoInClip();
|
||||
|
||||
switch( parms->stage )
|
||||
{
|
||||
case RELOAD_NOTSET:
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "reload_loop", false );
|
||||
parms->stage = RELOAD_WAIT;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case RELOAD_WAIT:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
if( ( ammoClip < clip_size ) && ( ammoClip < ammoAvail ) )
|
||||
{
|
||||
parms->stage = RELOAD_NOTSET;
|
||||
owner->Event_AddToClip( SHOTGUN_RELOADRATE );
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
parms->stage = RELOAD_END;
|
||||
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "reload_end", false );
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
owner->Event_AddToClip( owner->ClipSize() );
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
case RELOAD_END:
|
||||
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
|
||||
{
|
||||
return SRESULT_DONE;
|
||||
}
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Weapon_shotgun.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class rvmWeaponShotgun : public rvmWeaponObject
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE( rvmWeaponShotgun );
|
||||
|
||||
virtual void Init( idWeapon* weapon );
|
||||
|
||||
stateResult_t Raise( stateParms_t* parms );
|
||||
stateResult_t Lower( stateParms_t* parms );
|
||||
stateResult_t Idle( stateParms_t* parms );
|
||||
stateResult_t Fire( stateParms_t* parms );
|
||||
stateResult_t Reload( stateParms_t* parms );
|
||||
private:
|
||||
float spread;
|
||||
|
||||
const idSoundShader* snd_lowammo;
|
||||
};
|
||||
Reference in New Issue
Block a user