Add modified source code in framework and game directory (part 1)

This commit is contained in:
LegendGuard 2023-07-24 18:43:41 +02:00 committed by GitHub
parent 835ccde40d
commit cdc61a1a53
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 3624 additions and 69 deletions

View file

@ -46,6 +46,7 @@ const int BUTTON_RUN = BIT(1);
const int BUTTON_ZOOM = BIT(2);
const int BUTTON_SCORES = BIT(3);
const int BUTTON_MLOOK = BIT(4);
const int BUTTON_ATTACK2 = BIT(5); // Zeroth404
const int BUTTON_5 = BIT(5);
const int BUTTON_6 = BIT(6);
const int BUTTON_7 = BIT(7);
@ -82,6 +83,12 @@ const int IMPULSE_27 = 27; // <unused>
const int IMPULSE_28 = 28; // vote yes
const int IMPULSE_29 = 29; // vote no
const int IMPULSE_40 = 40; // use vehicle
// Zeroth
const int IMPULSE_41 = 41; // hec Inventory Scroll Right
const int IMPULSE_42 = 42; // hec Inventory Scroll Left
const int IMPULSE_43 = 43; // hec use selected item
const int IMPULSE_44 = 44; // hec drop selected item
const int IMPULSE_45 = 45; // toggle automap
// usercmd_t->flags
const int UCF_IMPULSE_SEQUENCE = 0x0001; // toggled every time an impulse command is sent

View file

@ -377,10 +377,10 @@ Pass damage to body at the bindjoint
============
*/
void idAFAttachment::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir,
const char *damageDefName, const float damageScale, const int location ) {
const char *damageDefName, const float damageScale, const int location, const idVec3 &iPoint ) {
if ( body ) {
body->Damage( inflictor, attacker, dir, damageDefName, damageScale, attachJoint );
body->Damage( inflictor, attacker, dir, damageDefName, damageScale, attachJoint, iPoint );
}
}
@ -1087,11 +1087,11 @@ void idAFEntity_Gibbable::Present( void ) {
idAFEntity_Gibbable::Damage
================
*/
void idAFEntity_Gibbable::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location ) {
void idAFEntity_Gibbable::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location, idVec3 &iPoint ) {
if ( !fl.takedamage ) {
return;
}
idAFEntity_Base::Damage( inflictor, attacker, dir, damageDefName, damageScale, location );
idAFEntity_Base::Damage( inflictor, attacker, dir, damageDefName, damageScale, location, iPoint );
if ( health < -20 && spawnArgs.GetBool( "gib" ) ) {
Gib( dir, damageDefName );
}

View file

@ -123,7 +123,7 @@ public:
virtual void ApplyImpulse( idEntity *ent, int id, const idVec3 &point, const idVec3 &impulse );
virtual void AddForce( idEntity *ent, int id, const idVec3 &point, const idVec3 &force );
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location );
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location, const idVec3 &iPoint );
virtual void AddDamageEffect( const trace_t &collision, const idVec3 &velocity, const char *damageDefName );
void SetCombatModel( void );
@ -225,7 +225,7 @@ public:
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
virtual void Present( void );
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location );
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location, idVec3 &iPoint );
virtual void SpawnGibs( const idVec3 &dir, const char *damageDefName );
protected:

View file

@ -1825,6 +1825,27 @@ idActor *idActor::ClosestEnemyToPoint( const idVec3 &pos ) {
return bestEnt;
}
// HEXEN : Zeroth
/*
================
idActor::IsEnemy
================
*/
bool idActor::IsEnemy( idEntity *test ) {
idActor *ent;
for( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
if ( ent->fl.hidden ) {
continue;
}
gameLocal.Printf(" [%s] - [%s]", ent->name.c_str(), test->name.c_str());
if ( ent->name.c_str() == test->name.c_str() ) {
return true;
}
}
return false;
}
/*
================
idActor::EnemyWithMostHealth
@ -2158,7 +2179,7 @@ calls Damage()
============
*/
void idActor::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir,
const char *damageDefName, const float damageScale, const int location ) {
const char *damageDefName, const float damageScale, const int location, const idVec3 &iPoint ) {
if ( !fl.takedamage ) {
return;
}
@ -2258,10 +2279,25 @@ bool idActor::Pain( idEntity *inflictor, idEntity *attacker, int damage, const i
return false;
}
// set the pain anim
idStr damageGroup = GetDamageGroup( location );
painAnim = "";
if ( g_debugDamage.GetBool() ) {
gameLocal.Printf( "Damage: joint: '%s', zone '%s', anim '%s'\n", animator.GetJointName( ( jointHandle_t )location ),
damageGroup.c_str(), painAnim.c_str() );
}
// HEXEN : Zeroth: don't do pain anims for trigger types
if ( inflictor ) {
if ( inflictor->IsType( idTrigger_Hurt::Type ) ) {
return false;
}
if ( inflictor->IsType( idTrigger_Touch::Type ) ) {
return false;
}
}
// set the pain anim
if ( animPrefix.Length() ) {
if ( damageGroup.Length() && ( damageGroup != "legs" ) ) {
sprintf( painAnim, "%s_pain_%s", animPrefix.c_str(), damageGroup.c_str() );
@ -2293,11 +2329,6 @@ bool idActor::Pain( idEntity *inflictor, idEntity *attacker, int damage, const i
painAnim = "pain";
}
if ( g_debugDamage.GetBool() ) {
gameLocal.Printf( "Damage: joint: '%s', zone '%s', anim '%s'\n", animator.GetJointName( ( jointHandle_t )location ),
damageGroup.c_str(), painAnim.c_str() );
}
return true;
}
@ -2403,11 +2434,49 @@ idActor::Event_EnableEyeFocus
void idActor::PlayFootStepSound( void ) {
const char *sound = NULL;
const idMaterial *material;
idPlayer *player;
if ( !GetPhysics()->HasGroundContacts() ) {
return;
}
// HEXEN : Zeroth
if ( this->IsType( idPlayer::Type ) ) {
player = static_cast< idPlayer* >( this );
// no footstep sounds when flying (wings of wrath)
if ( player->FreeMove ) {
return;
}
if ( player->inWater ) {
waterLevel_t level = static_cast< idPhysics_Player* >( player->GetPlayerPhysics() )->GetWaterLevel();
if ( level == WATERLEVEL_FEET ) {
sound = spawnArgs.GetString( "snd_footstep_water_feet" );
} else if ( level == WATERLEVEL_WAIST ) {
sound = spawnArgs.GetString( "snd_footstep_water_waist" );
} else if ( level == WATERLEVEL_HEAD ) {
sound = spawnArgs.GetString( "snd_footstep_water_head" );
} else {
sound = spawnArgs.GetString( "snd_footstep_water_feet" );
}
if ( *sound != '\0' ) {
StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, SSF_NO_DUPS, false, NULL );
}
return;
} else if ( player->leftWater != 0 && gameLocal.time < player->leftWater + 3000 ) {
sound = spawnArgs.GetString( "snd_footstep_wet" );
if ( *sound != '\0' ) {
StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, SSF_NO_DUPS, false, NULL );
}
return;
}
}
// start footstep sound based on material type
material = GetPhysics()->GetContact( 0 ).material;
if ( material != NULL ) {
@ -2417,7 +2486,7 @@ void idActor::PlayFootStepSound( void ) {
sound = spawnArgs.GetString( "snd_footstep" );
}
if ( *sound != '\0' ) {
StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, 0, false, NULL );
StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, SSF_NO_DUPS, false, NULL );
}
}
@ -3120,22 +3189,30 @@ idActor::Event_AnimLength
================
*/
void idActor::Event_AnimLength( int channel, const char *animname ) {
idThread::ReturnFloat( GetAnimLength(channel, animname) );
}
// HEXEN : Zeroth
/*
================
idActor::GetAnimLength
================
*/
float idActor::GetAnimLength( int channel, const char *animname ) {
int anim;
anim = GetAnim( channel, animname );
if ( anim ) {
if ( channel == ANIMCHANNEL_HEAD ) {
if ( head.GetEntity() ) {
idThread::ReturnFloat( MS2SEC( head.GetEntity()->GetAnimator()->AnimLength( anim ) ) );
return;
return MS2SEC( head.GetEntity()->GetAnimator()->AnimLength( anim ) );
}
} else {
idThread::ReturnFloat( MS2SEC( animator.AnimLength( anim ) ) );
return;
}
return MS2SEC( animator.AnimLength( anim ) );
}
}
idThread::ReturnFloat( 0.0f );
return 0.0f;
}
/*

View file

@ -165,7 +165,7 @@ public:
// damage
void SetupDamageGroups( void );
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location );
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location, const idVec3 &iPoint );
int GetDamageForLocation( int damage, int location );
const char * GetDamageGroup( int location );
void ClearPain( void );
@ -318,6 +318,15 @@ private:
void Event_SetState( const char *name );
void Event_GetState( void );
void Event_GetHead( void );
// HEXEN : Zeroth
protected:
void Event_VecForward( float spread ); // return a forward vector for the direction we're facing, with some random spread (like projectiles)
// HEXEN : Zeroth
public:
bool IsEnemy( idEntity *test );
float GetAnimLength( int channel, const char *animname );
};
#endif /* !__GAME_ACTOR_H__ */

View file

@ -39,8 +39,8 @@ CLASS_DECLARATION( idEntity, idBrittleFracture )
EVENT( EV_Touch, idBrittleFracture::Event_Touch )
END_CLASS
const int SHARD_ALIVE_TIME = 5000;
const int SHARD_FADE_START = 2000;
const int SHARD_ALIVE_TIME = 5000; // HEXEN : Zeroth - changed from 5000
const int SHARD_FADE_START = 3500; // HEXEN : Zeroth - changed from 2000
static const char *brittleFracture_SnapshotName = "_BrittleFracture_Snapshot_";
@ -772,13 +772,39 @@ void idBrittleFracture::ProjectDecal( const idVec3 &point, const idVec3 &dir, co
idBrittleFracture::DropShard
================
*/
void idBrittleFracture::DropShard( shard_t *shard, const idVec3 &point, const idVec3 &dir, const float impulse, const int time ) {
void idBrittleFracture::DropShard( shard_t *shard, const idVec3 &point, const idVec3 &odir, const float oimpulse, const int time ) {
int i, j, clipModelId;
float dist, f;
idVec3 dir2, origin;
idMat3 axis;
shard_t *neighbour;
idVec3 dir = odir; // HEXEN : Zeroth
float impulse = oimpulse; // HEXEN : Zeroth
// HEXEN : Zeroth
if ( dir.Length() < 5 ) { // 5 is just an (whats that word?)
dir = idVec3(0,0,-1) * spawnArgs.GetFloat( "forceIfZero", "0" );
impulse = dir.Normalize();
}
// HEXEN : Zeroth
if ( spawnArgs.GetBool( "blastBothWays", "0" ) ) {
dir = -dir;
//m = dir.Normalize();
}
// HEXEN : Zeroth
if ( spawnArgs.GetBool( "randomDir", "0" ) ) {
float len = dir.Length();
dir.x = gameLocal.random.RandomFloat() - 0.5;
dir.y = gameLocal.random.RandomFloat() - 0.5;
dir.z = gameLocal.random.RandomFloat() - 0.5;
dir.Normalize();
dir *= len;
//m = dir.Normalize();
}
// don't display decals on dropped shards
shard->decals.DeleteContents( true );
@ -818,10 +844,26 @@ void idBrittleFracture::DropShard( shard_t *shard, const idVec3 &point, const id
shard->physicsObj.SetAxis( axis );
shard->physicsObj.SetBouncyness( bouncyness );
shard->physicsObj.SetFriction( 0.6f, 0.6f, friction );
shard->physicsObj.SetGravity( gameLocal.GetGravity() );
// HEXEN : Zeroth
float grv = spawnArgs.GetFloat( "shardGravity", "0" );
if ( grv ) {
shard->physicsObj.SetGravity( idVec3(0,0,-1) * grv );
} else {
shard->physicsObj.SetGravity( gameLocal.GetGravity() );
}
// HEXEN : Zeroth
float velScale = 1;
if ( spawnArgs.GetBool( "shardRandomVelocity", "0" ) ) {
velScale = gameLocal.random.RandomFloat();
} else {
velScale = 1;
}
shard->physicsObj.SetContents( CONTENTS_RENDERMODEL );
shard->physicsObj.SetClipMask( MASK_SOLID | CONTENTS_MOVEABLECLIP );
shard->physicsObj.ApplyImpulse( 0, origin, impulse * linearVelocityScale * dir );
shard->physicsObj.ApplyImpulse( 0, origin, impulse * linearVelocityScale * dir * velScale ); // HEXEN : Zeroth: added velScale
shard->physicsObj.SetAngularVelocity( dir.Cross( dir2 ) * ( f * angularVelocityScale ) );
shard->clipModel->SetId( clipModelId );
@ -884,7 +926,10 @@ void idBrittleFracture::Shatter( const idVec3 &point, const idVec3 &impulse, con
DropShard( shard, point, dir, m, time );
}
DropFloatingIslands( point, impulse, time );
// HEXEN : Zeroth
if ( spawnArgs.GetBool( "dropFloatingIsland", "1" ) ) {
DropFloatingIslands( point, dir, time ); // impulse changed to dir
}
}
/*
@ -895,12 +940,13 @@ idBrittleFracture::DropFloatingIslands
void idBrittleFracture::DropFloatingIslands( const idVec3 &point, const idVec3 &impulse, const int time ) {
int i, j, numIslands;
int queueStart, queueEnd;
float m; // HEXEN : Zeroth
shard_t *curShard, *nextShard, **queue;
bool touchesEdge;
idVec3 dir;
dir = impulse;
dir.Normalize();
m = dir.Normalize(); // HEXEN : Zeroth - added 'm = '
numIslands = 0;
queue = (shard_t **) _alloca16( shards.Num() * sizeof(shard_t **) );
@ -955,7 +1001,7 @@ void idBrittleFracture::DropFloatingIslands( const idVec3 &point, const idVec3 &
// if the island is not connected to the world at any edges
if ( !touchesEdge ) {
for ( j = 0; j < queueEnd; j++ ) {
DropShard( queue[j], point, dir, 0.0f, time );
DropShard( queue[j], point, dir, m, time ); // HEXEN : Zeroth - 0.0f to m
}
}
}
@ -969,6 +1015,7 @@ idBrittleFracture::Break
void idBrittleFracture::Break( void ) {
fl.takedamage = false;
physicsObj.SetContents( CONTENTS_RENDERMODEL | CONTENTS_TRIGGER );
gameLocal.SetPersistentRemove( name.c_str() );
}
/*

View file

@ -141,7 +141,14 @@ public:
idList< idEntityPtr<idEntity> > targets; // when this entity is activated these entities entity are activated
int health; // FIXME: do all objects really need health?
// HEXEN : Zeroth
protected:
int nextFlame;
int fireJoint;
public:
int health;
int onFire;
struct entityFlags_s {
bool notarget :1; // if true never attack or target this entity
@ -158,6 +165,16 @@ public:
bool networkSync :1; // if true the entity is synchronized over the network
} fl;
// HEXEN : Zeroth
public:
bool gravityMod;
bool inWater;
// HEXEN : Zeroth
public:
idVec3 curGrav( void );
idVec3 curNorm( void );
public:
ABSTRACT_PROTOTYPE( idEntity );
@ -177,6 +194,16 @@ public:
// clients generate views based on all the player specific options,
// cameras have custom code, and everything else just uses the axis orientation
virtual renderView_t * GetRenderView();
void ShutdownThreads( void );
void UpdateScript( void );
void SetState( const char *statename );
void SetState( const function_t *newState );
const function_t *GetScriptFunction( const char *funcname );
const char *WaitState( void ) const;
void SetWaitState( const char *_waitstate );
//idThread *ConstructScriptObject( void );
//void idEntity::FinishSetup( void );
//bool IsInUse( void ); // HEXEN : Zeroth
// thinking
virtual void Think( void );
@ -302,7 +329,7 @@ public:
// returns true if this entity can be damaged from the given origin
virtual bool CanDamage( const idVec3 &origin, idVec3 &damagePoint ) const;
// applies damage to this entity
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location );
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location, const idVec3 &iPoint );
// adds a damage effect like overlays, blood, sparks, debris etc.
virtual void AddDamageEffect( const trace_t &collision, const idVec3 &velocity, const char *damageDefName );
// callback function for when another entity received damage from this entity. damage can be adjusted and returned to the caller.
@ -361,11 +388,24 @@ public:
void ServerSendEvent( int eventId, const idBitMsg *msg, bool saveEvent, int excludeClient ) const;
void ClientSendEvent( int eventId, const idBitMsg *msg ) const;
// HEXEN : Zeroth
// ****** thanks SnoopJeDi ( http://www.doom3world.org/phpbb2/viewtopic.php?f=56&t=12469&p=214427#p214427 )
void FadeMusic( int channel, float to, float over );
// ******
protected:
renderEntity_t renderEntity; // used to present a model to the renderer
int modelDefHandle; // handle to static renderer model
refSound_t refSound; // used to present sound to the audio engine
// HEXEN : Zeroth
// state variables
const function_t *state;
const function_t *idealState;
// script variables
idThread * scriptThread;
idStr waitState;
private:
idPhysics_Static defaultPhysicsObj; // default physics object
idPhysics * physics; // physics used for this entity
@ -381,6 +421,7 @@ private:
signalList_t * signals;
int mpGUIState; // local cache to avoid systematic SetStateInt
idThread * thread;
private:
void FixupLocalizedStrings();
@ -465,6 +506,32 @@ private:
void Event_HasFunction( const char *name );
void Event_CallFunction( const char *name );
void Event_SetNeverDormant( int enable );
// HEXEN : Zeroth
private:
idDict projectileDict;
idEntity *projectileEnt;
void Event_GetState( void );
void Event_SetState( const char *name );
void Event_SetNextState( const char *name );
void Event_SetGravity( const idVec3 &grav );
void Event_GetGravity( void );
void Event_GetGravityNormal( void );
void Event_GetSelfEntity( void );
void Event_SetHealth( float newHealth );
void Event_GetHealth( void );
void Event_GetType( void );
void Event_SpawnProjectiles( int num_projectiles, float spread, float fuseOffset, float launchPower, float dmgPower );
void Event_CreateProjectile( void );
void Event_GetMaster( void );
void Event_GetModelDims( void );
void Event_ReplaceMaterial( const char * replacee, const char * replacer );
void Event_ResetGravity( void );
void Event_HudMessage( const char *message );
public:
idAngles GetAngles( void );
idVec3 GetModelDims( void );
};
/*
@ -509,6 +576,7 @@ public:
virtual void AddDamageEffect( const trace_t &collision, const idVec3 &velocity, const char *damageDefName );
void AddLocalDamageEffect( jointHandle_t jointNum, const idVec3 &localPoint, const idVec3 &localNormal, const idVec3 &localDir, const idDeclEntityDef *def, const idMaterial *collisionMaterial );
void UpdateDamageEffects( void );
void EmitFlames( void );
virtual bool ClientReceiveEvent( int event, int time, const idBitMsg &msg );
@ -529,6 +597,15 @@ private:
void Event_SetJointAngle( jointHandle_t jointnum, jointModTransform_t transform_type, const idAngles &angles );
void Event_GetJointPos( jointHandle_t jointnum );
void Event_GetJointAngle( jointHandle_t jointnum );
// HEXEN : Zeroth
private:
void Event_TransitionJointAngle( jointHandle_t jointnum, jointModTransform_t transform_type, const idAngles &to, const idAngles &from, float seconds, float transitions );
public:
idVec3 idAnimatedEntity::GetJointPos( jointHandle_t jointnum );
void TransitionJointAngle( jointHandle_t jointnum, jointModTransform_t transform_type, const idAngles &to, const idAngles &from, float seconds, float transitions );
void SetJointAngle( jointHandle_t jointnum, jointModTransform_t transform_type, const idAngles &angles );
idAngles GetJointAngle( jointHandle_t jointnum );
};
#endif /* !__GAME_ENTITY_H__ */

View file

@ -34,6 +34,11 @@ If you have questions concerning this license or the applicable additional terms
#define SCRIPT_DEFAULT "script/doom_main.script"
#define SCRIPT_DEFAULTFUNC "doom_main"
// HEXEN : Zeroth
#define NUM_UNIQUE_ARTIFACTS (16)
#define EOC_NUM_VMODES (15)
#define EOC_RELEASE (1)
#define LAGO_IMG_WIDTH 64
#define LAGO_IMG_HEIGHT 64
#define LAGO_WIDTH 64
@ -50,7 +55,7 @@ If you have questions concerning this license or the applicable additional terms
#define GAME_VERSION "baseDOOM-1"
#define MAX_CLIENTS 32
#define GENTITYNUM_BITS 12
#define GENTITYNUM_BITS 13
#define MAX_GENTITIES (1<<GENTITYNUM_BITS)
#define ENTITYNUM_NONE (MAX_GENTITIES-1)
#define ENTITYNUM_WORLD (MAX_GENTITIES-2)

File diff suppressed because it is too large Load diff

View file

@ -80,6 +80,10 @@ class idThread;
class idEditEntities;
class idLocationEntity;
//============================================================================
// HEXEN : Zeroth - Forward Declarations
//============================================================================
extern const int NUM_RENDER_PORTAL_BITS;
@ -96,6 +100,13 @@ extern const int NUM_RENDER_PORTAL_BITS;
===============================================================================
*/
// HEXEN : Zeroth
struct r_vmodes_type {
int width;
int height;
int ratio;
};
typedef struct entityState_s {
int entityNumber;
idBitMsg state;
@ -232,6 +243,7 @@ public:
int firstFreeIndex; // first free index in the entities array
int num_entities; // current number <= MAX_GENTITIES
idHashIndex entityHash; // hash table to quickly find entities by name
idHashIndex entypeHash; // hash table to quickly find entities by type (works in paralel with entityHash)
idWorldspawn * world; // world entity
idLinkList<idEntity> spawnedEntities; // all spawned entities
idLinkList<idEntity> activeEntities; // all thinking entities (idEntity::thinkFlags != 0)
@ -273,6 +285,7 @@ public:
int previousTime; // time in msec of last frame
int time; // in msec
static const int msec = USERCMD_MSEC; // time since last update in milliseconds
bool paused;
int vacuumAreaNum; // -1 if level doesn't have any outside areas
@ -294,6 +307,15 @@ public:
idEntityPtr<idEntity> lastGUIEnt; // last entity with a GUI, used by Cmd_NextGUI_f
int lastGUI; // last GUI on the lastGUIEnt
// HEXEN : Zeroth
public:
idEntityPtr<idEntity> portalSkyEnt;
bool portalSkyActive;
void SetPortalSkyEnt( idEntity *ent );
bool IsPortalSkyAcive();
r_vmodes_type r_vmodes[EOC_NUM_VMODES];
int r_vmode;
// ---------------------- Public idGame Interface -------------------
idGameLocal();
@ -387,6 +409,9 @@ public:
bool InPlayerPVS( idEntity *ent ) const;
bool InPlayerConnectedArea( idEntity *ent ) const;
public:
pvsHandle_t GetPlayerPVS() { return playerPVS; };
void SetCamera( idCamera *cam );
idCamera * GetCamera( void ) const;
bool SkipCinematic( void );
@ -402,12 +427,16 @@ public:
static void ArgCompletion_EntityName( const idCmdArgs &args, void(*callback)( const char *s ) );
idEntity * FindTraceEntity( idVec3 start, idVec3 end, const idTypeInfo &c, const idEntity *skip ) const;
idEntity * FindEntity( const char *name ) const;
// HEXEN : Zeroth
idEntity * FindEntityType( const idTypeInfo &type ) const;
idEntity * FindEntityUsingDef( idEntity *from, const char *match ) const;
int EntitiesWithinRadius( const idVec3 org, float radius, idEntity **entityList, int maxCount ) const;
void KillBox( idEntity *ent, bool catch_teleport = false );
void RadiusDamage( const idVec3 &origin, idEntity *inflictor, idEntity *attacker, idEntity *ignoreDamage, idEntity *ignorePush, const char *damageDefName, float dmgPower = 1.0f );
void RadiusPush( const idVec3 &origin, const float radius, const float push, const idEntity *inflictor, const idEntity *ignore, float inflictorScale, const bool quake );
void RadiusPush( const idVec3 &origin, const float radius, const float push, const idEntity *inflictor, const idEntity *ignore, float inflictorScale, const bool quake, const bool notlocalplayer=false, const bool notprojectiles=true );
void RadiusPushClipModel( const idVec3 &origin, const float push, const idClipModel *clipModel );
void ProjectDecal( const idVec3 &origin, const idVec3 &dir, float depth, bool parallel, float size, const char *material, float angle = 0 );
@ -448,6 +477,31 @@ public:
bool NeedRestart();
// HEXEN : Zeroth
// ****** thanks SnoopJeDi ( http://www.doom3world.org/phpbb2/viewtopic.php?f=56&t=12469&p=214427#p214427 )
idList<int> musicSpeakers; //SnoopJeDi - holds entitynum values for speakers with s_music set
// ******
void SetLocalPlayerSpawnPoint(idStr point);
// void FoliageRendering( void );
idStr eoc_MapPath;
void InitHub(void);
void SendLocalUserHudMessage( const char *message );
void SendLocalUserHudMessage( idStr message );
void UpdateFog( void );
void SetPersistentRemove( const char *name );
void SetPersistentLightOn( const char *name, bool state );
void SetPersistentLightBroken( const char *name );
void SetPersistentTrigger( const char *type, const char *name, const bool state );
void SetPersistentTriggerInt( const char *type, const char *var, const char *name, int val );
void SavePersistentMoveables(void);
// HEXEN : Zeroth
public:
idStr eoc_LocalPlayerSpawnPoint;
float eoc_MapLoading;
float eoc_MapLoadingPrev;
idStr mapNameForCheat;
idList<idVec3 *> BanishLocationList;
private:
const static int INITIAL_SPAWN_COUNT = 1;
const static int INTERNAL_SAVEGAME_VERSION = 1; // DG: added this for >= 1305 savegames
@ -653,6 +707,7 @@ typedef enum {
} gameSoundChannel_t;
extern const float DEFAULT_GRAVITY;
const idVec3 DEFAULT_GRAVITY_NORMAL = idVec3( 0, 0, -1 ); // HEXEN : Zeroth
extern const idVec3 DEFAULT_GRAVITY_VEC3;
extern const int CINEMATIC_SKIP_DELAY;

View file

@ -589,6 +589,19 @@ void idGameLocal::ServerWriteSnapshot( int clientNum, int sequence, idBitMsg &ms
numSourceAreas = gameRenderWorld->BoundsInAreas( spectated->GetPlayerPhysics()->GetAbsBounds(), sourceAreas, idEntity::MAX_PVS_AREAS );
pvsHandle = gameLocal.pvs.SetupCurrentPVS( sourceAreas, numSourceAreas, PVS_NORMAL );
// HEXEN : Zeroth
// Add portalSky areas to PVS
if ( portalSkyEnt.GetEntity() ) {
pvsHandle_t otherPVS, newPVS;
idEntity *skyEnt = portalSkyEnt.GetEntity();
otherPVS = gameLocal.pvs.SetupCurrentPVS( skyEnt->GetPVSAreas(), skyEnt->GetNumPVSAreas() );
newPVS = gameLocal.pvs.MergeCurrentPVS( pvsHandle, otherPVS );
pvs.FreeCurrentPVS( pvsHandle );
pvs.FreeCurrentPVS( otherPVS );
pvsHandle = newPVS;
}
#if ASYNC_WRITE_TAGS
idRandom tagRandom;
tagRandom.SetSeed( random.RandomInt() );
@ -1120,6 +1133,19 @@ void idGameLocal::ClientReadSnapshot( int clientNum, int sequence, const int gam
numSourceAreas = gameRenderWorld->BoundsInAreas( spectated->GetPlayerPhysics()->GetAbsBounds(), sourceAreas, idEntity::MAX_PVS_AREAS );
pvsHandle = gameLocal.pvs.SetupCurrentPVS( sourceAreas, numSourceAreas, PVS_NORMAL );
// HEXEN : Zeroth
// Add portalSky areas to PVS
if ( portalSkyEnt.GetEntity() ) {
pvsHandle_t otherPVS, newPVS;
idEntity *skyEnt = portalSkyEnt.GetEntity();
otherPVS = gameLocal.pvs.SetupCurrentPVS( skyEnt->GetPVSAreas(), skyEnt->GetNumPVSAreas() );
newPVS = gameLocal.pvs.MergeCurrentPVS( pvsHandle, otherPVS );
pvs.FreeCurrentPVS( pvsHandle );
pvs.FreeCurrentPVS( otherPVS );
pvsHandle = newPVS;
}
// read the PVS from the snapshot
#if ASYNC_WRITE_PVS
int serverPVS[idEntity::MAX_PVS_AREAS];

View file

@ -50,6 +50,18 @@ const idEventDef EV_RespawnFx( "<respawnFx>" );
const idEventDef EV_GetPlayerPos( "<getplayerpos>" );
const idEventDef EV_HideObjective( "<hideobjective>", "e" );
const idEventDef EV_CamShot( "<camshot>" );
const idEventDef EV_SetNextState( "setNextState", "s" );
const idEventDef EV_SetState( "setState", "s" );
const idEventDef EV_GetState( "getState", NULL, 's' );
// HEXEN : Zeroth
const idEventDef EV_ArtifactStart( "ArtifactStart" );
const idEventDef EV_ArtifactCoolDown( "ArtifactCoolDown" );
const idEventDef EV_ArtifactDone( "ArtifactDone" );
const idEventDef EV_SetArtifactActive( "ArtifactActive", "f" );
const idEventDef EV_OwnerLaunchProjectiles( "OwnerLaunchProjectiles", "dffff" );
const idEventDef EV_OwnerCreateProjectile( "OwnerCreateProjectile", NULL, 'e' );
const idEventDef EV_GetOwner( "GetOwner", NULL, 'e' );
const idEventDef EV_HideMultiModel( "HideMultiModel" );
CLASS_DECLARATION( idEntity, idItem )
EVENT( EV_DropToFloor, idItem::Event_DropToFloor )
@ -57,6 +69,18 @@ CLASS_DECLARATION( idEntity, idItem )
EVENT( EV_Activate, idItem::Event_Trigger )
EVENT( EV_RespawnItem, idItem::Event_Respawn )
EVENT( EV_RespawnFx, idItem::Event_RespawnFx )
// EVENT( EV_SetNextState, idItem::Event_SetNextState )
// EVENT( EV_SetState, idItem::Event_SetState )
// EVENT( EV_GetState, idItem::Event_GetState )
// HEXEN : Zeroth
EVENT( EV_ArtifactStart, idItem::Event_ArtifactStart )
EVENT( EV_ArtifactDone, idItem::Event_ArtifactDone )
EVENT( EV_ArtifactCoolDown, idItem::Event_ArtifactCoolDown )
EVENT( EV_SetArtifactActive, idItem::Event_SetArtifactActive )
EVENT( EV_OwnerLaunchProjectiles, idItem::Event_OwnerLaunchProjectiles )
EVENT( EV_OwnerCreateProjectile, idItem::Event_OwnerCreateProjectile )
EVENT( EV_GetOwner, idItem::Event_GetOwner )
EVENT( EV_HideMultiModel, idItem::Event_HideMultiModel )
END_CLASS
@ -76,6 +100,12 @@ idItem::idItem() {
orgOrigin.Zero();
canPickUp = true;
fl.networkSync = true;
owner = NULL;
DeleteMe = false;
Cooling = false;
ArtifactActive = false;
Processing = false;
}
/*
@ -88,6 +118,99 @@ idItem::~idItem() {
if ( itemShellHandle != -1 ) {
gameRenderWorld->FreeEntityDef( itemShellHandle );
}
if ( multimodel ) {
delete multimodel;
}
//z.todo: necessary???
// delete scriptThread;
// DeconstructScriptObject();
// scriptObject.Free();
}
/*
================
HEXEN
idItem::Hide
================
*/
void idItem::Hide( void ) {
if ( !idEntity::IsHidden() ) {
idEntity::Hide();
if ( multimodel ) {
multimodel->Hide();
}
}
}
/*
================
HEXEN
idItem::Event_ArtifactStart
================
*/
void idItem::Event_ArtifactStart( void ) {
if ( owner != NULL ) {
Processing = true;
owner->RemoveInventoryItem(spawnArgs.GetString("inv_name"));
owner->UpdateHudArtifacts();
}
}
/*
================
HEXEN
idItem::Event_ArtifactDone
================
*/
void idItem::Event_ArtifactDone( void ) {
if ( owner != NULL ) {
Cooling = false;
DeleteMe = true;
}
}
/*
================
HEXEN
idItem::Event_ArtifactCoolDown
================
*/
void idItem::Event_ArtifactCoolDown( void ) {
if ( owner != NULL ) {
Cooling = true;
owner->UpdateHudActiveArtifacts();
}
}
/*
================
HEXEN
idItem::Event_SetArtifactActive
================
*/
void idItem::Event_SetArtifactActive( const float yesorno ) {
if ( owner != NULL ) {
if ( yesorno ) {
ArtifactActive = true;
owner->UpdateHudActiveArtifacts();
} else {
ArtifactActive = false;
owner->UpdateHudActiveArtifacts();
}
}
}
/*
================
HEXEN
idItem::Event_GetOwner
================
*/
void idItem::Event_GetOwner( void ) {
idThread::ReturnEntity( owner );
}
/*
@ -108,6 +231,42 @@ void idItem::Save( idSaveGame *savefile ) const {
savefile->WriteInt( inViewTime );
savefile->WriteInt( lastCycle );
savefile->WriteInt( lastRenderViewTime );
// HEXEN : Zeroth
savefile->WriteObject( scriptThread );
savefile->WriteString( waitState );
//FIXME: this is unneccesary
idToken token;
// HEXEN : Zeroth
if ( state ) {
idLexer src( state->Name(), idStr::Length( state->Name() ), "idItem::Save" );
src.ReadTokenOnLine( &token );
src.ExpectTokenString( "::" );
src.ReadTokenOnLine( &token );
savefile->WriteString( token );
} else {
savefile->WriteString( "" );
}
// HEXEN : Zeroth
if ( idealState ) {
idLexer src( idealState->Name(), idStr::Length( idealState->Name() ), "idItem::Save" );
src.ReadTokenOnLine( &token );
src.ExpectTokenString( "::" );
src.ReadTokenOnLine( &token );
savefile->WriteString( token );
} else {
savefile->WriteString( "" );
}
// HEXEN : Zeroth
savefile->WriteObject( projectileEnt );
savefile->WriteObject( multimodel );
}
/*
@ -130,6 +289,35 @@ void idItem::Restore( idRestoreGame *savefile ) {
savefile->ReadInt( lastRenderViewTime );
itemShellHandle = -1;
// HEXEN : Zeroth
savefile->ReadObject( reinterpret_cast<idClass *&>( scriptThread ) );
savefile->ReadString( waitState );
idStr statename;
// HEXEN : Zeroth
savefile->ReadString( statename );
if ( statename.Length() > 0 ) {
state = GetScriptFunction( statename );
}
// HEXEN : Zeroth
savefile->ReadString( statename );
if ( statename.Length() > 0 ) {
idealState = GetScriptFunction( statename );
}
// HEXEN : Zeroth
const idDeclEntityDef *projectileDef = gameLocal.FindEntityDef( spawnArgs.GetString( "def_projectile" ), false );
if ( projectileDef ) {
projectileDict = projectileDef->dict;
} else {
projectileDict.Clear();
}
// HEXEN : Zeroth
savefile->ReadObject( reinterpret_cast<idClass *&>( projectileEnt ) );
savefile->ReadObject( reinterpret_cast<idClass *&>( multimodel ) );
}
/*
@ -227,7 +415,7 @@ void idItem::Think( void ) {
ang.yaw = ( gameLocal.time & 4095 ) * 360.0f / -4096.0f;
SetAngles( ang );
float scale = 0.005f + entityNumber * 0.00001f;
float scale = 0.005f;
org = orgOrigin;
org.z += 4.0f + cos( ( gameLocal.time + 2000 ) * scale ) * 4.0f;
@ -236,6 +424,11 @@ void idItem::Think( void ) {
}
Present();
if ( !IsHidden() && multimodel ) {
multimodel->GetPhysics()->SetOrigin( GetPhysics()->GetOrigin() ); // bob up and down in unison
multimodel->SetAngles( -GetAngles() ); // make it spin the opposite direction
}
}
/*
@ -275,6 +468,30 @@ void idItem::Spawn( void ) {
idStr giveTo;
idEntity * ent;
float tsize;
const char *projectileName;
state = NULL;
idealState = NULL;
// HEXEN : Zeroth
// get the projectile
projectileDict.Clear();
projectileName = spawnArgs.GetString( "def_projectile" );
if ( projectileName[0] != '\0' ) {
const idDeclEntityDef *projectileDef = gameLocal.FindEntityDef( projectileName, false );
if ( !projectileDef ) {
gameLocal.Warning( "Unknown projectile '%s' in item '%s'", projectileName, spawnArgs.GetString("inv_name") );
} else {
const char *spawnclass = projectileDef->dict.GetString( "spawnclass" );
idTypeInfo *cls = idClass::GetClass( spawnclass );
if ( !cls || !cls->IsType( idProjectile::Type ) ) {
gameLocal.Warning( "Invalid spawnclass '%s' on projectile '%s' (used by item '%s')", spawnclass, projectileName, spawnArgs.GetString("inv_name") );
} else {
projectileDict = projectileDef->dict;
}
}
}
if ( spawnArgs.GetBool( "dropToFloor" ) ) {
PostEventMS( &EV_DropToFloor, 0 );
@ -317,6 +534,18 @@ void idItem::Spawn( void ) {
lastCycle = -1;
itemShellHandle = -1;
shellMaterial = declManager->FindMaterial( "itemHighlightShell" );
multimodel=NULL;
idStr mstr=spawnArgs.GetString("multimodel");
if ( mstr != "" ) {
const idDict *multimodeldef = gameLocal.FindEntityDefDict( mstr.c_str() );
if ( gameLocal.SpawnEntityDef( *multimodeldef, &multimodel ) && multimodel ) {
multimodel->GetPhysics()->SetOrigin( GetPhysics()->GetOrigin() ); // bob up and down in unison
multimodel->SetAngles( -GetAngles() ); // make it spin the opposite direction
spawnArgs.Set( "multimodel_name", multimodel->GetName() );
}
}
}
/*
@ -346,11 +575,26 @@ bool idItem::GiveToPlayer( idPlayer *player ) {
return false;
}
bool val = false;
if ( spawnArgs.GetBool( "inv_carry" ) ) {
return player->GiveInventoryItem( &spawnArgs );
val = player->GiveInventoryItem( this );
} else {
val = player->GiveItem( this );
}
return player->GiveItem( this );
if ( val ) {
if ( spawnArgs.GetString("scriptobject") != "" ) {
if ( !g_noPickupNotification.GetBool() && !spawnArgs.GetBool("dontNotifyOnPickup") ) {
CallFunc( "pickup_message" );
}
CallFunc( "pickup_effect" );
}
gameLocal.SetPersistentRemove( name.c_str() );
}
return val;
}
/*
@ -369,7 +613,9 @@ bool idItem::Pickup( idPlayer *player ) {
}
// play pickup sound
StartSound( "snd_acquire", SND_CHANNEL_ITEM, 0, false, NULL );
if ( !g_noPickupNotification.GetBool() ) {
StartSound( "snd_acquire", SND_CHANNEL_ITEM, 0, false, NULL );
}
// trigger our targets
ActivateTargets( player );
@ -508,15 +754,46 @@ idItem::Event_Touch
================
*/
void idItem::Event_Touch( idEntity *other, trace_t *trace ) {
idPlayer *player;
if ( !other->IsType( idPlayer::Type ) ) {
return;
}
player = static_cast<idPlayer *>( other );
if ( !canPickUp ) {
return;
}
Pickup( static_cast<idPlayer *>(other) );
player->CleanupArtifactItems();
// pickup delay for this player, to prevent instant pickup after drop.
if ( player == lastOwner && spawnArgs.GetBool( "eoc_dropped" ) ) {
if ( PickupDelayTime < MS2SEC( gameLocal.realClientTime ) ) {
return;
}
}
// I don't know why this happens, but it does. seems the player can hit an item multiple times and trigger this pickupevent before he has a chance to disappear after picking it up the first time.
if ( player == owner ) {
return;
}
if ( spawnArgs.GetBool( "instantEffect" ) && player->ActiveArtifact( spawnArgs.GetString( "inv_name" ) ) ) {
return;
}
// don't pickup if we're full on 'em
if ( spawnArgs.FindKey("artifact") ) {
if ( spawnArgs.GetInt( "max_inventory" ) > 0 && player->InventoryItemQty(spawnArgs.GetString( "inv_name" )) >= spawnArgs.GetInt( "max_inventory" ) ) {
return;
}
}
Pickup( static_cast<idPlayer *>( other ) );
}
/*
@ -637,9 +914,141 @@ bool idItemPowerup::GiveToPlayer( idPlayer *player ) {
return false;
}
player->GivePowerUp( type, time * 1000 );
gameLocal.SetPersistentRemove( name.c_str() );
return true;
}
/*
================
HEXEN
idItem::Event_OwnerLaunchProjectiles
================
*/
void idItem::Event_OwnerLaunchProjectiles( int num_projectiles, float spread, float fuseOffset, float launchPower, float dmgPower ) {
idProjectile *proj;
idEntity *ent;
int i;
idVec3 dir;
float ang;
float spin;
float distance;
trace_t tr;
idVec3 start;
idVec3 muzzle_pos;
idBounds ownerBounds, projBounds;
idVec3 playerViewOrigin;
idMat3 playerViewAxis;
idVec3 zzero;
zzero.Zero();
playerViewOrigin.Zero();
playerViewAxis.Zero();
playerViewOrigin = owner->firstPersonViewOrigin;
playerViewAxis = owner->firstPersonViewAxis;
if ( !projectileDict.GetNumKeyVals() ) {
const char *classname = this->spawnArgs.GetString("inv_name");
gameLocal.Warning( "No projectile defined on '%s'", classname );
return;
}
if ( gameLocal.isClient ) {
// predict instant hit projectiles
if ( projectileDict.GetBool( "net_instanthit" ) ) {
float spreadRad = DEG2RAD( spread );
muzzle_pos = playerViewOrigin + playerViewAxis[ 0 ] * 2.0f;
for( i = 0; i < num_projectiles; i++ ) {
ang = idMath::Sin( spreadRad * gameLocal.random.RandomFloat() );
spin = (float)DEG2RAD( 360.0f ) * gameLocal.random.RandomFloat();
dir = playerViewAxis[ 0 ] + playerViewAxis[ 2 ] * ( ang * idMath::Sin( spin ) ) - playerViewAxis[ 1 ] * ( ang * idMath::Cos( spin ) );
dir.Normalize();
gameLocal.clip.Translation( tr, muzzle_pos, muzzle_pos + dir * 4096.0f, NULL, mat3_identity, MASK_SHOT_RENDERMODEL, owner );
if ( tr.fraction < 1.0f ) {
idProjectile::ClientPredictionCollide( this, projectileDict, tr, vec3_origin, true );
}
}
}
} else {
ownerBounds = owner->GetPhysics()->GetAbsBounds();
owner->AddProjectilesFired( num_projectiles );
float spreadRad = DEG2RAD( spread );
for( i = 0; i < num_projectiles; i++ ) {
ang = idMath::Sin( spreadRad * gameLocal.random.RandomFloat() );
spin = (float)DEG2RAD( 360.0f ) * gameLocal.random.RandomFloat();
dir = playerViewAxis[ 0 ] + playerViewAxis[ 2 ] * ( ang * idMath::Sin( spin ) ) - playerViewAxis[ 1 ] * ( ang * idMath::Cos( spin ) );
dir.Normalize();
if ( projectileEnt ) {
ent = projectileEnt;
ent->Show();
ent->Unbind();
projectileEnt = NULL;
} else {
gameLocal.SpawnEntityDef( projectileDict, &ent, false );
}
if ( !ent || !ent->IsType( idProjectile::Type ) ) {
const char *projectileName = this->spawnArgs.GetString( "def_projectile" );
gameLocal.Error( "'%s' is not an idProjectile", projectileName );
}
if ( projectileDict.GetBool( "net_instanthit" ) ) {
// don't synchronize this on top of the already predicted effect
ent->fl.networkSync = false;
}
proj = static_cast<idProjectile *>(ent);
proj->Create( owner, playerViewOrigin, dir );
projBounds = proj->GetPhysics()->GetBounds().Rotate( proj->GetPhysics()->GetAxis() );
// make sure the projectile starts inside the bounding box of the owner
if ( i == 0 ) {
muzzle_pos = playerViewOrigin + playerViewAxis[ 0 ] * 2.0f;
if ( ( ownerBounds - projBounds).RayIntersection( muzzle_pos, playerViewAxis[0], distance ) ) {
start = muzzle_pos + distance * playerViewAxis[0];
} else {
start = ownerBounds.GetCenter();
}
gameLocal.clip.Translation( tr, start, muzzle_pos, proj->GetPhysics()->GetClipModel(), proj->GetPhysics()->GetClipModel()->GetAxis(), MASK_SHOT_RENDERMODEL, owner );
muzzle_pos = tr.endpos;
}
proj->Launch( muzzle_pos, dir, zzero, fuseOffset, launchPower, dmgPower );
}
}
}
/*
================
HEXEN
idItem::Event_OwnerCreateProjectile
================
*/
void idItem::Event_OwnerCreateProjectile( void ) {
if ( !gameLocal.isClient ) {
projectileEnt = NULL;
gameLocal.SpawnEntityDef( projectileDict, &projectileEnt, false );
if ( projectileEnt ) {
projectileEnt->SetOrigin( GetPhysics()->GetOrigin() );
projectileEnt->Bind( owner, false );
projectileEnt->Hide();
}
idThread::ReturnEntity( projectileEnt );
} else {
idThread::ReturnEntity( NULL );
}
}
/*
===============================================================================
@ -712,6 +1121,43 @@ void idObjective::Event_CamShot( ) {
renderView_t fullView = *view;
fullView.width = SCREEN_WIDTH;
fullView.height = SCREEN_HEIGHT;
// HEXEN : Zeroth
// HACK : always draw sky-portal view if there is one in the map, this isn't real-time
if ( gameLocal.portalSkyEnt.GetEntity() && g_enablePortalSky.GetBool() ) {
renderView_t portalView = fullView;
portalView.vieworg = gameLocal.portalSkyEnt.GetEntity()->GetPhysics()->GetOrigin();
// setup global fixup projection vars
#if 1
int vidWidth, vidHeight;
idVec2 shiftScale;
renderSystem->GetGLSettings( vidWidth, vidHeight );
float pot;
int temp;
int w = vidWidth;
for (temp = 1 ; temp < w ; temp<<=1) {
}
pot = (float)temp;
shiftScale.x = (float)w / pot;
int h = vidHeight;
for (temp = 1 ; temp < h ; temp<<=1) {
}
pot = (float)temp;
shiftScale.y = (float)h / pot;
fullView.shaderParms[4] = shiftScale.x;
fullView.shaderParms[5] = shiftScale.y;
#endif
gameRenderWorld->RenderScene( &portalView );
renderSystem->CaptureRenderToImage( "_currentRender" );
}
// draw a view to a texture
renderSystem->CropRenderSize( 256, 256, true );
gameRenderWorld->RenderScene( &fullView );
@ -821,6 +1267,7 @@ bool idVideoCDItem::GiveToPlayer( idPlayer *player ) {
if ( player && str.Length() ) {
player->GiveVideo( str, &spawnArgs );
}
gameLocal.SetPersistentRemove( name.c_str() );
return true;
}
@ -845,6 +1292,7 @@ bool idPDAItem::GiveToPlayer(idPlayer *player) {
if ( player ) {
player->GivePDA( str, &spawnArgs );
}
gameLocal.SetPersistentRemove( name.c_str() );
return true;
}
@ -1203,6 +1651,7 @@ bool idMoveablePDAItem::GiveToPlayer(idPlayer *player) {
if ( player ) {
player->GivePDA( str, &spawnArgs );
}
gameLocal.SetPersistentRemove( name.c_str() );
return true;
}
@ -1356,3 +1805,51 @@ void idObjectiveComplete::Event_HideObjective( idEntity *e ) {
}
}
}
/*
================
HEXEN
idItem::SetOwner
================
*/
void idItem::SetOwner( idPlayer *_owner ) {
assert( !owner );
owner = _owner;
lastOwner = _owner;
// SetName( va( "%s_weapon", owner->name.c_str() ) );
// if ( worldModel.GetEntity() ) {
// worldModel.GetEntity()->SetName( va( "%s_weapon_worldmodel", owner->name.c_str() ) );
// }
}
/*
================
HEXEN
idItem::CallFunc
================
*/
bool idItem::CallFunc( char *funcName ) {
const function_t *func = GetScriptFunction( (const char*) funcName );
if ( !func ) {
assert( 0 );
gameLocal.Error( "Can't find function use' in object '%s'", scriptObject.GetTypeName() );
return false;
}
SetState( func );
UpdateScript();
return true;
}
/*
================
HEXEN
idItem::Event_HideMultiModel
================
*/
void idItem::Event_HideMultiModel() {
if ( multimodel ) {
multimodel->Hide();
}
}

View file

@ -56,6 +56,14 @@ public:
virtual bool Pickup( idPlayer *player );
virtual void Think( void );
virtual void Present();
void Hide();
// HEXEN : Zeroth
public:
void SetOwner( idPlayer *owner );
idPlayer* GetOwner( void );
idPlayer* GetLastOwner( void );
bool CallFunc( char *funcName );
enum {
EVENT_PICKUP = idEntity::EVENT_MAXEVENTS,
@ -71,6 +79,20 @@ public:
virtual void WriteToSnapshot( idBitMsgDelta &msg ) const;
virtual void ReadFromSnapshot( const idBitMsgDelta &msg );
// HEXEN : Zeroth
public:
bool DeleteMe; // whether this artifact should be deleted in the next artifact cleanup (in player.cpp)
bool ArtifactActive; // whether this artifact is active (valid for time-based effects)
bool Processing; // whether this artifacts script is busy
bool Cooling; // whether artifact is in cooldown mode
int PickupDelayTime; // time in seconds for how long we should wait before letting a player pick up the item he dropped (necessary to prevent instant pickup afte drop)
// HEXEN : Zeroth
private:
idPlayer* owner;
idPlayer* lastOwner;
private:
idVec3 orgOrigin;
bool spin;
@ -95,6 +117,27 @@ private:
void Event_Trigger( idEntity *activator );
void Event_Respawn( void );
void Event_RespawnFx( void );
// HEXEN : Zeroth
private:
idDict projectileDict;
idEntity *projectileEnt;
// void Event_GetState( void );
// void Event_SetState( const char *name );
// void Event_SetNextState( const char *name );
void Event_ArtifactStart( void );
void Event_Artifact( void );
void Event_ArtifactDone( void );
void Event_ArtifactCoolDown( void );
void Event_SetArtifactActive( const float yesorno );
void Event_OwnerLaunchProjectiles( int num_projectiles, float spread, float fuseOffset, float launchPower, float dmgPower );
void Event_OwnerCreateProjectile( void );
void Event_GetOwner( void );
// MultiModel
void Event_HideMultiModel( void );
public:
idEntity *multimodel;
};
class idItemPowerup : public idItem {
@ -226,4 +269,12 @@ private:
void Event_GetPlayerPos();
};
ID_INLINE idPlayer* idItem::GetOwner( void ) {
return owner;
}
ID_INLINE idPlayer* idItem::GetLastOwner( void ) {
return lastOwner;
}
#endif /* !__GAME_ITEM_H__ */

View file

@ -567,6 +567,7 @@ idLight::On
================
*/
void idLight::On( void ) {
gameLocal.SetPersistentLightOn( name.c_str(), true );
currentLevel = levels;
// offset the start time of the shader to sync it to the game time
renderLight.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
@ -584,6 +585,7 @@ idLight::Off
================
*/
void idLight::Off( void ) {
gameLocal.SetPersistentLightOn( name.c_str(), false );
currentLevel = 0;
// kill any sound it was making
if ( refSound.referenceSound && refSound.referenceSound->CurrentlyPlaying() ) {
@ -646,6 +648,7 @@ idLight::BecomeBroken
================
*/
void idLight::BecomeBroken( idEntity *activator ) {
gameLocal.SetPersistentLightBroken( name.c_str() );
const char *damageDefName;
fl.takedamage = false;

View file

@ -2305,13 +2305,60 @@ CLASS_DECLARATION( idEntity, idLiquid )
EVENT( EV_Touch, idLiquid::Event_Touch )
END_CLASS
/*
================
Zeroth
idLiquid::idLiquid
================
*/
idLiquid::idLiquid( void ) {
clipModel = NULL;
touchingEntities.Clear();
flagEntities.Clear();
//resistTimeEntities.Clear();
// HEXEN : Zeroth - for limit entity types
dontTripby_LocalPlayer = false;
limitEntityType = false;
tripby_idPlayer = false;
tripby_idAI = false;
tripby_idMoveable = false;
tripby_idItem = false;
tripby_idActor = false;
tripby_idProjectile = false;
particleOnExit = false; // whether to spawn a particle when something leaves the water
moveResistance = 0;
moveDir.Zero();
moveAmt = 0;
}
/*
================
idLiquid::Save
================
*/
void idLiquid::Save( idSaveGame *savefile ) const {
// Nothing to save
// HEXEN : Zeroth
savefile->WriteClipModel( clipModel );
savefile->WriteBool( limitEntityType );
savefile->WriteBool( dontTripby_LocalPlayer );
savefile->WriteBool( tripby_idPlayer );
savefile->WriteBool( tripby_idAI );
savefile->WriteBool( tripby_idMoveable );
savefile->WriteBool( tripby_idItem );
savefile->WriteBool( tripby_idActor );
savefile->WriteBool( tripby_idProjectile );
savefile->WriteBool( particleOnExit );
savefile->WriteVec3( moveDir );
savefile->WriteFloat( moveAmt );
savefile->WriteFloat( moveResistance );
savefile->WriteInt( touchingEntities.Num() );
for ( int i = 0; i < touchingEntities.Num(); i++ ) {
savefile->WriteString( touchingEntities[i] );
savefile->WriteBool( flagEntities[i] );
}
}
/*
@ -2322,6 +2369,32 @@ idLiquid::Restore
void idLiquid::Restore( idRestoreGame *savefile ) {
//FIXME: NO!
Spawn();
// HEXEN : Zeroth
savefile->ReadClipModel( clipModel );
savefile->ReadBool( limitEntityType );
savefile->ReadBool( dontTripby_LocalPlayer );
savefile->ReadBool( tripby_idPlayer );
savefile->ReadBool( tripby_idAI );
savefile->ReadBool( tripby_idMoveable );
savefile->ReadBool( tripby_idItem );
savefile->ReadBool( tripby_idActor );
savefile->ReadBool( tripby_idProjectile );
savefile->ReadBool( particleOnExit );
savefile->ReadVec3( moveDir );
savefile->ReadFloat( moveAmt );
savefile->ReadFloat( moveResistance );
bool bol;
int num;
idStr str;
savefile->ReadInt( num );
for ( int i = 0; i < num; i++ ) {
savefile->ReadString( str );
touchingEntities.Append( str );
savefile->ReadBool( bol );
flagEntities.Append( bol );
}
}
/*
@ -2338,6 +2411,56 @@ void idLiquid::Spawn() {
model->Reset();
GetPhysics()->SetContents( CONTENTS_TRIGGER );
*/
// HEXEN : Zeroth - create clip model. copied from idTrigger_Touch
clipModel = new idClipModel( GetPhysics()->GetClipModel() ); // get the clip model
//GetPhysics()->SetClipModel( NULL, 1.0f ); // remove the collision model from the physics object
BecomeActive( TH_THINK );
// HEXEN : Zeroth - for limit entity types
spawnArgs.GetBool( "dontTripby_LocalPlayer", "0", dontTripby_LocalPlayer );
spawnArgs.GetBool( "limitEntityType", "0", limitEntityType );
spawnArgs.GetBool( "tripby_idPlayer", "0", tripby_idPlayer );
spawnArgs.GetBool( "tripby_idAI", "0", tripby_idAI );
spawnArgs.GetBool( "tripby_idMoveable", "0", tripby_idMoveable );
spawnArgs.GetBool( "tripby_idItem", "0", tripby_idItem );
spawnArgs.GetBool( "tripby_idActor", "0", tripby_idActor );
spawnArgs.GetBool( "tripby_idProjectile", "0", tripby_idProjectile );
spawnArgs.GetBool( "doParticleOnExit", "0", particleOnExit );
splashParticleRipple = NULL;
splashParticleTiny = NULL;
splashParticleSmall = NULL;
splashParticleBig = NULL;
splashParticleHuge = NULL;
const char *splashName = spawnArgs.GetString( "smoke_ripple" );
if ( *splashName != '\0' ) {
splashParticleRipple = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, splashName ) );
}
splashName = spawnArgs.GetString( "smoke_splashTiny" );
if ( *splashName != '\0' ) {
splashParticleTiny = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, splashName ) );
}
splashName = spawnArgs.GetString( "smoke_splashSmall" );
if ( *splashName != '\0' ) {
splashParticleSmall = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, splashName ) );
}
splashName = spawnArgs.GetString( "smoke_splashBig" );
if ( *splashName != '\0' ) {
splashParticleBig = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, splashName ) );
}
splashName = spawnArgs.GetString( "smoke_splashHuge" );
if ( *splashName != '\0' ) {
splashParticleHuge = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, splashName ) );
}
spawnArgs.GetVector( "moveDir", "0 0 0", moveDir );
spawnArgs.GetFloat( "moveAmt", "0", moveAmt );
spawnArgs.GetFloat( "moveResistance", "0", moveResistance );
}
/*
@ -2355,6 +2478,201 @@ void idLiquid::Event_Touch( idEntity *other, trace_t *trace ) {
*/
}
/*
================
Zeroth
idLiquid::Event_Touch
================
*/
void idLiquid::TouchEntities( void ) { // Z.TODO: this is getting messy, maybe split it into separate entities?
int numClipModels, i, c;
idBounds bounds;
idClipModel *cm, *clipModelList[ MAX_GENTITIES ];
// HEXEN : Zeroth - for limit entity type
idEntity *entity = NULL;
bool dontSplash;
idVec3 cmOrigin;
idMat3 cmAxis;
cmHandle_t cmHandle;
idVec3 myOrigin;
idMat3 myAxis;
if ( clipModel == NULL ) {
return;
}
for ( c = 0; c < touchingEntities.Num(); c++ ) {
entity = gameLocal.FindEntity( touchingEntities[c].c_str() );
// remove entities from list which are no longer touching or no longer exist
if ( !flagEntities[c] || !entity ) {
if ( entity ) {
if ( !gameLocal.isClient ) {
// entity->StartSound( "snd_splashexit", SND_CHANNEL_ANY, 0, false, NULL );
const idSoundShader *shader = declManager->FindSound( spawnArgs.GetString( "snd_splashexit" ) );
entity->StartSoundShader( shader, SND_CHANNEL_ANY, SSF_GLOBAL, false, NULL );
// spawn the exit splash
if ( particleOnExit ) {
// gameLocal.smokeParticles->EmitSmoke( splashParticle, gameLocal.time, gameLocal.random.CRandomFloat(), entity->GetPhysics()->GetOrigin(), idAngles( 0, gameLocal.random.CRandomFloat() * 360, 0 ).ToMat3() );
}
entity->inWater = false;
if ( entity->IsType( idPlayer::Type ) ) {
static_cast< idPlayer* >( entity )->leftWater = gameLocal.time;
}
}
}
touchingEntities.RemoveIndex( c );
touchingEntities.Condense();
flagEntities.RemoveIndex( c );
flagEntities.Condense();
c--;
} else {
// flag all entities as NOT touching, test if they are during the clip tests
flagEntities[c] = false;
}
}
bounds.FromTransformedBounds( clipModel->GetBounds(), clipModel->GetOrigin(), clipModel->GetAxis() );
numClipModels = gameLocal.clip.ClipModelsTouchingBounds( bounds, -1, clipModelList, MAX_GENTITIES );
for ( i = 0; i < numClipModels; i++ ) {
cm = clipModelList[ i ];
if ( !cm->IsTraceModel() ) {
continue;
}
entity = clipModelList[ i ]->GetEntity();
if ( !entity ) {
continue;
}
if ( entity->spawnArgs.GetBool("nosplash") ) {
continue;
}
cmOrigin = cm->GetOrigin();
cmAxis = cm->GetAxis();
cmHandle = clipModel->Handle();
myOrigin = clipModel->GetOrigin();
myAxis = clipModel->GetAxis();
if ( !gameLocal.clip.ContentsModel( cmOrigin, cm, cmAxis, -1, cmHandle, myOrigin, myAxis ) ) {
continue;
}
// get the intersection point so we know where to spawn the effect
// gameLocal.clip.Translation( trace, cmOrigin, cmOrigin, cm, cmAxis, -1, this );
if (limitEntityType) {
if ( ( !tripby_idPlayer && entity->IsType( idPlayer::Type ) ) ||
( !tripby_idAI && entity->IsType( idAI::Type ) ) ||
( !tripby_idActor && entity->IsType( idActor::Type ) ) ||
( !tripby_idProjectile && entity->IsType( idProjectile::Type ) ) ||
( !tripby_idItem && entity->IsType( idItem::Type ) ) ||
( !tripby_idMoveable && entity->IsType( idMoveable::Type ) ) ) {
continue;
}
}
if ( dontTripby_LocalPlayer && entity->IsType( idPlayer::Type ) && gameLocal.GetLocalPlayer() == ( static_cast<idPlayer *>( entity ) ) ) {
continue;
}
// if the entity is still touching, dont splash
dontSplash = false;
for ( c = 0; c < touchingEntities.Num(); c++ ) {
if ( touchingEntities[c] == entity->GetName() ) {
flagEntities[c] = true; // flag it as touching
dontSplash = true;
entity->inWater = true; // if the entity leaves another body of water, it will be set to false. it's still in this one, so keep it true.
break;
}
}
// if the entity was not in our list, add it. else don't trigger.
if ( !dontSplash ) {
touchingEntities.Append( idStr( entity->GetName() ) );
flagEntities.Append( true );
} else {
continue;
}
//if the entity is already in water, dont splash
if ( entity->inWater ) {
continue;
}
entity->inWater = true;
if ( !gameLocal.isClient ) {
const idDeclParticle * prt = NULL;
idVec3 v = entity->GetPhysics()->GetLinearVelocity();
float vel = v.Length();
int whichPrt, maxPrt;
float m = entity->GetPhysics()->GetMass();
// static const unsigned long double const * foo = NULL; // hahaha!
float a = spawnArgs.GetFloat( "rippleObjectMass" );
float b = spawnArgs.GetFloat( "tinyObjectMass" );
float c = spawnArgs.GetFloat( "smallObjectMass" );
float d = spawnArgs.GetFloat( "bigObjectMass" );
float e = spawnArgs.GetFloat( "largeObjectMass" );
if ( m <= a ) {
maxPrt = 0;
} else if ( m <= b ) {
maxPrt = 1;
} else if ( m <= c ) {
maxPrt = 2;
} else if ( m <= d ) {
maxPrt = 3;
} else {
maxPrt = 4;
}
whichPrt = ( vel / spawnArgs.GetFloat( "velocityForMaxiumSplash" ) ) * maxPrt;
if ( maxPrt == 0) {
prt = splashParticleRipple;
} else if ( whichPrt == 1 || maxPrt == 1) {
prt = splashParticleTiny;
} else if ( whichPrt == 2 || maxPrt == 2 ) {
prt = splashParticleSmall;
} else if ( whichPrt == 3 || maxPrt == 3 ) {
prt = splashParticleBig;
} else if ( whichPrt == 4 || maxPrt == 4 ) {
prt = splashParticleHuge;
}
if ( maxPrt != 0 ) {
// entity->StartSound( "snd_splash", SND_CHANNEL_ANY, 0, false, NULL );
const idSoundShader *shader = declManager->FindSound( spawnArgs.GetString( "snd_splash" ) );
entity->StartSoundShader( shader, SND_CHANNEL_ANY, SSF_GLOBAL, false, NULL );
}
if ( prt ) {
gameLocal.smokeParticles->EmitSmoke( prt, gameLocal.time, gameLocal.random.CRandomFloat(), entity->GetPhysics()->GetOrigin(), idAngles( 0, gameLocal.random.CRandomFloat() * 360, 0 ).ToMat3() );
}
}
}
}
/*
===============
Zeroth
idLiquid::Think
===============
*/
void idLiquid::Think( void ) {
if ( thinkFlags & TH_THINK ) {
TouchEntities();
}
idEntity::Think();
}
/*
===============================================================================
@ -3156,3 +3474,66 @@ void idPhantomObjects::Think( void ) {
BecomeInactive( TH_THINK );
}
}
/*
===============================================================================
Zeroth
idPortalSky
===============================================================================
*/
CLASS_DECLARATION( idEntity, idPortalSky )
EVENT( EV_PostSpawn, idPortalSky::Event_PostSpawn )
EVENT( EV_Activate, idPortalSky::Event_Activate )
END_CLASS
/*
===============
Zeroth
idPortalSky::idPortalSky
===============
*/
idPortalSky::idPortalSky( void ) { }
/*
===============
Zeroth
idPortalSky::~idPortalSky
===============
*/
idPortalSky::~idPortalSky( void ) { }
/*
===============
Zeroth
idPortalSky::Spawn
===============
*/
void idPortalSky::Spawn( void ) {
if ( !spawnArgs.GetBool( "triggered" ) ) {
PostEventMS( &EV_PostSpawn, 1 );
}
}
/*
================
Zeroth
idPortalSky::Event_PostSpawn
================
*/
void idPortalSky::Event_PostSpawn() {
gameLocal.SetPortalSkyEnt( this );
}
/*
================
Zeroth
idPortalSky::Event_Activate
================
*/
void idPortalSky::Event_Activate( idEntity *activator ) {
gameLocal.SetPortalSkyEnt( this );
}

View file

@ -548,13 +548,44 @@ class idLiquid : public idEntity {
public:
CLASS_PROTOTYPE( idLiquid );
idLiquid( void ); // HEXEN : Zeroth
void Spawn( void );
void Think( void ); // HEXEN : Zeroth
void Save( idSaveGame *savefile ) const;
void Restore( idRestoreGame *savefile );
private:
void Event_Touch( idEntity *other, trace_t *trace );
void Event_Touch( idEntity *other, trace_t *trace ); // HEXEN : Zeroth - was commented out
// Zeroth
idClipModel * clipModel;
void TouchEntities( void );
bool particleOnExit; // whether to spawn a particle when something leaves the water
const idDeclParticle * splashParticleRipple;
const idDeclParticle * splashParticleTiny;
const idDeclParticle * splashParticleSmall;
const idDeclParticle * splashParticleBig;
const idDeclParticle * splashParticleHuge;
float moveResistance;
idVec3 moveDir;
float moveAmt;
idList<idStr> touchingEntities; // list of entities touching the trigger
idList<bool> flagEntities; // used to test if touchingEntities[x] is still touching, if not to be removed from list
// idList<int> resistTimeEntities;
// HEXEN : Zeroth - for limit entity types
private:
bool dontTripby_LocalPlayer;
bool limitEntityType;
bool tripby_idPlayer;
bool tripby_idAI;
bool tripby_idMoveable;
bool tripby_idItem;
bool tripby_idActor;
bool tripby_idProjectile;
idRenderModelLiquid *model;
@ -765,4 +796,24 @@ private:
idList<idVec3> lastTargetPos;
};
/*
===============================================================================
Zeroth
idPortalSky
===============================================================================
*/
class idPortalSky : public idEntity {
public:
CLASS_PROTOTYPE( idPortalSky );
idPortalSky();
~idPortalSky();
void Spawn( void );
void Event_PostSpawn();
void Event_Activate( idEntity *activator );
};
#endif /* !__GAME_MISC_H__ */

File diff suppressed because it is too large Load diff

View file

@ -88,8 +88,13 @@ protected:
int nextDamageTime; // next time the movable can hurt the player
int nextSoundTime; // next time the moveable can make a sound
// HEXEN : Zeroth
protected:
bool brokenScript; // call ::Broken on killed.
bool removeWhenBroken; // removes entity after it's "fuse" delay
const idMaterial * GetRenderModelMaterial( void ) const;
void BecomeNonSolid( void );
void InitInitialSpline( int startTime );
bool FollowInitialSplinePath( void );
@ -98,6 +103,19 @@ protected:
void Event_SetOwnerFromSpawnArgs( void );
void Event_IsAtRest( void );
void Event_EnableDamage( float enable );
void Event_DirectDamage( idEntity *damageTarget, const char *damageDefName );
void DirectDamage( const char *meleeDefName, idEntity *ent );
// HEXEN : Zeroth
protected:
void Event_BecomeSolid( void );
// HEXEN : Zeroth
public:
void BecomeNonSolid( void );
void BecomeSolid( void );
public:
bool savePersistentInfo;
};
@ -160,7 +178,7 @@ public:
virtual void Think( void );
virtual void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir,
const char *damageDefName, const float damageScale, const int location );
const char *damageDefName, const float damageScale, const int location, const idVec3 &iPoint );
virtual void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
virtual void WriteToSnapshot( idBitMsgDelta &msg ) const;
@ -201,4 +219,65 @@ private:
void Event_TriggerTargets();
};
#if 0
// HEXEN : Zeroth
// for idWood and other entities with renderModels that need more vertex/face info
class Destructible_FaceData_t {
public:
// this could be a bit more effiecient with idVec3 pointers that point to surface geometry...
idList< idVec3 > verts;
idVec3 center; // center of face
float area;
idPlane * plane;
idList< int > adjacent; // stores indexes of adjacent faces
// idVec3 worldCenter(void) const;
// idVec3 worldNotm(void) const;
};
//ID_INLINE idVec3 faceData_t::worldCenter(void) const {
// return center + physicsObj.GetOrigin() * physicsObj.GetAxis();
//}
//ID_INLINE idVec3 faceData_t::worldNorm(void) const {
// return norm + physicsObj.GetOrigin() * physicsObj.GetAxis();
//}
class Destructible_ModelData_t {
public:
idList<Destructible_FaceData_t> faces;
idVec3 center;
float area;
float avgArea;
// idVec3 worldCenter(void) const;
};
//ID_INLINE idVec3 geoData_t::worldCenter(void) const {
// return geo.center + physicsObj.GetOrigin() * physicsObj.GetAxis();
//}
// HEXEN : Zeroth
class idWood : public idMoveable {
public:
CLASS_PROTOTYPE( idWood );
idWood::idWood( void );
void Spawn( void );
virtual void Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
void Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir,
const char *damageDefName, const float damageScale, const int location, idVec3 &iPoint );
bool CheckFloating( idWood *caller, idWood *chain[], int c );
bool geoConstructed;
Destructible_ModelData_t geo;
idVec3 lastiPoint; // last damage position
private:
void ConstructGeo( void );
};
#endif
#endif /* !__GAME_MOVEABLE_H__ */

View file

@ -90,6 +90,11 @@ const idEventDef EV_StartSpline( "startSpline", "e" );
const idEventDef EV_StopSpline( "stopSpline", NULL );
const idEventDef EV_IsMoving( "isMoving", NULL, 'd' );
const idEventDef EV_IsRotating( "isRotating", NULL, 'd' );
const idEventDef EV_EnableClip( "enableClip" );
const idEventDef EV_DisableClip( "disableClip" );
const idEventDef EV_CanBecomeSolid( "canBecomeSolid", NULL, 'f' );
const idEventDef EV_MoverBecomeSolid( "becomeSolid" );
const idEventDef EV_MoverBecomeNonSolid( "becomeNonSolid" );
CLASS_DECLARATION( idEntity, idMover )
EVENT( EV_FindGuiTargets, idMover::Event_FindGuiTargets )
@ -131,6 +136,11 @@ CLASS_DECLARATION( idEntity, idMover )
EVENT( EV_Activate, idMover::Event_Activate )
EVENT( EV_IsMoving, idMover::Event_IsMoving )
EVENT( EV_IsRotating, idMover::Event_IsRotating )
EVENT( EV_EnableClip, idMover::Event_EnableClip )
EVENT( EV_DisableClip, idMover::Event_DisableClip )
EVENT( EV_CanBecomeSolid, idMover::Event_CanBecomeSolid )
EVENT( EV_MoverBecomeSolid, idMover::Event_BecomeSolid )
EVENT( EV_MoverBecomeNonSolid, idMover::Event_BecomeNonSolid )
END_CLASS
/*
@ -345,7 +355,9 @@ void idMover::Spawn( void ) {
spawnArgs.GetFloat( "damage" , "0", damage );
dest_position = GetPhysics()->GetOrigin();
SetPersistentPos(dest_position);
dest_angles = GetPhysics()->GetAxis().ToAngles();
SetPersistentAng(dest_angles);
physicsObj.SetSelf( this );
physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), 1.0f );
@ -999,7 +1011,7 @@ idMover::Event_PartBlocked
*/
void idMover::Event_PartBlocked( idEntity *blockingEntity ) {
if ( damage > 0.0f ) {
blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT );
blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT, idVec3( 0, 0, 0 ) );
}
if ( g_debugMover.GetBool() ) {
gameLocal.Printf( "%d: '%s' blocked by '%s'\n", gameLocal.time, name.c_str(), blockingEntity->name.c_str() );
@ -1034,6 +1046,18 @@ void idMover::Event_SetMoveTime( float time ) {
move_time = SEC2MS( time );
}
#if 0
/*
================
Zeroth
idMover::eoc_SetMoveTime
================
*/
void idMover::eoc_SetMoveTime( float time ) {
Event_SetMoveTime( time );
}
#endif
/*
================
idMover::Event_SetAccellerationTime
@ -1071,9 +1095,54 @@ void idMover::Event_MoveTo( idEntity *ent ) {
}
dest_position = GetLocalCoordinates( ent->GetPhysics()->GetOrigin() );
SetPersistentPos( dest_position );
BeginMove( idThread::CurrentThread() );
}
/*
================
Zeroth
idMover::SetPersistentPos
================
*/
void idMover::SetPersistentPos( idVec3 &pos ) {
// for removing items/creatures/etc after returning to a level (hubs)
idStr name_str, st;
name_str = gameLocal.GetMapName();
name_str += "_mover_pos";
gameLocal.persistentLevelInfo.SetVector( name_str, pos );
}
/*
================
Zeroth
idMover::SetPersistentAng
================
*/
void idMover::SetPersistentAng( idAngles &ang ) {
// for removing items/creatures/etc after returning to a level (hubs)
idStr name_str, st;
name_str = gameLocal.GetMapName();
name_str += "_mover_ang";
gameLocal.persistentLevelInfo.SetAngles( name_str, ang );
}
#if 0
/*
================
Zeroth
idMover::eoc_MoveToPos
================
*/
void idMover::eoc_MoveToPos( const idVec3 &pos ) {
MoveToPos( pos );
}
#endif
/*
================
idMover::MoveToPos
@ -1081,6 +1150,7 @@ idMover::MoveToPos
*/
void idMover::MoveToPos( const idVec3 &pos ) {
dest_position = GetLocalCoordinates( pos );
SetPersistentPos( dest_position );
BeginMove( NULL );
}
@ -1105,6 +1175,7 @@ void idMover::Event_MoveDir( float angle, float distance ) {
physicsObj.GetLocalOrigin( org );
VectorForDir( angle, dir );
dest_position = org + dir * distance;
SetPersistentPos( dest_position );
BeginMove( idThread::CurrentThread() );
}
@ -1456,6 +1527,10 @@ idMover::Event_Activate
================
*/
void idMover::Event_Activate( idEntity *activator ) {
if ( spawnArgs.GetBool( "NoActivateWhenTriggered", "0" ) ) {
return;
}
Show();
Event_StartSpline( this );
}
@ -1535,6 +1610,112 @@ void idMover::SetPortalState( bool open ) {
gameLocal.SetPortalState( areaPortal, open ? PS_BLOCK_NONE : PS_BLOCK_ALL );
}
/*
================
HEXEN
idMover::Event_EnableClip
================
*/
void idMover::Event_EnableClip( void ) {
physicsObj.SetClipMask( MASK_SOLID );
}
/*
================
HEXEN
idMover::Event_DisableClip
================
*/
void idMover::Event_DisableClip( void ) {
physicsObj.SetClipMask( 0 );
}
/*
================
HEXEN
idMover::Event_CanBecomeSolid
================
*/
void idMover::Event_CanBecomeSolid( void ) {
idThread::ReturnFloat( CanBecomeSolid() );
}
/*
================
HEXEN
idMover::CanBecomeSolid
================
*/
bool idMover::CanBecomeSolid( void ) {
int i;
int num;
idEntity * hit;
idClipModel *cm;
idClipModel *clipModels[ MAX_GENTITIES ];
num = gameLocal.clip.ClipModelsTouchingBounds( physicsObj.GetAbsBounds(), MASK_MONSTERSOLID, clipModels, MAX_GENTITIES );
for ( i = 0; i < num; i++ ) {
cm = clipModels[ i ];
// don't check render entities
if ( cm->IsRenderModel() ) {
continue;
}
hit = cm->GetEntity();
if ( ( hit == this ) || !hit->fl.takedamage ) {
continue;
}
if ( physicsObj.ClipContents( cm ) ) {
return false;
}
}
return true;
}
/*
================
HEXEN
idMover::Event_BecomeSolid
================
*/
void idMover::Event_BecomeSolid( void ) {
BecomeSolid( );
}
/*
================
HEXEN
idMover::BecomeSolid
================
*/
void idMover::BecomeSolid( void ) {
physicsObj.SetContents( MASK_SOLID );
}
/*
================
HEXEN
idMover::Event_BecomeNonSolid
================
*/
void idMover::Event_BecomeNonSolid( void ) {
BecomeNonSolid();
}
/*
================
HEXEN
idMover::BecomeSolid
================
*/
void idMover::BecomeNonSolid( void ) {
physicsObj.SetContents( 0 );
}
/*
===============================================================================
@ -3788,7 +3969,7 @@ idDoor::Event_PartBlocked
*/
void idDoor::Event_PartBlocked( idEntity *blockingEntity ) {
if ( damage > 0.0f ) {
blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT );
blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT, idVec3( 0, 0, 0 ) );
}
}
@ -4225,7 +4406,7 @@ idPlat::Event_PartBlocked
*/
void idPlat::Event_PartBlocked( idEntity *blockingEntity ) {
if ( damage > 0.0f ) {
blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT );
blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT, idVec3( 0, 0, 0 ) );
}
}
@ -4316,7 +4497,7 @@ idMover_Periodic::Event_PartBlocked
*/
void idMover_Periodic::Event_PartBlocked( idEntity *blockingEntity ) {
if ( damage > 0.0f ) {
blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT );
blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT, idVec3( 0, 0, 0 ) );
}
}

View file

@ -66,6 +66,26 @@ public:
void SetPortalState( bool open );
void Event_EnableClip( void );
void Event_DisableClip( void );
void Event_BecomeSolid( void );
void Event_CanBecomeSolid( void );
void Event_BecomeNonSolid( void );
bool CanBecomeSolid( void );
void BecomeSolid( void );
void BecomeNonSolid( void );
// only for use with hub-style map initialization
void SetDestPos( const idVec3 &pos ) { dest_position=pos; }
void SetDestAng( const idAngles &ang ) { dest_angles=ang; }
// HEXEN : Zeroth
// void eoc_SetMoveTime( float time );
// void eoc_MoveToPos( const idVec3 &pos );
void SetPersistentPos( idVec3 &pos );
void SetPersistentAng( idAngles &ang );
protected:
typedef enum {
ACCELERATION_STAGE,