📄 gravpath.cpp
字号:
//-----------------------------------------------------------------------------
//
// $Logfile:: /Quake 2 Engine/Sin/code/game/gravpath.cpp $
// $Revision:: 18 $
// $Author:: Markd $
// $Date:: 10/24/98 12:42a $
//
// Copyright (C) 1998 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// $Log:: /Quake 2 Engine/Sin/code/game/gravpath.cpp $
//
// 18 10/24/98 12:42a Markd
// changed origins to worldorigins where appropriate
//
// 17 10/21/98 2:24a Jimdose
// Made GravPath not add to the gravPathManager while loading savegames
//
// 16 10/09/98 5:22p Aldie
// Changed commands to activate and deactivate
//
// 15 10/07/98 11:52p Jimdose
// Added destructor for GravPathManager
//
// 14 9/30/98 4:34p Aldie
// Free gravpath when level changes
//
// 13 9/30/98 1:17p Markd
// Fixed gravpath null pointer checks
//
// 12 9/29/98 5:33p Aldie
// Added force gravity to the path
//
// 11 8/29/98 9:43p Jimdose
// Added call info to G_Trace
//
// 10 8/27/98 2:55p Aldie
// Added a headnode spawnflag
//
// 9 8/27/98 2:33p Aldie
// Added functionality so gravpaths work out of water
//
// 8 8/26/98 8:46p Aldie
// Added activate and deactivate commands
//
// 7 5/26/98 4:45p Aldie
// Fixed an error printf
//
// 6 5/25/98 2:28p Aldie
// Fixed issues with not loading game dll
//
// 5 5/23/98 10:21p Aldie
// Removed drawing of gravpath.
//
// 4 5/23/98 5:15p Aldie
// Removed traces checking for obstacles when finding the closest grav point.
//
// 3 5/22/98 12:24p Aldie
// Updated defaults
//
// 2 5/22/98 12:19p Aldie
// First version of gravity path
//
// DESCRIPTION:
// Gravity path - Used for underwater currents and wells.
#include "g_local.h"
#include "entity.h"
#include "gravpath.h"
#include "container.h"
#include "navigate.h"
#include "misc.h"
#include "player.h"
GravPathManager gravPathManager;
CLASS_DECLARATION(Class, GravPathManager, NULL);
ResponseDef GravPathManager::Responses[] =
{
{ NULL,NULL }
};
GravPathManager::~GravPathManager()
{
Reset();
}
void GravPathManager::Reset( void )
{
while( pathList.NumObjects() > 0 )
{
delete ( GravPath * )pathList.ObjectAt( 1 );
}
pathList.FreeObjectList();
}
void GravPathManager::AddPath(GravPath *p)
{
int num;
num = pathList.AddObject( p );
pathList.Resize( pathList.NumObjects() );
}
void GravPathManager::RemovePath(GravPath *p)
{
pathList.RemoveObject( p );
pathList.Resize( pathList.NumObjects() );
}
Vector GravPathManager::CalculateGravityPull(Entity &ent, Vector pos, qboolean *force)
{
int i,num;
GravPath *p;
GravPathNode *node;
Vector point;
Vector newpoint;
Vector dir;
float bestdist = 99999;
float dist;
float speed;
float radius;
Vector velocity;
int bestpath = 0;
int entity_contents, grav_contents;
num = pathList.NumObjects();
entity_contents = gi.pointcontents( ent.worldorigin.vec3() );
for( i = 1; i <= num; i++ )
{
p = ( GravPath * )pathList.ObjectAt( i );
if ( !p )
continue;
// Check to see if path is active
node = p->GetNode( 1 );
if ( !node || !node->active )
continue;
// Check to see if the contents are the same
grav_contents = gi.pointcontents( node->worldorigin.vec3() );
// If grav node is in water, make sure ent is too.
if ( ( grav_contents & CONTENTS_WATER ) && !( entity_contents & CONTENTS_WATER ) )
continue;
// Test to see if we are in this path's bounding box
if ( (pos.x < p->maxs.x) && (pos.y < p->maxs.y) && (pos.z < p->maxs.z) &&
(pos.x > p->mins.x) && (pos.y > p->mins.y) && (pos.z > p->mins.z) )
{
point = p->ClosestPointOnPath(pos, ent, &dist, &speed, &radius);
// If the closest distance on the path is greater than the radius, then
// do not consider this path.
if (dist > radius)
{
continue;
}
else if (dist < bestdist)
{
bestpath = i;
bestdist = dist;
}
}
}
if (!bestpath)
{
return vec_zero;
}
p = ( GravPath * )pathList.ObjectAt( bestpath );
if ( !p )
return velocity;
*force = p->force;
dist = p->DistanceAlongPath(pos, &speed);
newpoint = p->PointAtDistance( dist + speed);
dir = newpoint-pos;
dir.normalize();
velocity = dir * speed;
return velocity;
}
/*****************************************************************************/
/*SINED info_grav_pathnode (0 0 .5) (-16 -16 0) (16 16 32) HEADNODE FORCE
"radius" Radius of the effect of the pull (Default is 256)
"speed" Speed of the pull (Use negative for a repulsion) (Default is 100)
Set HEADNODE to signify the head of the path.
Set FORCE if you want un-fightable gravity ( i.e. can't go backwards )
/*****************************************************************************/
CLASS_DECLARATION( Entity, GravPathNode, "info_grav_pathnode" );
Event EV_GravPath_Create( "gravpath_create" );
Event EV_GravPath_Activate( "activate" );
Event EV_GravPath_Deactivate( "deactivate" );
ResponseDef GravPathNode::Responses[] =
{
{ &EV_GravPath_Create, ( Response )GravPathNode::CreatePath },
{ &EV_GravPath_Activate, ( Response )GravPathNode::Activate },
{ &EV_GravPath_Deactivate, ( Response )GravPathNode::Deactivate },
{ NULL, NULL }
};
GravPathNode::GravPathNode()
{
setMoveType( MOVETYPE_NONE );
setSolidType( SOLID_NOT );
hideModel();
speed = G_GetFloatArg( "speed",100.0f );
radius = G_GetFloatArg( "radius",256.0f );
headnode = spawnflags & 1;
active = true;
// This is the head of a new path, post an event to create the path
if ( headnode )
{
PostEvent( EV_GravPath_Create, 0 );
}
}
float GravPathNode::Speed( void )
{
if ( active )
return speed;
else
return 0;
};
void GravPathNode::Activate(Event *ev)
{
GravPathNode *node;
int num;
const char *target;
active = true;
node = this;
// Go through the entire path and activate it
target = node->Target();
while (target[0])
{
if (num = G_FindTarget(0, target))
{
node = (GravPathNode *)G_GetEntity( num );
assert( node );
node->active = true;
}
else
{
gi.error("GravPathNode::CreatePath: target %s not found\n",target);
}
target = node->Target();
}
}
void GravPathNode::Deactivate(Event *ev)
{
GravPathNode *node;
int num;
const char *target;
active = false;
node = this;
// Go through the entire path and activate it
target = node->Target();
while (target[0])
{
if (num = G_FindTarget(0, target))
{
node = (GravPathNode *)G_GetEntity( num );
assert( node );
node->active = false;
}
else
{
gi.error("GravPathNode::CreatePath: target %s not found\n",target);
}
target = node->Target();
}
}
void GravPathNode::CreatePath(Event *ev)
{
const char *target;
GravPath *path = new GravPath;
GravPathNode *node;
int num;
ClearBounds(path->mins.vec3(),path->maxs.vec3());
// This node is the head of a path, create a new path in the path manager.
// and add it in, then add all of it's children in the path.
node = this;
path->AddNode(node);
path->force = spawnflags & 2;
// Make the path from the targetlist.
target = node->Target();
while (target[0])
{
if (num = G_FindTarget(0, target))
{
node = (GravPathNode *)G_GetEntity( num );
assert( node );
path->AddNode(node);
}
else
{
gi.error("GravPathNode::CreatePath: target %s not found\n",target);
}
target = node->Target();
}
// Set the origin.
path->origin = path->mins + path->maxs;
path->origin *= 0.5f;
}
CLASS_DECLARATION( Listener, GravPath, NULL );
Event EV_DrawGravPath( "drawpath" );
ResponseDef GravPath::Responses[] =
{
{ &EV_DrawGravPath, (Response)GravPath::DrawPath },
{ NULL, NULL }
};
GravPath::GravPath()
{
// Event *event;
pathlength = 0;
from = NULL;
to = NULL;
nextnode = 1;
if ( !LoadingSavegame )
{
gravPathManager.AddPath(this);
}
// event = new Event(EV_DrawGravPath);
// event->AddFloat(1);
// event->AddFloat(0);
// event->AddFloat(0);
// PostEvent(event,0.1f);
}
GravPath::~GravPath()
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -